Merge pull request #8093 from pcdiem/devgroupsend

Add DevGroupSend command
This commit is contained in:
Theo Arends 2020-04-08 08:50:17 +02:00 committed by GitHub
commit 83122f7d09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 341 additions and 53 deletions

View File

@ -13,7 +13,7 @@ To enable device groups, execute the command SetOption85 1.
The device group name is set with the DevGroupName command. If the device group name is not set for a group, the MQTT group topic is used (with the device group number appended for device group numbers > 1). All devices in the same IP network with the same device group name 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 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).
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 it’s 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
@ -26,13 +26,6 @@ The items that are sent to the group and the items that are received from the gr
<td><strong>Parameters</strong>
</td>
</tr>
<tr>
<td>DevGroupShare
</td>
<td>&lt;in>,&lt;out> = set incoming and outgoing shared item mask (default = 0xffffffff,0xffffffff)<br>
1 = Power, 2 = Light brightness, 4 = Light fade/speed, 8 = Light scheme, 16 = Light color, 32 = Dimmer settings (presets)
</td>
</tr>
<tr>
<td>DevGroupName&lt;x>
</td>
@ -40,4 +33,100 @@ The items that are sent to the group and the items that are received from the gr
&lt;value> = set device group &lt;x> name and restart
</td>
</tr>
</tr>
<tr>
<td>DevGroupSend&lt;x>
</td>
<td>&lt;item>=&lt;value>[ ...] = send an update to device grouup &lt;x>. The device group name must have been previously set with DevGroupName&lt;x>. Multiple items/value pairs can be specified separated by a space. For example, DevGroupSend 4=90 128=1 will send an update to set the light brightness to 90 and turn relay 1 on.<br>
<br>
For items with numeric values, &lt;value> can be specified as @&lt;operator>&lt;value> to send a value after performing an operation on the current value. &lt;operator> can be + (add), - (subtract) or ^ (invert). If a value is not specified for the invert operator, 0xffffffff is used. For example, if the group's current light brightness is 40, DevGroupSend 4=@10 will send an update to increase the light brightness to 50. If all the groups relays are currently on, DevGroupSend 128=^ will turn all the relays off.<br><br>
<table>
<tr>
<td><strong>Item</strong>
</td>
<td><strong>Description</strong>
</td>
<td><strong>Value</strong>
</td>
</tr>
<tr>
<td>2
</td>
<td>Light fade
</td>
<td>0 = Off<br>1 = On
</tr>
<tr>
<td>3
</td>
<td>Light speed
</td>
<td>1..40
</tr>
<tr>
<td>4
</td>
<td>Light brightness
</td>
<td>0..255
</tr>
<tr>
<td>5
</td>
<td>Light scheme
</td>
<td>See Scheme command in <a href="https://tasmota.github.io/docs/Commands/#light">Light Commands</a>
</tr>
<tr>
<td>6
</td>
<td>Light fixed color
</td>
<td>0 = white (using CT channels), 1 = red, 2 = green, 3 = blue, 4 = orange, 5 = light green, 6 = light blue, 7 = amber, 8 = cyan, 9 = purple, 10 = yellow, 11 = pink, 12 = white (using RGB channels)
</tr>
<tr>
<td>7
</td>
<td>PWM dimmer low preset
</td>
<td>0..255
</tr>
<tr>
<td>8
</td>
<td>PWM dimmer high preset
</td>
<td>0..255
</tr>
<tr>
<td>9
</td>
<td>PWM dimmer power-on brightness
</td>
<td>0..255
</tr>
<tr>
<td>128
</td>
<td>Relay Power
</td>
<td>Bitmask with bits set for relays to be powered on. The number of relays can be specified in bits 24 - 31. If the number of relays is not specified, only relay 1 is set.
</tr>
<tr>
<td>224
</td>
<td>Light channels
</td>
<td>Comma separated list of brightness levels (0..255) for channels 1 - 5 (e.g. 255,128,0,0,0 will turn the red channel on at 100% and the green channel on at 50% on an RBG light).
</tr>
</table>
</td>
</tr>
</tr>
<tr>
<td>DevGroupShare
</td>
<td>&lt;in>,&lt;out> = set incoming and outgoing shared item mask (default = 0xffffffff,0xffffffff)<br>
1 = Power, 2 = Light brightness, 4 = Light fade/speed, 8 = Light scheme, 16 = Light color, 32 = Dimmer settings (presets)
</td>
</table>

