Skip to content

Commit

Permalink
Revert "Feature/controller"
Browse files Browse the repository at this point in the history
  • Loading branch information
marcoschwartz authored Jul 5, 2018
1 parent bd6d998 commit 71bf91c
Show file tree
Hide file tree
Showing 21 changed files with 58 additions and 1,083 deletions.
20 changes: 1 addition & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ To install the library, simply clone this repository in the /libraries folder of

## API documentation

The API currently supports five type of commands: digital, analog, and mode, variables, and user-defined functions and api-extensions.
The API currently supports five type of commands: digital, analog, and mode, variables, and user-defined functions.

### Digital

Expand Down Expand Up @@ -189,24 +189,6 @@ You can also define your own functions in your sketch that can be called using t
* `rest.function("led",ledControl);` declares the function in the Arduino sketch
* `/led?params=0` executes the function

### API-Extensions

With api-extensions you have the possibility to extend the api by your own subcommands and customized responses.

You define your api extensions in your sketch that can be called using the REST API. To access an user-defined api-extension defined in your sketch, you have to declare it first, and then call it from with a REST call. Note that all api-extension functions need to have the following signature `void api_extension(aREST *arest, const String& name, const String& request_url)`. For example, if your aREST instance is called "rest" and the function "aquariumController":
* `rest.api_extension("aquarium",aquariumController);` declares the api extension in the Arduino sketch
* `/aquarium/water_limit/lower/set/65` executes the api-extension function and passes the value `"/aquarium/water_limit/lower/set/65"` as the third parameter (`request_url`) into the api-extension function
* You can then customize your JSON result and extend it to something like this:
```
{
"sensor-ids": ["100", "101", "102", "103", "104"],
"id": "008",
"name": "dapper_drake",
"hardware": "arduino",
"connected": true
}
```
### Get data about the board

You can also access a description of all the variables that were declared on the board with a single command. This is useful to automatically build graphical interfaces based on the variables exposed to the API. This can be done via the following calls:
Expand Down
145 changes: 56 additions & 89 deletions aREST.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ struct Handler {
Handler() : include_into_root_answer{false} { }
Handler(bool include) : include_into_root_answer{include} { }

virtual void addToBuffer(aREST *arest, const String& name, const String& request_url) const = 0;
virtual void addToBuffer(aREST *arest, const String& name, const String& arguments) const = 0;
};


