Merge branch 'device-groups' of https://github.com/pcdiem/Tasmota into pwm-dimmer

This commit is contained in:
Paul C Diem 2020-02-24 20:06:47 -06:00
commit d0bb1b36e4
9 changed files with 92 additions and 94 deletions

View File

@ -2,7 +2,7 @@
The device groups module provides a framework to allow multiple devices to be in a group with values such as power, light color/temperature/brightness, PWM values, sensor values, etc. shared with other devices in the group. For example, with multiple light modules in a device group, the light settings can be changed on one module and the settings will automatically be changed on the other light modules. Dimmer switch modules could be in a device group with light modules and the dimmer switch could control the power, brightness and colors of all the lights in the group. Multiple dimmer switches could be in a device group to form a 3-way/4-way dimmer switch.
UDP broadcasts, followed by UDP unicasts if necessary, are used to send updates to all devices so updates are fast. There is no need for an MQTT server but all the devices in a group must be on the same IP network.
UDP multicasts, followed by UDP unicasts if necessary, are used to send updates to all devices so updates are fast. There is no need for an MQTT server but all the devices in a group must be on the same IP network.
To include device groups support in the build, define USE_DEVICE_GROUPS in your user_config_override. This adds 3.5K to the code size. All devices in a group must be running firmware with device group support and have device groups enabled.
@ -13,7 +13,7 @@ To enable device groups, set Option16 to 1 and **restart the device**.
The device group name is the MQTT group topic set with the GroupTopic command. All devices in the same IP network with the same group topic are in the same group. Some modules may define additional device groups. For example, if Remote Device Mode is enabled, the PWM Dimmer module defines three devices groups.
The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change its brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 255 on the dimmer switch (DevGroupShare 255,255) and set the incoming item mask to 255 and outgoing item mask to 0 on all the lights (DevGroupShare 255,0).
The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change its brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 0xffffffff (all items) on the dimmer switch (DevGroupShare 0xffffffff,0xffffffff) and set the incoming item mask to 0xffffffff and outgoing item mask to 0 on all the lights (DevGroupShare 0xffffffff,0).
### Commands
@ -29,7 +29,7 @@ The items that are sent to the group and the items that are received from the gr
<tr>
<td>DevGroupShare
</td>
<td><in>,&lt;out> = set incoming and outgoing shared item mask (default = 255,255)
<td><in>,&lt;out> = set incoming and outgoing shared item mask (default = 0xffffffff,0xffffffff)
<p>
1 = Power, 2 = Light brightness, 4 = Light fade/speed, 8 = Light scheme, 16 = Light color, 32 = Minimum brightness
</td>

View File

@ -575,11 +575,6 @@ typedef union {
ADC_MODE(ADC_VCC); // Set ADC input for Power Supply Voltage usage
#endif
// Settings re-purposed for device groups
#define device_groups_enabled ws_clock_reverse // SetOption16 - Enable device groups
#define device_group_share_in domoticz_sensor_idx[0] // Bitmask of device group items imported
#define device_group_share_out domoticz_sensor_idx[1] // Bitmask of device group items exported
// Settings re-purposed for the PWM_DIMMER module
#ifdef USE_PWM_DIMMER
#define led_timeout light_signal // SetOption18 - Turn brightness LED's off 5 seconds after last change

View File

@ -1677,7 +1677,7 @@ void CmndDevGroupShare(void)
ParseParameters(2, parm);
Settings.device_group_share_in = parm[0];
Settings.device_group_share_out = parm[1];
Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%d,\"Out\":%d}}"), Settings.device_group_share_in, Settings.device_group_share_out);
Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%x,\"Out\":%x}}"), Settings.device_group_share_in, Settings.device_group_share_out);
}
#endif // USE_DEVICE_GROUPS

View File

