diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index ecae372..deb31c1 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -35,6 +35,11 @@ typedef class MyRFDriverNRF24 MyRFDriverClass; typedef class MyRFDriverRF69 MyRFDriverClass; #endif +#if defined(MYSENSORS_SERIAL_GATEWAY) || defined(MYSENSORS_ETHERNET_GATEWAY) +#include "MyParserSerial.h" +typedef class MyParserSerial MyParserClass; +#endif + #ifdef MYSENSORS_SIGNING_DUMMY #include "MySigningDriverDummy.h" #define SIGNING_IDENTIFIER (0) // Reserved for dummy implementation, will not work with other backends diff --git a/libraries/MySensors/MyParser.cpp b/libraries/MySensors/MyParser.cpp new file mode 100644 index 0000000..dacd32b --- /dev/null +++ b/libraries/MySensors/MyParser.cpp @@ -0,0 +1,4 @@ +#include "MyParser.h" + +MyParser::MyParser() { +} diff --git a/libraries/MySensors/MyParser.h b/libraries/MySensors/MyParser.h new file mode 100644 index 0000000..e606a0d --- /dev/null +++ b/libraries/MySensors/MyParser.h @@ -0,0 +1,16 @@ +#ifndef MyParser_h +#define MyParser_h + +#include "MyMessage.h" + +class MyParser +{ +public: + // MyParser constructor + MyParser(); + // parse(message, inputString) + // parse a string into a message element + // returns true if successfully parsed the input string + virtual bool parse(MyMessage &message, char *inputString) = 0; +}; +#endif \ No newline at end of file diff --git a/libraries/MySensors/MyParserSerial.cpp b/libraries/MySensors/MyParserSerial.cpp new file mode 100644 index 0000000..dc233c0 --- /dev/null +++ b/libraries/MySensors/MyParserSerial.cpp @@ -0,0 +1,81 @@ +#include "MyParser.h" +#include "MyParserSerial.h" + +MyParserSerial::MyParserSerial() : MyParser() {} + +bool MyParserSerial::parse(MyMessage &message, char *inputString) { + char *str, *p, *value=NULL; + uint8_t bvalue[MAX_PAYLOAD]; + uint8_t blen = 0; + int i = 0; + uint8_t command = 0; + uint8_t ack = 0; + + // Extract command data coming on serial line + for (str = strtok_r(inputString, ";", &p); // split using semicolon + str && i < 6; // loop while str is not null an max 5 times + str = strtok_r(NULL, ";", &p) // get subsequent tokens + ) { + switch (i) { + case 0: // Radioid (destination) + message.destination = atoi(str); + break; + case 1: // Childid + message.sensor = atoi(str); + break; + case 2: // Message type + command = atoi(str); + mSetCommand(message, command); + break; + case 3: // Should we request ack from destination? + ack = atoi(str); + break; + case 4: // Data type + message.type = atoi(str); + break; + case 5: // Variable value + if (command == C_STREAM) { + blen = 0; + uint8_t val; + while (*str) { + val = h2i(*str++) << 4; + val += h2i(*str++); + bvalue[blen] = val; + blen++; + } + } else { + value = str; + // Remove ending carriage return character (if it exists) + uint8_t lastCharacter = strlen(value)-1; + if (value[lastCharacter] == '\r') + value[lastCharacter] = 0; + } + break; + } + i++; + } + // Check for invalid input + if (i < 5) + return false; + + message.sender = GATEWAY_ADDRESS; + message.last = GATEWAY_ADDRESS; + mSetRequestAck(message, ack?1:0); + mSetAck(message, false); + if (command == C_STREAM) + message.set(bvalue, blen); + else + message.set(value); + return true; +} + +uint8_t MyParserSerial::h2i(char c) { + uint8_t i = 0; + if (c <= '9') + i += c - '0'; + else if (c >= 'a') + i += c - 'a' + 10; + else + i += c - 'A' + 10; + return i; +} diff --git a/libraries/MySensors/MyParserSerial.h b/libraries/MySensors/MyParserSerial.h new file mode 100644 index 0000000..e7baf9b --- /dev/null +++ b/libraries/MySensors/MyParserSerial.h @@ -0,0 +1,15 @@ +#ifndef MyParserSerial_h +#define MyParserSerial_h + +#include "MyConfig.h" +#include "MyParser.h" + +class MyParserSerial : public MyParser +{ +public: + MyParserSerial(); + bool parse(MyMessage &message, char *inputString); +private: + uint8_t h2i(char c); +}; +#endif \ No newline at end of file diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 7c6405e..cdac00c 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -14,6 +14,7 @@ #include "Version.h" // Auto generated by bot #include "MyRFDriver.h" +#include "MyParser.h" #include "MySigningDriver.h" #include "MyConfig.h" #include "MyMessage.h" diff --git a/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h b/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h index b5ac2ba..109f330 100644 --- a/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h +++ b/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h @@ -23,7 +23,7 @@ volatile uint8_t countErr; boolean inclusionMode; // Keeps track on inclusion mode void (*serial)(const char *fmt, ... ); -MyMessage msg; +MyParserClass parser; void setInclusionMode(boolean newMode); void txBlink(uint8_t cnt); @@ -104,102 +104,32 @@ void checkInclusionFinished() { } } -uint8_t h2i(char c) { - uint8_t i = 0; - if (c <= '9') - i += c - '0'; - else if (c >= 'a') - i += c - 'a' + 10; - else - i += c - 'A' + 10; - return i; -} - void parseAndSend(MySensor gw, char *commandBuffer) { - boolean ok = false; - char *str, *p, *value=NULL; - uint8_t bvalue[MAX_PAYLOAD]; - uint8_t blen = 0; - int i = 0; - uint16_t destination = 0; - uint8_t sensor = 0; - uint8_t command = 0; - uint8_t type = 0; - uint8_t ack = 0; + boolean ok; + MyMessage &msg = gw.getLastMessage(); - // Extract command data coming on serial line - for (str = strtok_r(commandBuffer, ";", &p); // split using semicolon - str && i < 6; // loop while str is not null an max 5 times - str = strtok_r(NULL, ";", &p) // get subsequent tokens - ) { - switch (i) { - case 0: // Radioid (destination) - destination = atoi(str); - break; - case 1: // Childid - sensor = atoi(str); - break; - case 2: // Message type - command = atoi(str); - break; - case 3: // Should we request ack from destination? - ack = atoi(str); - break; - case 4: // Data type - type = atoi(str); - break; - case 5: // Variable value - if (command == C_STREAM) { - blen = 0; - uint8_t val; - while (*str) { - val = h2i(*str++) << 4; - val += h2i(*str++); - bvalue[blen] = val; - blen++; - } - } else { - value = str; - // Remove ending carriage return character (if it exists) - uint8_t lastCharacter = strlen(value)-1; - if (value[lastCharacter] == '\r') - value[lastCharacter] = 0; - } - break; - } - i++; - } + if (parser.parse(msg, commandBuffer)) { + uint8_t command = mGetCommand(msg); - if (destination==GATEWAY_ADDRESS && command==C_INTERNAL) { - // Handle messages directed to gateway - if (type == I_VERSION) { - // Request for version - serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); - } else if (type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(value) == 1); - } - } else { - txBlink(1); - msg.sender = GATEWAY_ADDRESS; - msg.destination = destination; - msg.sensor = sensor; - msg.type = type; - mSetCommand(msg,command); - mSetRequestAck(msg,ack?1:0); - mSetAck(msg,false); - if (command == C_STREAM) - msg.set(bvalue, blen); - else - msg.set(value); - ok = gw.sendRoute(msg); - if (!ok) { - errBlink(1); + if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { + // Handle messages directed to gateway + if (msg.type == I_VERSION) { + // Request for version + serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); + } else if (msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + setInclusionMode(atoi(msg.data) == 1); + } + } else { + txBlink(1); + ok = gw.sendRoute(msg); + if (!ok) { + errBlink(1); + } } } } - void setInclusionMode(boolean newMode) { if (newMode != inclusionMode) inclusionMode = newMode; diff --git a/libraries/MySensors/examples/SerialGateway/GatewayUtil.h b/libraries/MySensors/examples/SerialGateway/GatewayUtil.h index b5ac2ba..109f330 100644 --- a/libraries/MySensors/examples/SerialGateway/GatewayUtil.h +++ b/libraries/MySensors/examples/SerialGateway/GatewayUtil.h @@ -23,7 +23,7 @@ volatile uint8_t countErr; boolean inclusionMode; // Keeps track on inclusion mode void (*serial)(const char *fmt, ... ); -MyMessage msg; +MyParserClass parser; void setInclusionMode(boolean newMode); void txBlink(uint8_t cnt); @@ -104,102 +104,32 @@ void checkInclusionFinished() { } } -uint8_t h2i(char c) { - uint8_t i = 0; - if (c <= '9') - i += c - '0'; - else if (c >= 'a') - i += c - 'a' + 10; - else - i += c - 'A' + 10; - return i; -} - void parseAndSend(MySensor gw, char *commandBuffer) { - boolean ok = false; - char *str, *p, *value=NULL; - uint8_t bvalue[MAX_PAYLOAD]; - uint8_t blen = 0; - int i = 0; - uint16_t destination = 0; - uint8_t sensor = 0; - uint8_t command = 0; - uint8_t type = 0; - uint8_t ack = 0; + boolean ok; + MyMessage &msg = gw.getLastMessage(); - // Extract command data coming on serial line - for (str = strtok_r(commandBuffer, ";", &p); // split using semicolon - str && i < 6; // loop while str is not null an max 5 times - str = strtok_r(NULL, ";", &p) // get subsequent tokens - ) { - switch (i) { - case 0: // Radioid (destination) - destination = atoi(str); - break; - case 1: // Childid - sensor = atoi(str); - break; - case 2: // Message type - command = atoi(str); - break; - case 3: // Should we request ack from destination? - ack = atoi(str); - break; - case 4: // Data type - type = atoi(str); - break; - case 5: // Variable value - if (command == C_STREAM) { - blen = 0; - uint8_t val; - while (*str) { - val = h2i(*str++) << 4; - val += h2i(*str++); - bvalue[blen] = val; - blen++; - } - } else { - value = str; - // Remove ending carriage return character (if it exists) - uint8_t lastCharacter = strlen(value)-1; - if (value[lastCharacter] == '\r') - value[lastCharacter] = 0; - } - break; - } - i++; - } + if (parser.parse(msg, commandBuffer)) { + uint8_t command = mGetCommand(msg); - if (destination==GATEWAY_ADDRESS && command==C_INTERNAL) { - // Handle messages directed to gateway - if (type == I_VERSION) { - // Request for version - serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); - } else if (type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(value) == 1); - } - } else { - txBlink(1); - msg.sender = GATEWAY_ADDRESS; - msg.destination = destination; - msg.sensor = sensor; - msg.type = type; - mSetCommand(msg,command); - mSetRequestAck(msg,ack?1:0); - mSetAck(msg,false); - if (command == C_STREAM) - msg.set(bvalue, blen); - else - msg.set(value); - ok = gw.sendRoute(msg); - if (!ok) { - errBlink(1); + if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { + // Handle messages directed to gateway + if (msg.type == I_VERSION) { + // Request for version + serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); + } else if (msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + setInclusionMode(atoi(msg.data) == 1); + } + } else { + txBlink(1); + ok = gw.sendRoute(msg); + if (!ok) { + errBlink(1); + } } } } - void setInclusionMode(boolean newMode) { if (newMode != inclusionMode) inclusionMode = newMode;