Expand All @@ -201,7 +201,7 @@ struct Variable: Handler {

virtual void addToBuffer(aREST *arest) const = 0;

void addToBuffer(aREST *arest, const String& name, const String& request_url) const override {
void addToBuffer(aREST *arest, const String& name, const String& arguments) const override {
if (LIGHTWEIGHT) {
addToBuffer(arest);
} else {
Expand Down Expand Up @@ -231,8 +231,7 @@ struct FunctionHandler: Handler {

FunctionHandler(int (*f)(String)) : func{f} { }

void addToBuffer(aREST *arest, const String& name, const String& request_url) const override {
String arguments = extractParams(name, request_url);
void addToBuffer(aREST *arest, const String& name, const String& arguments) const override {
int result = func(arguments);

if (!LIGHTWEIGHT) {
Expand All @@ -243,36 +242,6 @@ struct FunctionHandler: Handler {
// arest->addToBufferF(F(" executed\", "));
}
}

String extractParams(const String& name, const String& request_url) const {
// We're expecting a string of the form <handlerName>?xxxxx=<arguments>, where xxxxx can be almost anything as long as it's followed by an '='
// Get command -- Anything following the first '=' in answer will be put in the arguments string.
uint16_t header_length = name.length() + 1; // +1 for the '/' at the start
if (request_url.substring(header_length, header_length + 1) == "?") {
// Standard operation --> strip off anything preceeding the first "=", pass the rest to the handler
if(AREST_PARAMS_MODE == 0) {
uint16_t eq_position = request_url.indexOf('=', header_length); // Replacing 'magic number' 8 for fixed location of '='
if (eq_position != -1)
return request_url.substring(eq_position + 1, request_url.length());
}
// All params mode --> pass all parameters, if any, to the handler. Handler will be resonsible for parsing
else if(AREST_PARAMS_MODE == 1) {
return request_url.substring(header_length + 1, request_url.length());
}
}
return String("");
}
};


struct ApiHandler: Handler {
void (*func)(aREST *, const String&, const String&);

ApiHandler(void (*f)(aREST *, const String&, const String&)) : func{f} { }

void addToBuffer(aREST *arest, const String& name, const String& request_url) const override {
func(arest, name, request_url);
}
};

public:
Expand Down Expand Up @@ -313,13 +282,6 @@ void function(const char *name, int (*f)(String)) {
}


void api_extension(const char *name, void (*f)(aREST *, const String&, const String&)) {
handlers[handlers_index] = new ApiHandler(f);
handler_names[handlers_index] = name;
handlers_index++;
}


private:

void initialize() {
Expand Down Expand Up @@ -495,7 +457,7 @@ void reset_status() {

reset();
answer = "";
request_url = "";
arguments = "";

index = 0;
//memset(&buffer[0], 0, sizeof(buffer));
Expand Down Expand Up @@ -1182,29 +1144,42 @@ void process(char c) {
// Handler request received ?
if (command == 'u') {

if (answer.endsWith(" HTTP/") || answer.endsWith("\r")) {
// Check if handler name is registered in array
for (uint8_t i = 0; i < handlers_index; i++) {
if (answer.startsWith(handler_names[i])) {

// End here
pin_selected = true;
state = 'x';

// Set state
command = 'h';
value = i;

answer.trim();

if (answer.endsWith(" HTTP/")) {
request_url = "/" + answer.substring(0, answer.length() - 6); // length of " HTTP/"
} else {
request_url = "/" + answer;
// Check if handler name is registered in array
for (uint8_t i = 0; i < handlers_index; i++) {
if (answer.startsWith(handler_names[i])) {

// End here
pin_selected = true;
state = 'x';

// Set state
command = 'h';
value = i;

answer.trim();

// We're expecting a string of the form <handlerName>?xxxxx=<arguments>, where xxxxx can be almost anything as long as it's followed by an '='
// Get command -- Anything following the first '=' in answer will be put in the arguments string.
arguments = "";
uint16_t header_length = strlen(handler_names[i]);
if (answer.substring(header_length, header_length + 1) == "?") {
uint16_t footer_start = answer.length();
if (answer.endsWith(" HTTP/"))
footer_start -= 6; // length of " HTTP/"

// Standard operation --> strip off anything preceeding the first "=", pass the rest to the handler
if(AREST_PARAMS_MODE == 0) {
uint16_t eq_position = answer.indexOf('=', header_length); // Replacing 'magic number' 8 for fixed location of '='
if (eq_position != -1)
arguments = answer.substring(eq_position + 1, footer_start);
}
// All params mode --> pass all parameters, if any, to the handler. Handler will be resonsible for parsing
else if(AREST_PARAMS_MODE == 1) {
arguments = answer.substring(header_length + 1, footer_start);
}

break; // We found what we're looking for
}

break; // We found what we're looking for
}
}

Expand Down Expand Up @@ -1239,23 +1214,19 @@ void process(char c) {
// Serial.print("Selected method: ");
// Serial.println(method);
// }
} else {
answer = "";
}

if (c == '\r' || answer.startsWith("GET /") || answer.startsWith("/")) {
answer = "";
}
answer = "";
}


// Modifies request_url in place
void urldecode(String &request_url) {
// Modifies arguments in place
void urldecode(String &arguments) {
char a, b;
int j = 0;
for(int i = 0; i < request_url.length(); i++) {
// %20 ==> request_url[i] = '%', a = '2', b = '0'
if ((request_url[i] == '%') && ((a = request_url[i + 1]) && (b = request_url[i + 2])) && (isxdigit(a) && isxdigit(b))) {
for(int i = 0; i < arguments.length(); i++) {
// %20 ==> arguments[i] = '%', a = '2', b = '0'
if ((arguments[i] == '%') && ((a = arguments[i + 1]) && (b = arguments[i + 2])) && (isxdigit(a) && isxdigit(b))) {
if (a >= 'a') a -= 'a'-'A';
if (a >= 'A') a -= ('A' - 10);
else a -= '0';
Expand All @@ -1264,17 +1235,17 @@ void urldecode(String &request_url) {
if (b >= 'A') b -= ('A' - 10);
else b -= '0';

request_url[j] = char(16 * a + b);
arguments[j] = char(16 * a + b);
i += 2; // Skip ahead
} else if (request_url[i] == '+') {
request_url[j] = ' ';
} else if (arguments[i] == '+') {
arguments[j] = ' ';
} else {
request_url[j] = request_url[i];
arguments[j] = arguments[i];
}
j++;
}

request_url.remove(j); // Truncate string to new possibly reduced length
arguments.remove(j); // Truncate string to new possibly reduced length
}


Expand Down Expand Up @@ -1474,19 +1445,15 @@ bool send_command(bool headers, bool decodeArgs) {
// Handler selected
if (command == 'h') {
if (decodeArgs) {
urldecode(request_url); // Modifies request_url
urldecode(arguments); // Modifies arguments
}
// Send feedback to client
if (LIGHTWEIGHT) {
addHandlerToBuffer(value, request_url);
addHandlerToBuffer(value, arguments);
} else {
addToBufferF(F("{"));
auto bufferPos = index;
addHandlerToBuffer(value, request_url);
if (bufferPos < index) {
// index has changed -> the handler added some stuff to the buffer
addToBufferF(F(", "));
}
addHandlerToBuffer(value, arguments);
addToBufferF(F(", "));
}
}

Expand Down Expand Up @@ -1901,8 +1868,8 @@ uint8_t esp_12_pin_map(uint8_t pin) {
}


void addHandlerToBuffer(uint8_t index, const String& request_url) {
handlers[index]->addToBuffer(this, String(handler_names[index]), request_url);
void addHandlerToBuffer(uint8_t index, const String& arguments) {
handlers[index]->addToBuffer(this, String(handler_names[index]), arguments);
}


Expand Down Expand Up @@ -1954,7 +1921,7 @@ void setMQTTServer(char* new_mqtt_server){

char name[NAME_SIZE];
String id;
String request_url;
String arguments;

// Output uffer
char buffer[OUTPUT_BUFFER_SIZE];
Expand Down
57 changes: 0 additions & 57 deletions examples/BLE/BLE.ino
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RD
int temperature;
int humidity;

// Declare functions to be exposed to the API
int ledControl(String command);
void aquariumController(aREST *arest, const String& name, const String& request_url);

void setup(void)
{
// Start Serial
Expand All @@ -46,9 +42,6 @@ void setup(void)
// Function to be exposed
rest.function("led",ledControl);

// API-Extension to be exposed
rest.api_extension("aquarium", aquariumController);

// Give name & ID to the device (ID should be 6 characters long)
rest.set_id("008");
rest.set_name("ble_drake");
Expand Down Expand Up @@ -95,53 +88,3 @@ int ledControl(String command) {
digitalWrite(7,state);
return 1;
}

void aquariumController(aREST *arest, const String& name, const String& request_url) {
// check format of request_url
if (request_url == F("/aquarium")
|| request_url == F("/aquarium/")) {
// Send feedback to client
if (LIGHTWEIGHT) {
bool isFirstSensor = true;
auto count = 5;
for (uint32_t i = 0; i < count; ++i) {
if (isFirstSensor) {
isFirstSensor = false;
} else {
arest->addToBufferF(F(","));
}
auto id = i + 100;
arest->addToBuffer(id);
}
} else {
arest->addToBufferF(F("\"sensor-ids\": ["));
bool isFirstSensor = true;
auto count = 5;
for (uint32_t i = 0; i < count; ++i) {
if (isFirstSensor) {
isFirstSensor = false;
} else {
arest->addToBufferF(F(", "));
}
arest->addToBufferF(F("\""));
auto id = i + 100;
arest->addToBuffer(id);
arest->addToBufferF(F("\""));
}
arest->addToBufferF(F("]"));
}
} else if (request_url.startsWith(F("/aquarium/water_limit/lower/set/"))) {
String args = request_url.substring(32); // 32 = length of "/aquarium/water_limit/lower/set/"

// Send feedback to client
if (!LIGHTWEIGHT) {
arest->addToBufferF(F("\"message\": \"lower water limit set to "));
arest->addToBuffer(args);
arest->addToBufferF(F("cm\""));
}
} else {
arest->addToBufferF(F("\"message\": \"Unknown request_url '"));
arest->addToBuffer(request_url);
arest->addToBufferF(F("'.\""));
}
}
Loading

0 comments on commit 71bf91c

Please sign in to comment.