mirror of https://github.com/arendst/Tasmota.git
Merge pull request #8093 from pcdiem/devgroupsend
Add DevGroupSend command
This commit is contained in:
commit
83122f7d09
107
Device_Groups.md
107
Device_Groups.md
|
@ -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 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).
|
||||
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,18 +26,107 @@ 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>DevGroupName<x>
|
||||
</td>
|
||||
<td>0 = clear device group <x> name and restart<br>
|
||||
<value> = set device group <x> name and restart
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DevGroupSend<x>
|
||||
</td>
|
||||
<td><item>=<value>[ ...] = send an update to device grouup <x>. The device group name must have been previously set with DevGroupName<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, <value> can be specified as @<operator><value> to send a value after performing an operation on the current value. <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><in>,<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<x>
|
||||
</td>
|
||||
<td>0 = clear device group <x> name and restart<br>
|
||||
<value> = set device group <x>name and restart
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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,26 +262,53 @@ 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.
|
||||
va_start(ap, message_type);
|
||||
#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;
|
||||
if (item <= DGR_ITEM_MAX_32BIT)
|
||||
va_arg(ap, int);
|
||||
else if (item <= DGR_ITEM_MAX_STRING)
|
||||
va_arg(ap, char *);
|
||||
else {
|
||||
switch (item) {
|
||||
case DGR_ITEM_LIGHT_CHANNELS:
|
||||
va_arg(ap, uint8_t *) ;
|
||||
break;
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
if (use_command) {
|
||||
if (!*delim_ptr) break;
|
||||
if (*delim_ptr == '=') {
|
||||
delim_ptr = strchr(delim_ptr, ' ');
|
||||
if (!delim_ptr) break;
|
||||
}
|
||||
value_ptr = delim_ptr + 1;
|
||||
}
|
||||
else {
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
if (item <= DGR_ITEM_MAX_32BIT)
|
||||
va_arg(ap, int);
|
||||
else if (item <= DGR_ITEM_MAX_STRING)
|
||||
va_arg(ap, char *);
|
||||
else {
|
||||
switch (item) {
|
||||
case DGR_ITEM_LIGHT_CHANNELS:
|
||||
va_arg(ap, uint8_t *);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
}
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
if (!use_command) va_end(ap);
|
||||
#else // USE_DEVICE_GROUPS_SEND
|
||||
va_end(ap);
|
||||
#endif // !USE_DEVICE_GROUPS_SEND
|
||||
item_array[item_index] = 0;
|
||||
|
||||
// Rebuild the previous update message, removing any items 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.
|
||||
va_start(ap, message_type);
|
||||
#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) {
|
||||
value = va_arg(ap, int);
|
||||
|
||||
#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;
|
||||
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
|
||||
}
|
||||
if (item > DGR_ITEM_MAX_16BIT) {
|
||||
value >>= 8;
|
||||
*message_ptr++ = value & 0xff;
|
||||
*message_ptr++ = (item == DGR_ITEM_POWER ? devices_present : value >> 8);
|
||||
#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 *);
|
||||
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
|
||||
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) {
|
||||
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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue