diff --git a/lib/extension/groups.js b/lib/extension/groups.js index 40d6c539..07c622cd 100644 --- a/lib/extension/groups.js +++ b/lib/extension/groups.js @@ -12,10 +12,14 @@ class Groups extends BaseExtension { } onMQTTConnected() { - this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/group/+/remove`); - this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/group/+/add`); - this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/group/+/remove_all`); this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/group/remove_all`); + + for (let step = 1; step < 20; step++) { + const topic = `${settings.get().mqtt.base_topic}/bridge/group/${'+/'.repeat(step)}`; + this.mqtt.subscribe(`${topic}remove`); + this.mqtt.subscribe(`${topic}add`); + this.mqtt.subscribe(`${topic}remove_all`); // DEPRECATED + } } async onZigbeeStarted() { diff --git a/test/entityPublish.test.js b/test/entityPublish.test.js index 021d9c88..05d0e19e 100644 --- a/test/entityPublish.test.js +++ b/test/entityPublish.test.js @@ -353,10 +353,10 @@ describe('Entity publish', () => { it('Should create and publish to group which is in configuration.yaml but not in zigbee-herdsman', async () => { delete zigbeeHerdsman.groups.group_2; - expect(Object.values(zigbeeHerdsman.groups).length).toBe(2); + expect(Object.values(zigbeeHerdsman.groups).length).toBe(3); await MQTT.events.message('zigbee2mqtt/group_2/set', JSON.stringify({state: 'ON'})); await flushPromises(); - expect(Object.values(zigbeeHerdsman.groups).length).toBe(3); + expect(Object.values(zigbeeHerdsman.groups).length).toBe(4); expect(zigbeeHerdsman.groups.group_2.command).toHaveBeenCalledTimes(1); expect(zigbeeHerdsman.groups.group_2.command).toHaveBeenCalledWith("genOnOff", "on", {}, {}); }); diff --git a/test/group.test.js b/test/group.test.js index 908c0c5f..65a491df 100644 --- a/test/group.test.js +++ b/test/group.test.js @@ -93,6 +93,27 @@ describe('Groups', () => { expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bridge/log", '{"type":"device_group_add","message":{"friendly_name":"bulb_color","group":"group_1"}}', {"retain": false, qos: 0}, expect.any(Function)); }); + it('Add to group with slashes via MQTT', async () => { + const device = zigbeeHerdsman.devices.bulb_color; + const endpoint = device.getEndpoint(1); + const group = zigbeeHerdsman.groups["group/with/slashes"]; + settings.set(['groups'], {'99': {friendly_name: 'group/with/slashes', retain: false, devices: []}}); + expect(group.members.length).toBe(0); + await controller.start(); + await flushPromises(); + MQTT.events.message('zigbee2mqtt/bridge/group/group/with/slashes/add', 'bulb_color'); + await flushPromises(); + expect(group.members).toStrictEqual([endpoint]); + expect(settings.getGroup('group/with/slashes').devices).toStrictEqual([`${device.ieeeAddr}/1`]); + expect(MQTT.publish).toHaveBeenCalledWith("zigbee2mqtt/bridge/log", '{"type":"device_group_add","message":{"friendly_name":"bulb_color","group":"group/with/slashes"}}', {"retain": false, qos: 0}, expect.any(Function)); + + // Test if subscribed to topics with slashes + expect(MQTT.subscribe).toHaveBeenCalledWith('zigbee2mqtt/bridge/group/+/remove'); + expect(MQTT.subscribe).toHaveBeenCalledWith('zigbee2mqtt/bridge/group/+/+/remove'); + expect(MQTT.subscribe).toHaveBeenCalledWith('zigbee2mqtt/bridge/group/+/+/+/+/+/remove'); + expect(MQTT.subscribe).toHaveBeenCalledWith('zigbee2mqtt/bridge/group/+/+/+/+/+/add'); + }); + it('Add to group via MQTT with postfix', async () => { const device = zigbeeHerdsman.devices.QBKG03LM; const endpoint = device.getEndpoint(3); diff --git a/test/stub/zigbeeHerdsman.js b/test/stub/zigbeeHerdsman.js index f0a8decf..0b07f02c 100644 --- a/test/stub/zigbeeHerdsman.js +++ b/test/stub/zigbeeHerdsman.js @@ -132,6 +132,7 @@ const devices = { const groups = { 'group_1': new Group(1, []), 'group_tradfri_remote': new Group(15071, [bulb_color_2.endpoints[0], bulb_2.endpoints[0]]), + 'group/with/slashes': new Group(99, []), } const mock = {