add parser class for serial and ethernet gateways
This commit is contained in:
@@ -35,6 +35,11 @@ typedef class MyRFDriverNRF24 MyRFDriverClass;
|
|||||||
typedef class MyRFDriverRF69 MyRFDriverClass;
|
typedef class MyRFDriverRF69 MyRFDriverClass;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MYSENSORS_SERIAL_GATEWAY) || defined(MYSENSORS_ETHERNET_GATEWAY)
|
||||||
|
#include "MyParserSerial.h"
|
||||||
|
typedef class MyParserSerial MyParserClass;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MYSENSORS_SIGNING_DUMMY
|
#ifdef MYSENSORS_SIGNING_DUMMY
|
||||||
#include "MySigningDriverDummy.h"
|
#include "MySigningDriverDummy.h"
|
||||||
#define SIGNING_IDENTIFIER (0) // Reserved for dummy implementation, will not work with other backends
|
#define SIGNING_IDENTIFIER (0) // Reserved for dummy implementation, will not work with other backends
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#include "MyParser.h"
|
||||||
|
|
||||||
|
MyParser::MyParser() {
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "Version.h" // Auto generated by bot
|
#include "Version.h" // Auto generated by bot
|
||||||
#include "MyRFDriver.h"
|
#include "MyRFDriver.h"
|
||||||
|
#include "MyParser.h"
|
||||||
#include "MySigningDriver.h"
|
#include "MySigningDriver.h"
|
||||||
#include "MyConfig.h"
|
#include "MyConfig.h"
|
||||||
#include "MyMessage.h"
|
#include "MyMessage.h"
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ volatile uint8_t countErr;
|
|||||||
boolean inclusionMode; // Keeps track on inclusion mode
|
boolean inclusionMode; // Keeps track on inclusion mode
|
||||||
void (*serial)(const char *fmt, ... );
|
void (*serial)(const char *fmt, ... );
|
||||||
|
|
||||||
MyMessage msg;
|
MyParserClass parser;
|
||||||
|
|
||||||
void setInclusionMode(boolean newMode);
|
void setInclusionMode(boolean newMode);
|
||||||
void txBlink(uint8_t cnt);
|
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) {
|
void parseAndSend(MySensor gw, char *commandBuffer) {
|
||||||
boolean ok = false;
|
boolean ok;
|
||||||
char *str, *p, *value=NULL;
|
MyMessage &msg = gw.getLastMessage();
|
||||||
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;
|
|
||||||
|
|
||||||
// Extract command data coming on serial line
|
if (parser.parse(msg, commandBuffer)) {
|
||||||
for (str = strtok_r(commandBuffer, ";", &p); // split using semicolon
|
uint8_t command = mGetCommand(msg);
|
||||||
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 (destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
|
if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
|
||||||
// Handle messages directed to gateway
|
// Handle messages directed to gateway
|
||||||
if (type == I_VERSION) {
|
if (msg.type == I_VERSION) {
|
||||||
// Request for version
|
// Request for version
|
||||||
serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION);
|
serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION);
|
||||||
} else if (type == I_INCLUSION_MODE) {
|
} else if (msg.type == I_INCLUSION_MODE) {
|
||||||
// Request to change inclusion mode
|
// Request to change inclusion mode
|
||||||
setInclusionMode(atoi(value) == 1);
|
setInclusionMode(atoi(msg.data) == 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
txBlink(1);
|
txBlink(1);
|
||||||
msg.sender = GATEWAY_ADDRESS;
|
ok = gw.sendRoute(msg);
|
||||||
msg.destination = destination;
|
if (!ok) {
|
||||||
msg.sensor = sensor;
|
errBlink(1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setInclusionMode(boolean newMode) {
|
void setInclusionMode(boolean newMode) {
|
||||||
if (newMode != inclusionMode)
|
if (newMode != inclusionMode)
|
||||||
inclusionMode = newMode;
|
inclusionMode = newMode;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ volatile uint8_t countErr;
|
|||||||
boolean inclusionMode; // Keeps track on inclusion mode
|
boolean inclusionMode; // Keeps track on inclusion mode
|
||||||
void (*serial)(const char *fmt, ... );
|
void (*serial)(const char *fmt, ... );
|
||||||
|
|
||||||
MyMessage msg;
|
MyParserClass parser;
|
||||||
|
|
||||||
void setInclusionMode(boolean newMode);
|
void setInclusionMode(boolean newMode);
|
||||||
void txBlink(uint8_t cnt);
|
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) {
|
void parseAndSend(MySensor gw, char *commandBuffer) {
|
||||||
boolean ok = false;
|
boolean ok;
|
||||||
char *str, *p, *value=NULL;
|
MyMessage &msg = gw.getLastMessage();
|
||||||
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;
|
|
||||||
|
|
||||||
// Extract command data coming on serial line
|
if (parser.parse(msg, commandBuffer)) {
|
||||||
for (str = strtok_r(commandBuffer, ";", &p); // split using semicolon
|
uint8_t command = mGetCommand(msg);
|
||||||
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 (destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
|
if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
|
||||||
// Handle messages directed to gateway
|
// Handle messages directed to gateway
|
||||||
if (type == I_VERSION) {
|
if (msg.type == I_VERSION) {
|
||||||
// Request for version
|
// Request for version
|
||||||
serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION);
|
serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION);
|
||||||
} else if (type == I_INCLUSION_MODE) {
|
} else if (msg.type == I_INCLUSION_MODE) {
|
||||||
// Request to change inclusion mode
|
// Request to change inclusion mode
|
||||||
setInclusionMode(atoi(value) == 1);
|
setInclusionMode(atoi(msg.data) == 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
txBlink(1);
|
txBlink(1);
|
||||||
msg.sender = GATEWAY_ADDRESS;
|
ok = gw.sendRoute(msg);
|
||||||
msg.destination = destination;
|
if (!ok) {
|
||||||
msg.sensor = sensor;
|
errBlink(1);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setInclusionMode(boolean newMode) {
|
void setInclusionMode(boolean newMode) {
|
||||||
if (newMode != inclusionMode)
|
if (newMode != inclusionMode)
|
||||||
inclusionMode = newMode;
|
inclusionMode = newMode;
|
||||||
|
|||||||
Reference in New Issue
Block a user