Skip to content

Add multi-message feature, for handling multiple sensor data in one message #1515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MySensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs

#include "core/MyCapabilities.h"
#include "core/MyMessage.cpp"
#include "core/MyMultiMessage.cpp"
#include "core/MySplashScreen.cpp"
#include "core/MySensorsCore.cpp"

Expand Down
1 change: 1 addition & 0 deletions core/MyMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ typedef enum {
V_VAR = 54, //!< S_POWER, Reactive power: volt-ampere reactive (var)
V_VA = 55, //!< S_POWER, Apparent power: volt-ampere (VA)
V_POWER_FACTOR = 56, //!< S_POWER, Ratio of real power to apparent power: floating point value in the range [-1,..,1]
V_MULTI_MESSAGE = 57, //!< Special type, multiple sensors in one message
} mysensors_data_t;
#endif

Expand Down
225 changes: 225 additions & 0 deletions core/MyMultiMessage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/*
* 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 <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2020 Sensnology AB
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* Multi message feature added by Constantin Petra <constantin.petra@gmail.com>
* Copyright (C) 2022 Constantin Petra
*
* 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 "Version.h"
#include "MyConfig.h"
#include "MyEepromAddresses.h"
#include "MyMessage.h"
#include "MyMultiMessage.h"
#include "stddef.h"

#define SET_PAYLOAD_TYPE(u, type) BF_SET(u, type, V2_MYS_HEADER_CEP_PAYLOADTYPE_POS, \
V2_MYS_HEADER_CEP_PAYLOADTYPE_SIZE)
#define GET_PAYLOAD_TYPE(u) BF_GET(u, V2_MYS_HEADER_CEP_PAYLOADTYPE_POS, \
V2_MYS_HEADER_CEP_PAYLOADTYPE_SIZE)
#define SET_COMMAND(u, command) BF_SET(u, command, V2_MYS_HEADER_CEP_COMMAND_POS, \
V2_MYS_HEADER_CEP_COMMAND_SIZE)
#define GET_COMMAND(u) BF_GET(u, V2_MYS_HEADER_CEP_COMMAND_POS, \
V2_MYS_HEADER_CEP_COMMAND_SIZE)
#define SET_LENGTH(u, finalLength) BF_SET(u, finalLength, V2_MYS_HEADER_VSL_LENGTH_POS, \
V2_MYS_HEADER_VSL_LENGTH_SIZE)
#define GET_LENGTH(u) BF_GET(u, V2_MYS_HEADER_VSL_LENGTH_POS, \
V2_MYS_HEADER_VSL_LENGTH_SIZE)
#define SET_VERSION(u) BF_SET(u, V2_MYS_HEADER_PROTOCOL_VERSION, \
V2_MYS_HEADER_VSL_VERSION_POS, V2_MYS_HEADER_VSL_VERSION_SIZE);

#define MAX_BLOB_SIZE (MAX_PAYLOAD_SIZE)

// replicates part of the MyMesgage structure related to a single sensor data.
typedef struct {
uint8_t command_echo_payload;
uint8_t type;
uint8_t sensor;
union {
uint8_t bValue;
uint16_t uiValue;
int16_t iValue;
uint32_t ulValue;
int32_t lValue;
struct {
float fValue;
uint8_t fPrecision;
};
} __attribute__((packed));
} __attribute__((packed)) blob;

MyMultiMessage::~MyMultiMessage()
{

}

MyMultiMessage::MyMultiMessage(MyMessage *msg)
{
_msg = msg;
_offset = 0;
_msg->setPayloadType(P_CUSTOM);
}

void *MyMultiMessage::common(uint8_t messageType, uint8_t sensor, uint8_t ptype, uint8_t size,
uint8_t cmd)
{
blob *b;
if (_offset + size > MAX_BLOB_SIZE) {
return NULL;
}
b = (blob *)(_msg->data + _offset);
SET_PAYLOAD_TYPE(b->command_echo_payload, ptype);
SET_COMMAND(b->command_echo_payload, cmd);
b->type = messageType;
b->sensor = sensor;
_offset += size;
SET_LENGTH(_msg->version_length, _offset);
SET_VERSION(_msg->version_length);
return b;
}

bool MyMultiMessage::set(uint8_t messageType, uint8_t sensor, uint8_t value)
{
blob *b = (blob *)common(messageType, sensor, P_BYTE, 4, C_SET);
if (b == NULL) {
return false;
}
b->bValue = value;
return true;
}

bool MyMultiMessage::set(uint8_t messageType, uint8_t sensor, uint16_t value)
{
blob *b = (blob *)common(messageType, sensor, P_UINT16, 5, C_SET);
if (b == NULL) {
return false;
}
b->uiValue = value;
return true;
}

bool MyMultiMessage::set(uint8_t messageType, uint8_t sensor, int16_t value)
{
blob *b = (blob *)common(messageType, sensor, P_INT16, 5, C_SET);
if (b == NULL) {
return false;
}
b->uiValue = value;
return true;
}

bool MyMultiMessage::set(uint8_t messageType, uint8_t sensor, uint32_t value)
{
blob *b = (blob *)common(messageType, sensor, P_ULONG32, 7, C_SET);
if (b == NULL) {
return false;
}
b->ulValue = value;
return true;
}

bool MyMultiMessage::set(uint8_t messageType, uint8_t sensor, int32_t value)
{
blob *b = (blob *)common(messageType, sensor, P_LONG32, 7, C_SET);

if (b == NULL) {
return false;
}
b->lValue = value;
return true;
}

bool MyMultiMessage::set(uint8_t messageType, uint8_t sensor, float value, uint8_t decimals)
{
blob *b = (blob *)common(messageType, sensor, P_FLOAT32, 8, C_SET);

if (b == NULL) {
return false;
}
b->fValue = value;
b->fPrecision = decimals;
return true;
}

bool MyMultiMessage::setBattery(uint8_t value)
{
blob *b = (blob *)common(I_BATTERY_LEVEL, NODE_SENSOR_ID, P_BYTE, 4, C_INTERNAL);

if (b == NULL) {
return false;
}
b->bValue = value;
return true;
}


bool MyMultiMessage::getNext(MyMessage &m)
{
uint8_t size = GET_LENGTH(_msg->version_length);
uint8_t type;

blob *b;
if (_offset >= size) {
return false;
}

m.last = _msg->last;
m.sender = _msg->sender;
m.destination = _msg->destination;
m.version_length = _msg->version_length;

b = (blob *)(_msg->data + _offset);
m.type = b->type;
m.sensor = b->sensor;

type = GET_PAYLOAD_TYPE(b->command_echo_payload);
m.command_echo_payload = b->command_echo_payload;

if (type == P_BYTE) {
m.bValue = b->bValue;
_offset += 4;
return true;
} else if (type == P_UINT16) {
m.uiValue = b->uiValue;
_offset += 5;
return true;
} else if (type == P_INT16) {
m.iValue = b->iValue;
_offset += 5;
return true;
} else if (type == P_ULONG32) {
m.ulValue = b->ulValue;
_offset += 7;
return true;
} else if (type == P_LONG32) {
m.lValue = b->lValue;
_offset += 7;
return true;
} else if (type == P_FLOAT32) {
m.fValue = b->fValue;
m.fPrecision = b->fPrecision;
_offset += 8;
return true;
}
return false;
}

void MyMultiMessage::reset()
{
_offset = 0;
SET_LENGTH(_msg->version_length, _offset);
}
Loading