Touchlink factory reset specific device and scan. https://github.com/Koenkk/zigbee2mqtt/issues/3281

This commit is contained in:
Koen Kanters
2020-09-08 20:24:49 +02:00
parent b94c5d7283
commit 14da75f4a7
4 changed files with 72 additions and 11 deletions
+25 -3
View File
@@ -30,6 +30,7 @@ class Bridge extends Extension {
'config/elapsed': this.configElapsed.bind(this),
'config/log_level': this.configLogLevel.bind(this),
'touchlink/factory_reset': this.touchlinkFactoryReset.bind(this),
'touchlink/scan': this.touchlinkScan.bind(this),
'health_check': this.healthCheck.bind(this),
};
}
@@ -218,17 +219,38 @@ class Bridge extends Extension {
}
async touchlinkFactoryReset(message) {
logger.info('Start touchlink factory reset');
const result = await this.zigbee.touchlinkFactoryReset();
let result = false;
const payload = {};
if (typeof message === 'object' && message.hasOwnProperty('ieee_address') &&
message.hasOwnProperty('channel')) {
logger.info(`Start Touchlink factory reset of '${message.ieee_address}' on channel ${message.channel}`);
result = await this.zigbee.touchlinkFactoryReset(message.ieee_address, message.channel);
payload.ieee_address = message.ieee_address;
payload.channel = message.channel;
} else {
logger.info('Start Touchlink factory reset of first found device');
result = await this.zigbee.touchlinkFactoryResetFirst();
}
if (result) {
logger.info('Successfully factory reset device through Touchlink');
return utils.getResponse(message, {}, null);
return utils.getResponse(message, payload, null);
} else {
logger.error('Failed to factory reset device through Touchlink');
throw new Error('Failed to factory reset device through Touchlink');
}
}
async touchlinkScan(message) {
logger.info('Start Touchlink scan');
const result = await this.zigbee.touchlinkScan();
const found = result.map((r) => {
return {ieee_address: r.ieeeAddr, channel: r.channel};
});
logger.info('Finished Touchlink scan');
return utils.getResponse(message, {found}, null);
}
/**
* Utils
*/
+10 -2
View File
@@ -287,8 +287,16 @@ class Zigbee extends events.EventEmitter {
}
}
async touchlinkFactoryReset() {
return this.herdsman.touchlinkFactoryReset();
async touchlinkFactoryResetFirst() {
return this.herdsman.touchlinkFactoryResetFirst();
}
async touchlinkFactoryReset(ieeeAddr, channel) {
return this.herdsman.touchlinkFactoryReset(ieeeAddr, channel);
}
async touchlinkScan() {
return this.herdsman.touchlinkScan();
}
}
+35 -6
View File
@@ -684,11 +684,11 @@ describe('Bridge', () => {
it('Should allow to touchlink factory reset (succeeds)', async () => {
MQTT.publish.mockClear();
zigbeeHerdsman.touchlinkFactoryReset.mockClear();
zigbeeHerdsman.touchlinkFactoryReset.mockReturnValueOnce(true);
zigbeeHerdsman.touchlinkFactoryResetFirst.mockClear();
zigbeeHerdsman.touchlinkFactoryResetFirst.mockReturnValueOnce(true);
MQTT.events.message('zigbee2mqtt/bridge/request/touchlink/factory_reset', '');
await flushPromises();
expect(zigbeeHerdsman.touchlinkFactoryReset).toHaveBeenCalledTimes(1);
expect(zigbeeHerdsman.touchlinkFactoryResetFirst).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/touchlink/factory_reset',
stringify({"data":{},"status":"ok"}),
@@ -696,17 +696,46 @@ describe('Bridge', () => {
);
});
it('Should allow to touchlink factory reset (fails)', async () => {
it('Should allow to touchlink factory reset specific device', async () => {
MQTT.publish.mockClear();
zigbeeHerdsman.touchlinkFactoryReset.mockClear();
zigbeeHerdsman.touchlinkFactoryReset.mockReturnValueOnce(false);
MQTT.events.message('zigbee2mqtt/bridge/request/touchlink/factory_reset', '');
zigbeeHerdsman.touchlinkFactoryReset.mockReturnValueOnce(true);
MQTT.events.message('zigbee2mqtt/bridge/request/touchlink/factory_reset', stringify({ieee_address: '0x1239', channel: 12}));
await flushPromises();
expect(zigbeeHerdsman.touchlinkFactoryReset).toHaveBeenCalledTimes(1);
expect(zigbeeHerdsman.touchlinkFactoryReset).toHaveBeenCalledWith('0x1239', 12);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/touchlink/factory_reset',
stringify({"data":{"ieee_address":'0x1239',"channel":12},"status":"ok"}),
{retain: false, qos: 0}, expect.any(Function)
);
});
it('Should allow to touchlink factory reset (fails)', async () => {
MQTT.publish.mockClear();
zigbeeHerdsman.touchlinkFactoryResetFirst.mockClear();
zigbeeHerdsman.touchlinkFactoryResetFirst.mockReturnValueOnce(false);
MQTT.events.message('zigbee2mqtt/bridge/request/touchlink/factory_reset', '');
await flushPromises();
expect(zigbeeHerdsman.touchlinkFactoryResetFirst).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/touchlink/factory_reset',
stringify({"data":{},"status":"error","error":"Failed to factory reset device through Touchlink"}),
{retain: false, qos: 0}, expect.any(Function)
);
});
it('Should allow to touchlink scan', async () => {
MQTT.publish.mockClear();
zigbeeHerdsman.touchlinkScan.mockClear();
zigbeeHerdsman.touchlinkScan.mockReturnValueOnce([{ieeeAddr: '0x123', channel: 12}, {ieeeAddr: '0x124', channel: 24}]);
MQTT.events.message('zigbee2mqtt/bridge/request/touchlink/scan', '');
await flushPromises();
expect(zigbeeHerdsman.touchlinkScan).toHaveBeenCalledTimes(1);
expect(MQTT.publish).toHaveBeenCalledWith(
'zigbee2mqtt/bridge/response/touchlink/scan',
stringify({"data":{"found":[{ieee_address: '0x123', channel: 12}, {ieee_address: '0x124', channel: 24}]},"status":"ok"}),
{retain: false, qos: 0}, expect.any(Function)
);
});
});
+2
View File
@@ -178,6 +178,8 @@ const groups = {
const mock = {
setTransmitPower: jest.fn(),
touchlinkFactoryReset: jest.fn(),
touchlinkFactoryResetFirst: jest.fn(),
touchlinkScan: jest.fn(),
start: jest.fn(),
permitJoin: jest.fn(),
getCoordinatorVersion: jest.fn().mockReturnValue({type: 'z-Stack', meta: {version: 1, revision: 20190425}}),