Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/handlers #244

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 108 additions & 86 deletions aREST.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@
#define LIGHTWEIGHT 0
#endif


// -------- for backwards compatibility --------
#ifdef AREST_NUMBER_VARIABLES
#define NUMBER_VARIABLES AREST_NUMBER_VARIABLES
#endif
Expand All @@ -143,21 +145,36 @@
#define NUMBER_FUNCTIONS AREST_NUMBER_FUNCTIONS
#endif

// Default number of max. exposed variables
#ifndef NUMBER_VARIABLES
#if defined(NUMBER_VARIABLES) && defined(NUMBER_FUNCTIONS)
#define AREST_NUMBER_HANDLERS (NUMBER_VARIABLES + NUMBER_FUNCTIONS)
#elif defined(NUMBER_VARIABLES)
#if defined(__AVR_ATmega1280__) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266)
#define NUMBER_FUNCTIONS 10
#else
#define NUMBER_FUNCTIONS 5
#endif
#define AREST_NUMBER_HANDLERS (NUMBER_VARIABLES + NUMBER_FUNCTIONS)
#elif defined(NUMBER_FUNCTIONS)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266)|| defined(ESP32) || !defined(ADAFRUIT_CC3000_H)
#define NUMBER_VARIABLES 10
#else
#define NUMBER_VARIABLES 5
#endif
#define AREST_NUMBER_HANDLERS (NUMBER_VARIABLES + NUMBER_FUNCTIONS)
#endif
// -------- end --------

// Default number of max. exposed functions
#ifndef NUMBER_FUNCTIONS
#if defined(__AVR_ATmega1280__) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266)
#define NUMBER_FUNCTIONS 10

#ifdef AREST_NUMBER_HANDLERS
#define NUMBER_HANDLERS AREST_NUMBER_HANDLERS
#endif

// Default number of max. exposed handlers
#ifndef NUMBER_HANDLERS
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266)|| defined(ESP32) || !defined(ADAFRUIT_CC3000_H)
#define NUMBER_HANDLERS 20
#else
#define NUMBER_FUNCTIONS 5
#define NUMBER_HANDLERS 10
#endif
#endif

