From fe62ceb0f9f03b19557179f77d70f5c847490264 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Mon, 27 Jan 2020 20:56:11 +0100 Subject: [PATCH] Add unbind for default_bind_group. https://github.com/Koenkk/zigbee2mqtt/issues/2772 --- lib/extension/deviceBind.js | 15 +++++++++++---- test/deviceBind.test.js | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/extension/deviceBind.js b/lib/extension/deviceBind.js index e9366f156..5fc2bf48b 100644 --- a/lib/extension/deviceBind.js +++ b/lib/extension/deviceBind.js @@ -6,6 +6,9 @@ const BaseExtension = require('./baseExtension'); const clusters = ['genScenes', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'closuresWindowCovering']; +// See zigbee-herdsman-converters devices.js +const defaultBindGroup = {type: 'group_number', ID: 901}; + class DeviceBind extends BaseExtension { onMQTTConnected() { for (let step = 1; step < 20; step++) { @@ -28,22 +31,26 @@ class DeviceBind extends BaseExtension { // Find source; can only be a device and target const source = this.zigbee.resolveEntity(sourceKey); assert(source != null && source.type === 'device', 'Source undefined or not a device'); - const target = this.zigbee.resolveEntity(targetKey); + const target = targetKey === 'default_bind_group' ? defaultBindGroup : this.zigbee.resolveEntity(targetKey); assert(target != null, 'Target is unknown'); const sourceName = source.settings.friendlyName; - const targetName = target.settings.friendlyName; + const targetName = targetKey === 'default_bind_group' ? targetKey : target.settings.friendlyName; // Find which clusters are supported by both the source and target. // Groups are assumed to support all clusters. for (const cluster of clusters) { - const targetValid = target.type === 'group' || + const targetValid = target.type === 'group' || target.type === 'group_number' || target.device.type === 'Coordinator' || target.endpoint.supportsInputCluster(cluster); if (source.endpoint.supportsOutputCluster(cluster) && targetValid) { logger.debug(`${type}ing cluster '${cluster}' from '${sourceName}' to '${targetName}'`); try { - const bindTarget = target.type === 'group' ? target.group : target.endpoint; + let bindTarget = null; + if (target.type === 'group') bindTarget = target.group; + else if (target.type === 'group_number') bindTarget = target.ID; + else bindTarget = target.endpoint; + if (type === 'bind') { await source.endpoint.bind(cluster, bindTarget); } else { diff --git a/test/deviceBind.test.js b/test/deviceBind.test.js index b450b7b9b..e73dd4001 100644 --- a/test/deviceBind.test.js +++ b/test/deviceBind.test.js @@ -15,6 +15,7 @@ describe('Device bind', () => { endpoint.write.mockClear(); endpoint.configureReporting.mockClear(); endpoint.bind.mockClear(); + endpoint.unbind.mockClear(); } } @@ -171,4 +172,24 @@ describe('Device bind', () => { expect(endpoint.bind).toHaveBeenCalledTimes(1); expect(endpoint.bind).toHaveBeenCalledWith("genOnOff", target); }); + + it('Should unbind from default_bind_group', async () => { + const device = zigbeeHerdsman.devices.remote; + const target = 'default_bind_group'; + const endpoint = device.getEndpoint(1); + mockClear(device); + MQTT.events.message('zigbee2mqtt/bridge/unbind/remote', target); + await flushPromises(); + expect(endpoint.unbind).toHaveBeenCalledTimes(3); + expect(endpoint.unbind).toHaveBeenCalledWith("genOnOff", 901); + expect(endpoint.unbind).toHaveBeenCalledWith("genLevelCtrl", 901); + expect(endpoint.unbind).toHaveBeenCalledWith("genScenes", 901); + expect(MQTT.publish).toHaveBeenCalledTimes(3); + expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/bridge/log'); + expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({type: 'device_unbind', message: {from: 'remote', to: 'default_bind_group', cluster: 'genScenes'}}); + expect(MQTT.publish.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/bridge/log'); + expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({type: 'device_unbind', message: {from: 'remote', to: 'default_bind_group', cluster: 'genOnOff'}}); + expect(MQTT.publish.mock.calls[2][0]).toStrictEqual('zigbee2mqtt/bridge/log'); + expect(JSON.parse(MQTT.publish.mock.calls[2][1])).toStrictEqual({type: 'device_unbind', message: {from: 'remote', to: 'default_bind_group', cluster: 'genLevelCtrl'}}); + }); });