mirror of https://github.com/arendst/Tasmota.git
Merge pull request #8251 from pcdiem/device-groups-9
Add DGR Command item and message logging
This commit is contained in:
commit
14e19b7cde
|
@ -420,8 +420,8 @@
|
|||
#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code)
|
||||
// #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code)
|
||||
//#define USE_HOTPLUG // Add support for sensor HotPlug
|
||||
#define USE_DEVICE_GROUPS // Add support for device groups (+5k code)
|
||||
#define USE_DEVICE_GROUPS_SEND // Add support for the DevGroupSend command (+0k6 code)
|
||||
#define USE_DEVICE_GROUPS // Add support for device groups (+5k6 code)
|
||||
#define USE_DEVICE_GROUPS_SEND // Add support for the DevGroupSend command (+0k5 code)
|
||||
#define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+2k5 code)
|
||||
#define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+1k code plus device groups size)
|
||||
//#define USE_KEELOQ // Add support for Jarolift rollers by Keeloq algorithm (+4k5 code)
|
||||
|
|
|
@ -41,6 +41,7 @@ struct device_group {
|
|||
uint32_t next_announcement_time;
|
||||
uint32_t next_ack_check_time;
|
||||
uint32_t member_timeout_time;
|
||||
uint16_t outgoing_sequence;
|
||||
uint16_t last_full_status_sequence;
|
||||
uint16_t message_length;
|
||||
uint16_t ack_check_interval;
|
||||
|
@ -58,12 +59,13 @@ struct device_group {
|
|||
};
|
||||
|
||||
struct device_group * device_groups;
|
||||
char * log_ptr;
|
||||
int log_remaining;
|
||||
uint32_t next_check_time = 0;
|
||||
uint16_t outgoing_sequence = 0;
|
||||
bool device_groups_initialized = false;
|
||||
bool device_groups_initialization_failed = false;
|
||||
bool building_status_message = false;
|
||||
bool processing_remote_device_message = false;
|
||||
bool ignore_dgr_sends = false;
|
||||
bool udp_was_connected = false;
|
||||
|
||||
void DeviceGroupsInit(void)
|
||||
|
@ -117,12 +119,21 @@ char * IPAddressToString(const IPAddress& ip_address)
|
|||
return buffer;
|
||||
}
|
||||
|
||||
void AddDeviceGroupLog(const char * format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int log_length = vsnprintf_P(log_ptr, log_remaining, format, ap);
|
||||
va_end(ap);
|
||||
log_ptr += log_length;
|
||||
log_remaining -= log_length;
|
||||
}
|
||||
|
||||
char * BeginDeviceGroupMessage(struct device_group * device_group, uint16_t flags, bool hold_sequence = false)
|
||||
{
|
||||
char * message_ptr = &device_group->message[device_group->message_header_length];
|
||||
if (!hold_sequence && !++outgoing_sequence) outgoing_sequence = 1;
|
||||
*message_ptr++ = outgoing_sequence & 0xff;
|
||||
*message_ptr++ = outgoing_sequence >> 8;
|
||||
if (!hold_sequence && !++device_group->outgoing_sequence) device_group->outgoing_sequence = 1;
|
||||
*message_ptr++ = device_group->outgoing_sequence & 0xff;
|
||||
*message_ptr++ = device_group->outgoing_sequence >> 8;
|
||||
*message_ptr++ = flags & 0xff;
|
||||
*message_ptr++ = flags >> 8;
|
||||
return message_ptr;
|
||||
|
@ -162,17 +173,241 @@ bool DeviceGroupItemShared(bool incoming, uint8_t item)
|
|||
return (!mask || ((incoming ? Settings.device_group_share_in : Settings.device_group_share_out) & mask));
|
||||
}
|
||||
|
||||
void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * label)
|
||||
void SendReceiveDeviceGroupPacket(struct device_group * device_group, struct device_group_member * device_group_member, char * message, int message_length, bool received)
|
||||
{
|
||||
if (!ip) ip = IPAddress(239,255,255,250);
|
||||
for (int attempt = 1; attempt <= 5; attempt++) {
|
||||
if (PortUdp.beginPacket(ip, 1900)) {
|
||||
PortUdp_write(packet, len);
|
||||
if (PortUdp.endPacket()) return;
|
||||
char log_buffer[LOGSZ];
|
||||
bool item_processed = false;
|
||||
uint16_t message_sequence;
|
||||
uint16_t flags;
|
||||
int device_group_index = device_group - device_groups;
|
||||
|
||||
log_ptr = log_buffer;
|
||||
log_remaining = sizeof(log_buffer);
|
||||
AddDeviceGroupLog(PSTR("DGR: %s %s message"), (received ? PSTR("Received") : PSTR("Sending")), device_group->group_name);
|
||||
if (received || device_group_member) AddDeviceGroupLog(PSTR(" %s %s"), (received ? PSTR("from") : PSTR("to")), (device_group_member ? IPAddressToString(device_group_member->ip_address) : PSTR("local")));
|
||||
|
||||
// Find the start of the actual message (after the http header).
|
||||
char * message_end_ptr = message + message_length;
|
||||
char * message_ptr = strstr_P(message, PSTR("\n\n"));
|
||||
if (message_ptr == nullptr) return;
|
||||
message_ptr += 2;
|
||||
|
||||
// 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
|
||||
message_sequence = *message_ptr++;
|
||||
message_sequence |= *message_ptr++ << 8;
|
||||
flags = *message_ptr++;
|
||||
flags |= *message_ptr++ << 8;
|
||||
AddDeviceGroupLog(PSTR(": seq=%u, flags=%u"), message_sequence, flags);
|
||||
|
||||
// If this is an announcement, just log it.
|
||||
if (flags == DGR_FLAG_ANNOUNCEMENT) goto write_log;
|
||||
|
||||
// If this is a received ack message, save the message sequence if it's newwer than the last ack
|
||||
// we received from this member.
|
||||
if (flags == DGR_FLAG_ACK) {
|
||||
if (received && device_group_member && (message_sequence > device_group_member->acked_sequence || device_group_member->acked_sequence - message_sequence < 64536)) {
|
||||
device_group_member->acked_sequence = message_sequence;
|
||||
}
|
||||
delay(10);
|
||||
goto write_log;
|
||||
}
|
||||
|
||||
// If this is a received message, send an ack message to the sender.
|
||||
if (device_group_member) {
|
||||
if (received) {
|
||||
if (!(flags & DGR_FLAG_MORE_TO_COME)) {
|
||||
*(message_ptr - 2) = DGR_FLAG_ACK;
|
||||
*(message_ptr - 1) = 0;
|
||||
SendReceiveDeviceGroupPacket(device_group, device_group_member, message, message_ptr - message, false);
|
||||
}
|
||||
}
|
||||
|
||||
// If we're sending this message directly to a member, it's a resend of the lst message.
|
||||
else {
|
||||
AddDeviceGroupLog(PSTR(", last ack=%u"), device_group_member->acked_sequence);
|
||||
goto write_log;
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a status request message, skip item processing.
|
||||
if ((flags & DGR_FLAG_STATUS_REQUEST)) goto write_log;
|
||||
|
||||
// If this is a received message, ...
|
||||
if (received) {
|
||||
|
||||
// If we already processed this or a later message from this group member, ignore this message.
|
||||
if (device_group_member) {
|
||||
if (message_sequence <= device_group_member->received_sequence) {
|
||||
if (message_sequence == device_group_member->received_sequence || device_group_member->received_sequence - message_sequence > 64536) {
|
||||
AddDeviceGroupLog(PSTR(" (old)"));
|
||||
goto write_log;
|
||||
}
|
||||
}
|
||||
device_group_member->received_sequence = message_sequence;
|
||||
}
|
||||
|
||||
/*
|
||||
XdrvMailbox
|
||||
bool grpflg
|
||||
bool usridx
|
||||
uint16_t command_code Item code
|
||||
uint32_t index 0:15 Flags, 16:31 Message sequence
|
||||
uint32_t data_len String item value length
|
||||
int32_t payload Integer item value
|
||||
char *topic Pointer to device group index
|
||||
char *data Pointer to non-integer item value
|
||||
char *command nullptr
|
||||
*/
|
||||
XdrvMailbox.command = nullptr; // Indicates the source is a device group update
|
||||
XdrvMailbox.index = flags | message_sequence << 16;
|
||||
XdrvMailbox.topic = (char *)&device_group_index;
|
||||
if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true;
|
||||
|
||||
// Set the flag to ignore device group send message request so callbacks from the drivers do not
|
||||
// send updates.
|
||||
ignore_dgr_sends = true;
|
||||
}
|
||||
|
||||
uint8_t item;
|
||||
int32_t value;
|
||||
for (;;) {
|
||||
if (message_ptr >= message_end_ptr) goto badmsg; // Malformed message
|
||||
item = *message_ptr++;
|
||||
if (!item) break; // Done
|
||||
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
switch (item) {
|
||||
case DGR_ITEM_LIGHT_FADE:
|
||||
case DGR_ITEM_LIGHT_SPEED:
|
||||
case DGR_ITEM_LIGHT_BRI:
|
||||
case DGR_ITEM_LIGHT_SCHEME:
|
||||
case DGR_ITEM_LIGHT_FIXED_COLOR:
|
||||
case DGR_ITEM_BRI_PRESET_LOW:
|
||||
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:
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: *** Invalid item=%u"), item);
|
||||
}
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
|
||||
AddDeviceGroupLog(PSTR(", %u="), item);
|
||||
if (received) XdrvMailbox.data = message_ptr;
|
||||
if (item <= DGR_ITEM_LAST_32BIT) {
|
||||
value = *message_ptr++;
|
||||
if (item > DGR_ITEM_MAX_8BIT) {
|
||||
value |= *message_ptr++ << 8;
|
||||
if (item > DGR_ITEM_MAX_16BIT) {
|
||||
value |= *message_ptr++ << 16;
|
||||
value |= *message_ptr++ << 24;
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1] = (item == DGR_ITEM_POWER ? value & 0xffffff : value);
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
else {
|
||||
device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] = value;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
else {
|
||||
device_group->values_8bit[item] = value;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
AddDeviceGroupLog(PSTR("%u"), value);
|
||||
}
|
||||
else if (item <= DGR_ITEM_MAX_STRING) {
|
||||
value = strlen(message_ptr);
|
||||
if (message_ptr + value >= message_end_ptr) goto badmsg; // Malformed message
|
||||
AddDeviceGroupLog(PSTR("'%s'"), message_ptr);
|
||||
message_ptr += value + 1;
|
||||
}
|
||||
else {
|
||||
switch (item) {
|
||||
case DGR_ITEM_LIGHT_CHANNELS:
|
||||
AddDeviceGroupLog(PSTR("%08X%02X"), *(uint32_t *)message_ptr, *(message_ptr + 4));
|
||||
message_ptr += 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (received && DeviceGroupItemShared(true, item)) {
|
||||
item_processed = true;
|
||||
XdrvMailbox.command_code = item;
|
||||
XdrvMailbox.payload = value;
|
||||
XdrvMailbox.data_len = value;
|
||||
AddDeviceGroupLog(PSTR("*"));
|
||||
switch (item) {
|
||||
case DGR_ITEM_POWER:
|
||||
if (device_group->local) {
|
||||
uint8_t mask_devices = value >> 24;
|
||||
if (mask_devices > devices_present) mask_devices = devices_present;
|
||||
for (uint32_t i = 0; i < devices_present; i++) {
|
||||
uint32_t mask = 1 << i;
|
||||
bool on = (value & mask);
|
||||
if (on != (power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DGR_ITEM_EVENT:
|
||||
CmndEvent();
|
||||
break;
|
||||
case DGR_ITEM_COMMAND:
|
||||
ExecuteCommand(XdrvMailbox.data, SRC_REMOTE);
|
||||
break;
|
||||
}
|
||||
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
|
||||
}
|
||||
}
|
||||
|
||||
if (received) {
|
||||
if (item_processed) {
|
||||
XdrvMailbox.command_code = DGR_ITEM_EOL;
|
||||
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
|
||||
}
|
||||
|
||||
skip_light_fade = false;
|
||||
ignore_dgr_sends = false;
|
||||
}
|
||||
|
||||
write_log:
|
||||
AddLog_P(LOG_LEVEL_DEBUG_MORE, log_buffer);
|
||||
|
||||
// If this is a received status request message, then if the requestor didn't just ack our
|
||||
// previous full status update, send a full status update.
|
||||
if (received) {
|
||||
if ((flags & DGR_FLAG_STATUS_REQUEST)) {
|
||||
if ((flags & DGR_FLAG_RESET) || device_group_member->acked_sequence != device_group->last_full_status_sequence) {
|
||||
_SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a message being sent, send it.
|
||||
else {
|
||||
for (int attempt = 1; attempt <= 5; attempt++) {
|
||||
if (PortUdp.beginPacket((device_group_member ? device_group_member->ip_address : IPAddress(239,255,255,250)), 1900)) {
|
||||
PortUdp_write(message, message_length);
|
||||
if (PortUdp.endPacket()) return;
|
||||
}
|
||||
delay(10);
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error sending message"));
|
||||
}
|
||||
goto cleanup;
|
||||
|
||||
badmsg:
|
||||
AddLog_P(LOG_LEVEL_ERROR, PSTR("%s ** incorrect length"), log_buffer);
|
||||
|
||||
cleanup:
|
||||
if (received) {
|
||||
skip_light_fade = false;
|
||||
ignore_dgr_sends = false;
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error sending %s packet"), label);
|
||||
}
|
||||
|
||||
void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...)
|
||||
|
@ -184,7 +419,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
if (!udp_connected) return;
|
||||
|
||||
// If we're currently processing a remote device message, ignore this request.
|
||||
if (processing_remote_device_message && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return;
|
||||
if (ignore_dgr_sends && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return;
|
||||
|
||||
// Get a pointer to the device information for this device.
|
||||
struct device_group * device_group = &device_groups[device_group_index];
|
||||
|
@ -192,35 +427,44 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
// If we're still sending initial status requests, ignore this request.
|
||||
if (device_group->initial_status_requests_remaining) return;
|
||||
|
||||
// Load the message header, sequence and flags.
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Building %s %spacket"), device_group->group_name, (message_type == DGR_MSGTYP_FULL_STATUS ? PSTR("full status ") : PSTR("")));
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
uint16_t original_sequence = device_group->outgoing_sequence;
|
||||
uint16_t flags = 0;
|
||||
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME)
|
||||
flags = DGR_FLAG_MORE_TO_COME;
|
||||
else if (message_type == DGR_MSGTYP_UPDATE_DIRECT)
|
||||
flags = DGR_FLAG_DIRECT;
|
||||
char * message_ptr = BeginDeviceGroupMessage(device_group, flags, building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE);
|
||||
|
||||
// A full status request is a request from a remote device for the status of every item we
|
||||
// control. As long as we're building it, we may as well multicast the status update to all
|
||||
// device group members.
|
||||
char * message_ptr = &device_group->message[device_group->message_header_length];
|
||||
if (message_type == DGR_MSGTYP_FULL_STATUS) {
|
||||
device_group->last_full_status_sequence = device_group->outgoing_sequence;
|
||||
device_group->message_length = 0;
|
||||
|
||||
// Set the flag indicating we're currently building a status message. SendDeviceGroupMessage
|
||||
// will build but not send messages while this flag is set.
|
||||
building_status_message = true;
|
||||
|
||||
// Call the drivers to build the status update.
|
||||
if (!++outgoing_sequence) outgoing_sequence = 1;
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s full status packet"), device_group->group_name);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
device_group->message_length = 0;
|
||||
SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power);
|
||||
if (device_group->local) SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power);
|
||||
XdrvMailbox.index = device_group_index << 16;
|
||||
XdrvMailbox.command_code = DGR_ITEM_STATUS;
|
||||
XdrvMailbox.topic = (char *)&device_group_index;
|
||||
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
|
||||
building_status_message = false;
|
||||
|
||||
// If we have nothing to share with the other members, restore the message sequence and return.
|
||||
// If we have nothing to share with the other members, just send the EOL item.
|
||||
if (!device_group->message_length) {
|
||||
if (!--outgoing_sequence) outgoing_sequence = -1;
|
||||
return;
|
||||
*message_ptr++ = 0;
|
||||
device_group->message_length = message_ptr - device_group->message;
|
||||
}
|
||||
device_group->last_full_status_sequence = outgoing_sequence;
|
||||
|
||||
// Set the status update flag in the outgoing message.
|
||||
*(message_ptr + 2) |= DGR_FLAG_FULL_STATUS;
|
||||
|
@ -229,7 +473,6 @@ 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;
|
||||
|
@ -240,6 +483,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
uint32_t value;
|
||||
void * value_ptr;
|
||||
} item_array[32];
|
||||
// bool items_added = false;
|
||||
bool shared;
|
||||
uint8_t item;
|
||||
uint32_t value;
|
||||
|
@ -247,26 +491,11 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
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
|
||||
|
||||
value = 0;
|
||||
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME)
|
||||
value |= DGR_FLAG_MORE_TO_COME;
|
||||
else if (message_type == DGR_MSGTYP_UPDATE_DIRECT)
|
||||
value |= DGR_FLAG_DIRECT;
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">sequence=%u, flags=%u"), outgoing_sequence, value);
|
||||
#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) {
|
||||
if (message_type == DGR_MSGTYPE_UPDATE_COMMAND) {
|
||||
value_ptr = XdrvMailbox.data;
|
||||
while ((item = strtoul(value_ptr, &value_ptr, 0))) {
|
||||
item_ptr->item = item;
|
||||
|
@ -405,7 +634,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
}
|
||||
}
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: %u items carried over"), kept_item_count);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
}
|
||||
|
||||
|
@ -416,52 +645,28 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
shared = true;
|
||||
if (!device_group_index) shared = DeviceGroupItemShared(false, item);
|
||||
if (shared) {
|
||||
// items_added = true;
|
||||
*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
|
||||
old_value = value;
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
value >>= 8;
|
||||
*message_ptr++ = value & 0xff;
|
||||
if (item > DGR_ITEM_MAX_16BIT) {
|
||||
value >>= 8;
|
||||
*message_ptr++ = value & 0xff;
|
||||
value >>= 8;
|
||||
|
||||
// For the power item, the device count is overlayed onto the highest 8 bits.
|
||||
if (item == DGR_ITEM_POWER) {
|
||||
if (!value)
|
||||
value = (device_group_index == 0 ? devices_present : 1);
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
else
|
||||
old_value = old_value & 0xffffff;
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
|
||||
*message_ptr++ = value;
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1] = old_value;
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
else {
|
||||
device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] = old_value;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
else {
|
||||
device_group->values_8bit[item] = value;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
|
||||
// For string items, add the null-terminated string to the message.
|
||||
|
@ -472,9 +677,6 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
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.
|
||||
|
@ -485,28 +687,39 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
for (int i = 0; i < 5; i++) {
|
||||
*message_ptr++ = (value_ptr ? *value_ptr++ : 0);
|
||||
}
|
||||
//#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the EOL item code and calculate the message length.
|
||||
*message_ptr++ = 0;
|
||||
device_group->message_length = message_ptr - device_group->message;
|
||||
// If we added any items, add the EOL item code and calculate the message length.
|
||||
// if (items_added) {
|
||||
*message_ptr++ = 0;
|
||||
device_group->message_length = message_ptr - device_group->message;
|
||||
// }
|
||||
|
||||
// If there's going to be more items added to this message, return.
|
||||
if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return;
|
||||
}
|
||||
|
||||
// If there is no message, restore the sequence number and return.
|
||||
if (!device_group->message_length) {
|
||||
device_group->outgoing_sequence = original_sequence;
|
||||
return;
|
||||
}
|
||||
|
||||
// Multicast the packet.
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Multicast"));
|
||||
SendReceiveDeviceGroupPacket(device_group, nullptr, device_group->message, device_group->message_length, false);
|
||||
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
// If the device group is local, handle the message locally.
|
||||
if (message_type == DGR_MSGTYPE_UPDATE_COMMAND && device_group->local) {
|
||||
struct XDRVMAILBOX save_XdrvMailbox = XdrvMailbox;
|
||||
SendReceiveDeviceGroupPacket(device_group, nullptr, device_group->message, device_group->message_length, true);
|
||||
XdrvMailbox = save_XdrvMailbox;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
|
||||
uint32_t now = millis();
|
||||
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) {
|
||||
|
@ -514,7 +727,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
device_group->next_ack_check_time = 0;
|
||||
}
|
||||
else {
|
||||
device_group->ack_check_interval = 100;
|
||||
device_group->ack_check_interval = 200;
|
||||
device_group->next_ack_check_time = now + device_group->ack_check_interval;
|
||||
if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time;
|
||||
device_group->member_timeout_time = now + DGR_MEMBER_TIMEOUT;
|
||||
|
@ -524,10 +737,10 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
|
|||
if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time;
|
||||
}
|
||||
|
||||
void ProcessDeviceGroupMessage(char * packet, int packet_length)
|
||||
void ProcessDeviceGroupMessage(char * message, int message_length)
|
||||
{
|
||||
// Make the group name a null-terminated string.
|
||||
char * message_group_name = packet + sizeof(DEVICE_GROUP_MESSAGE) - 1;
|
||||
char * message_group_name = message + sizeof(DEVICE_GROUP_MESSAGE) - 1;
|
||||
char * message_ptr = strchr(message_group_name, ' ');
|
||||
if (message_ptr == nullptr) return;
|
||||
*message_ptr = 0;
|
||||
|
@ -543,15 +756,15 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
|
|||
*message_ptr++ = ' ';
|
||||
|
||||
// Find the group member. If this is a new group member, add it.
|
||||
struct device_group_member * device_group_member;
|
||||
IPAddress remote_ip = PortUdp.remoteIP();
|
||||
struct device_group_member * * flink = &device_group->device_group_members;
|
||||
struct device_group_member * device_group_member;
|
||||
for (;;) {
|
||||
device_group_member = *flink;
|
||||
if (!device_group_member) {
|
||||
device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member));
|
||||
if (device_group_member == nullptr) {
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating device group member block"));
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating member block"));
|
||||
return;
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Adding member %s"), IPAddressToString(remote_ip));
|
||||
|
@ -565,205 +778,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
|
|||
flink = &device_group_member->flink;
|
||||
}
|
||||
|
||||
// Find the start of the actual message (after the http header).
|
||||
message_ptr = strstr_P(message_ptr, PSTR("\n\n"));
|
||||
if (message_ptr == nullptr) return;
|
||||
message_ptr += 2;
|
||||
|
||||
bool light_fade;
|
||||
uint16_t flags;
|
||||
uint16_t item;
|
||||
uint16_t message_sequence;
|
||||
int32_t value;
|
||||
|
||||
// Get the message sequence and flags.
|
||||
if (packet_length - (message_ptr - packet) < 4) goto badmsg; // Malformed message - must be at least 16-bit sequence, 16-bit flags left
|
||||
message_sequence = *message_ptr++;
|
||||
message_sequence |= *message_ptr++ << 8;
|
||||
flags = *message_ptr++;
|
||||
flags |= *message_ptr++ << 8;
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Received device group %s packet from %s: sequence=%u, flags=%u"), device_group->group_name, IPAddressToString(remote_ip), message_sequence, flags);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
|
||||
// If this is an announcement, simply return.
|
||||
if (flags == DGR_FLAG_ANNOUNCEMENT) return;
|
||||
|
||||
// If this is an ack message, save the message sequence if it's newwer than the last ack we
|
||||
// received from this member.
|
||||
if (flags == DGR_FLAG_ACK) {
|
||||
if (message_sequence > device_group_member->acked_sequence || device_group_member->acked_sequence - message_sequence < 64536) {
|
||||
device_group_member->acked_sequence = message_sequence;
|
||||
}
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<ack"));
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
return;
|
||||
}
|
||||
|
||||
// Send an ack message to the sender.
|
||||
if (!(flags & DGR_FLAG_MORE_TO_COME)) {
|
||||
*(message_ptr - 2) = DGR_FLAG_ACK;
|
||||
*(message_ptr - 1) = 0;
|
||||
SendDeviceGroupPacket(remote_ip, packet, message_ptr - packet, PSTR("Ack"));
|
||||
}
|
||||
|
||||
// If this is a status request message, then if the requestor didn't just ack our previous full
|
||||
// status update, send a full status update.
|
||||
if ((flags & DGR_FLAG_STATUS_REQUEST)) {
|
||||
if ((flags & DGR_FLAG_RESET) || device_group_member->acked_sequence != device_group->last_full_status_sequence) {
|
||||
_SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS);
|
||||
}
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<status request"));
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
return;
|
||||
}
|
||||
|
||||
// If we already processed this or a later message from this group member, ignore this message.
|
||||
if (message_sequence <= device_group_member->received_sequence) {
|
||||
if (message_sequence == device_group_member->received_sequence || device_group_member->received_sequence - message_sequence > 64536) {
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<old message"));
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
return;
|
||||
}
|
||||
}
|
||||
device_group_member->received_sequence = message_sequence;
|
||||
|
||||
// Set the flag indicating we're currently processing a remote device message.
|
||||
// SendDeviceGroupMessage will not send messages while this flag is set.
|
||||
processing_remote_device_message = true;
|
||||
|
||||
/*
|
||||
XdrvMailbox
|
||||
bool grpflg
|
||||
bool usridx
|
||||
uint16_t command_code Item code
|
||||
uint32_t index 0:15 Flags, 16:31 Message sequence
|
||||
uint32_t data_len String item value length
|
||||
int32_t payload Integer item value
|
||||
char *topic Pointer to device group index
|
||||
char *data Pointer to non-integer item value
|
||||
char *command nullptr
|
||||
*/
|
||||
XdrvMailbox.command = nullptr; // Indicates the source is a device group update
|
||||
XdrvMailbox.index = flags | message_sequence << 16;
|
||||
XdrvMailbox.topic = (char *)&device_group_index;
|
||||
if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true;
|
||||
|
||||
for (;;) {
|
||||
if (packet_length - (message_ptr - packet) < 1) goto badmsg; // Malformed message
|
||||
item = *message_ptr++;
|
||||
if (!item) break; // Done
|
||||
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
switch (item) {
|
||||
case DGR_ITEM_LIGHT_FADE:
|
||||
case DGR_ITEM_LIGHT_SPEED:
|
||||
case DGR_ITEM_LIGHT_BRI:
|
||||
case DGR_ITEM_LIGHT_SCHEME:
|
||||
case DGR_ITEM_LIGHT_FIXED_COLOR:
|
||||
case DGR_ITEM_BRI_PRESET_LOW:
|
||||
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:
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** Invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip));
|
||||
}
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
|
||||
XdrvMailbox.command_code = item;
|
||||
if (item <= DGR_ITEM_LAST_32BIT) {
|
||||
value = *message_ptr++;
|
||||
if (item > DGR_ITEM_MAX_8BIT) {
|
||||
value |= *message_ptr++ << 8;
|
||||
if (item > DGR_ITEM_MAX_16BIT) {
|
||||
value |= *message_ptr++ << 16;
|
||||
value |= *message_ptr++ << 24;
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1] = (item == DGR_ITEM_POWER ? value & 0xffffff : value);
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
else {
|
||||
device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] = value;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
else {
|
||||
device_group->values_8bit[item] = value;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
|
||||
//#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 = strlen(message_ptr);
|
||||
if (value >= packet_length - (message_ptr - packet)) goto badmsg; // Malformed message
|
||||
//#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 + 1;
|
||||
}
|
||||
else {
|
||||
switch (item) {
|
||||
case DGR_ITEM_LIGHT_CHANNELS:
|
||||
//#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;
|
||||
}
|
||||
}
|
||||
|
||||
if (DeviceGroupItemShared(true, item)) {
|
||||
if (item == DGR_ITEM_POWER) {
|
||||
if (device_group->local) {
|
||||
uint8_t mask_devices = value >> 24;
|
||||
if (mask_devices > devices_present) mask_devices = devices_present;
|
||||
for (uint32_t i = 0; i < devices_present; i++) {
|
||||
uint32_t mask = 1 << i;
|
||||
bool on = (value & mask);
|
||||
if (on != (power & mask)) ExecuteCommandPower(i + 1, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (item == DGR_ITEM_EVENT) {
|
||||
#ifdef USE_RULES
|
||||
CmndEvent();
|
||||
#endif
|
||||
}
|
||||
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
|
||||
}
|
||||
}
|
||||
|
||||
XdrvMailbox.command_code = DGR_ITEM_EOL;
|
||||
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
|
||||
skip_light_fade = false;
|
||||
|
||||
processing_remote_device_message = false;
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<processed"));
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
return;
|
||||
|
||||
badmsg:
|
||||
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Malformed message received from %s"), IPAddressToString(remote_ip));
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("packet_length=%u, offset=%u"), packet_length, message_ptr - packet);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
processing_remote_device_message = false;
|
||||
SendReceiveDeviceGroupPacket(device_group, device_group_member, message, message_length, true);
|
||||
}
|
||||
|
||||
void DeviceGroupStatus(uint8_t device_group_index)
|
||||
|
@ -774,10 +789,10 @@ void DeviceGroupStatus(uint8_t device_group_index)
|
|||
struct device_group * device_group = &device_groups[device_group_index];
|
||||
buffer[0] = buffer[1] = 0;
|
||||
for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member; device_group_member = device_group_member->flink) {
|
||||
snprintf(buffer, sizeof(buffer), PSTR("%s,{\"IPAddress\":\"%s\",\"ResendCount\":%u,\"LastRcvdSeq\":%u,\"LastAckedSeq\":%u}"), buffer, IPAddressToString(device_group_member->ip_address), device_group_member->unicast_count, device_group_member->received_sequence, device_group_member->acked_sequence);
|
||||
snprintf_P(buffer, sizeof(buffer), PSTR("%s,{\"IPAddress\":\"%s\",\"ResendCount\":%u,\"LastRcvdSeq\":%u,\"LastAckedSeq\":%u}"), buffer, IPAddressToString(device_group_member->ip_address), device_group_member->unicast_count, device_group_member->received_sequence, device_group_member->acked_sequence);
|
||||
member_count++;
|
||||
}
|
||||
Response_P(PSTR("{\"" D_CMND_DEVGROUPSTATUS "\":{\"Index\":%u,\"GroupName\":\"%s\",\"MessageSeq\":%u,\"MemberCount\":%d,\"Members\":[%s]}"), device_group_index, device_group->group_name, outgoing_sequence, member_count, &buffer[1]);
|
||||
Response_P(PSTR("{\"" D_CMND_DEVGROUPSTATUS "\":{\"Index\":%u,\"GroupName\":\"%s\",\"MessageSeq\":%u,\"MemberCount\":%d,\"Members\":[%s]}"), device_group_index, device_group->group_name, device_group->outgoing_sequence, member_count, &buffer[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,11 +814,12 @@ void DeviceGroupsLoop(void)
|
|||
next_check_time = now + 3000;
|
||||
for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) {
|
||||
device_group * device_group = &device_groups[device_group_index];
|
||||
device_group->next_announcement_time = -1;
|
||||
device_group->message_length = BeginDeviceGroupMessage(device_group, DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST) - device_group->message;
|
||||
device_group->initial_status_requests_remaining = 10;
|
||||
device_group->next_ack_check_time = next_check_time;
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: (Re)discovering device groups"));
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: (Re)discovering members"));
|
||||
}
|
||||
|
||||
if (device_groups_initialization_failed) return;
|
||||
|
@ -830,7 +846,8 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
|
|||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending initial status request for group %s"), device_group->group_name);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Initial"));
|
||||
SendReceiveDeviceGroupPacket(device_group, nullptr, device_group->message, device_group->message_length, false);
|
||||
|
||||
device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; // The reset flag is on only for the first packet - turn it off now
|
||||
device_group->next_ack_check_time = now + 200;
|
||||
}
|
||||
|
@ -854,7 +871,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
|
|||
while ((device_group_member = *flink)) {
|
||||
|
||||
// If we have not received an ack to our last message from this member, ...
|
||||
if (device_group_member->acked_sequence != outgoing_sequence) {
|
||||
if (device_group_member->acked_sequence != device_group->outgoing_sequence) {
|
||||
|
||||
// If we haven't receive an ack from this member in DGR_MEMBER_TIMEOUT ms, assume
|
||||
// they're offline and remove them from the group.
|
||||
|
@ -866,10 +883,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
|
|||
|
||||
// Otherwise, unicast the last message directly to this member.
|
||||
else {
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, PSTR("Unicast"));
|
||||
SendReceiveDeviceGroupPacket(device_group, device_group_member, device_group->message, device_group->message_length, false);
|
||||
device_group_member->unicast_count++;
|
||||
acked = false;
|
||||
flink = &device_group_member->flink;
|
||||
|
@ -910,10 +924,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
|
|||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: next_announcement_time=%u, now=%u"), device_group->next_announcement_time, now);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
if (device_group->next_announcement_time <= now) {
|
||||
#ifdef DEVICE_GROUPS_DEBUG
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending device group %s announcement"), device_group->group_name);
|
||||
#endif // DEVICE_GROUPS_DEBUG
|
||||
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, PSTR("Announcement"));
|
||||
SendReceiveDeviceGroupPacket(device_group, nullptr, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, false);
|
||||
device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000);
|
||||
}
|
||||
if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time;
|
||||
|
|
|
@ -315,7 +315,7 @@ 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,
|
||||
DGR_ITEM_EVENT, DGR_ITEM_COMMAND,
|
||||
// Add new string items before this line
|
||||
DGR_ITEM_LAST_STRING, DGR_ITEM_MAX_STRING = 223,
|
||||
DGR_ITEM_LIGHT_CHANNELS };
|
||||
|
|
|
@ -282,6 +282,7 @@ struct LIGHT {
|
|||
bool fade_initialized = false; // dont't fade at startup
|
||||
bool fade_running = false;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
uint8_t last_scheme = 0;
|
||||
bool devgrp_no_channels_out = false; // don't share channels with device group (e.g. if scheme set by other device)
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
#ifdef USE_LIGHT_PALETTE
|
||||
|
@ -1477,9 +1478,6 @@ void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value)
|
|||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Light signal %d"), signal);
|
||||
light_controller.changeRGB(signal, 255 - signal, 0, true); // keep bri
|
||||
Settings.light_scheme = 0;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
LightUpdateScheme();
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
if (0 == light_state.getBri()) {
|
||||
light_controller.changeBri(50);
|
||||
}
|
||||
|
@ -1833,9 +1831,6 @@ void LightAnimate(void)
|
|||
|
||||
Light.wakeup_active = 0;
|
||||
Settings.light_scheme = LS_POWER;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
LightUpdateScheme();
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1858,6 +1853,14 @@ void LightAnimate(void)
|
|||
default:
|
||||
XlgtCall(FUNC_SET_SCHEME);
|
||||
}
|
||||
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
if (Settings.light_scheme != Light.last_scheme) {
|
||||
Light.last_scheme = Settings.light_scheme;
|
||||
SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme);
|
||||
Light.devgrp_no_channels_out = false;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
}
|
||||
|
||||
if ((Settings.light_scheme < LS_MAX) || power_off) { // exclude WS281X Neopixel schemes
|
||||
|
@ -2270,7 +2273,7 @@ void LightHandleDevGroupItem(void)
|
|||
break;
|
||||
case DGR_ITEM_LIGHT_SCHEME:
|
||||
if (Settings.light_scheme != value) {
|
||||
Settings.light_scheme = value;
|
||||
Light.last_scheme = Settings.light_scheme = value;
|
||||
Light.devgrp_no_channels_out = (value != 0);
|
||||
send_state = true;
|
||||
}
|
||||
|
@ -2330,17 +2333,6 @@ void LightHandleDevGroupItem(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LightUpdateScheme(void)
|
||||
{
|
||||
static uint8_t last_scheme;
|
||||
|
||||
if (Settings.light_scheme != last_scheme) {
|
||||
last_scheme = Settings.light_scheme;
|
||||
SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme);
|
||||
}
|
||||
Light.devgrp_no_channels_out = false;
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -2473,9 +2465,6 @@ void CmndSupportColor(void)
|
|||
}
|
||||
#endif // USE_LIGHT_PALETTE
|
||||
Settings.light_scheme = 0;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
LightUpdateScheme();
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
coldim = true;
|
||||
} else { // Color3, 4, 5 and 6
|
||||
for (uint32_t i = 0; i < LST_RGB; i++) {
|
||||
|
@ -2645,9 +2634,6 @@ void CmndScheme(void)
|
|||
#endif // USE_LIGHT_PALETTE
|
||||
}
|
||||
Settings.light_scheme = XdrvMailbox.payload;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
LightUpdateScheme();
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
if (LS_WAKEUP == Settings.light_scheme) {
|
||||
Light.wakeup_active = 3;
|
||||
}
|
||||
|
@ -2671,9 +2657,6 @@ void CmndWakeup(void)
|
|||
}
|
||||
Light.wakeup_active = 3;
|
||||
Settings.light_scheme = LS_WAKEUP;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
LightUpdateScheme();
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
LightPowerOn();
|
||||
ResponseCmndChar(D_JSON_STARTED);
|
||||
}
|
||||
|
@ -2753,8 +2736,11 @@ void CmndDimmer(void)
|
|||
}
|
||||
}
|
||||
#if defined(USE_PWM_DIMMER) && defined(USE_DEVICE_GROUPS)
|
||||
Settings.bri_power_on = light_state.getBri();;
|
||||
SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on);
|
||||
uint8_t bri = light_state.getBri();
|
||||
if (bri != Settings.bri_power_on) {
|
||||
Settings.bri_power_on = bri;
|
||||
SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on);
|
||||
}
|
||||
#endif // USE_PWM_DIMMER && USE_DEVICE_GROUPS
|
||||
Light.update = true;
|
||||
if (skip_light_fade) LightAnimate();
|
||||
|
|
|
@ -344,8 +344,8 @@ void PWMDimmerHandleButton(void)
|
|||
// If this is about the power button, ...
|
||||
if (is_power_button) {
|
||||
|
||||
// If no other buttons are pressed and the up or down button was tapped while holding the
|
||||
// power button before this, ...
|
||||
// If no other buttons are pressed and the up or down button was not tapped while holding
|
||||
// the power button before this, ...
|
||||
if (buttons_pressed == 1 && !tap_count) {
|
||||
|
||||
// If the power is on, adjust the brightness. Set the direction based on the current
|
||||
|
@ -602,7 +602,7 @@ void PWMDimmerHandleButton(void)
|
|||
}
|
||||
if (new_bri != bri) {
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
SendDeviceGroupMessage(power_button_index, (dgr_item ? DGR_MSGTYP_UPDATE : DGR_MSGTYP_UPDATE_MORE_TO_COME), DGR_ITEM_LIGHT_BRI, new_bri);
|
||||
SendDeviceGroupMessage(power_button_index, (dgr_item ? DGR_MSGTYP_PARTIAL_UPDATE : DGR_MSGTYP_UPDATE_MORE_TO_COME), DGR_ITEM_LIGHT_BRI, new_bri);
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
#ifdef USE_PWM_DIMMER_REMOTE
|
||||
if (!active_device_is_local)
|
||||
|
@ -610,9 +610,15 @@ void PWMDimmerHandleButton(void)
|
|||
else {
|
||||
#endif // USE_PWM_DIMMER_REMOTE
|
||||
skip_light_fade = true;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
ignore_dgr_sends = true;
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
light_state.setBri(new_bri);
|
||||
LightAnimate();
|
||||
skip_light_fade = false;
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
ignore_dgr_sends = false;
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
Settings.bri_power_on = new_bri;
|
||||
#ifdef USE_PWM_DIMMER_REMOTE
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue