diff --git a/lib/extension/bridgeConfig.js b/lib/extension/bridgeConfig.js index b4d5899cd..2c765dbdb 100644 --- a/lib/extension/bridgeConfig.js +++ b/lib/extension/bridgeConfig.js @@ -5,7 +5,8 @@ const utils = require('../util/utils'); const assert = require('assert'); const BaseExtension = require('./baseExtension'); -const configRegex = new RegExp(`${settings.get().mqtt.base_topic}/bridge/config/((?:\\w+/get)|(?:\\w+))`); +const configRegex = + new RegExp(`${settings.get().mqtt.base_topic}/bridge/config/((?:\\w+/get)|(?:\\w+/factory_reset)|(?:\\w+))`); const allowedLogLevels = ['error', 'warn', 'info', 'debug']; class BridgeConfig extends BaseExtension { @@ -27,7 +28,8 @@ class BridgeConfig extends BaseExtension { this.deviceOptions = this.deviceOptions.bind(this); this.addGroup = this.addGroup.bind(this); this.removeGroup = this.removeGroup.bind(this); - this.whitelist= this.whitelist.bind(this); + this.whitelist = this.whitelist.bind(this); + this.touchlinkFactoryReset = this.touchlinkFactoryReset.bind(this); // Set supported options this.supportedOptions = { @@ -47,6 +49,7 @@ class BridgeConfig extends BaseExtension { 'add_group': this.addGroup, 'remove_group': this.removeGroup, 'whitelist': this.whitelist, + 'touchlink/factory_reset': this.touchlinkFactoryReset, }; } @@ -293,6 +296,7 @@ class BridgeConfig extends BaseExtension { async onMQTTConnected() { this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/config/+`); + this.mqtt.subscribe(`${settings.get().mqtt.base_topic}/bridge/config/+/+`); await this.publish(); } @@ -326,6 +330,17 @@ class BridgeConfig extends BaseExtension { await this.mqtt.publish(topic, JSON.stringify(payload), {retain: true, qos: 0}); } + + async touchlinkFactoryReset() { + logger.info('Starting touchlink factory reset...'); + const result = await this.zigbee.touchlinkFactoryReset(); + + if (result) { + logger.info('Succesfully factory reset device through Touchlink'); + } else { + logger.warn('Failed to factory reset device through Touchlink'); + } + } } module.exports = BridgeConfig; diff --git a/lib/zigbee.js b/lib/zigbee.js index 6d6b159fa..258cb7545 100644 --- a/lib/zigbee.js +++ b/lib/zigbee.js @@ -237,6 +237,10 @@ class Zigbee extends events.EventEmitter { return true; } } + + async touchlinkFactoryReset() { + return this.herdsman.touchlinkFactoryReset(); + } } module.exports = Zigbee; diff --git a/test/bridgeConfig.test.js b/test/bridgeConfig.test.js index 0cc81e08a..800b07055 100644 --- a/test/bridgeConfig.test.js +++ b/test/bridgeConfig.test.js @@ -22,6 +22,8 @@ describe('Bridge config', () => { data.writeDefaultConfiguration(); settings._reRead(); data.writeDefaultState(); + logger.info.mockClear(); + logger.warn.mockClear(); }); it('Should publish bridge configuration on startup', async () => { @@ -355,4 +357,24 @@ describe('Bridge config', () => { expect(settings.getDevice('bulb_color')).toStrictEqual({"ID": "0x000b57fffec6a5b3", "friendlyName": "bulb_color", "friendly_name": "bulb_color", "retain": false}) expect(MQTT.publish).toHaveBeenCalledTimes(0); }); + + it('Should allow to touchlink factory reset (OK)', async () => { + zigbeeHerdsman.touchlinkFactoryReset.mockClear(); + + zigbeeHerdsman.touchlinkFactoryReset.mockReturnValueOnce(true); + MQTT.events.message('zigbee2mqtt/bridge/config/touchlink/factory_reset', ''); + await flushPromises(); + expect(zigbeeHerdsman.touchlinkFactoryReset).toHaveBeenCalledTimes(1); + expect(logger.info).toHaveBeenCalledWith('Succesfully factory reset device through Touchlink'); + }); + + it('Should allow to touchlink factory reset (FAILS)', async () => { + zigbeeHerdsman.touchlinkFactoryReset.mockClear(); + + zigbeeHerdsman.touchlinkFactoryReset.mockReturnValueOnce(false); + MQTT.events.message('zigbee2mqtt/bridge/config/touchlink/factory_reset', ''); + await flushPromises(); + expect(zigbeeHerdsman.touchlinkFactoryReset).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith('Failed to factory reset device through Touchlink'); + }); }); diff --git a/test/stub/zigbeeHerdsman.js b/test/stub/zigbeeHerdsman.js index fd36c8bc4..99f2da7fa 100644 --- a/test/stub/zigbeeHerdsman.js +++ b/test/stub/zigbeeHerdsman.js @@ -139,6 +139,7 @@ const groups = { } const mock = { + touchlinkFactoryReset: jest.fn(), start: jest.fn(), permitJoin: jest.fn(), getCoordinatorVersion: jest.fn().mockReturnValue({type: 'z-Stack', meta: {version: 1, revision: 20190425}}),