Expand All @@ -170,8 +187,30 @@
class aREST {

private:
struct Variable {
struct Handler {
bool include_into_root_answer;

Handler() : include_into_root_answer{false} { }
Handler(bool include) : include_into_root_answer{include} { }

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


struct Variable: Handler {
Variable() : Handler(true) { }

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

void addToBuffer(aREST *arest, const String& name, const String& arguments) const override {
if (LIGHTWEIGHT) {
addToBuffer(arest);
} else {
arest->addStringToBuffer(name.c_str(), true);
arest->addToBufferF(F(": "));
addToBuffer(arest);
}
}
};


Expand All @@ -187,6 +226,25 @@ struct TypedVariable: Variable {
}
};


struct FunctionHandler: Handler {
int (*func)(String);

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

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

if (!LIGHTWEIGHT) {
arest->addToBufferF(F("\"return_value\": "));
arest->addToBuffer(result, true);
// arest->addToBufferF(F(", \"message\": \""));
// arest->addStringToBuffer(name.c_str());
// arest->addToBufferF(F(" executed\", "));
}
}
};

public:

public:
Expand All @@ -207,9 +265,9 @@ aREST(char* rest_remote_server, int rest_port) {

template<typename T>
void variable(const char *name, T *var, bool quotable) {
variables[variables_index] = new TypedVariable<T>(var, quotable);
variable_names[variables_index] = name;
variables_index++;
handlers[handlers_index] = new TypedVariable<T>(var, quotable);
handler_names[handlers_index] = name;
handlers_index++;
}

template<typename T>
Expand All @@ -218,6 +276,13 @@ void variable(const char *name, T *var) {
}


void function(const char *name, int (*f)(String)) {
handlers[handlers_index] = new FunctionHandler(f);
handler_names[handlers_index] = name;
handlers_index++;
}


private:

void initialize() {
Expand Down Expand Up @@ -351,7 +416,6 @@ void setKey(char* api_key, PubSubClient& client) {
// Build client ID
client_id = id + String(api_key);
client_id = id + String(proKey);

}

#endif
Expand Down Expand Up @@ -1106,55 +1170,39 @@ void process(char c) {
#endif
}

// Variable or function request received ?
// Handler request received ?
if (command == 'u') {

// Check if variable name is in int array
for (uint8_t i = 0; i < variables_index; i++) {
if (answer.startsWith(variable_names[i])) {
// 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 = 'v';
value = i;

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

// Check if function name is in array
for (uint8_t i = 0; i < functions_index; i++) {
if (answer.startsWith(functions_names[i])) {

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

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

answer.trim();

// We're expecting a string of the form <functionName>?xxxxx=<arguments>, where xxxxx can be almost anything as long as it's followed by an '='
// 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(functions_names[i]);
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 function
// 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 function. Function will be resonsible for parsing
// 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);
}
Expand Down Expand Up @@ -1423,38 +1471,21 @@ bool send_command(bool headers, bool decodeArgs) {
}
}

// Variable selected
if (command == 'v') {
// Handler selected
if (command == 'h') {
if (decodeArgs) {
urldecode(arguments); // Modifies arguments
}
// Send feedback to client
if (LIGHTWEIGHT) {
variables[value]->addToBuffer(this);
addHandlerToBuffer(value, arguments);
} else {
addToBufferF(F("{"));
addVariableToBuffer(value);
addHandlerToBuffer(value, arguments);
addToBufferF(F(", "));
}
}

// Function selected
if (command == 'f') {

// Execute function
if (decodeArgs)
urldecode(arguments); // Modifies arguments

int result = functions[value](arguments);

// Send feedback to client
if (!LIGHTWEIGHT) {
addToBufferF(F("{\"return_value\": "));
addToBuffer(result, true);
addToBufferF(F(", "));
// addToBufferF(F(", \"message\": \""));
// addStringToBuffer(functions_names[value]);
// addToBufferF(F(" executed\", "));
}
}

if (command == 'r' || command == 'u') {
root_answer();
}
Expand Down Expand Up @@ -1510,11 +1541,16 @@ virtual void root_answer() {
else {
addToBufferF(F("{\"variables\": {"));

for (uint8_t i = 0; i < variables_index; i++){
addVariableToBuffer(i);

if (i < variables_index - 1) {
addToBufferF(F(", "));
bool isFirst = true;
for (uint8_t i = 0; i < handlers_index; i++){
if (handlers[i]->include_into_root_answer) {
// variable should be included into root answer
if (isFirst) {
isFirst = false;
} else {
addToBufferF(F(", "));
}
addHandlerToBuffer(i, String(""));
}
}

Expand All @@ -1530,13 +1566,6 @@ virtual void root_answer() {
}


void function(char * function_name, int (*f)(String)){

functions_names[functions_index] = function_name;
functions[functions_index] = f;
functions_index++;
}

// Set device ID
void set_id(const String& device_id) {

Expand Down Expand Up @@ -1871,10 +1900,8 @@ uint8_t esp_12_pin_map(uint8_t pin) {
}


void addVariableToBuffer(uint8_t index) {
addStringToBuffer(variable_names[index], true);
addToBufferF(F(": "));
variables[index]->addToBuffer(this);
void addHandlerToBuffer(uint8_t index, const String& arguments) {
handlers[index]->addToBuffer(this, String(handler_names[index]), arguments);
}


Expand Down Expand Up @@ -1936,10 +1963,10 @@ void setMQTTServer(char* new_mqtt_server){
// Status LED
uint8_t status_led_pin;

// Int variables arrays
uint8_t variables_index;
Variable* variables[NUMBER_VARIABLES];
const char * variable_names[NUMBER_VARIABLES];
// Handlers arrays
uint8_t handlers_index;
Handler* handlers[NUMBER_HANDLERS];
const char * handler_names[NUMBER_HANDLERS];

// MQTT client
#if defined(PubSubClient_h)
Expand All @@ -1961,11 +1988,6 @@ void setMQTTServer(char* new_mqtt_server){
#endif


// Functions array
uint8_t functions_index;
int (*functions[NUMBER_FUNCTIONS])(String);
char * functions_names[NUMBER_FUNCTIONS];

// Memory debug
#if defined(ESP8266) || defined(ESP32)
int freeMemory;
Expand Down