From 7b7f511dc7b91f3d30ae410fb4eb40471854f9bc Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Tue, 22 Jun 2021 22:45:12 +0200 Subject: [PATCH] Fix non supported color_mode and color properties being published for group members. https://github.com/Koenkk/zigbee2mqtt/issues/7220 https://github.com/Koenkk/zigbee2mqtt/issues/7736 --- lib/extension/groups.js | 29 +++++++++++++++++++++++++---- test/group.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/lib/extension/groups.js b/lib/extension/groups.js index 2b9990b1..39abe1c3 100644 --- a/lib/extension/groups.js +++ b/lib/extension/groups.js @@ -11,6 +11,21 @@ const topicRegex = const legacyTopicRegex = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/group/(.+)/(remove|add|remove_all)$`); const legacyTopicRegexRemoveAll = new RegExp(`^${settings.get().mqtt.base_topic}/bridge/group/remove_all$`); +const stateProperties = { + 'state': (value, definition) => true, + 'brightness': (value, definition) => + definition.exposes.find((e) => e.type === 'light' && e.features.find((f) => f.name === 'brightness')), + 'color_temp': (value, definition) => + definition.exposes.find((e) => e.type === 'light' && e.features.find((f) => f.name === 'color_temp')), + 'color': (value, definition) => + definition.exposes.find((e) => e.type === 'light' && + e.features.find((f) => f.name === 'color_xy' || f.name === 'color_hs')), + 'color_mode': (value, definition) => + definition.exposes.find((e) => e.type === 'light' && ( + (e.features.find((f) => f.name === `color_${value}`)) || + (value === 'color_temp' && e.features.find((f) => f.name === 'color_temp')) )), +}; + class Groups extends Extension { constructor(zigbee, mqtt, state, publishEntityState, eventBus) { super(zigbee, mqtt, state, publishEntityState, eventBus); @@ -82,7 +97,6 @@ class Groups extends Extension { return; } - const properties = ['state', 'brightness', 'color_temp', 'color', 'color_mode']; const payload = {}; let endpointName; @@ -93,7 +107,7 @@ class Groups extends Extension { endpointName = endpointNameMatch; } - if (properties.includes(prop)) { + if (prop in stateProperties) { payload[prop] = value; } } @@ -121,8 +135,15 @@ class Groups extends Extension { const groupIDsToPublish = new Set(); for (const member of resolvedEntity.group.members) { - const memberPayload = {...payload}; - const endpointName = this.zigbee.resolveEntity(member).endpointName; + const resolvedEntity = this.zigbee.resolveEntity(member); + const memberPayload = {}; + Object.keys(payload).forEach((key) => { + if (stateProperties[key](payload[key], resolvedEntity.definition)) { + memberPayload[key] = payload[key]; + } + }); + + const endpointName = resolvedEntity.endpointName; if (endpointName) { Object.keys(memberPayload).forEach((key) => { memberPayload[`${key}_${endpointName}`] = memberPayload[key]; diff --git a/test/group.test.js b/test/group.test.js index f36e0b89..54900239 100644 --- a/test/group.test.js +++ b/test/group.test.js @@ -874,4 +874,31 @@ describe('Groups', () => { {retain: false, qos: 0}, expect.any(Function) ); }); + + it('onlythis Should only include relevant properties when publishing member states', async () => { + const bulbColor = zigbeeHerdsman.devices.bulb_color; + const bulbColorTemp = zigbeeHerdsman.devices.bulb; + const group = zigbeeHerdsman.groups.group_1; + group.members.push(bulbColor.getEndpoint(1)); + group.members.push(bulbColorTemp.getEndpoint(1)); + settings.set(['groups'], {'1': {friendly_name: 'group_1', retain: false, devices: [bulbColor.ieeeAddr, bulbColorTemp.ieeeAddr]}}); + await controller.start(); + await flushPromises(); + + MQTT.publish.mockClear(); + await MQTT.events.message('zigbee2mqtt/group_1/set', stringify({color_temp: 50})); + await flushPromises(); + expect(MQTT.publish).toHaveBeenCalledTimes(3); + expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", stringify({"color_mode":"color_temp","color_temp":50}), {"retain": false, qos: 0}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/group_1", stringify({"color_mode":"color_temp","color_temp":50}), {"retain": false, qos: 0}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb", stringify({"color_mode":"color_temp","color_temp":50}), {"retain": true, qos: 0}, expect.any(Function)); + + MQTT.publish.mockClear(); + await MQTT.events.message('zigbee2mqtt/group_1/set', stringify({color: {x: 0.5, y: 0.3}})); + await flushPromises(); + expect(MQTT.publish).toHaveBeenCalledTimes(3); + expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb_color", stringify({"color":{"x":0.5,"y":0.3},"color_mode":"xy","color_temp":548}), {"retain": false, qos: 0}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/group_1", stringify({"color":{"x":0.5,"y":0.3},"color_mode":"xy","color_temp":548}), {"retain": false, qos: 0}, expect.any(Function)); + expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bulb", stringify({"color_mode":"color_temp","color_temp":548}), {"retain": true, qos: 0}, expect.any(Function)); + }); });