xpl lib
Dependents: XPL-App4_cleanup XPL-App5
Diff: xPL_Message.cpp
- Revision:
- 0:23c0d0e1c31d
--- /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; +}