Merge pull request #8224 from pcdiem/device-groups-8

Add DGR Event item, Rework item parsing
This commit is contained in:
Theo Arends 2020-04-19 08:53:47 +02:00 committed by GitHub
commit 5286075ab7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 145 additions and 184 deletions

View File

@ -155,6 +155,9 @@ bool DeviceGroupItemShared(bool incoming, uint8_t item)
case DGR_ITEM_BRI_PRESET_HIGH:
mask = DGR_SHARE_DIMMER_SETTINGS;
break;
case DGR_ITEM_EVENT:
mask = DGR_SHARE_EVENT;
break;
}
return (!mask || ((incoming ? Settings.device_group_share_in : Settings.device_group_share_out) & mask));
}
@ -225,24 +228,29 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
else {
#ifdef USE_DEVICE_GROUPS_SEND
bool escaped;
bool use_command;
char chr;
char oper;
uint32_t old_value;
char * delim_ptr;
char * out_ptr;
#endif // USE_DEVICE_GROUPS_SEND
struct item {
uint8_t item;
uint32_t value;
void * value_ptr;
} item_array[32];
bool shared;
uint8_t item;
uint32_t value;
char * value_ptr;
struct item * item_ptr;
va_list ap;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s packet"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
#ifdef USE_DEVICE_GROUPS_SEND
use_command = (message_type == DGR_MSGTYPE_UPDATE_COMMAND);
#endif // USE_DEVICE_GROUPS_SEND
value = 0;
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME)
value |= DGR_FLAG_MORE_TO_COME;
@ -253,73 +261,96 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
#endif // DEVICE_GROUPS_DEBUG
message_ptr = BeginDeviceGroupMessage(device_group, value, building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE);
// Build an array of all the items and values in this update.
memset(item_array, 0, sizeof(item_array));
item_ptr = item_array;
#ifdef USE_DEVICE_GROUPS_SEND
use_command = (message_type == DGR_MSGTYPE_UPDATE_COMMAND);
if (use_command) {
value_ptr = XdrvMailbox.data;
while ((item = strtoul(value_ptr, &value_ptr, 0))) {
item_ptr->item = item;
if (*value_ptr == '=') {
value_ptr++;
if (item <= DGR_ITEM_MAX_32BIT) {
oper = 0;
if (*value_ptr == '@') {
oper = value_ptr[1];
value_ptr += 2;
}
value = strtoul(value_ptr, &value_ptr, 0);
if (oper) {
old_value = (item <= DGR_ITEM_MAX_8BIT ? device_group->values_8bit[item] : (item <= DGR_ITEM_MAX_16BIT ? device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] : device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1]));
value = (oper == '+' ? old_value + value : (oper == '-' ? old_value - value : (oper == '^' ? old_value ^ (value ? value : 0xffffffff) : old_value)));
}
item_ptr->value = value;
}
else if (item <= DGR_ITEM_MAX_STRING) {
item_ptr->value_ptr = out_ptr = value_ptr;
escaped = false;
while ((chr = *value_ptr++)) {
if (chr == ' ' && !escaped) break;
if (!(escaped = (chr == '\\' && !escaped))) *out_ptr++ = chr;
}
*out_ptr = 0;
}
else {
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
item_ptr->value_ptr = out_ptr = value_ptr;
for (int i = 0; i < 5; i++) {
*out_ptr = strtoul(value_ptr, &value_ptr, 0);
if (*value_ptr == ',') value_ptr++;
}
break;
}
}
}
item_ptr++;
}
}
else {
#endif // USE_DEVICE_GROUPS_SEND
va_start(ap, message_type);
while ((item = va_arg(ap, int))) {
item_ptr->item = item;
if (item <= DGR_ITEM_MAX_32BIT)
item_ptr->value = va_arg(ap, int);
else if (item <= DGR_ITEM_MAX_STRING)
item_ptr->value_ptr = va_arg(ap, char *);
else {
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
item_ptr->value_ptr = va_arg(ap, uint8_t *);
break;
}
}
item_ptr++;
}
va_end(ap);
#ifdef USE_DEVICE_GROUPS_SEND
}
#endif // USE_DEVICE_GROUPS_SEND
// If we're still building this update or all group members haven't acknowledged the previous
// update yet, update the message to include these new updates. First we need to rebuild the
// previous update message to remove any items and their values that are included in this new
// update.
if (device_group->message_length) {
uint8_t item_array[32];
int item_index = 0;
int kept_item_count = 0;
// Build an array of all the items in this new update.
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command)
value_ptr = XdrvMailbox.data;
else
#endif // USE_DEVICE_GROUPS_SEND
va_start(ap, message_type);
#ifdef USE_DEVICE_GROUPS_SEND
while (use_command ? (item = strtoul(value_ptr, &delim_ptr, 0)) : (item = va_arg(ap, int))) {
#else // USE_DEVICE_GROUPS_SEND
while ((item = va_arg(ap, int))) {
#endif // !USE_DEVICE_GROUPS_SEND
item_array[item_index++] = item;
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command) {
if (!*delim_ptr) break;
if (*delim_ptr == '=') {
delim_ptr = strchr(delim_ptr, ' ');
if (!delim_ptr) break;
}
value_ptr = delim_ptr + 1;
}
else {
#endif // USE_DEVICE_GROUPS_SEND
if (item <= DGR_ITEM_MAX_32BIT)
va_arg(ap, int);
else if (item <= DGR_ITEM_MAX_STRING)
va_arg(ap, char *);
else {
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
va_arg(ap, uint8_t *);
break;
}
}
#ifdef USE_DEVICE_GROUPS_SEND
}
#endif // USE_DEVICE_GROUPS_SEND
}
#ifdef USE_DEVICE_GROUPS_SEND
if (!use_command) va_end(ap);
#else // USE_DEVICE_GROUPS_SEND
va_end(ap);
#endif // !USE_DEVICE_GROUPS_SEND
item_array[item_index] = 0;
// Rebuild the previous update message, removing any items whose values are included in this
// new update.
char * previous_message_ptr = message_ptr;
while (item = *previous_message_ptr++) {
// Search for this item in the new update.
for (item_index = 0; item_array[item_index]; item_index++) {
if (item_array[item_index] == item) break;
for (item_ptr = item_array; item_ptr->item; item_ptr++) {
if (item_ptr->item == item) break;
}
// If this item was found in the new update skip over it and it's value.
if (item_array[item_index]) {
if (item_ptr->item) {
if (item <= DGR_ITEM_MAX_32BIT) {
previous_message_ptr++;
if (item > DGR_ITEM_MAX_8BIT) {
@ -330,8 +361,9 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
}
}
}
else if (item <= DGR_ITEM_MAX_STRING)
previous_message_ptr += *previous_message_ptr++;
else if (item <= DGR_ITEM_MAX_STRING) {
previous_message_ptr += strlen(previous_message_ptr) + 1;
}
else {
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
@ -355,7 +387,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
}
}
else if (item <= DGR_ITEM_MAX_STRING) {
*message_ptr++ = value = *previous_message_ptr++;
value = strlen(previous_message_ptr) + 1;
memmove(message_ptr, previous_message_ptr, value);
previous_message_ptr += value;
message_ptr += value;
@ -378,58 +410,20 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
}
// Itertate through the passed items adding them and their values to the message.
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command)
value_ptr = XdrvMailbox.data;
else
#endif // USE_DEVICE_GROUPS_SEND
va_start(ap, message_type);
#ifdef USE_DEVICE_GROUPS_SEND
while (use_command ? (item = strtoul(value_ptr, &delim_ptr, 0)) : (item = va_arg(ap, int))) {
#else // !USE_DEVICE_GROUPS_SEND
while ((item = va_arg(ap, int))) {
#endif // !USE_DEVICE_GROUPS_SEND
for (item_ptr = item_array; (item = item_ptr->item); item_ptr++) {
// Find out if this item is shared with the group and add the item code to the message if yes.
// If this item is shared with the group add it to the message.
shared = true;
if (!device_group_index) shared = DeviceGroupItemShared(false, item);
if (shared) *message_ptr++ = item;
#ifdef USE_DEVICE_GROUPS_SEND
// If we're processing a command, get a pointer to the value if one was specified.
if (use_command) value_ptr = (*delim_ptr == '=' ? delim_ptr + 1 : nullptr);
#endif // USE_DEVICE_GROUPS_SEND
// For numeric items, get the specified value.
if (item <= DGR_ITEM_MAX_32BIT) {
#ifdef USE_DEVICE_GROUPS_SEND
// If we're processing a command, get the final value after processing any specified
// operators.
if (use_command) {
value = 0;
if (value_ptr) {
oper = 0;
if (*value_ptr == '@') {
oper = value_ptr[1];
value_ptr += 2;
}
value = strtoul(value_ptr, nullptr, 0);
if (oper) {
old_value = (item <= DGR_ITEM_MAX_8BIT ? device_group->values_8bit[item] : (item <= DGR_ITEM_MAX_16BIT ? device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] : device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1]));
value = (oper == '+' ? old_value + value : (oper == '-' ? old_value - value : (oper == '^' ? old_value ^ (value ? value : 0xffffffff) : old_value)));
}
}
}
else
#endif // USE_DEVICE_GROUPS_SEND
value = va_arg(ap, int);
// If the item is shared, add it to the message.
if (shared) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u"), item, value);
#endif // DEVICE_GROUPS_DEBUG
*message_ptr++ = item;
// For integer items, add the value to the message.
if (item <= DGR_ITEM_MAX_32BIT) {
value = item_ptr->value;
//#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(">%u=%u"), item, value);
//#endif // DEVICE_GROUPS_DEBUG
*message_ptr++ = value & 0xff;
if (item > DGR_ITEM_MAX_8BIT) {
#ifdef USE_DEVICE_GROUPS_SEND
@ -469,77 +463,36 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
}
#endif // USE_DEVICE_GROUPS_SEND
}
}
// For string items, add the string to the message prefixed by the length.
// For string items, add the null-terminated string to the message.
else if (item <= DGR_ITEM_MAX_STRING) {
#ifdef USE_DEVICE_GROUPS_SEND
if (!use_command)
#endif // USE_DEVICE_GROUPS_SEND
value_ptr = va_arg(ap, char *);
if (shared) {
value = (value_ptr ? strlen((const char *)value_ptr) : 0);
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%s"), item, value_ptr);
#endif // DEVICE_GROUPS_DEBUG
*message_ptr++ = value;
memcpy(message_ptr, value_ptr, value);
if (item_ptr->value_ptr) {
value = strlen((const char *)item_ptr->value_ptr);
memcpy(message_ptr, item_ptr->value_ptr, value);
message_ptr += value;
}
*message_ptr++ = 0;
//#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(">%u='%s'"), item, item_ptr->value_ptr);
//#endif // DEVICE_GROUPS_DEBUG
}
// For special items, handle them individually.
else {
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command) {
if (shared) {
value_ptr = (char *)item_ptr->value_ptr;
for (int i = 0; i < 5; i++) {
value = 0;
if (value_ptr) {
value = strtoul(value_ptr, &value_ptr, 0);
value_ptr = (*value_ptr == ',' ? value_ptr + 1 : nullptr);
*message_ptr++ = (value_ptr ? *value_ptr++ : 0);
}
*message_ptr++ = value;
}
}
}
else {
#endif // USE_DEVICE_GROUPS_SEND
value_ptr = va_arg(ap, char *);
if (shared) {
memmove(message_ptr, value_ptr, 5);
message_ptr += 5;
}
#ifdef USE_DEVICE_GROUPS_SEND
}
#endif // USE_DEVICE_GROUPS_SEND
#ifdef DEVICE_GROUPS_DEBUG
if (shared) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u,%u,%u,%u,%u"), item, *(message_ptr - 5), *(message_ptr - 4), *(message_ptr - 3), *(message_ptr - 2), *(message_ptr - 1));
#endif // DEVICE_GROUPS_DEBUG
//#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(">%u=%u,%u,%u,%u,%u"), item, *(message_ptr - 5), *(message_ptr - 4), *(message_ptr - 3), *(message_ptr - 2), *(message_ptr - 1));
//#endif // DEVICE_GROUPS_DEBUG
break;
}
}
#ifdef USE_DEVICE_GROUPS_SEND
// If we're processing a command, advance to the next item. If there are no more, break out of
// the loop.
if (use_command) {
if (!*delim_ptr) break;
if (*delim_ptr == '=') {
delim_ptr = strchr(delim_ptr, ' ');
if (!delim_ptr) break;
}
value_ptr = delim_ptr + 1;
}
#endif // USE_DEVICE_GROUPS_SEND
}
#ifdef USE_DEVICE_GROUPS_SEND
if (!use_command) va_end(ap);
#else // USE_DEVICE_GROUPS_SEND
va_end(ap);
#endif // !USE_DEVICE_GROUPS_SEND
// Add the EOL item code and calculate the message length.
*message_ptr++ = 0;
@ -715,6 +668,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
case DGR_ITEM_BRI_PRESET_HIGH:
case DGR_ITEM_BRI_POWER_ON:
case DGR_ITEM_POWER:
case DGR_ITEM_EVENT:
case DGR_ITEM_LIGHT_CHANNELS:
break;
default:
@ -746,27 +700,27 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
}
#endif // USE_DEVICE_GROUPS_SEND
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<item=%u, value=%u"), item, value);
#endif // DEVICE_GROUPS_DEBUG
//#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("<%u=%u"), item, value);
//#endif // DEVICE_GROUPS_DEBUG
XdrvMailbox.payload = value;
}
else if (item <= DGR_ITEM_MAX_STRING) {
value = *message_ptr++;
value = strlen(message_ptr);
if (value >= packet_length - (message_ptr - packet)) goto badmsg; // Malformed message
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<item=%u, value=%.*s"), item, value, message_ptr);
#endif // DEVICE_GROUPS_DEBUG
//#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("<%u='%s'"), item, message_ptr);
//#endif // DEVICE_GROUPS_DEBUG
XdrvMailbox.data_len = value;
XdrvMailbox.data = message_ptr;
message_ptr += value;
message_ptr += value + 1;
}
else {
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<item=%u, value=%u,%u,%u,%u,%u"), item, *message_ptr, *(message_ptr + 1), *(message_ptr + 2), *(message_ptr + 3), *(message_ptr + 4));
#endif // DEVICE_GROUPS_DEBUG
//#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("<%u=%u,%u,%u,%u,%u"), item, *message_ptr, *(message_ptr + 1), *(message_ptr + 2), *(message_ptr + 3), *(message_ptr + 4));
//#endif // DEVICE_GROUPS_DEBUG
XdrvMailbox.data = message_ptr;
message_ptr += 5;
break;
@ -785,6 +739,9 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
}
}
}
else if (item == DGR_ITEM_EVENT) {
CmndEvent();
}
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
}
}

