Merge pull request #10888 from pcdiem/dgr1

Add support for device groups where members temporarily have some items of sync
This commit is contained in:
Theo Arends 2021-02-09 13:42:18 +01:00 committed by GitHub
commit 2621c3b5f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 181 additions and 101 deletions

View File

@ -42,6 +42,7 @@ struct device_group {
uint32_t next_announcement_time; uint32_t next_announcement_time;
uint32_t next_ack_check_time; uint32_t next_ack_check_time;
uint32_t member_timeout_time; uint32_t member_timeout_time;
uint32_t no_status_share;
uint16_t outgoing_sequence; uint16_t outgoing_sequence;
uint16_t last_full_status_sequence; uint16_t last_full_status_sequence;
uint16_t message_length; uint16_t message_length;
@ -84,10 +85,9 @@ uint8_t * BeginDeviceGroupMessage(struct device_group * device_group, uint16_t f
return message_ptr; return message_ptr;
} }
// Return true if we're configured to share the specified item. uint32_t DeviceGroupSharedMask(uint8_t item)
bool DeviceGroupItemShared(bool incoming, uint8_t item)
{ {
uint32_t mask; uint32_t mask = 0;
if (item == DGR_ITEM_LIGHT_BRI || item == DGR_ITEM_BRI_POWER_ON) if (item == DGR_ITEM_LIGHT_BRI || item == DGR_ITEM_BRI_POWER_ON)
mask = DGR_SHARE_LIGHT_BRI; mask = DGR_SHARE_LIGHT_BRI;
else if (item == DGR_ITEM_POWER) else if (item == DGR_ITEM_POWER)
@ -102,9 +102,7 @@ bool DeviceGroupItemShared(bool incoming, uint8_t item)
mask = DGR_SHARE_DIMMER_SETTINGS; mask = DGR_SHARE_DIMMER_SETTINGS;
else if (item == DGR_ITEM_EVENT) else if (item == DGR_ITEM_EVENT)
mask = DGR_SHARE_EVENT; mask = DGR_SHARE_EVENT;
else return mask;
return true;
return mask & (incoming ? Settings.device_group_share_in : Settings.device_group_share_out);
} }
void DeviceGroupsInit(void) void DeviceGroupsInit(void)
@ -153,6 +151,7 @@ void DeviceGroupsInit(void)
} }
} }
device_group->message_header_length = sprintf_P((char *)device_group->message, PSTR("%s%s"), kDeviceGroupMessage, device_group->group_name) + 1; device_group->message_header_length = sprintf_P((char *)device_group->message, PSTR("%s%s"), kDeviceGroupMessage, device_group->group_name) + 1;
device_group->no_status_share = 0;
device_group->last_full_status_sequence = -1; device_group->last_full_status_sequence = -1;
} }
@ -204,7 +203,6 @@ void DeviceGroupsStop()
void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct device_group_member * device_group_member, uint8_t * message, int message_length, bool received) void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct device_group_member * device_group_member, uint8_t * message, int message_length, bool received)
{ {
char log_buffer[512];
bool item_processed = false; bool item_processed = false;
uint16_t message_sequence; uint16_t message_sequence;
uint16_t flags; uint16_t flags;
@ -218,16 +216,17 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
uint8_t * message_ptr = message + strlen((char *)message) + 1; uint8_t * message_ptr = message + strlen((char *)message) + 1;
// Get the message sequence and flags. // Get the message sequence and flags.
if (message_ptr + 4 > message_end_ptr) goto badmsg; // Malformed message - must be at least 16-bit sequence, 16-bit flags left if (message_ptr + 4 > message_end_ptr) return; // Malformed message - must be at least 16-bit sequence, 16-bit flags left
message_sequence = *message_ptr++; message_sequence = *message_ptr++;
message_sequence |= *message_ptr++ << 8; message_sequence |= *message_ptr++ << 8;
flags = *message_ptr++; flags = *message_ptr++;
flags |= *message_ptr++ << 8; flags |= *message_ptr++ << 8;
// Initialize the log buffer. // Initialize the log buffer.
char * log_buffer = (char *)malloc(512);
log_length = sprintf(log_buffer, PSTR("DGR: %s %s message %s %s: seq=%u, flags=%u"), (received ? PSTR("Received") : PSTR("Sending")), device_group->group_name, (received ? PSTR("from") : PSTR("to")), (device_group_member ? IPAddressToString(device_group_member->ip_address) : received ? PSTR("local") : PSTR("network")), message_sequence, flags); log_length = sprintf(log_buffer, PSTR("DGR: %s %s message %s %s: seq=%u, flags=%u"), (received ? PSTR("Received") : PSTR("Sending")), device_group->group_name, (received ? PSTR("from") : PSTR("to")), (device_group_member ? IPAddressToString(device_group_member->ip_address) : received ? PSTR("local") : PSTR("network")), message_sequence, flags);
log_ptr = log_buffer + log_length; log_ptr = log_buffer + log_length;
log_remaining = sizeof(log_buffer) - log_length; log_remaining = 512 - log_length;
// If this is an announcement, just log it. // If this is an announcement, just log it.
if (flags == DGR_FLAG_ANNOUNCEMENT) goto write_log; if (flags == DGR_FLAG_ANNOUNCEMENT) goto write_log;
@ -303,7 +302,10 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
} }
uint8_t item; uint8_t item;
uint8_t item_flags;
int32_t value; int32_t value;
uint32_t mask;
item_flags = 0;
for (;;) { for (;;) {
if (message_ptr >= message_end_ptr) goto badmsg; // Malformed message if (message_ptr >= message_end_ptr) goto badmsg; // Malformed message
item = *message_ptr++; item = *message_ptr++;
@ -321,6 +323,7 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
case DGR_ITEM_BRI_PRESET_HIGH: case DGR_ITEM_BRI_PRESET_HIGH:
case DGR_ITEM_BRI_POWER_ON: case DGR_ITEM_BRI_POWER_ON:
case DGR_ITEM_POWER: case DGR_ITEM_POWER:
case DGR_ITEM_NO_STATUS_SHARE:
case DGR_ITEM_EVENT: case DGR_ITEM_EVENT:
case DGR_ITEM_LIGHT_CHANNELS: case DGR_ITEM_LIGHT_CHANNELS:
break; break;
@ -376,45 +379,60 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
log_ptr += log_length; log_ptr += log_length;
log_remaining -= log_length; log_remaining -= log_length;
if (received && DeviceGroupItemShared(true, item)) { if (received) {
item_processed = true; if (item == DGR_ITEM_FLAGS) {
XdrvMailbox.command_code = item; item_flags = value;
XdrvMailbox.payload = value; continue;
XdrvMailbox.data_len = value;
*log_ptr++ = '*';
log_remaining--;
switch (item) {
case DGR_ITEM_POWER:
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
if (device_group_index < TasmotaGlobal.devices_present) {
bool on = (value & 1);
if (on != (TasmotaGlobal.power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
}
}
else if (XdrvMailbox.index & DGR_FLAG_LOCAL) {
uint8_t mask_devices = value >> 24;
if (mask_devices > TasmotaGlobal.devices_present) mask_devices = TasmotaGlobal.devices_present;
for (uint32_t i = 0; i < mask_devices; i++) {
uint32_t mask = 1 << i;
bool on = (value & mask);
if (on != (TasmotaGlobal.power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
}
}
break;
#ifdef USE_RULES
case DGR_ITEM_EVENT:
CmndEvent();
break;
#endif
case DGR_ITEM_COMMAND:
ExecuteCommand(XdrvMailbox.data, SRC_REMOTE);
break;
} }
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
}
}
if (received) { mask = DeviceGroupSharedMask(item);
if (item_flags & DGR_ITEM_FLAG_NO_SHARE)
device_group->no_status_share |= mask;
else
device_group->no_status_share &= ~mask;
if ((!(device_group->no_status_share & mask) || device_group_member == nullptr) && (!mask || (mask & Settings.device_group_share_in))) {
item_processed = true;
XdrvMailbox.command_code = item;
XdrvMailbox.payload = value;
XdrvMailbox.data_len = value;
*log_ptr++ = '*';
log_remaining--;
switch (item) {
case DGR_ITEM_POWER:
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
if (device_group_index < TasmotaGlobal.devices_present) {
bool on = (value & 1);
if (on != (TasmotaGlobal.power & (1 << device_group_index))) ExecuteCommandPower(device_group_index + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
}
}
else if (XdrvMailbox.index & DGR_FLAG_LOCAL) {
uint8_t mask_devices = value >> 24;
if (mask_devices > TasmotaGlobal.devices_present) mask_devices = TasmotaGlobal.devices_present;
for (uint32_t i = 0; i < mask_devices; i++) {
uint32_t mask = 1 << i;
bool on = (value & mask);
if (on != (TasmotaGlobal.power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
}
}
break;
case DGR_ITEM_NO_STATUS_SHARE:
device_group->no_status_share = value;
break;
#ifdef USE_RULES
case DGR_ITEM_EVENT:
CmndEvent();
break;
#endif
case DGR_ITEM_COMMAND:
ExecuteCommand(XdrvMailbox.data, SRC_REMOTE);
break;
}
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
}
item_flags = 0;
}
if (item_processed) { if (item_processed) {
XdrvMailbox.command_code = DGR_ITEM_EOL; XdrvMailbox.command_code = DGR_ITEM_EOL;
XdrvCall(FUNC_DEVICE_GROUP_ITEM); XdrvCall(FUNC_DEVICE_GROUP_ITEM);
@ -454,6 +472,7 @@ badmsg:
AddLog(LOG_LEVEL_ERROR, PSTR("%s ** incorrect length"), log_buffer); AddLog(LOG_LEVEL_ERROR, PSTR("%s ** incorrect length"), log_buffer);
cleanup: cleanup:
free(log_buffer);
if (received) { if (received) {
TasmotaGlobal.skip_light_fade = false; TasmotaGlobal.skip_light_fade = false;
ignore_dgr_sends = false; ignore_dgr_sends = false;
@ -465,9 +484,6 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
// If device groups is not up, ignore this request. // If device groups is not up, ignore this request.
if (!device_groups_up) return 1; if (!device_groups_up) return 1;
// If the device group index is higher then the number of device groups, ignore this request.
if (device_group_index >= device_group_count) return 0;
// Extract the flags from the message type. // Extract the flags from the message type.
bool with_local = ((message_type & DGR_MSGTYPFLAG_WITH_LOCAL) != 0); bool with_local = ((message_type & DGR_MSGTYPFLAG_WITH_LOCAL) != 0);
message_type = (DevGroupMessageType)(message_type & 0x7F); message_type = (DevGroupMessageType)(message_type & 0x7F);
@ -475,6 +491,14 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
// If we're currently processing a remote device message, ignore this request. // If we're currently processing a remote device message, ignore this request.
if (ignore_dgr_sends && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return 0; if (ignore_dgr_sends && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return 0;
// If device is < 0, the device group index is the device negated. If not, get the device group
// index from the device group maps.
// uint8_t device_group_index = -device;
// if (device > 0) device_group_index = (Settings.device_group_maps >> (device - 1) * 3 & 0x7 - 1;
// If the device group index is higher then the number of device groups, ignore this request.
if (device_group_index >= device_group_count) return 0;
// Get a pointer to the device information for this device. // Get a pointer to the device information for this device.
struct device_group * device_group = &device_groups[device_group_index]; struct device_group * device_group = &device_groups[device_group_index];
@ -510,7 +534,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
power >>= device_group_index; power >>= device_group_index;
power &= 1; power &= 1;
} }
SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_NO_STATUS_SHARE, device_group->no_status_share, DGR_ITEM_POWER, power);
XdrvMailbox.index = 0; XdrvMailbox.index = 0;
if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index = DGR_FLAG_LOCAL; if (device_group_index == 0 && first_device_group_is_local) XdrvMailbox.index = DGR_FLAG_LOCAL;
XdrvMailbox.command_code = DGR_ITEM_STATUS; XdrvMailbox.command_code = DGR_ITEM_STATUS;
@ -539,11 +563,13 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
#endif // USE_DEVICE_GROUPS_SEND #endif // USE_DEVICE_GROUPS_SEND
struct item { struct item {
uint8_t item; uint8_t item;
uint8_t flags;
uint32_t value; uint32_t value;
void * value_ptr; void * value_ptr;
} item_array[32]; } item_array[32];
bool shared; bool shared;
uint8_t item; uint8_t item;
uint32_t mask;
uint32_t value; uint32_t value;
uint8_t * value_ptr; uint8_t * value_ptr;
uint8_t * first_item_ptr = message_ptr; uint8_t * first_item_ptr = message_ptr;
@ -559,6 +585,14 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
item_ptr->item = item; item_ptr->item = item;
if (*value_ptr != '=') return 1; if (*value_ptr != '=') return 1;
value_ptr++; value_ptr++;
// If flags were specified for this item, save them.
item_ptr->flags = 0;
if (toupper(*value_ptr) == 'N') {
value_ptr++;
item_ptr->flags = DGR_ITEM_FLAG_NO_SHARE;
}
if (item <= DGR_ITEM_MAX_32BIT) { if (item <= DGR_ITEM_MAX_32BIT) {
oper = 0; oper = 0;
if (*value_ptr == '@') { if (*value_ptr == '@') {
@ -568,7 +602,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
value = (isdigit(*value_ptr) ? strtoul((char *)value_ptr, (char **)&value_ptr, 0) : 1); value = (isdigit(*value_ptr) ? strtoul((char *)value_ptr, (char **)&value_ptr, 0) : 1);
if (oper) { 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])); 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))); value = (oper == '+' ? old_value + value : oper == '-' ? old_value - value : oper == '^' ? old_value ^ (value ? value : 0xffffffff) : oper == '|' ? old_value | value : old_value == '&' ? old_value & value : old_value);
} }
item_ptr->value = value; item_ptr->value = value;
} }
@ -580,14 +614,29 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
if (chr == ' ' && !escaped) break; if (chr == ' ' && !escaped) break;
if (!(escaped = (chr == '\\' && !escaped))) *out_ptr++ = chr; if (!(escaped = (chr == '\\' && !escaped))) *out_ptr++ = chr;
} }
*out_ptr = 0; *out_ptr++ = 0;
} }
else { else {
switch (item) { switch (item) {
case DGR_ITEM_LIGHT_CHANNELS: case DGR_ITEM_LIGHT_CHANNELS:
for (int i = 0; i < 6; i++) { {
*out_ptr++ = strtoul((char *)value_ptr, (char **)&value_ptr, 0); int i = 0;
if (*value_ptr == ',') value_ptr++; char * endptr;
value = strtoul((char *)value_ptr, &endptr, 10);
if ((*endptr && *endptr != ',' && *endptr != ' ') || value > 255) {
for (; i < 6; i++) {
if (!*value_ptr || *value_ptr == ' ') break;
uint8_t * next_value_ptr = value_ptr + 2;
uint8_t save_char = *next_value_ptr;
*next_value_ptr = 'X';
*out_ptr++ = strtoul((char *)value_ptr, (char **)&value_ptr, 16);
*next_value_ptr = save_char;
}
}
for (; i < 6; i++) {
*out_ptr++ = (*value_ptr == ' ' ? 0 : strtoul((char *)value_ptr, (char **)&value_ptr, 10));
if (*value_ptr == ',') value_ptr++;
}
} }
break; break;
} }
@ -601,6 +650,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
va_start(ap, message_type); va_start(ap, message_type);
while ((item = va_arg(ap, int))) { while ((item = va_arg(ap, int))) {
item_ptr->item = item; item_ptr->item = item;
item_ptr->flags = 0;
if (item <= DGR_ITEM_MAX_32BIT) if (item <= DGR_ITEM_MAX_32BIT)
item_ptr->value = va_arg(ap, int); item_ptr->value = va_arg(ap, int);
else if (item <= DGR_ITEM_MAX_STRING) else if (item <= DGR_ITEM_MAX_STRING)
@ -621,6 +671,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
// previous update message to remove any items and their values that are included in this new // previous update message to remove any items and their values that are included in this new
// update. // update.
if (device_group->message_length) { if (device_group->message_length) {
uint8_t item_flags = 0;
int kept_item_count = 0; int kept_item_count = 0;
// Rebuild the previous update message, removing any items whose values are included in this // Rebuild the previous update message, removing any items whose values are included in this
@ -628,31 +679,44 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
uint8_t * previous_message_ptr = message_ptr; uint8_t * previous_message_ptr = message_ptr;
while (item = *previous_message_ptr++) { while (item = *previous_message_ptr++) {
// Determine the length of this item's value. // If this is the flags item, save the flags.
if (item <= DGR_ITEM_MAX_32BIT) { if (item == DGR_ITEM_FLAGS) {
value = 1; item_flags = *previous_message_ptr++;
if (item > DGR_ITEM_MAX_8BIT) { }
value = 2;
if (item > DGR_ITEM_MAX_16BIT) { // Otherwise, determine the length of this item's value.
value = 4; else {
if (item <= DGR_ITEM_MAX_32BIT) {
value = 1;
if (item > DGR_ITEM_MAX_8BIT) {
value = 2;
if (item > DGR_ITEM_MAX_16BIT) {
value = 4;
}
} }
} }
} else {
else { value = *previous_message_ptr + 1;
value = *previous_message_ptr + 1; }
}
// Search for this item in the new update. // Search for this item in the new update.
for (item_ptr = item_array; item_ptr->item; item_ptr++) { for (item_ptr = item_array; item_ptr->item; item_ptr++) {
if (item_ptr->item == item) break; if (item_ptr->item == item) break;
} }
// If this item was not found in the new update, copy it to the new update message. // If this item was not found in the new update, copy it to the new update message. If the
if (!item_ptr->item) { // item has flags, first copy the flags item to the new update message.
kept_item_count++; if (!item_ptr->item) {
*message_ptr++ = item; kept_item_count++;
memmove(message_ptr, previous_message_ptr, value); if (item_flags) {
message_ptr += value; *message_ptr++ = DGR_ITEM_FLAGS;
*message_ptr++ = item_flags;
}
*message_ptr++ = item;
memmove(message_ptr, previous_message_ptr, value);
message_ptr += value;
}
item_flags = 0;
} }
// Advance past the item value. // Advance past the item value.
@ -668,8 +732,20 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
// If this item is shared with the group add it to the message. // If this item is shared with the group add it to the message.
shared = true; shared = true;
if (!device_group_index && message_type != DGR_MSGTYPE_UPDATE_COMMAND) shared = DeviceGroupItemShared(false, item); if ((mask = DeviceGroupSharedMask(item))) {
if (item_ptr->flags & DGR_ITEM_FLAG_NO_SHARE)
device_group->no_status_share |= mask;
else if (!building_status_message)
device_group->no_status_share &= ~mask;
if (message_type != DGR_MSGTYPE_UPDATE_COMMAND) {
shared = (!(mask & device_group->no_status_share) && (device_group_index || (mask & Settings.device_group_share_out)));
}
}
if (shared) { if (shared) {
if (item_ptr->flags) {
*message_ptr++ = DGR_ITEM_FLAGS;
*message_ptr++ = item_ptr->flags;
}
*message_ptr++ = item; *message_ptr++ = item;
// For integer items, add the value to the message. // For integer items, add the value to the message.
@ -684,7 +760,7 @@ bool _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
*message_ptr++ = value & 0xff; *message_ptr++ = value & 0xff;
value >>= 8; value >>= 8;
// For the power item, the device count is overlayed onto the highest 8 bits. // For the power item, the device count is overlayed onto the highest 8 bits.
if (item == DGR_ITEM_POWER && !value) value = (device_group_index == 0 && first_device_group_is_local ? TasmotaGlobal.devices_present : 1); if (item == DGR_ITEM_POWER && !value) value = (!Settings.flag4.multiple_device_groups && device_group_index == 0 && first_device_group_is_local ? TasmotaGlobal.devices_present : 1);
*message_ptr++ = value; *message_ptr++ = value;
} }
} }

View File

@ -571,6 +571,9 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
interlock_mutex = false; interlock_mutex = false;
} }
#ifdef USE_DEVICE_GROUPS
power_t old_power = TasmotaGlobal.power;
#endif // USE_DEVICE_GROUPS
switch (state) { switch (state) {
case POWER_OFF: { case POWER_OFF: {
TasmotaGlobal.power &= (POWER_MASK ^ mask); TasmotaGlobal.power &= (POWER_MASK ^ mask);
@ -582,7 +585,7 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
TasmotaGlobal.power ^= mask; TasmotaGlobal.power ^= mask;
} }
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
if (SRC_REMOTE != source && SRC_RETRY != source) { if (TasmotaGlobal.power != old_power && SRC_REMOTE != source && SRC_RETRY != source) {
if (Settings.flag4.multiple_device_groups) // SetOption88 - Enable relays in separate device groups if (Settings.flag4.multiple_device_groups) // SetOption88 - Enable relays in separate device groups
SendDeviceGroupMessage(device - 1, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, (TasmotaGlobal.power >> (device - 1)) & 1 | 0x01000000); // Explicitly set number of relays to one SendDeviceGroupMessage(device - 1, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, (TasmotaGlobal.power >> (device - 1)) & 1 | 0x01000000); // Explicitly set number of relays to one
else else

View File

@ -347,7 +347,7 @@ enum DevGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS, DGR_ITEM_FLAGS,
//DGR_ITEM_ANALOG1, DGR_ITEM_ANALOG2, DGR_ITEM_ANALOG3, DGR_ITEM_ANALOG4, DGR_ITEM_ANALOG5, //DGR_ITEM_ANALOG1, DGR_ITEM_ANALOG2, DGR_ITEM_ANALOG3, DGR_ITEM_ANALOG4, DGR_ITEM_ANALOG5,
// Add new 16-bit items before this line // Add new 16-bit items before this line
DGR_ITEM_LAST_16BIT, DGR_ITEM_MAX_16BIT = 127, DGR_ITEM_LAST_16BIT, DGR_ITEM_MAX_16BIT = 127,
DGR_ITEM_POWER, DGR_ITEM_POWER, DGR_ITEM_NO_STATUS_SHARE,
// Add new 32-bit items before this line // Add new 32-bit items before this line
DGR_ITEM_LAST_32BIT, DGR_ITEM_MAX_32BIT = 191, DGR_ITEM_LAST_32BIT, DGR_ITEM_MAX_32BIT = 191,
DGR_ITEM_EVENT, DGR_ITEM_COMMAND, DGR_ITEM_EVENT, DGR_ITEM_COMMAND,
@ -355,6 +355,8 @@ enum DevGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS, DGR_ITEM_FLAGS,
DGR_ITEM_LAST_STRING, DGR_ITEM_MAX_STRING = 223, DGR_ITEM_LAST_STRING, DGR_ITEM_MAX_STRING = 223,
DGR_ITEM_LIGHT_CHANNELS }; DGR_ITEM_LIGHT_CHANNELS };
enum DevGroupItemFlag { DGR_ITEM_FLAG_NO_SHARE = 1 };
enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE_LIGHT_FADE = 4, DGR_SHARE_LIGHT_SCHEME = 8, 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_EVENT = 64 }; DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_DIMMER_SETTINGS = 32, DGR_SHARE_EVENT = 64 };

View File

@ -1730,7 +1730,7 @@ void LightAnimate(void)
} }
if (Light.update) { if (Light.update) {
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
if (Light.power && !Light.devgrp_no_channels_out) LightSendDeviceGroupStatus(false); if (Light.power && !Light.devgrp_no_channels_out) LightSendDeviceGroupStatus();
#endif // USE_DEVICE_GROUPS #endif // USE_DEVICE_GROUPS
uint16_t cur_col_10[LST_MAX]; // 10 bits resolution uint16_t cur_col_10[LST_MAX]; // 10 bits resolution
@ -2172,21 +2172,24 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) {
} }
#ifdef USE_DEVICE_GROUPS #ifdef USE_DEVICE_GROUPS
void LightSendDeviceGroupStatus(bool status) void LightSendDeviceGroupStatus()
{ {
static uint8_t last_bri; static uint8_t last_bri;
uint8_t bri = light_state.getBri(); uint8_t bri = light_state.getBri();
bool send_bri_update = (status || bri != last_bri); bool send_bri_update = (building_status_message || bri != last_bri);
if (Light.subtype > LST_SINGLE) { if (Light.subtype > LST_SINGLE) {
static uint8_t channels[LST_MAX + 1] = { 0, 0, 0, 0, 0, 0 }; static uint8_t last_channels[LST_MAX + 1] = { 0, 0, 0, 0, 0, 0 };
if (status) { uint8_t channels[LST_MAX];
light_state.getChannels(channels);
light_state.getChannelsRaw(channels);
uint8_t color_mode = light_state.getColorMode();
if (!(color_mode & LCM_RGB)) channels[0] = channels[1] = channels[2] = 0;
if (!(color_mode & LCM_CT)) channels[3] = channels[4] = 0;
if (building_status_message || memcmp(channels, last_channels, LST_MAX)) {
memcpy(last_channels, channels, LST_MAX);
last_channels[LST_MAX]++;
SendDeviceGroupMessage(Light.device_group_index, (send_bri_update ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_CHANNELS, last_channels);
} }
else {
memcpy(channels, Light.new_color, LST_MAX);
channels[LST_MAX]++;
}
SendDeviceGroupMessage(Light.device_group_index, (send_bri_update ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE), DGR_ITEM_LIGHT_CHANNELS, channels);
} }
if (send_bri_update) { if (send_bri_update) {
last_bri = bri; last_bri = bri;
@ -2199,9 +2202,6 @@ void LightHandleDevGroupItem(void)
static bool send_state = false; static bool send_state = false;
static bool restore_power = false; static bool restore_power = false;
//#ifdef USE_PWM_DIMMER_REMOTE
// if (!(XdrvMailbox.index & DGR_FLAG_LOCAL)) return;
//#endif // USE_PWM_DIMMER_REMOTE
if (*XdrvMailbox.topic != Light.device_group_index) return; if (*XdrvMailbox.topic != Light.device_group_index) return;
bool more_to_come; bool more_to_come;
uint32_t value = XdrvMailbox.payload; uint32_t value = XdrvMailbox.payload;
@ -2218,7 +2218,7 @@ void LightHandleDevGroupItem(void)
LightAnimate(); LightAnimate();
TasmotaGlobal.skip_light_fade = true; TasmotaGlobal.skip_light_fade = false;
if (send_state && !more_to_come) { if (send_state && !more_to_come) {
light_controller.saveSettings(); light_controller.saveSettings();
if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
@ -2242,8 +2242,9 @@ void LightHandleDevGroupItem(void)
} }
break; break;
case DGR_ITEM_LIGHT_CHANNELS: case DGR_ITEM_LIGHT_CHANNELS:
#ifdef USE_DGR_LIGHT_SEQUENCE
{ {
uint8_t bri = light_state.getBri();
#ifdef USE_DGR_LIGHT_SEQUENCE
static uint8_t last_sequence = 0; static uint8_t last_sequence = 0;
// If a sequence offset is set, set the channels to the ones we received <SequenceOffset> // If a sequence offset is set, set the channels to the ones we received <SequenceOffset>
@ -2259,13 +2260,11 @@ void LightHandleDevGroupItem(void)
memcpy(&Light.channels_fifo[last_entry], XdrvMailbox.data, LST_MAX); memcpy(&Light.channels_fifo[last_entry], XdrvMailbox.data, LST_MAX);
} }
} }
else { else
#endif // USE_DGR_LIGHT_SEQUENCE #endif // USE_DGR_LIGHT_SEQUENCE
light_controller.changeChannels((uint8_t *)XdrvMailbox.data); light_controller.changeChannels((uint8_t *)XdrvMailbox.data);
#ifdef USE_DGR_LIGHT_SEQUENCE light_controller.changeBri(bri);
}
} }
#endif // USE_DGR_LIGHT_SEQUENCE
send_state = true; send_state = true;
break; break;
case DGR_ITEM_LIGHT_FIXED_COLOR: case DGR_ITEM_LIGHT_FIXED_COLOR:
@ -2321,7 +2320,7 @@ void LightHandleDevGroupItem(void)
case DGR_ITEM_STATUS: case DGR_ITEM_STATUS:
SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade,
DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme);
LightSendDeviceGroupStatus(true); LightSendDeviceGroupStatus();
break; break;
} }
} }