Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: XPL-App4_cleanup XPL-App5
Revision 0:23c0d0e1c31d, committed 2018-10-09
- Comitter:
- richnash
- Date:
- Tue Oct 09 17:37:05 2018 +0000
- Commit message:
- ready to move to cli to explore D11 pin fix
Changed in this revision
diff -r 000000000000 -r 23c0d0e1c31d xPL.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xPL.cpp Tue Oct 09 17:37:05 2018 +0000
@@ -0,0 +1,402 @@
+/*
+ * xPL.Arduino v0.1, xPL Implementation for Arduino
+ *
+ * This code is parsing a xPL message stored in 'received' buffer
+ * - isolate and store in 'line' buffer each part of the message -> detection of EOL character (DEC 10)
+ * - analyse 'line', function of its number and store information in xpl_header memory
+ * - check for each step if the message respect xPL protocol
+ * - parse each command line
+ *
+ * Copyright (C) 2012 johan@pirlouit.ch, olivier.lebrun@gmail.com
+ * Original version by Gromain59@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "xPL.h"
+
+#define XPL_LINE_MESSAGE_BUFFER_MAX 128 // max length of a line // maximum command in a xpl message
+#define XPL_END_OF_LINE 10
+
+// define the line number identifier
+#define XPL_MESSAGE_TYPE_IDENTIFIER 1
+#define XPL_OPEN_HEADER 2
+#define XPL_HOP_COUNT 3
+#define XPL_SOURCE 4
+#define XPL_TARGET 5
+#define XPL_CLOSE_HEADER 6
+#define XPL_SCHEMA_IDENTIFIER 7
+#define XPL_OPEN_SCHEMA 8
+
+// Heartbeat request class definition
+//prog_char XPL_HBEAT_REQUEST_CLASS_ID[] PROGMEM = "hbeat";
+//prog_char XPL_HBEAT_REQUEST_TYPE_ID[] PROGMEM = "request";
+//prog_char XPL_HBEAT_ANSWER_CLASS_ID[] PROGMEM = "hbeat";
+//prog_char XPL_HBEAT_ANSWER_TYPE_ID[] PROGMEM = "basic"; //app, basic
+#define XPL_HBEAT_REQUEST_CLASS_ID "hbeat"
+#define XPL_HBEAT_REQUEST_TYPE_ID "request"
+#define XPL_HBEAT_ANSWER_CLASS_ID "hbeat"
+#define XPL_HBEAT_ANSWER_TYPE_ID "app"
+
+/* xPL Class */
+xPL::xPL()
+{
+ udp_port = XPL_UDP_PORT;
+
+ SendExternal = NULL;
+
+#ifdef ENABLE_PARSING
+ AfterParseAction = NULL;
+
+ last_heartbeat = 0;
+ hbeat_interval = XPL_DEFAULT_HEARTBEAT_INTERVAL;
+ xpl_accepted = XPL_ACCEPT_ALL;
+#endif
+}
+
+xPL::~xPL()
+{
+}
+
+/// Set the source of outgoing xPL messages
+void xPL::SetSource(const char * _vendorId, const char * _deviceId, const char * _instanceId)
+{
+ memcpy(source.vendor_id, _vendorId, XPL_VENDOR_ID_MAX);
+ memcpy(source.device_id, _deviceId, XPL_DEVICE_ID_MAX);
+ memcpy(source.instance_id, _instanceId, XPL_INSTANCE_ID_MAX);
+}
+
+/**
+ * \brief Send an xPL message
+ * \details There is no validation of the message, it is sent as is.
+ * \param buffer buffer containing the xPL message.
+ */
+void xPL::SendMessage(char *_buffer)
+{
+ (*SendExternal)(_buffer);
+}
+
+/**
+ * \brief Send an xPL message
+ * \details There is no validation of the message, it is sent as is.
+ * \param message An xPL message.
+ * \param _useDefaultSource if true, insert the default source (defined in SetSource) on the message.
+ */
+void xPL::SendMessage(xPL_Message *_message, bool _useDefaultSource)
+{
+ if(_useDefaultSource)
+ {
+ _message->SetSource(source.vendor_id, source.device_id, source.instance_id);
+ }
+
+ SendMessage(_message->toString());
+}
+
+#ifdef ENABLE_PARSING
+
+/**
+ * \brief xPL Stuff
+ * \details Send heartbeat messages at "hbeat_interval" interval
+ */
+void xPL::Process()
+{
+ static bool bFirstRun = true;
+
+ // Check heartbeat + send
+ //if ((millis()-last_heartbeat >= (unsigned long)hbeat_interval * 1000)
+ // || (bFirstRun && millis() > 3000))
+ if ((clock()-last_heartbeat >= (unsigned long)hbeat_interval * 1000)
+ || (bFirstRun && clock() > 3000))
+ {
+ SendHBeat();
+ bFirstRun = false;
+ }
+}
+
+/**
+ * \brief Parse an ingoing xPL message
+ * \details Parse a message, check for hearbeat request and call user defined callback for post processing.
+ * \param buffer buffer of the ingoing UDP Packet
+ */
+void xPL::ParseInputMessage(char* _buffer)
+{
+ xPL_Message* xPLMessage = new xPL_Message();
+ Parse(xPLMessage, _buffer);
+
+ // check if the message is an hbeat.request to send a heartbeat
+ if (CheckHBeatRequest(xPLMessage))
+ {
+ SendHBeat();
+ }
+
+ // call the user defined callback to execute an action
+ if(AfterParseAction != NULL)
+ {
+ (*AfterParseAction)(xPLMessage);
+ }
+
+ delete xPLMessage;
+}
+
+/**
+ * \brief Check the xPL message target
+ * \details Check if the xPL message is for us
+ * \param _message an xPL message
+ */
+bool xPL::TargetIsMe(xPL_Message * _message)
+{
+ if (memcmp(_message->target.vendor_id, source.vendor_id, strlen(source.vendor_id)) != 0)
+ return false;
+
+ if (memcmp(_message->target.device_id, source.device_id, strlen(source.device_id)) != 0)
+ return false;
+
+ if (memcmp(_message->target.instance_id, source.instance_id, strlen(source.instance_id)) != 0)
+ return false;
+
+ return true;
+}
+
+/**
+ * \brief Send a heartbeat message
+ */
+void xPL::SendHBeat()
+{
+ last_heartbeat = clock(); //millis();
+ char buffer[XPL_MESSAGE_BUFFER_MAX];
+
+// sprintf_P(buffer, PSTR("xpl-stat\n{\nhop=1\nsource=%s-%s.%s\ntarget=*\n}\n%s.%s\n{\ninterval=%d\n}\n"), source.vendor_id, source.device_id, source.instance_id, XPL_HBEAT_ANSWER_CLASS_ID, XPL_HBEAT_ANSWER_TYPE_ID, hbeat_interval);
+ //sprintf(buffer, "xpl-stat\r\n{\r\nhop=1\r\nsource=%s-%s.%s\r\ntarget=*\r\n}\r\n%s.%s\r\n{\r\ninterval=%d\r\nport=3865\r\nremote-ip=8.8.8.8\r\nversion=1.0\r\n}\r\n", source.vendor_id, source.device_id, source.instance_id, XPL_HBEAT_ANSWER_CLASS_ID, XPL_HBEAT_ANSWER_TYPE_ID, hbeat_interval);
+ sprintf(buffer, "xpl-stat\n{\nhop=1\nsource=%s-%s.%s\ntarget=*\n}\n%s.%s\n{\ninterval=%d\nport=3865\nremote-ip=8.8.8.8\nversion=1.0\n}\n", source.vendor_id, source.device_id, source.instance_id, XPL_HBEAT_ANSWER_CLASS_ID, XPL_HBEAT_ANSWER_TYPE_ID, hbeat_interval);
+
+ //(*SendExternal)(buffer);
+ SendMessage(buffer);
+
+ printf("XPL: HB Sent\r\n");
+}
+
+/**
+ * \brief Check if the message is a heartbeat request
+ * \param _message an xPL message
+ */
+inline bool xPL::CheckHBeatRequest(xPL_Message* _message)
+{
+ if (!TargetIsMe(_message))
+ return false;
+
+ return _message->IsSchema(XPL_HBEAT_REQUEST_CLASS_ID, XPL_HBEAT_REQUEST_TYPE_ID);
+}
+
+/**
+ * \brief Parse a buffer and generate a xPL_Message
+ * \details Line based xPL parser
+ * \param _xPLMessage the result xPL message
+ * \param _message the buffer
+ */
+void xPL::Parse(xPL_Message* _xPLMessage, char* _buffer)
+{
+ int len = strlen(_buffer);
+
+ short j=0;
+ short line=0;
+ int result=0;
+ char lineBuffer[XPL_LINE_MESSAGE_BUFFER_MAX+1];
+
+ // read each character of the message
+ for(short i = 0; i < len; i++)
+ {
+ // load byte by byte in 'line' buffer, until '\n' is detected
+ if(_buffer[i] == XPL_END_OF_LINE) // is it a linefeed (ASCII: 10 decimal)
+ {
+ ++line;
+ lineBuffer[j]='\0'; // add the end of string id
+
+ if(line <= XPL_OPEN_SCHEMA)
+ {
+ // first part: header and schema determination
+ // we analyse the line, function of the line number in the xpl message
+ result = AnalyseHeaderLine(_xPLMessage, lineBuffer ,line);
+ }
+
+ if(line > XPL_OPEN_SCHEMA)
+ {
+ // second part: command line
+ // we analyse the specific command line, function of the line number in the xpl message
+ result = AnalyseCommandLine(_xPLMessage, lineBuffer, line-9, j);
+
+ if(result == _xPLMessage->command_count+1)
+ break;
+ }
+
+ if (result < 0) break;
+
+ j = 0; // reset the buffer pointer
+ clearStr(lineBuffer); // clear the buffer
+ }
+ else
+ {
+ // next character
+ lineBuffer[j++] = _buffer[i];
+ }
+ }
+}
+
+/**
+ * \brief Parse the header part of the xPL message line by line
+ * \param _xPLMessage the result xPL message
+ * \param _buffer the line to parse
+ * \param _line the line number
+ */
+short xPL::AnalyseHeaderLine(xPL_Message* _xPLMessage, char* _buffer, short _line)
+{
+ switch (_line)
+ {
+ case XPL_MESSAGE_TYPE_IDENTIFIER: //message type identifier
+
+ if (memcmp(_buffer,"xpl-",4)==0) //xpl
+ {
+ if (memcmp(_buffer+4,"cmnd",4)==0) //command type
+ {
+ _xPLMessage->type=XPL_CMND; //xpl-cmnd
+ }
+ else if (memcmp(_buffer+4,"stat",4)==0) //statut type
+ {
+ _xPLMessage->type=XPL_STAT; //xpl-stat
+ }
+ else if (memcmp(_buffer+4,"trig",4)==0) // trigger type
+ {
+ _xPLMessage->type=XPL_TRIG; //xpl-trig
+ }
+ }
+ else
+ {
+ return 0; //unknown message
+ }
+
+ return 1;
+
+ //break;
+
+ case XPL_OPEN_HEADER: //header begin
+
+ if (memcmp(_buffer,"{",1)==0)
+ {
+ return 2;
+ }
+ //else
+ //{
+ return -2;
+ //}
+
+ //break;
+
+ case XPL_HOP_COUNT: //hop
+ if (sscanf(_buffer, XPL_HOP_COUNT_PARSER, &_xPLMessage->hop))
+ {
+ return 3;
+ }
+ //else
+ //{
+ return -3;
+ //}
+
+ //break;
+
+ case XPL_SOURCE: //source
+ if (sscanf(_buffer, XPL_SOURCE_PARSER, &_xPLMessage->source.vendor_id, &_xPLMessage->source.device_id, &_xPLMessage->source.instance_id) == 3)
+ {
+ return 4;
+ }
+ //else
+ //{
+ return -4;
+ //}
+
+ //break;
+
+ case XPL_TARGET: //target
+
+ if (sscanf(_buffer, XPL_TARGET_PARSER, &_xPLMessage->target.vendor_id, &_xPLMessage->target.device_id, &_xPLMessage->target.instance_id) == 3)
+ {
+ return 5;
+ }
+ //else
+ //{
+ if(memcmp(_xPLMessage->target.vendor_id,"*", 1) == 0) // check if broadcast message
+ {
+ return 5;
+ }
+ //else
+ //{
+ return -5;
+ //}
+ //}
+ //break;
+
+ case XPL_CLOSE_HEADER: //header end
+ if (memcmp(_buffer,"}",1)==0)
+ {
+ return 6;
+ }
+ //else
+ //{
+ return -6;
+ //}
+
+ //break;
+
+ case XPL_SCHEMA_IDENTIFIER: //schema
+ sscanf(_buffer, XPL_SCHEMA_PARSER, &_xPLMessage->schema.class_id, &_xPLMessage->schema.type_id);
+ return 7;
+
+ case XPL_OPEN_SCHEMA: //header begin
+ if (memcmp(_buffer,"{",1)==0)
+ {
+ return 8;
+ }
+ //else
+ //{
+ return -8;
+ //}
+ //break;
+ }
+
+ return -100;
+}
+
+/**
+ * \brief Parse the body part of the xPL message line by line
+ * \param _xPLMessage the result xPL message
+ * \param _buffer the line to parse
+ * \param _command_line the line number
+ */
+short xPL::AnalyseCommandLine(xPL_Message * _xPLMessage, char *_buffer, short _command_line, short line_length)
+{
+ if (memcmp(_buffer,"}",1) == 0) // End of schema
+ {
+ return _xPLMessage->command_count+1;
+ }
+ else // parse the next command
+ {
+ struct_command newcmd;
+
+ sscanf(_buffer, XPL_COMMAND_PARSER, &newcmd.name, &newcmd.value);
+
+ _xPLMessage->AddCommand(newcmd.name, newcmd.value);
+
+ return _command_line;
+ }
+}
+#endif
diff -r 000000000000 -r 23c0d0e1c31d xPL.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xPL.h Tue Oct 09 17:37:05 2018 +0000
@@ -0,0 +1,104 @@
+/*
+ * xPL.Arduino v0.1, xPL Implementation for Arduino
+ *
+ * This code is parsing a xPL message stored in 'received' buffer
+ * - isolate and store in 'line' buffer each part of the message -> detection of EOL character (DEC 10)
+ * - analyse 'line', function of its number and store information in xpl_header memory
+ * - check for each step if the message respect xPL protocol
+ * - parse each command line
+ *
+ * Copyright (C) 2012 johan@pirlouit.ch, olivier.lebrun@gmail.com
+ * Original version by Gromain59@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef xPL_h
+#define xPL_h
+
+#define ENABLE_PARSING 1
+
+//#include "Arduino.h"
+#include "mbed.h"
+
+#include "xPL_utils.h"
+#include "xPL_Message.h"
+
+#define XPL_CMND 1
+#define XPL_STAT 2
+#define XPL_TRIG 3
+
+#define XPL_DEFAULT_HEARTBEAT_INTERVAL 300
+
+#define XPL_UDP_PORT 3865
+
+#define XPL_PORT_L 0x19
+#define XPL_PORT_H 0xF
+
+typedef enum {XPL_ACCEPT_ALL, XPL_ACCEPT_SELF, XPL_ACCEPT_SELF_ANY} xpl_accepted_type;
+// XPL_ACCEPT_ALL = all xpl messages
+// XPL_ACCEPT_SELF = only for me
+// XPL_ACCEPT_SELF_ANY = only for me and any (*)
+
+typedef void (*xPLSendExternal)(char*);
+typedef void (*xPLAfterParseAction)(xPL_Message * message);
+
+class xPL
+{
+ public:
+ xPL();
+ ~xPL();
+
+ struct_id source; // my source
+ unsigned short udp_port; // default 3865
+
+ xPLSendExternal SendExternal;
+
+ void SendMessage(char *);
+ void SendMessage(xPL_Message *, bool = true);
+
+ void SetSource(const char *,const char *,const char *); // define my source
+
+#ifdef ENABLE_PARSING
+ xPLAfterParseAction AfterParseAction;
+
+
+ //byte hbeat_interval; // default 5
+ short hbeat_interval; // default 5
+ xpl_accepted_type xpl_accepted;
+
+
+ void Process();
+ void ParseInputMessage(char *buffer);
+
+ bool TargetIsMe(xPL_Message * message);
+
+ void SendHBeat();
+
+ private:
+ //void ClearData();
+ unsigned long last_heartbeat;
+// void SendHBeat();
+ bool CheckHBeatRequest(xPL_Message * message);
+
+ void Parse(xPL_Message *, char *);
+ //byte AnalyseHeaderLine(xPL_Message *, char *, byte );
+ //byte AnalyseCommandLine(xPL_Message *, char *, byte, byte );
+ short AnalyseHeaderLine(xPL_Message *, char *, short );
+ short AnalyseCommandLine(xPL_Message *, char *, short, short );
+#endif
+};
+
+#endif
diff -r 000000000000 -r 23c0d0e1c31d xPL_Message.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xPL_Message.cpp Tue Oct 09 17:37:05 2018 +0000
@@ -0,0 +1,215 @@
+/*
+ * xPL.Arduino v0.1, xPL Implementation for Arduino
+ *
+ * This code is parsing a xPL message stored in 'received' buffer
+ * - isolate and store in 'line' buffer each part of the message -> detection of EOL character (DEC 10)
+ * - analyse 'line', function of its number and store information in xpl_header memory
+ * - check for each step if the message respect xPL protocol
+ * - parse each command line
+ *
+ * Copyright (C) 2012 johan@pirlouit.ch, olivier.lebrun@gmail.com
+ * Original version by Gromain59@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "xPL_Message.h"
+
+xPL_Message::xPL_Message()
+{
+ command = NULL;
+ command_count = 0;
+}
+
+xPL_Message::~xPL_Message()
+{
+ if(command != NULL)
+ {
+ free(command);
+ }
+}
+
+/**
+ * \brief Set source of the message (optional)
+ * \param _vendorId vendor id.
+ * \param _deviceId device id.
+ * \param _instanceId instance id.
+ */
+void xPL_Message::SetSource(char * _vendorId, char * _deviceId, char * _instanceId)
+{
+ memcpy(source.vendor_id, _vendorId, XPL_VENDOR_ID_MAX + 1);
+ memcpy(source.device_id, _deviceId, XPL_DEVICE_ID_MAX + 1);
+ memcpy(source.instance_id, _instanceId, XPL_INSTANCE_ID_MAX + 1);
+}
+
+/**
+ * \brief Set Target of the message
+ * \details insert "*" into _vendorId to broadcast the message
+ * \param _vendorId vendor id.
+ * \param _deviceId device id. (optional)
+ * \param _instanceId instance id. (optional)
+ */
+void xPL_Message::SetTarget(const char * _vendorId, const char * _deviceId, const char * _instanceId)
+{
+ memcpy(target.vendor_id, _vendorId, XPL_VENDOR_ID_MAX + 1);
+ if(_deviceId != NULL) memcpy(target.device_id, _deviceId, XPL_DEVICE_ID_MAX + 1);
+ if(_instanceId != NULL) memcpy(target.instance_id, _instanceId, XPL_INSTANCE_ID_MAX + 1);
+}
+
+/**
+ * \brief Set Schema of the message
+ * \param _classId Class
+ * \param _typeId Type
+ */
+void xPL_Message::SetSchema(const char * _classId, const char * _typeId)
+{
+ memcpy(schema.class_id, _classId, XPL_CLASS_ID_MAX + 1);
+ memcpy(schema.type_id, _typeId, XPL_TYPE_ID_MAX + 1);
+}
+
+/**
+ * \brief Create a new command/value pair
+ * \details Check if maximun command is reach and add memory to command array
+ */
+bool xPL_Message::CreateCommand()
+{
+ struct_command *ncommand;
+
+ // Maximun command reach
+ // To avoid oom, we arbitrary accept only XPL_MESSAGE_COMMAND_MAX command
+ if(command_count > XPL_MESSAGE_COMMAND_MAX)
+ return false;
+
+ ncommand = (struct_command*)realloc ( command, (command_count + 1) * sizeof(struct_command) );
+
+ if (ncommand != NULL) {
+ command = ncommand;
+ command_count++;
+ return true;
+ }
+ else
+ return false;
+}
+
+/**
+ * \brief Add a command to the message's body
+ * \details PROGMEM Version
+ * \param _name name of the command
+ * \param _value value of the command
+ */
+bool xPL_Message::AddCommand(const char* _name, const char* _value)
+{
+ if(!CreateCommand()) return false;
+
+ struct_command newcmd;
+ memcpy(newcmd.name, _name, XPL_NAME_LENGTH_MAX + 1);
+ memcpy(newcmd.value, _value, XPL_VALUE_LENGTH_MAX + 1);
+ command[command_count-1] = newcmd;
+ return true;
+}
+
+/**
+ * \brief Add a command to the message's body
+ * \details char* Version
+ * \param _name name of the command
+ * \param _value value of the command
+ */
+bool xPL_Message::AddCommand(char* _name, char* _value)
+{
+ if(!CreateCommand()) return false;
+
+ struct_command newcmd;
+ memcpy(newcmd.name, _name, XPL_NAME_LENGTH_MAX + 1);
+ memcpy(newcmd.value, _value, XPL_VALUE_LENGTH_MAX + 1);
+ command[command_count-1] = newcmd;
+ return true;
+}
+
+/**
+ * \brief Convert xPL_Message to char* buffer
+ */
+char message_buffer[XPL_MESSAGE_BUFFER_MAX];
+char* xPL_Message::toString()
+{
+ int pos;
+
+ clearStr(message_buffer);
+
+ switch(type)
+ {
+ case (XPL_CMND):
+ pos = sprintf(message_buffer, "xpl-cmnd");
+ break;
+ case (XPL_STAT):
+ pos = sprintf(message_buffer, "xpl-stat");
+ break;
+ case (XPL_TRIG):
+ pos = sprintf(message_buffer, "xpl-trig");
+ break;
+ }
+
+ pos += sprintf(message_buffer + pos, "\n{\nhop=1\nsource=%s-%s.%s\ntarget=", source.vendor_id, source.device_id, source.instance_id);
+
+ if(memcmp(target.vendor_id,"*", 1) == 0) // check if broadcast message
+ {
+ pos += sprintf(message_buffer + pos, "*\n}\n");
+ }
+ else
+ {
+ pos += sprintf(message_buffer + pos, "%s-%s.%s\n}\n",target.vendor_id, target.device_id, target.instance_id);
+ }
+
+ pos += sprintf(message_buffer + pos, "%s.%s\n{\n",schema.class_id, schema.type_id);
+
+ for (short i=0; i<command_count; i++)
+ {
+ pos += sprintf(message_buffer + pos, "%s=%s\n", command[i].name, command[i].value);
+ }
+
+ sprintf(message_buffer + pos, "}\n");
+
+ return message_buffer;
+}
+
+bool xPL_Message::IsSchema(char* _classId, char* _typeId)
+{
+ if (strcmp(schema.class_id, _classId) == 0)
+ {
+ if (strcmp(schema.type_id, _typeId) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * \brief Check the message's schema
+ * \param _classId class
+ * \param _typeId type
+ */
+bool xPL_Message::IsSchema(const char* _classId, const char* _typeId)
+{
+ if (strncmp(schema.class_id, _classId, XPL_CLASS_ID_MAX) == 0)
+ {
+ if (strncmp(schema.type_id, _typeId, XPL_TYPE_ID_MAX) == 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
diff -r 000000000000 -r 23c0d0e1c31d xPL_Message.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xPL_Message.h Tue Oct 09 17:37:05 2018 +0000
@@ -0,0 +1,76 @@
+/*
+ * xPL.Arduino v0.1, xPL Implementation for Arduino
+ *
+ * This code is parsing a xPL message stored in 'received' buffer
+ * - isolate and store in 'line' buffer each part of the message -> detection of EOL character (DEC 10)
+ * - analyse 'line', function of its number and store information in xpl_header memory
+ * - check for each step if the message respect xPL protocol
+ * - parse each command line
+ *
+ * Copyright (C) 2012 johan@pirlouit.ch, olivier.lebrun@gmail.com
+ * Original version by Gromain59@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef xPLMessage_h
+#define xPLMessage_h
+
+//#include "Arduino.h"
+#include "mbed.h"
+#include "xPL_utils.h"
+
+#define XPL_CMND 1
+#define XPL_STAT 2
+#define XPL_TRIG 3
+
+#define XPL_MESSAGE_BUFFER_MAX 256 // going over 256 would mean changing index from byte to int
+#define XPL_MESSAGE_COMMAND_MAX 10
+
+class xPL_Message
+{
+ public:
+ short type; // 1=cmnd, 2=stat, 3=trig
+ short hop; // Hop count
+
+ struct_id source; // source identification
+ struct_id target; // target identification
+
+ struct_xpl_schema schema;
+ struct_command *command;
+ //byte command_count;
+ short command_count;
+
+ bool AddCommand(const char *,const char *);
+ bool AddCommand(char*, char*);
+
+ xPL_Message();
+ ~xPL_Message();
+
+ char *toString();
+
+ bool IsSchema(char*, char*);
+ bool IsSchema(const char*, const char*);
+
+ void SetSource(char *, char *, char *); // define my source
+ void SetTarget(const char *, const char * = NULL, const char * = NULL);
+ void SetSchema(const char *, const char *);
+
+
+ private:
+ bool CreateCommand();
+};
+
+#endif
diff -r 000000000000 -r 23c0d0e1c31d xPL_utils.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xPL_utils.cpp Tue Oct 09 17:37:05 2018 +0000
@@ -0,0 +1,38 @@
+/*
+ * xPL.Arduino v0.1, xPL Implementation for Arduino
+ *
+ * This code is parsing a xPL message stored in 'received' buffer
+ * - isolate and store in 'line' buffer each part of the message -> detection of EOL character (DEC 10)
+ * - analyse 'line', function of its number and store information in xpl_header memory
+ * - check for each step if the message respect xPL protocol
+ * - parse each command line
+ *
+ * Copyright (C) 2012 johan@pirlouit.ch, olivier.lebrun@gmail.com
+ * Original version by Gromain59@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "xPL_utils.h"
+
+// Function to clear a string
+void clearStr (char* str)
+{
+ int len = strlen(str);
+ for (short c = 0; c < len; c++)
+ {
+ str[c] = 0;
+ }
+}
diff -r 000000000000 -r 23c0d0e1c31d xPL_utils.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xPL_utils.h Tue Oct 09 17:37:05 2018 +0000
@@ -0,0 +1,74 @@
+/*
+ * xPL.Arduino v0.1, xPL Implementation for Arduino
+ *
+ * This code is parsing a xPL message stored in 'received' buffer
+ * - isolate and store in 'line' buffer each part of the message -> detection of EOL character (DEC 10)
+ * - analyse 'line', function of its number and store information in xpl_header memory
+ * - check for each step if the message respect xPL protocol
+ * - parse each command line
+ *
+ * Copyright (C) 2012 johan@pirlouit.ch, olivier.lebrun@gmail.com
+ * Original version by Gromain59@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef xPLutil_h
+#define xPLutil_h
+
+//#include "Arduino.h"
+#include "mbed.h"
+#include <string.h>
+
+#define XPL_VENDOR_ID_MAX 8
+#define XPL_DEVICE_ID_MAX 20
+#define XPL_INSTANCE_ID_MAX 16
+#define XPL_CLASS_ID_MAX 8
+#define XPL_TYPE_ID_MAX 8
+#define XPL_NAME_LENGTH_MAX 20
+#define XPL_VALUE_LENGTH_MAX 128 // should be 128 but need to spare RAM
+
+#define XPL_HOP_COUNT_PARSER "hop=%d"
+#define XPL_SOURCE_PARSER "source=%20[^-]-%20[^'.'].%16s"
+#define XPL_TARGET_PARSER "target=%20[^-]-%20[^'.'].%16s"
+#define XPL_SCHEMA_PARSER "%8[^'.'].%8s"
+// 32 shall match XPL_VALUE_LENGTH_MAX
+#define XPL_COMMAND_PARSER "%20[^'=']=%32s"
+
+typedef struct struct_id struct_id;
+struct struct_id // source or target
+{
+ char vendor_id[XPL_VENDOR_ID_MAX+1]; // vendor id
+ char device_id[XPL_DEVICE_ID_MAX+1]; // device id
+ char instance_id[XPL_INSTANCE_ID_MAX+1]; // instance id
+};
+
+typedef struct struct_xpl_schema struct_xpl_schema;
+struct struct_xpl_schema
+{
+ char class_id[XPL_CLASS_ID_MAX+1]; // class of schema (x10, alarm...)
+ char type_id[XPL_TYPE_ID_MAX+1]; // type of schema (basic...)
+};
+
+typedef struct struct_command struct_command;
+struct struct_command // source or target
+{
+ char name[XPL_NAME_LENGTH_MAX+1]; // vendor id
+ char value[XPL_VALUE_LENGTH_MAX+1]; // device id
+};
+
+void clearStr (char* str);
+
+#endif