View File

@ -315,12 +315,13 @@ enum DevGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS,
DGR_ITEM_POWER, DGR_ITEM_DIMMER_RANGE,
// Add new 32-bit items before this line
DGR_ITEM_LAST_32BIT, DGR_ITEM_MAX_32BIT = 191,
DGR_ITEM_EVENT,
// Add new string items before this line
DGR_ITEM_LAST_STRING, DGR_ITEM_MAX_STRING = 223,
DGR_ITEM_LIGHT_CHANNELS };
enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE_LIGHT_FADE = 4, DGR_SHARE_LIGHT_SCHEME = 8,
DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_DIMMER_SETTINGS = 32 };
DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_DIMMER_SETTINGS = 32, DGR_SHARE_EVENT = 64 };
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,

View File

@ -50,7 +50,7 @@
#define USE_DEEPSLEEP // Add support for deepsleep (+1k code)
#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer
//#define USE_HOTPLUG // Add support for sensor HotPlug
#undef USE_DEVICE_GROUPS // Disable support for device groups (+5k6 code)
//#undef USE_DEVICE_GROUPS // Disable support for device groups (+5k6 code)
#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code)
#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code)
#undef USE_SONOFF_D1 // DIsable support for Sonoff D1 Dimmer (+0k7 code)

View File

@ -1797,8 +1797,11 @@ void CmndEvent(void)
{
if (XdrvMailbox.data_len > 0) {
strlcpy(Rules.event_data, XdrvMailbox.data, sizeof(Rules.event_data));
#ifdef USE_DEVICE_GROUPS
SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_EVENT, XdrvMailbox.data);
#endif // USE_DEVICE_GROUPS
}
ResponseCmndDone();
if (XdrvMailbox.command) ResponseCmndDone();
}
void CmndVariable(void)