@ -49,7 +49,8 @@ struct device_group {
struct device_group * device_groups;
uint16_t outgoing_sequence = 0;
bool initialized = false;
bool device_groups_initialized = false;
bool device_groups_initialization_failed = false;
bool building_status_message = false;
bool processing_remote_device_message = false;
bool waiting_for_acks;
@ -57,39 +58,35 @@ bool udp_was_connected = false;
void DeviceGroupsInit(void)
{
/*
Initialize the device information for each device group. The group name is the MQTT group topic.
*/
if (Settings.flag.device_groups_enabled) {
device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group));
if (device_groups == nullptr) {
AddLog_P2(LOG_LEVEL_ERROR, "DGR: error allocating %u-element device group array", device_group_count);
Settings.flag.device_groups_enabled = false;
return;
}
for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) {
struct device_group * device_group = &device_groups[device_group_index];
strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1)));
device_group->message_header_length = sprintf(device_group->message, "%s%s HTTP/1.1\n\n", kDeviceGroupMessage, device_group->group_name);
device_group->last_full_status_sequence = -1;
}
device_groups[0].local = true;
// If both in and out shared items masks are 0, assume they're unitialized and initialize them.
if (!Settings.device_group_share_in && !Settings.device_group_share_out) {
Settings.device_group_share_in = Settings.device_group_share_out = 0xff;
}
initialized = true;
// Initialize the device information for each device group. The group name is the MQTT group topic.
device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group));
if (device_groups == nullptr) {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count);
device_groups_initialization_failed = true;
return;
}
for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) {
struct device_group * device_group = &device_groups[device_group_index];
strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1)));
device_group->message_header_length = sprintf_P(device_group->message, PSTR("%s%s HTTP/1.1\n\n"), kDeviceGroupMessage, device_group->group_name);
device_group->last_full_status_sequence = -1;
}
device_groups[0].local = true;
// If both in and out shared items masks are 0, assume they're unitialized and initialize them.
if (!Settings.device_group_share_in && !Settings.device_group_share_out) {
Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff;
}
device_groups_initialized = true;
}
char * IPAddressToString(const IPAddress& ip_address)
{
static char buffer[16];
sprintf(buffer, "%u.%u.%u.%u", ip_address[0], ip_address[1], ip_address[2], ip_address[3]);
sprintf_P(buffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]);
return buffer;
}
@ -131,13 +128,13 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la
}
delay(10);
}
AddLog_P2(LOG_LEVEL_ERROR, "DGR: error sending %s packet", label);
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error sending %s packet"), label);
}
void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...)
{
// If device groups are not enabled, ignore this request.
if (!Settings.flag.device_groups_enabled) return;
if (!Settings.flag4.device_groups_enabled) return;
// If UDP is not set up, ignore this request.
if (!udp_connected) return;
@ -152,7 +149,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
if (device_group->initial_status_requests_remaining) return;
// 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 broadcast the status update to all
// 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) {
@ -164,10 +161,10 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
// Call the drivers to build the status update.
if (!++outgoing_sequence) outgoing_sequence = 1;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "Building device group %s full status packet", device_group->group_name);
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);
SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power);
XdrvMailbox.command_code = DGR_ITEM_STATUS;
XdrvCall(FUNC_DEVICE_GROUP_REQUEST);
building_status_message = false;
@ -191,7 +188,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
va_list ap;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "Building device group %s packet", device_group->group_name);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s packet"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
uint16_t original_sequence = outgoing_sequence;
if (!building_status_message && message_type != DGR_MSGTYP_PARTIAL_UPDATE && !++outgoing_sequence) outgoing_sequence = 1;
@ -204,7 +201,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
else if (message_type == DGR_MSGTYP_UPDATE_DIRECT)
value |= DGR_FLAG_DIRECT;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, ">sequence=%u, flags=%u", outgoing_sequence, value);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">sequence=%u, flags=%u"), outgoing_sequence, value);
#endif // DEVICE_GROUPS_DEBUG
*message_ptr++ = value & 0xff;
*message_ptr++ = value >> 8;
@ -303,7 +300,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
}
}
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "%u items carried over from previous update", kept_item_count);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count);
#endif // DEVICE_GROUPS_DEBUG
}
@ -316,7 +313,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
value = va_arg(ap, int);
if (shared) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%u", item, value);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u"), item, value);
#endif // DEVICE_GROUPS_DEBUG
*message_ptr++ = value & 0xff;
if (item > DGR_ITEM_MAX_8BIT) {
@ -335,7 +332,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
if (shared) {
value = strlen((const char *)value_ptr);
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%s", item, value_ptr);
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);
@ -348,7 +345,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
value_ptr = va_arg(ap, uint8_t *);
if (shared) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%u,%u,%u,%u,%u", item, *value_ptr, *(value_ptr + 1), *(value_ptr + 2), *(value_ptr + 3), *(value_ptr + 4));
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u,%u,%u,%u,%u"), item, *value_ptr, *(value_ptr + 1), *(value_ptr + 2), *(value_ptr + 3), *(value_ptr + 4));
#endif // DEVICE_GROUPS_DEBUG
memmove(message_ptr, value_ptr, 5);
message_ptr += 5;
@ -374,11 +371,11 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return;
}
// Broadcast the packet.
// Multicast the packet.
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending %u-byte device group %s packet via broadcast, 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);
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(239,255,255,250), device_group->message, device_group->message_length, "Broadcast");
SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Multicast"));
device_group->next_ack_check_time = millis() + 100;
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) {
@ -418,11 +415,11 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
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, "DGR: error allocating device group member block");
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating device group member block"));
return;
}
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "DGR: adding member %s (%p)", IPAddressToString(remote_ip), device_group_member);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: adding member %s (%p)"), IPAddressToString(remote_ip), device_group_member);
#endif // DEVICE_GROUPS_DEBUG
device_group_member->ip_address = remote_ip;
*flink = device_group_member;
@ -435,7 +432,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
}
// Find the start of the actual message (after the http header).
message_ptr = strstr(message_ptr, "\n\n");
message_ptr = strstr_P(message_ptr, PSTR("\n\n"));
if (message_ptr == nullptr) return;
message_ptr += 2;
@ -452,7 +449,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
flags = *message_ptr++;
flags |= *message_ptr++ << 8;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "Received device group %s packet from %s: sequence=%u, flags=%u", device_group->group_name, IPAddressToString(remote_ip), message_sequence, flags);
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 ack message, save the message sequence if it's newwer than the last ack we
@ -463,7 +460,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
}
device_group_member->timeout_time = 0;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "<ack");
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<ack"));
#endif // DEVICE_GROUPS_DEBUG
return;
}
@ -472,7 +469,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
if (!(flags & DGR_FLAG_MORE_TO_COME)) {
*(message_ptr - 2) = DGR_FLAG_ACK;
*(message_ptr - 1) = 0;
SendDeviceGroupPacket(remote_ip, packet, message_ptr - packet, "Ack");
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
@ -482,7 +479,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
_SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS);
}
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "<status request");
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<status request"));
#endif // DEVICE_GROUPS_DEBUG
return;
}
@ -490,7 +487,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
// If we already processed this or a later message from this group member, ignore this message.
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, "<old message");
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<old message"));
#endif // DEVICE_GROUPS_DEBUG
return;
}
@ -537,7 +534,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
case DGR_ITEM_LIGHT_CHANNELS:
break;
default:
AddLog_P2(LOG_LEVEL_ERROR, "DGR: ********** invalid item=%u received from device group %s member %s", item, device_group->group_name, IPAddressToString(remote_ip));
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
@ -555,7 +552,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
light_fade = value;
}
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "<item=%u, value=%u", item, value);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<item=%u, value=%u"), item, value);
#endif // DEVICE_GROUPS_DEBUG
XdrvMailbox.payload = value;
}
@ -563,7 +560,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
value = *message_ptr++;
if (value >= packet_length - (message_ptr - packet)) goto badmsg; // Malformed message
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "<item=%u, value=%.*s", item, value, message_ptr);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<item=%u, value=%.*s"), item, value, message_ptr);
#endif // DEVICE_GROUPS_DEBUG
XdrvMailbox.data_len = value;
XdrvMailbox.data = message_ptr;
@ -573,7 +570,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "<item=%u, value=%u,%u,%u,%u,%u", item, *message_ptr, *(message_ptr + 1), *(message_ptr + 2), *(message_ptr + 3), *(message_ptr + 4));
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
XdrvMailbox.data = message_ptr;
message_ptr += 5;
@ -601,28 +598,27 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
processing_remote_device_message = false;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "<processed");
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("<processed"));
#endif // DEVICE_GROUPS_DEBUG
return;
badmsg:
AddLog_P2(LOG_LEVEL_ERROR, "DGR: malformed message received from %s", IPAddressToString(remote_ip));
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: malformed message received from %s"), IPAddressToString(remote_ip));
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "packet_length=%u, offset=%u", packet_length, message_ptr - packet);
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;
}
void DeviceGroupsLoop(void)
{
if (!Settings.flag.device_groups_enabled) return;
if (!Settings.flag4.device_groups_enabled) return;
if (udp_connected) {
if (!udp_was_connected) {
udp_was_connected = true;
if (!initialized) {
DeviceGroupsInit();
if (!Settings.flag.device_groups_enabled) return;
}
if (!device_groups_initialized) DeviceGroupsInit();
if (device_groups_initialization_failed) return;
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];
@ -634,12 +630,14 @@ void DeviceGroupsLoop(void)
*message_ptr++ = 0;
device_group->message_length = message_ptr - device_group->message;
device_group->initial_status_requests_remaining = 5;
device_group->next_ack_check_time = millis() + 2000;
device_group->next_ack_check_time = millis() + 1000;
}
waiting_for_acks = true;
}
if (device_groups_initialization_failed) return;
if (waiting_for_acks) {
uint32_t now = millis();
waiting_for_acks = false;
@ -649,10 +647,10 @@ void DeviceGroupsLoop(void)
if (device_group->next_ack_check_time <= now) {
if (device_group->initial_status_requests_remaining) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending initial status request for group %s", device_group->group_name);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending initial status request for group %s"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
if (--device_group->initial_status_requests_remaining) {
SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, "Initial");
SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Initial"));
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;
waiting_for_acks = true;
@ -671,16 +669,16 @@ void DeviceGroupsLoop(void)
if (device_group_member->timeout_time && device_group_member->timeout_time < now) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "DGR: removing member %s (%p)", IPAddressToString(device_group_member->ip_address), device_group_member);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: removing member %s (%p)"), IPAddressToString(device_group_member->ip_address), device_group_member);
#endif // DEVICE_GROUPS_DEBUG
*flink = device_group_member->flink;
free(device_group_member);
}
else {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, "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);
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, "Unicast");
SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, PSTR("Unicast"));
if (!device_group_member->timeout_time) device_group_member->timeout_time = now + 15000;
acked = false;
flink = &device_group_member->flink;

