/* * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad * Copyright (C) 2013-2018 Sensnology AB * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ #include "MyMessage.h" #include #include #include MyMessage::MyMessage(void) { clear(); } MyMessage::MyMessage(const uint8_t _sensor, const uint8_t _type) { clear(); sensor = _sensor; type = _type; } void MyMessage::clear(void) { last = 0u; sender = 0u; destination = 0u; // Gateway is default destination version_length = 0u; command_ack_payload = 0u; type = 0u; sensor = 0u; (void)memset(data, 0u, sizeof(data)); // set message protocol version miSetVersion(PROTOCOL_VERSION); } bool MyMessage::isAck(void) const { return miGetAck(); } uint8_t MyMessage::getCommand(void) const { return miGetCommand(); } /* Getters for payload converted to desired form */ void* MyMessage::getCustom(void) const { return (void *)data; } const char* MyMessage::getString(void) const { uint8_t payloadType = miGetPayloadType(); if (payloadType == P_STRING) { return data; } else { return NULL; } } char MyMessage::i2h(const uint8_t i) const { uint8_t k = i & 0x0F; if (k <= 9) { return '0' + k; } else { return 'A' + k - 10; } } char* MyMessage::getCustomString(char *buffer) const { for (uint8_t i = 0; i < miGetLength(); i++) { buffer[i * 2] = i2h(data[i] >> 4); buffer[(i * 2) + 1] = i2h(data[i]); } buffer[miGetLength() * 2] = '\0'; return buffer; } char* MyMessage::getStream(char *buffer) const { uint8_t cmd = miGetCommand(); if ((cmd == C_STREAM) && (buffer != NULL)) { return getCustomString(buffer); } else { return NULL; } } char* MyMessage::getString(char *buffer) const { uint8_t payloadType = miGetPayloadType(); if (buffer != NULL) { if (payloadType == P_STRING) { (void)strncpy(buffer, data, miGetLength()); buffer[miGetLength()] = 0; } else if (payloadType == P_BYTE) { (void)itoa(bValue, buffer, 10); } else if (payloadType == P_INT16) { (void)itoa(iValue, buffer, 10); } else if (payloadType == P_UINT16) { (void)utoa(uiValue, buffer, 10); } else if (payloadType == P_LONG32) { (void)ltoa(lValue, buffer, 10); } else if (payloadType == P_ULONG32) { (void)ultoa(ulValue, buffer, 10); } else if (payloadType == P_FLOAT32) { (void)dtostrf(fValue, 2, min(fPrecision, (uint8_t)8), buffer); } else if (payloadType == P_CUSTOM) { return getCustomString(buffer); } return buffer; } else { return NULL; } } bool MyMessage::getBool(void) const { return getByte(); } uint8_t MyMessage::getByte(void) const { if (miGetPayloadType() == P_BYTE) { return data[0]; } else if (miGetPayloadType() == P_STRING) { return atoi(data); } else { return 0; } } float MyMessage::getFloat(void) const { if (miGetPayloadType() == P_FLOAT32) { return fValue; } else if (miGetPayloadType() == P_STRING) { return atof(data); } else { return 0; } } int32_t MyMessage::getLong(void) const { if (miGetPayloadType() == P_LONG32) { return lValue; } else if (miGetPayloadType() == P_STRING) { return atol(data); } else { return 0; } } uint32_t MyMessage::getULong(void) const { if (miGetPayloadType() == P_ULONG32) { return ulValue; } else if (miGetPayloadType() == P_STRING) { return atol(data); } else { return 0; } } int16_t MyMessage::getInt(void) const { if (miGetPayloadType() == P_INT16) { return iValue; } else if (miGetPayloadType() == P_STRING) { return atoi(data); } else { return 0; } } uint16_t MyMessage::getUInt(void) const { if (miGetPayloadType() == P_UINT16) { return uiValue; } else if (miGetPayloadType() == P_STRING) { return atoi(data); } else { return 0; } } MyMessage& MyMessage::setType(const uint8_t _type) { type = _type; return *this; } MyMessage& MyMessage::setSensor(const uint8_t _sensor) { sensor = _sensor; return *this; } MyMessage& MyMessage::setDestination(const uint8_t _destination) { destination = _destination; return *this; } // Set payload MyMessage& MyMessage::set(const void* value, const uint8_t length) { uint8_t payloadLength = value == NULL ? 0 : min(length, (uint8_t)MAX_PAYLOAD); miSetLength(payloadLength); miSetPayloadType(P_CUSTOM); memcpy(data, value, payloadLength); return *this; } MyMessage& MyMessage::set(const char* value) { uint8_t length = value == NULL ? 0 : min(strlen(value), (size_t)MAX_PAYLOAD); miSetLength(length); miSetPayloadType(P_STRING); if (length) { strncpy(data, value, length); } // null terminate string data[length] = 0; return *this; } #if !defined(__linux__) MyMessage& MyMessage::set(const __FlashStringHelper* value) { uint8_t length = value == NULL ? 0 : min(strlen_P(reinterpret_cast(value)), (size_t)MAX_PAYLOAD); miSetLength(length); miSetPayloadType(P_STRING); if (length) { strncpy_P(data, reinterpret_cast(value), length); } // null terminate string data[length] = 0; return *this; } #endif MyMessage& MyMessage::set(const bool value) { miSetLength(1); miSetPayloadType(P_BYTE); data[0] = value; return *this; } MyMessage& MyMessage::set(const uint8_t value) { miSetLength(1); miSetPayloadType(P_BYTE); data[0] = value; return *this; } MyMessage& MyMessage::set(const float value, const uint8_t decimals) { miSetLength(5); // 32 bit float + persi miSetPayloadType(P_FLOAT32); fValue=value; fPrecision = decimals; return *this; } MyMessage& MyMessage::set(const uint32_t value) { miSetPayloadType(P_ULONG32); miSetLength(4); ulValue = value; return *this; } MyMessage& MyMessage::set(const int32_t value) { miSetPayloadType(P_LONG32); miSetLength(4); lValue = value; return *this; } MyMessage& MyMessage::set(const uint16_t value) { miSetPayloadType(P_UINT16); miSetLength(2); uiValue = value; return *this; } MyMessage& MyMessage::set(const int16_t value) { miSetPayloadType(P_INT16); miSetLength(2); iValue = value; return *this; }