diff --git a/src/controller/controller.ts b/src/controller/controller.ts index 810daf8eb1..1a43225736 100644 --- a/src/controller/controller.ts +++ b/src/controller/controller.ts @@ -540,21 +540,27 @@ class Controller extends events.EventEmitter { this.unknownDevices.add(nwkAddress); const clusterId = Zdo.ClusterId.IEEE_ADDRESS_REQUEST; const zdoPayload = Zdo.Buffalo.buildRequest(this.adapter.hasZdoMessageOverhead, clusterId, nwkAddress, false, 0); - const response = await this.adapter.sendZdo(ZSpec.BLANK_EUI64, nwkAddress, clusterId, zdoPayload, false); - if (Zdo.Buffalo.checkStatus(response)) { - const payload = response[1]; - const device = Device.byIeeeAddr(payload.eui64); + try { + const response = await this.adapter.sendZdo(ZSpec.BLANK_EUI64, nwkAddress, clusterId, zdoPayload, false); - /* istanbul ignore else */ - if (device) { - this.checkDeviceNetworkAddress(device, payload.eui64, payload.nwkAddress); - this.unknownDevices.delete(payload.nwkAddress); - } + if (Zdo.Buffalo.checkStatus(response)) { + const payload = response[1]; + const device = Device.byIeeeAddr(payload.eui64); - return device; - } else { - logger.debug(`Failed to retrieve IEEE address for device '${nwkAddress}': ${Zdo.Status[response[0]]}`, NS); + /* istanbul ignore else */ + if (device) { + this.checkDeviceNetworkAddress(device, payload.eui64, payload.nwkAddress); + this.unknownDevices.delete(payload.nwkAddress); + } + + return device; + } else { + throw new Zdo.StatusError(response[0]); + } + } catch (error) { + // Catches 2 types of exception: Zdo.StatusError and no response from `adapter.sendZdo()`. + logger.debug(`Failed to retrieve IEEE address for device '${nwkAddress}': ${error}`, NS); } // NOTE: by keeping nwkAddress in `this.unknownDevices` on fail, it prevents a non-responding device from potentially spamming identify. diff --git a/test/controller.test.ts b/test/controller.test.ts index f16bf8c711..8449126b7e 100755 --- a/test/controller.test.ts +++ b/test/controller.test.ts @@ -10413,7 +10413,7 @@ describe('Controller', () => { expect(device.networkAddress).toStrictEqual(oldNwkAddress); expect(device.modelID).toBe('TRADFRI bulb E27 WS opal 980lm'); expect(mockLogger.debug).toHaveBeenCalledWith( - `Failed to retrieve IEEE address for device '${newNwkAddress}': INV_REQUESTTYPE`, + `Failed to retrieve IEEE address for device '${newNwkAddress}': Error: Status 'INV_REQUESTTYPE'`, 'zh:controller', ); expect(events.lastSeenChanged.length).toBe(0); @@ -10484,12 +10484,7 @@ describe('Controller', () => { events.lastSeenChanged = []; events.deviceNetworkAddressChanged = []; mockAdapterSendZdo.mockClear(); - mockAdapterSendZdo.mockImplementationOnce(async () => { - const zdoResponse = [Zdo.Status.NOT_SUPPORTED, undefined]; - - await mockAdapterEvents['zdoResponse'](Zdo.ClusterId.IEEE_ADDRESS_RESPONSE, zdoResponse); - return zdoResponse; - }); + mockAdapterSendZdo.mockRejectedValueOnce(new Error('timeout')); const identifyUnknownDeviceSpy = jest.spyOn(controller, 'identifyUnknownDevice'); const frame = Zcl.Frame.create(0, 1, true, undefined, 10, 'readRsp', 0, [{attrId: 5, status: 0, dataType: 66, attrData: 'new.model.id'}], {}); @@ -10506,7 +10501,7 @@ describe('Controller', () => { expect(mockAdapterSendZdo).toHaveBeenCalledTimes(1); expect(identifyUnknownDeviceSpy).toHaveBeenCalledTimes(1); - expect(mockLogger.debug).toHaveBeenCalledWith(`Failed to retrieve IEEE address for device '${nwkAddress}': NOT_SUPPORTED`, 'zh:controller'); + expect(mockLogger.debug).toHaveBeenCalledWith(`Failed to retrieve IEEE address for device '${nwkAddress}': Error: timeout`, 'zh:controller'); await mockAdapterEvents['zclPayload']({ wasBroadcast: false,