View File

@ -294,6 +294,7 @@
#define D_CMND_I2CSCAN "I2CScan"
#define D_CMND_I2CDRIVER "I2CDriver"
#define D_CMND_DEVGROUP_NAME "DevGroupName"
#define D_CMND_DEVGROUP_SEND "DevGroupSend"
#define D_CMND_DEVGROUP_SHARE "DevGroupShare"
#define D_CMND_SERIALSEND "SerialSend"
#define D_CMND_SERIALDELIMITER "SerialDelimiter"

View File

@ -416,9 +416,10 @@
#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 (+5k6 code)
#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_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 (+1k1 code plus device groups size)
#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)
#define USE_SONOFF_D1 // Add support for Sonoff D1 Dimmer (+0k7 code)

View File

@ -32,7 +32,11 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|"
#endif
#ifdef USE_DEVICE_GROUPS
D_CMND_DEVGROUP_NAME "|" D_CMND_DEVGROUP_SHARE "|"
D_CMND_DEVGROUP_NAME "|"
#ifdef USE_DEVICE_GROUPS_SEND
D_CMND_DEVGROUP_SEND "|"
#endif // USE_DEVICE_GROUPS_SEND
D_CMND_DEVGROUP_SHARE "|"
#endif // USE_DEVICE_GROUPS
D_CMND_SENSOR "|" D_CMND_DRIVER;
@ -51,7 +55,11 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
&CmndI2cScan, CmndI2cDriver,
#endif
#ifdef USE_DEVICE_GROUPS
&CmndDevGroupName, &CmndDevGroupShare,
&CmndDevGroupName,
#ifdef USE_DEVICE_GROUPS_SEND
&CmndDevGroupSend,
#endif // USE_DEVICE_GROUPS_SEND
&CmndDevGroupShare,
#endif // USE_DEVICE_GROUPS
&CmndSensor, &CmndDriver };
@ -1722,6 +1730,17 @@ void CmndDevGroupName(void)
}
}
#ifdef USE_DEVICE_GROUPS_SEND
void CmndDevGroupSend(void)
{
uint8_t device_group_index = (XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0);
if (device_group_index < device_group_count) {
_SendDeviceGroupMessage(device_group_index, DGR_MSGTYPE_UPDATE_COMMAND);
ResponseCmndChar(XdrvMailbox.data);
}
}
#endif // USE_DEVICE_GROUPS_SEND
void CmndDevGroupShare(void)
{
uint32_t parm[2] = { Settings.device_group_share_in, Settings.device_group_share_out };

View File

@ -49,6 +49,11 @@ struct device_group {
char message[128];
uint8_t group_member_count;
struct device_group_member * device_group_members;
#ifdef USE_DEVICE_GROUPS_SEND
uint8_t values_8bit[DGR_ITEM_LAST_8BIT];
uint16_t values_16bit[DGR_ITEM_LAST_16BIT - DGR_ITEM_MAX_8BIT - 1];
uint32_t values_32bit[DGR_ITEM_LAST_32BIT - DGR_ITEM_MAX_16BIT - 1];
#endif // USE_DEVICE_GROUPS_SEND
};
struct device_group * device_groups;
@ -62,6 +67,12 @@ bool udp_was_connected = false;
void DeviceGroupsInit(void)
{
// If there are more device group names set than the number of device groups needed by the
// mdoule, use the device group name count as the device group count.
for (; device_group_count < MAX_DEV_GROUP_NAMES; device_group_count++) {
if (!*SettingsText(SET_DEV_GROUP_NAME1 + device_group_count)) break;
}
// Initialize the device information for each device group.
device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group));
if (device_groups == nullptr) {
@ -117,7 +128,7 @@ char * BeginDeviceGroupMessage(struct device_group * device_group, uint16_t flag
}
// Return true if we're configured to share the specified item.
bool DevGroupItemShared(bool incoming, uint8_t item)
bool DeviceGroupItemShared(bool incoming, uint8_t item)
{
uint8_t mask = 0;
switch (item) {
@ -169,7 +180,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) return;
if (processing_remote_device_message && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return;
// Get a pointer to the device information for this device.
device_group * device_group = &device_groups[device_group_index];
@ -194,6 +205,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
#endif // DEVICE_GROUPS_DEBUG
device_group->message_length = 0;
SendDeviceGroupMessage(device_group_index, 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);
@ -211,16 +223,25 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
}
else {
#ifdef USE_DEVICE_GROUPS_SEND
bool use_command;
char oper;
uint32_t old_value;
char * delim_ptr;
#endif // USE_DEVICE_GROUPS_SEND
bool shared;
uint8_t item;
uint32_t value;
uint8_t * value_ptr;
char * value_ptr;
va_list ap;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s packet"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
#ifdef USE_DEVICE_GROUPS_SEND
use_command = (message_type == DGR_MSGTYPE_UPDATE_COMMAND);
#endif // USE_DEVICE_GROUPS_SEND
value = 0;
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME)
value |= DGR_FLAG_MORE_TO_COME;
@ -241,9 +262,29 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
int kept_item_count = 0;
// Build an array of all the items in this new update.
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command)
value_ptr = XdrvMailbox.data;
else
#endif // USE_DEVICE_GROUPS_SEND
va_start(ap, message_type);
#ifdef USE_DEVICE_GROUPS_SEND
while (use_command ? (item = strtoul(value_ptr, &delim_ptr, 0)) : (item = va_arg(ap, int))) {
#else // USE_DEVICE_GROUPS_SEND
while ((item = va_arg(ap, int))) {
#endif // !USE_DEVICE_GROUPS_SEND
item_array[item_index++] = item;
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command) {
if (!*delim_ptr) break;
if (*delim_ptr == '=') {
delim_ptr = strchr(delim_ptr, ' ');
if (!delim_ptr) break;
}
value_ptr = delim_ptr + 1;
}
else {
#endif // USE_DEVICE_GROUPS_SEND
if (item <= DGR_ITEM_MAX_32BIT)
va_arg(ap, int);
else if (item <= DGR_ITEM_MAX_STRING)
@ -255,12 +296,19 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
break;
}
}
#ifdef USE_DEVICE_GROUPS_SEND
}
#endif // USE_DEVICE_GROUPS_SEND
}
#ifdef USE_DEVICE_GROUPS_SEND
if (!use_command) va_end(ap);
#else // USE_DEVICE_GROUPS_SEND
va_end(ap);
#endif // !USE_DEVICE_GROUPS_SEND
item_array[item_index] = 0;
// Rebuild the previous update message, removing any items their values that are included in
// this new update.
// Rebuild the previous update message, removing any items whose values are included in this
// new update.
char * previous_message_ptr = message_ptr;
while (item = *previous_message_ptr++) {
@ -329,32 +377,107 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
}
// Itertate through the passed items adding them and their values to the message.
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command)
value_ptr = XdrvMailbox.data;
else
#endif // USE_DEVICE_GROUPS_SEND
va_start(ap, message_type);
#ifdef USE_DEVICE_GROUPS_SEND
while (use_command ? (item = strtoul(value_ptr, &delim_ptr, 0)) : (item = va_arg(ap, int))) {
#else // !USE_DEVICE_GROUPS_SEND
while ((item = va_arg(ap, int))) {
shared = DevGroupItemShared(false, item);
#endif // !USE_DEVICE_GROUPS_SEND
// Find out if this item is shared with the group and add the item code to the message if yes.
shared = true;
if (!device_group_index) shared = DeviceGroupItemShared(false, item);
if (shared) *message_ptr++ = item;
#ifdef USE_DEVICE_GROUPS_SEND
// If we're processing a command, get a pointer to the value if one was specified.
if (use_command) value_ptr = (*delim_ptr == '=' ? delim_ptr + 1 : nullptr);
#endif // USE_DEVICE_GROUPS_SEND
// For numeric items, get the specified value.
if (item <= DGR_ITEM_MAX_32BIT) {
#ifdef USE_DEVICE_GROUPS_SEND
// If we're processing a command, get the final value after processing any specified
// operators.
if (use_command) {
value = 0;
if (value_ptr) {
oper = 0;
if (*value_ptr == '@') {
oper = value_ptr[1];
value_ptr += 2;
}
value = strtoul(value_ptr, nullptr, 0);
if (oper) {
old_value = (item <= DGR_ITEM_MAX_8BIT ? device_group->values_8bit[item] : (item <= DGR_ITEM_MAX_16BIT ? device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] : device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1]));
value = (oper == '+' ? old_value + value : (oper == '-' ? old_value - value : (oper == '^' ? old_value ^ (value ? value : 0xffffffff) : old_value)));
}
}
}
else
#endif // USE_DEVICE_GROUPS_SEND
value = va_arg(ap, int);
// If the item is shared, add it to the message.
if (shared) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u"), item, value);
#endif // DEVICE_GROUPS_DEBUG
*message_ptr++ = 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;
*message_ptr++ = (item == DGR_ITEM_POWER ? devices_present : value >> 8);
}
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 string to the message prefixed by the length.
else if (item <= DGR_ITEM_MAX_STRING) {
value_ptr = va_arg(ap, uint8_t *);
#ifdef USE_DEVICE_GROUPS_SEND
if (!use_command)
#endif // USE_DEVICE_GROUPS_SEND
value_ptr = va_arg(ap, char *);
if (shared) {
value = strlen((const char *)value_ptr);
value = (value_ptr ? strlen((const char *)value_ptr) : 0);
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%s"), item, value_ptr);
#endif // DEVICE_GROUPS_DEBUG
@ -363,22 +486,59 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
message_ptr += value;
}
}
// For special items, handle them individually.
else {
switch (item) {
case DGR_ITEM_LIGHT_CHANNELS:
value_ptr = va_arg(ap, uint8_t *);
#ifdef USE_DEVICE_GROUPS_SEND
if (use_command) {
if (shared) {
for (int i = 0; i < 5; i++) {
value = 0;
if (value_ptr) {
value = strtoul(value_ptr, &value_ptr, 0);
value_ptr = (*value_ptr == ',' ? value_ptr + 1 : nullptr);
}
*message_ptr++ = value;
}
}
}
else {
#endif // USE_DEVICE_GROUPS_SEND
value_ptr = va_arg(ap, char *);
if (shared) {
#ifdef DEVICE_GROUPS_DEBUG
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;
}
#ifdef USE_DEVICE_GROUPS_SEND
}
#endif // USE_DEVICE_GROUPS_SEND
#ifdef DEVICE_GROUPS_DEBUG
if (shared) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u,%u,%u,%u,%u"), item, *(message_ptr - 5), *(message_ptr - 4), *(message_ptr - 3), *(message_ptr - 2), *(message_ptr - 1));
#endif // DEVICE_GROUPS_DEBUG
break;
}
}
#ifdef USE_DEVICE_GROUPS_SEND
// If we're processing a command, advance to the next item. If there are no more, break out of
// the loop.
if (use_command) {
if (!*delim_ptr) break;
if (*delim_ptr == '=') {
delim_ptr = strchr(delim_ptr, ' ');
if (!delim_ptr) break;
}
value_ptr = delim_ptr + 1;
}
#endif // USE_DEVICE_GROUPS_SEND
}
#ifdef USE_DEVICE_GROUPS_SEND
if (!use_command) va_end(ap);
#else // USE_DEVICE_GROUPS_SEND
va_end(ap);
#endif // !USE_DEVICE_GROUPS_SEND
// Add the EOL item code and calculate the message length.
*message_ptr++ = 0;
@ -571,8 +731,22 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
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, PSTR("<item=%u, value=%u"), item, value);
#endif // DEVICE_GROUPS_DEBUG
@ -600,7 +774,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
}
}
if (DevGroupItemShared(true, item)) {
if (DeviceGroupItemShared(true, item)) {
if (item == DGR_ITEM_POWER) {
if (device_group->local) {
uint8_t mask_devices = value >> 24;
@ -649,7 +823,7 @@ void DeviceGroupsLoop(void)
// Load the status request message for all device groups. This message will be multicast 5
// times.
next_check_time = now + 1000;
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->message_length = BeginDeviceGroupMessage(device_group, DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST) - device_group->message;
@ -679,10 +853,10 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
// If we're still sending the initial status request message, send it.
if (device_group->initial_status_requests_remaining) {
if (--device_group->initial_status_requests_remaining) {
#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
if (--device_group->initial_status_requests_remaining) {
SendDeviceGroupPacket(0, 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;
@ -765,7 +939,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
#endif // DEVICE_GROUPS_DEBUG
if (device_group->next_announcement_time <= now) {
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s announcement"), device_group->message_length, device_group->group_name);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending device group %s announcement"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(0, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, PSTR("Announcement"));
device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000);

View File

@ -306,7 +306,7 @@ enum SettingsTextIndex { SET_OTAURL,
SET_TEMPLATE_NAME, SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4,
SET_MAX };
enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYP_REUPDATE };
enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND };
enum DevGroupMessageFlag { DGR_FLAG_RESET = 1, DGR_FLAG_STATUS_REQUEST = 2, DGR_FLAG_FULL_STATUS = 4, DGR_FLAG_ACK = 8, DGR_FLAG_MORE_TO_COME = 16, DGR_FLAG_DIRECT = 32, DGR_FLAG_ANNOUNCEMENT = 64 };
@ -315,7 +315,7 @@ enum DevGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS,
DGR_ITEM_BRI_PRESET_LOW, DGR_ITEM_BRI_PRESET_HIGH, DGR_ITEM_BRI_POWER_ON,
// Add new 8-bit items before this line
DGR_ITEM_LAST_8BIT, DGR_ITEM_MAX_8BIT = 63,
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
DGR_ITEM_LAST_16BIT, DGR_ITEM_MAX_16BIT = 127,
DGR_ITEM_POWER, DGR_ITEM_DIMMER_RANGE,

View File

@ -68,6 +68,7 @@ bool button_hold_processed[3];
#ifdef USE_PWM_DIMMER_REMOTE
struct remote_pwm_dimmer * remote_pwm_dimmers;
struct remote_pwm_dimmer * active_remote_pwm_dimmer;
uint8_t remote_pwm_dimmer_count;
bool active_device_is_local;
#endif // USE_PWM_DIMMER_REMOTE
@ -106,8 +107,8 @@ void PWMModulePreInit(void)
if (pin[GPIO_KEY1 + button_index] < 99) device_group_count++;
}
if (device_group_count > 1) {
uint8_t remote_pwm_dimmer_count = device_group_count - 1;
remote_pwm_dimmer_count = device_group_count - 1;
if (remote_pwm_dimmer_count) {
if ((remote_pwm_dimmers = (struct remote_pwm_dimmer *) calloc(remote_pwm_dimmer_count, sizeof(struct remote_pwm_dimmer))) == nullptr) {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("PWMDimmer: error allocating PWM dimmer array"));
Settings.flag4.remote_device_mode = false;
@ -175,9 +176,12 @@ void PWMDimmerHandleDevGroupItem(void)
uint32_t value = XdrvMailbox.payload;
#ifdef USE_PWM_DIMMER_REMOTE
uint8_t device_group_index = *(uint8_t *)XdrvMailbox.topic;
if (device_group_index > remote_pwm_dimmer_count) return;
bool device_is_local = device_groups[device_group_index].local;
struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index];
#endif // USE_PWM_DIMMER_REMOTE
#else // USE_PWM_DIMMER_REMOTE
if (*(uint8_t *)XdrvMailbox.topic) return;
#endif // !USE_PWM_DIMMER_REMOTE
switch (XdrvMailbox.command_code) {
#ifdef USE_PWM_DIMMER_REMOTE