View File

@ -137,7 +137,7 @@ void PollUdp(void)
}
#ifdef USE_DEVICE_GROUPS
if (Settings.flag.device_groups_enabled && !strncmp_P(packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) {
if (Settings.flag4.device_groups_enabled && !strncmp_P(packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) {
ProcessDeviceGroupMessage(packet_buffer, len);
}
#endif // USE_DEVICE_GROUPS

View File

@ -560,7 +560,7 @@ void WifiCheck(uint8_t param)
}
#ifdef USE_EMULATION
#ifdef USE_DEVICE_GROUPS
if (Settings.flag2.emulation || Settings.flag.device_groups_enabled) { UdpConnect(); }
if (Settings.flag2.emulation || Settings.flag4.device_groups_enabled) { UdpConnect(); }
#else // USE_DEVICE_GROUPS
if (Settings.flag2.emulation) { UdpConnect(); }
#endif // USE_DEVICE_GROUPS

View File

@ -290,9 +290,6 @@ void setup(void)
#ifdef USE_ARDUINO_OTA
ArduinoOTAInit();
#endif // USE_ARDUINO_OTA
#ifdef USE_DEVICE_GROUPS
DeviceGroupsInit();
#endif // USE_DEVICE_GROUPS
XdrvCall(FUNC_INIT);
XsnsCall(FUNC_INIT);

View File

@ -73,6 +73,16 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#define MODULE SONOFF_BASIC // [Module] Select default model
#endif
#ifdef USE_PWM_DIMMER_REMOTE
#ifdef USE_PWM_DIMMER
#ifndef USE_DEVICE_GROUPS
#define USE_DEVICE_GROUPS
#endif // USE_DEVICE_GROUPS
#else // USE_PWM_DIMMER
#undef USE_PWM_DIMMER_REMOTE
#endif // USE_PWM_DIMMER
#endif // USE_PWM_DIMMER_REMOTE
/*********************************************************************************************\
* [tasmota-sensors.bin]
* Provide an image with useful supported sensors enabled
@ -249,6 +259,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem)
#undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common)
#undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common)
#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code)
#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer
#undef DEBUG_THEO // Disable debug code
#undef USE_DEBUG_DRIVER // Disable debug code
#endif // FIRMWARE_KNX_NO_EMULATION
@ -286,6 +298,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code)
#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer
#undef USE_HOTPLUG // Disable support for HotPlug
#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code)
#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer
#undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code)
#undef USE_PZEM004T // Disable PZEM004T energy sensor
@ -362,6 +376,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code)
#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer
#undef USE_HOTPLUG // Disable support for HotPlug
#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code)
#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer
// -- Optional light modules ----------------------
//#undef USE_LIGHT // Also disable all Dimmer/Light support
@ -583,6 +599,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code)
#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer
#undef USE_HOTPLUG // Disable support for HotPlug
#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code)
#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer
// -- Optional light modules ----------------------
#undef USE_LIGHT // Disable support for lights
@ -711,16 +729,6 @@ const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE;
uint8_t device_group_count = 1;
#endif // USE_DEVICE_GROUPS
#ifdef USE_PWM_DIMMER_REMOTE
#ifdef USE_PWM_DIMMER
#ifndef USE_DEVICE_GROUPS
#define USE_DEVICE_GROUPS
#endif // USE_DEVICE_GROUPS
#else // USE_PWM_DIMMER
#undef USE_PWM_DIMMER_REMOTE
#endif // USE_PWM_DIMMER
#endif // USE_PWM_DIMMER_REMOTE
#ifdef DEBUG_TASMOTA_CORE
#define DEBUG_CORE_LOG(...) AddLog_Debug(__VA_ARGS__)
#else

View File

@ -2982,7 +2982,7 @@ bool Xdrv01(uint8_t function)
PollDnsWebserver();
#ifdef USE_EMULATION
#ifdef USE_DEVICE_GROUPS
if (Settings.flag2.emulation || Settings.flag.device_groups_enabled) { PollUdp(); }
if (Settings.flag2.emulation || Settings.flag4.device_groups_enabled) { PollUdp(); }
#else // USE_DEVICE_GROUPS
if (Settings.flag2.emulation) { PollUdp(); }
#endif // USE_DEVICE_GROUPS