From c6c1949701320a092394ded74374d963e4e00bdf Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:05:45 +0100 Subject: [PATCH 01/15] Update main.js Test: convertGet Changes ? --- main.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index b95d9b35..58cdcef2 100644 --- a/main.js +++ b/main.js @@ -694,8 +694,12 @@ class Zigbee extends utils.Adapter { try { await converter.convertGet(entity.device.endpoints[0], ckey, {}); } catch (error) { - this.log.warn(`Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after query with '${JSON.stringify(error)}'`); - + this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after query with '${error && error.message ? error.message : 'no error message'}`); + } + try { + await converter.convertGet(entity.device, ckey, {}); + } catch (error) { + this.log.warn(`Failed to read state (2)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after query with '${error && error.message ? error.message : 'no error message'}`); } } } From eaae381188be7f3b617c39e5c2f4240c21a656e4 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:17:06 +0100 Subject: [PATCH 02/15] Update main.js change log message --- main.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index 58cdcef2..ee73b0c4 100644 --- a/main.js +++ b/main.js @@ -692,14 +692,18 @@ class Zigbee extends utils.Adapter { if (converter.hasOwnProperty('convertGet')) { for (const ckey of converter.key) { try { + const t = Date.getTime(); await converter.convertGet(entity.device.endpoints[0], ckey, {}); } catch (error) { - this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after query with '${error && error.message ? error.message : 'no error message'}`); + const delta = Date.getTime()-t; + this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); } try { + const t = Date.getTime(); await converter.convertGet(entity.device, ckey, {}); } catch (error) { - this.log.warn(`Failed to read state (2)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after query with '${error && error.message ? error.message : 'no error message'}`); + const delta = Date.getTime()-t; + this.log.warn(`Failed to read state (2)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); } } } From c107f6180c646f7f5816816f01e81f461cc8cfe0 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:23:14 +0100 Subject: [PATCH 03/15] Update main.js bugfix --- main.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main.js b/main.js index ee73b0c4..7110f4f7 100644 --- a/main.js +++ b/main.js @@ -692,17 +692,17 @@ class Zigbee extends utils.Adapter { if (converter.hasOwnProperty('convertGet')) { for (const ckey of converter.key) { try { - const t = Date.getTime(); + const t = new Date().getTime(); await converter.convertGet(entity.device.endpoints[0], ckey, {}); } catch (error) { - const delta = Date.getTime()-t; + const delta = new Date().getTime()-t; this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); } try { - const t = Date.getTime(); + const t = new Date().getTime(); await converter.convertGet(entity.device, ckey, {}); } catch (error) { - const delta = Date.getTime()-t; + const delta = new Date().getTime()-t; this.log.warn(`Failed to read state (2)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); } } From ab8a5fc7c0bdc11b60fb643e5af792e6d693146a Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:27:46 +0100 Subject: [PATCH 04/15] Update main.js --- main.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index 7110f4f7..7d804d99 100644 --- a/main.js +++ b/main.js @@ -688,18 +688,19 @@ class Zigbee extends utils.Adapter { if (mappedModel) { this.query_device_block.push(deviceId); this.log.debug(`Device query for '${entity.device.ieeeAddr}' started`); + let t; for (const converter of mappedModel.toZigbee) { if (converter.hasOwnProperty('convertGet')) { for (const ckey of converter.key) { + t = new Date().getTime(); try { - const t = new Date().getTime(); await converter.convertGet(entity.device.endpoints[0], ckey, {}); } catch (error) { const delta = new Date().getTime()-t; this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); } + t = new Date().getTime(); try { - const t = new Date().getTime(); await converter.convertGet(entity.device, ckey, {}); } catch (error) { const delta = new Date().getTime()-t; From 5a643119435b40ddafe7ec9f41e48519022f0998 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Fri, 10 Jan 2025 22:42:10 +0100 Subject: [PATCH 05/15] Update main.js --- main.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/main.js b/main.js index 7d804d99..e4a6f58c 100644 --- a/main.js +++ b/main.js @@ -687,7 +687,7 @@ class Zigbee extends utils.Adapter { } if (mappedModel) { this.query_device_block.push(deviceId); - this.log.debug(`Device query for '${entity.device.ieeeAddr}' started`); + this.log.warn(`Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' triggered`); let t; for (const converter of mappedModel.toZigbee) { if (converter.hasOwnProperty('convertGet')) { @@ -699,17 +699,17 @@ class Zigbee extends utils.Adapter { const delta = new Date().getTime()-t; this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); } - t = new Date().getTime(); - try { - await converter.convertGet(entity.device, ckey, {}); - } catch (error) { - const delta = new Date().getTime()-t; - this.log.warn(`Failed to read state (2)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); - } +// t = new Date().getTime(); +// try { +// await converter.convertGet(entity.device, ckey, {}); +// } catch (error) { +// const delta = new Date().getTime()-t; +// this.log.warn(`Failed to read state (2)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); +// } } } } - this.log.debug(`Device query for '${entity.device.ieeeAddr}' done`); + this.log.warn(`Device query for '${entity.device.ieeeAddr}' complete`); const idToRemove = deviceId; setTimeout(() => { const idx = this.query_device_block.indexOf(idToRemove); From cb387c486ec77255c5dc0a47e0925b247843b008 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 15:34:02 +0100 Subject: [PATCH 06/15] Update main.js --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index e4a6f58c..d8a75eea 100644 --- a/main.js +++ b/main.js @@ -697,7 +697,7 @@ class Zigbee extends utils.Adapter { await converter.convertGet(entity.device.endpoints[0], ckey, {}); } catch (error) { const delta = new Date().getTime()-t; - this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); + this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}('${error && error.stack ? error.stack : 'no call stack'})`); } // t = new Date().getTime(); // try { From c1eb64fcfb681e4688fb4c9d91a35060bd1b5743 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:02:43 +0100 Subject: [PATCH 07/15] Error messages replaced error reporting via JSON.stringify(error) to specific messaging via error.message and error.stack --- lib/commands.js | 4 ++-- lib/groups.js | 2 +- lib/statescontroller.js | 6 +++--- lib/zigbeecontroller.js | 14 +++++++------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/commands.js b/lib/commands.js index a10915fb..473f3fd3 100644 --- a/lib/commands.js +++ b/lib/commands.js @@ -150,8 +150,8 @@ class Commands { return; } } - catch (e) { - this.error(JSON.stringify(e)); + catch (error) { + this.error(`Pairing with code failed with: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`); this.adapter.sendTo( from, command, {error: 'Exception when trying to add QR code'}, diff --git a/lib/groups.js b/lib/groups.js index 831a7451..410b2cef 100644 --- a/lib/groups.js +++ b/lib/groups.js @@ -85,7 +85,7 @@ class Groups { } } catch (error) { - if (error) this.error(`getGroupMembersFromController: error is ${JSON.stringify(error)} ${JSON.stringify(new Error().stack)}`); + if (error) this.error(`getGroupMembersFromController: error is ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`); else this.error('unidentifed error in getGroupMembersFromController'); } return members; diff --git a/lib/statescontroller.js b/lib/statescontroller.js index e16c75db..a2dc9c82 100644 --- a/lib/statescontroller.js +++ b/lib/statescontroller.js @@ -54,9 +54,9 @@ class StatesController extends EventEmitter { retainDeviceNames() { clearTimeout(this.retTimeoutHandle); this.retTimeoutHanlde = setTimeout(() => { - fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNamesDB, null, 2), err => { - if (err) { - this.error(`error saving device names: ${JSON.stringify(err)}`); + fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNamesDB, null, 2), error => { + if (error) { + this.error(`error saving device names: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`); } else { this.debug('saved device names'); } diff --git a/lib/zigbeecontroller.js b/lib/zigbeecontroller.js index c5c8271a..36e4f09b 100644 --- a/lib/zigbeecontroller.js +++ b/lib/zigbeecontroller.js @@ -148,9 +148,9 @@ class ZigbeeController extends EventEmitter { } this.debug(`Zigbee network parameters: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`); - } catch (e) { - this.sendError(e); - this.error(`Starting zigbee-herdsman problem : ${JSON.stringify(e.message)}`); + } catch (error) { + this.sendError(error); + this.error(`Starting zigbee-herdsman problem : ${(error && error.message ? error.message : 'no error message')}`); throw 'Error herdsman start'; } // Check if we have to turn off the LED @@ -297,7 +297,7 @@ class ZigbeeController extends EventEmitter { } } catch (error) { this.sendError(error); - this.error(JSON.stringify(error)); + this.error(`error in getGroups: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`); return undefined; } } @@ -308,7 +308,7 @@ class ZigbeeController extends EventEmitter { group && group.removeFromNetwork(); } catch (error) { this.sendError(error); - this.error(`error in removeGroupById: ${error}`); + this.error(`error in removeGroupById: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`); } } @@ -369,7 +369,7 @@ class ZigbeeController extends EventEmitter { } catch (error) { this.sendError(error); if (error) { - this.error(`getGroupMembersFromController: error is ${JSON.stringify(error)} ${JSON.stringify(new Error().stack)}`); + this.error(`getGroupMembersFromController: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`); } else { this.error('unidentified error in getGroupMembersFromController'); } @@ -894,7 +894,7 @@ class ZigbeeController extends EventEmitter { } catch (error) { this.sendError(error); this.error(`Exception when trying to Add ${devId} to group ${groupId}`, error); - return {error: `Failed to add ${devId} to group ${groupId}: ${JSON.stringify(error)}`}; + return {error: `Failed to add ${devId} to group ${groupId}: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`}; } return {}; } From 67304dc99747d61aab9432c78c5a977b9b2e49b3 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:02:00 +0100 Subject: [PATCH 08/15] Error handling Added try/catch to a number of internal functions when calling zigbee-herdsman or zigbee-herdsman-converters functions --- lib/binding.js | 2 +- lib/groups.js | 6 +- lib/zbDeviceAvailability.js | 2 +- lib/zigbeecontroller.js | 312 +++++++++++++++++++++--------------- 4 files changed, 187 insertions(+), 135 deletions(-) diff --git a/lib/binding.js b/lib/binding.js index d38e9c9b..e956b133 100644 --- a/lib/binding.js +++ b/lib/binding.js @@ -238,7 +238,7 @@ class Binding { await this.doBindUnbind(type, bind_source, bind_source_ep, 'coordinator', '1'); this.debug('Successfully ' + (type === 'bind' ? 'bound' : 'unbound') + ' Coordinator from ' + bind_source); } catch (e) { - this.error(`Could not ${type} Coordinator from ${bind_source}: ${JSON.stringify(e)}`); + this.error(`Could not ${type} Coordinator from ${bind_source}: ${(e && e.message ? e.message : 'no error message')} ${(e && e.stack ? e.stack : 'no call stack')}`); } } } catch (error) { diff --git a/lib/groups.js b/lib/groups.js index 410b2cef..d56cde37 100644 --- a/lib/groups.js +++ b/lib/groups.js @@ -138,7 +138,7 @@ class Groups { for (const gpid of groups[epid]) { const gpidn = parseInt(gpid); if (gpidn < 0) { - this.warn(`calling removeDevFromGroup with ${sysid}, ${-gpidn}, ${epid}` ); + this.debug(`calling removeDevFromGroup with ${sysid}, ${-gpidn}, ${epid}` ); const response = await this.zbController.removeDevFromGroup(sysid, (-gpidn), epid); if (response && response.error) { errors.push(response.error); @@ -146,7 +146,7 @@ class Groups { } } else if (gpidn > 0) { - this.warn(`calling addDevToGroup with ${sysid}, ${gpidn}, ${epid}` ); + this.debug(`calling addDevToGroup with ${sysid}, ${gpidn}, ${epid}` ); const response = await this.zbController.addDevToGroup(sysid, (gpidn), epid); if (response && response.error) { errors.push(response.error); @@ -158,7 +158,7 @@ class Groups { } } } catch (e) { - this.warn('caught error ' + JSON.stringify(e) + ' in updateGroupMembership'); + this.warn('caught error ' + (e && e.message ? e.message : 'no error message') + ' in updateGroupMembership'); this.adapter.sendTo(from, command, {error: e}, callback); return; } diff --git a/lib/zbDeviceAvailability.js b/lib/zbDeviceAvailability.js index 70389589..f9cc3fcf 100644 --- a/lib/zbDeviceAvailability.js +++ b/lib/zbDeviceAvailability.js @@ -181,7 +181,7 @@ class DeviceAvailability extends BaseExtension { } } catch (error) { this.sendError(error); - this.debug(`Exception in readState of '${device.ieeeAddr}' - error : '${error}'`); + this.debug(`Exception in readState of '${device.ieeeAddr}' - error : '${(error && error.message ? error.message : 'no error message')}'`); // intentionally empty: Just present to ensure we cause no harm // when reading the state fails. => fall back on standard Ping function } diff --git a/lib/zigbeecontroller.js b/lib/zigbeecontroller.js index 36e4f09b..0de3be55 100644 --- a/lib/zigbeecontroller.js +++ b/lib/zigbeecontroller.js @@ -322,24 +322,34 @@ class ZigbeeController extends EventEmitter { } async verifyGroupExists(id) { - const nid = typeof id === 'number' ? id : parseInt(id); - let group = await this.herdsman.getGroupByID(nid); - if (!group) { - group = await this.herdsman.createGroup(nid); - group.toZigbee = groupConverters; - group.model = 'group'; - this.debug(`verifyGroupExists: created group ${nid}`); - } else { - this.debug(`verifyGroupExists: group ${nid} exists`); + try { + const nid = typeof id === 'number' ? id : parseInt(id); + let group = await this.herdsman.getGroupByID(nid); + if (!group) { + group = await this.herdsman.createGroup(nid); + group.toZigbee = groupConverters; + group.model = 'group'; + this.debug(`verifyGroupExists: created group ${nid}`); + } else { + this.debug(`verifyGroupExists: group ${nid} exists`); + } + } + catch (error) { + this.error(`verifyGroupExists: ${error && error.message ? error.message : 'unspecified error'}`); } } async addPairingCode(code) { this.debug(`calling addPairingCode with ${code}`); if (code) { - await this.herdsman.addInstallCode(code); - this.info(`added code ${code} for pairing`); - return true; + try { + await this.herdsman.addInstallCode(code); + this.info(`added code ${code} for pairing`); + return true; + } + catch (error) { + this.error(`addPairingCode: ${error && error.message ? error.message : 'unspecified error'}`); + } } return false; } @@ -378,100 +388,125 @@ class ZigbeeController extends EventEmitter { } getDevice(key) { - return this.herdsman.getDeviceByIeeeAddr(key); + try { + return this.herdsman.getDeviceByIeeeAddr(key); + } + catch { + return undefined; + } } getDevicesByType(type) { - return this.herdsman.getDevicesByType(type); + try { + return this.herdsman.getDevicesByType(type); + } + catch { + return undefined; + } } getDeviceByNetworkAddress(networkAddress) { - return this.herdsman.getDeviceByNetworkAddress(networkAddress); + try { + return this.herdsman.getDeviceByNetworkAddress(networkAddress); + } + catch { + return undefined; + } } async resolveEntity(key, ep) { // assert(typeof key === 'string' || key.constructor.name === 'Device', `Wrong type '${typeof key}'`); - - if (typeof key === 'string') { - if (key === 'coordinator') { - const coordinator = this.herdsman.getDevicesByType('Coordinator')[0]; - return { - type: 'device', - device: coordinator, - endpoint: coordinator.getEndpoint(1), - name: 'Coordinator', - }; - } else { - const device = await this.herdsman.getDeviceByIeeeAddr(key); - if (device) { - const mapped = await zigbeeHerdsmanConverters.findByDevice(device); - const endpoints = mapped && mapped.endpoint ? mapped.endpoint(device) : null; - let endpoint; - if (endpoints && ep != undefined && endpoints[ep]) { - endpoint = device.getEndpoint(endpoints[ep]); - } else if (endpoints && endpoints['default']) { - endpoint = device.getEndpoint(endpoints['default']); - } else { - const epNum = parseInt(ep); - if (!isNaN(epNum)) { - endpoint = device.getEndpoint(epNum); - } else { - endpoint = device.endpoints[0]; - } - } + try { + if (typeof key === 'string') { + if (key === 'coordinator') { + const coordinator = this.herdsman.getDevicesByType('Coordinator')[0]; return { type: 'device', - device, - mapped, - endpoint, - endpoints: device.endpoints, - name: key, + device: coordinator, + endpoint: coordinator.getEndpoint(1), + name: 'Coordinator', }; + } else { + const device = await this.herdsman.getDeviceByIeeeAddr(key); + if (device) { + const mapped = await zigbeeHerdsmanConverters.findByDevice(device); + const endpoints = mapped && mapped.endpoint ? mapped.endpoint(device) : null; + let endpoint; + if (endpoints && ep != undefined && endpoints[ep]) { + endpoint = device.getEndpoint(endpoints[ep]); + } else if (endpoints && endpoints['default']) { + endpoint = device.getEndpoint(endpoints['default']); + } else { + const epNum = parseInt(ep); + if (!isNaN(epNum)) { + endpoint = device.getEndpoint(epNum); + } else { + endpoint = device.endpoints[0]; + } + } + return { + type: 'device', + device, + mapped, + endpoint, + endpoints: device.endpoints, + name: key, + }; + } + } + } else if (typeof key === 'number') { + let group = await this.herdsman.getGroupByID(key); + if (!group) group = await this.herdsman.createGroup(key); + group.toZigbee = groupConverters; + group.model = 'group'; + return { + type: 'group', + mapped: group, + group, + name: `Group ${key}`, + }; + } else { + let mapped; + try { + mapped = await zigbeeHerdsmanConverters.findByDevice(key); + } catch (err) { + this.error(`zigbeeHerdsmanConverters findByDevice ${key.ieeeAddr}`); } - } - } else if (typeof key === 'number') { - let group = await this.herdsman.getGroupByID(key); - if (!group) group = await this.herdsman.createGroup(key); - group.toZigbee = groupConverters; - group.model = 'group'; - return { - type: 'group', - mapped: group, - group, - name: `Group ${key}`, - }; - } else { - let mapped; - try { - mapped = await zigbeeHerdsmanConverters.findByDevice(key); - } catch (err) { - this.error(`zigbeeHerdsmanConverters findByDevice ${key.ieeeAddr}`); - } - return { - type: 'device', - device: key, - mapped: mapped, - name: key.type === 'Coordinator' ? 'Coordinator' : key.ieeeAddr, - }; + return { + type: 'device', + device: key, + mapped: mapped, + name: key.type === 'Coordinator' ? 'Coordinator' : key.ieeeAddr, + }; + } + } + catch { + return undefined; } + } async incMsgHandler(message) { - this.debug('incoming msg', message); - const device = await this.herdsman.getDeviceByIeeeAddr(message.srcaddr); - if (!device) { - this.debug('Message without device!'); - return; - } - // We can't handle devices without modelId. - if (!device.modelId) { - this.debug('Message without modelId!'); + try { + this.debug('incoming msg', message); + const device = await this.herdsman.getDeviceByIeeeAddr(message.srcaddr); + if (!device) { + this.debug('Message without device!'); + return; + } + // We can't handle devices without modelId. + if (!device.modelId) { + this.debug('Message without modelId!'); + return; + } + this.event('msg', device.ieeeAddr, message, { + modelId: device.modelId + }); + } + catch { return; } - this.event('msg', device.ieeeAddr, message, { - modelId: device.modelId - }); } // Stop controller @@ -814,39 +849,45 @@ class ZigbeeController extends EventEmitter { if (cfg == null) { cfg = {}; } - - if (type === 'foundation') { - cfg.disableDefaultResponse = true; - - if (cmd === 'read' && !Array.isArray(zclData)) { - /* // needs to be iterable (string[] | number []) - zclData[Symbol.iterator] = function* () { - let k; - for (k in this) { - yield k; - } - }; -*/ - } - let result; - if (cmd === 'configReport') { - result = await endpoint.configureReporting(cid, zclData, cfg); + try { + if (type === 'foundation') { + cfg.disableDefaultResponse = true; + /* + if (cmd === 'read' && !Array.isArray(zclData)) { + // needs to be iterable (string[] | number []) + zclData[Symbol.iterator] = function* () { + let k; + for (k in this) { + yield k; + } + }; + } + */ + let result; + if (cmd === 'configReport') { + result = await endpoint.configureReporting(cid, zclData, cfg); + } else { + if (cmd === 'read' && !Array.isArray(zclData)) + result = await endpoint[cmd](cid, Object.keys(zclData), cfg); + else + result = await endpoint[cmd](cid, zclData, cfg); + } + callback && callback(undefined, result); + } else if (type === 'functionalResp') { + cfg.disableDefaultResponse = false; + const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum); + callback && callback(undefined, result); } else { - if (cmd === 'read' && !Array.isArray(zclData)) - result = await endpoint[cmd](cid, Object.keys(zclData), cfg); - else - result = await endpoint[cmd](cid, zclData, cfg); + cfg.disableDefaultResponse = false; + const result = await endpoint.command(cid, cmd, zclData, cfg); + callback && callback(undefined, result); } - callback && callback(undefined, result); - } else if (type === 'functionalResp') { - cfg.disableDefaultResponse = false; - const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum); - callback && callback(undefined, result); - } else { - cfg.disableDefaultResponse = false; - const result = await endpoint.command(cid, cmd, zclData, cfg); - callback && callback(undefined, result); } + catch (error) + { + this.log.error(`error sending ${type} ${cmd} to endpoint: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`) + } + } async addDevToGroup(devId, groupId, epid) { @@ -957,16 +998,21 @@ class ZigbeeController extends EventEmitter { target = !target ? this.getCoordinator() : target; this.debug(`Binding ${log}`); - ep.bind(cluster, target, error => { - if (error) { - this.sendError(error); - this.error(`Failed to bind ${log} - (${error})`); - } else { - this.debug(`Successfully bound ${log}`); - } + try { + ep.bind(cluster, target, error => { + if (error) { + this.sendError(error); + this.error(`Failed to bind ${log} - (${error})`); + } else { + this.debug(`Successfully bound ${log}`); + } + callback(error); + }); + } + catch (error) { callback(error); - }); + } } unbind(ep, cluster, target, callback) { @@ -974,15 +1020,21 @@ class ZigbeeController extends EventEmitter { target = !target ? this.getCoordinator() : target; this.debug(`Unbinding ${log}`); - ep.unbind(cluster, target, (error) => { - if (error) { - this.error(`Failed to unbind ${log} - (${error})`); - } else { - this.debug(`Successfully unbound ${log}`); - } + try { + ep.unbind(cluster, target, (error) => { + if (error) { + this.error(`Failed to unbind ${log} - (${error})`); + } else { + this.debug(`Successfully unbound ${log}`); + } + callback(error); + }); + } + catch (error) + { callback(error); - }); + } } reset(mode, callback) { From 4f654a3d2fca4f7fe4d9e18b9f5d7a4c5fd41315 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:18:56 +0100 Subject: [PATCH 09/15] Update main.js --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index d8a75eea..66c139d2 100644 --- a/main.js +++ b/main.js @@ -694,7 +694,7 @@ class Zigbee extends utils.Adapter { for (const ckey of converter.key) { t = new Date().getTime(); try { - await converter.convertGet(entity.device.endpoints[0], ckey, {}); + await converter.convertGet(entity.device.endpoints[0], ckey, {endpoint_name:entity.device.endpoints[0].ID.toString()}); } catch (error) { const delta = new Date().getTime()-t; this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}('${error && error.stack ? error.stack : 'no call stack'})`); From c51e1a2b4694b21cf96ee41b1d7e842fd1a530cc Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:22:39 +0100 Subject: [PATCH 10/15] Update main.js --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index 66c139d2..f6e6a065 100644 --- a/main.js +++ b/main.js @@ -833,7 +833,7 @@ class Zigbee extends utils.Adapter { } }); } catch (err) { - this.log.error(`No entity for ${deviceId}`); + this.log.error(`No entity for ${deviceId} : ${err && err.message ? err.message : ''}`); } } From bdc6d75fa32b87692e4ac229a7b5dde80c930fb5 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:46:51 +0100 Subject: [PATCH 11/15] Update main.js updated logging --- main.js | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/main.js b/main.js index f6e6a065..e4e69259 100644 --- a/main.js +++ b/main.js @@ -629,7 +629,14 @@ class Zigbee extends utils.Adapter { let isGroup = false; const has_elevated_debug = this.stController.checkDebugDevice(deviceId) - this.log.debug(`publishFromState : ${deviceId} ${model} ${safeJsonStringify(stateList)}`); + if (has_elevated_debug) + { + let stateNames = []; + stateList.forEach( state => stateNames.push(state.id)); + this.log.warn(`ELEVATED O03: Publishing to ${deviceId} of model ${model} ${stateNames.join(', ')}`); + } + else + this.log.debug(`publishFromState : ${deviceId} ${model} ${safeJsonStringify(stateList)}`); if (model === 'group') { isGroup = true; deviceId = parseInt(deviceId); @@ -637,13 +644,13 @@ class Zigbee extends utils.Adapter { try { const entity = await this.zbController.resolveEntity(deviceId); - this.log.debug(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`); + this.log.warn(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`); - const mappedModel = entity.mapped; + const mappedModel = (entity ? entity.mapped : undefined); if (!mappedModel) { - this.log.debug(`No mapped model for ${model}`); - if (has_elevated_debug) this.log.warn(`ELEVATED O2: No mapped model for ${model}`) + this.log.debug(`No mapped model for ${deviceId} (model ${model})`); + if (has_elevated_debug) this.log.error(`ELEVATED OE01: No mapped model ${deviceId} (model ${model})`) return; } @@ -699,13 +706,6 @@ class Zigbee extends utils.Adapter { const delta = new Date().getTime()-t; this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}('${error && error.stack ? error.stack : 'no call stack'})`); } -// t = new Date().getTime(); -// try { -// await converter.convertGet(entity.device, ckey, {}); -// } catch (error) { -// const delta = new Date().getTime()-t; -// this.log.warn(`Failed to read state (2)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}`); -// } } } } @@ -724,6 +724,7 @@ class Zigbee extends utils.Adapter { } let converter = undefined; + let msgCnt = 1; for (const c of mappedModel.toZigbee) { if (!c.hasOwnProperty('convertSet')) continue; @@ -733,13 +734,14 @@ class Zigbee extends utils.Adapter { if (c.hasOwnProperty('convertSet') && converter === undefined) { converter = c; - if (has_elevated_debug) - this.log.warn(`ELEVATED O3A: Setting converter to keyless converter for ${deviceId} of type ${model}`) + if (has_elevated_debug) { + this.log.warn(`ELEVATED O4.${msgCnt++}: Setting converter to keyless converter for ${deviceId} of type ${model}`) + } this.log.debug('setting converter to keyless converter') } else { - if (has_elevated_debug) this.log.warn(`ELEVATED O3B: ignoring keyless converter for ${deviceId} of type ${model}`) + if (has_elevated_debug) this.log.warn(`ELEVATED O4.${msgCnt++}: ignoring keyless converter for ${deviceId} of type ${model}`) this.log.debug('ignoring keyless converter') } continue; @@ -747,7 +749,7 @@ class Zigbee extends utils.Adapter { if (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id)) { this.log.debug(`${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`) - if (has_elevated_debug) this.log.warn(`ELEVATED O3C: ${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`) + if (has_elevated_debug) this.log.warn(`ELEVATED O4.${msgCnt++}: ${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`) converter = c; } } @@ -813,7 +815,7 @@ class Zigbee extends utils.Adapter { try { const result = await converter.convertSet(target, key, preparedValue, meta); this.log.debug(`convert result ${safeJsonStringify(result)}`); - if (has_elevated_debug) this.log.warn(`ELEVATED O5: convert result ${safeJsonStringify(result)} for device ${deviceId}`); + if (has_elevated_debug) this.log.warn(`ELEVATED O05: convert result ${safeJsonStringify(result)} sent to device ${deviceId}`); if (result !== undefined) { if (stateModel && !isGroup) { this.acknowledgeState(deviceId, model, stateDesc, value); From 66464f3c0b0cc9bc0041eb783a76bb01a256dfa3 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:51:36 +0100 Subject: [PATCH 12/15] Update main.js --- main.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/main.js b/main.js index e4e69259..7f1fe0de 100644 --- a/main.js +++ b/main.js @@ -644,8 +644,6 @@ class Zigbee extends utils.Adapter { try { const entity = await this.zbController.resolveEntity(deviceId); - this.log.warn(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`); - const mappedModel = (entity ? entity.mapped : undefined); if (!mappedModel) { From 88f7befce80b82f836aa097797ec668fd31c1a42 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sat, 11 Jan 2025 21:19:26 +0100 Subject: [PATCH 13/15] Update statescontroller.js --- lib/statescontroller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/statescontroller.js b/lib/statescontroller.js index a2dc9c82..951a1873 100644 --- a/lib/statescontroller.js +++ b/lib/statescontroller.js @@ -109,7 +109,7 @@ class StatesController extends EventEmitter { } if (this.checkDebugDevice(id)) - this.warn(`ELEVATED O1: User state change of state ${id} with value ${state.val} (ack: ${state.ack}) from ${state.from}`); + this.warn(`ELEVATED O01: User state change of state ${id} with value ${state.val} (ack: ${state.ack}) from ${state.from}`); this.debug(`User stateChange ${id} ${JSON.stringify(state)}`); const devId = getAdId(this.adapter, id); // iobroker device id @@ -211,7 +211,7 @@ class StatesController extends EventEmitter { this.debug(`Change state '${stateKey}' at device ${deviceId} type '${model}'`); const elevated = this.checkDebugDevice(deviceId); - if (elevated) this.warn(`ELEVATED O2: Change state '${stateKey}' at device ${deviceId} type '${model}'`); + if (elevated) this.warn(`ELEVATED O02: Change state '${stateKey}' at device ${deviceId} type '${model}'`); const devStates = await this.getDevStates(deviceId, model); if (!devStates) { From d161b74430430d6b8110766d1f65ff61e46770db Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sun, 12 Jan 2025 14:47:19 +0100 Subject: [PATCH 14/15] Update main.js Fix Ikea Parasoll battery (can be queried again) Possibly fix random crashes due to unhandled promise rejection --- main.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/main.js b/main.js index 7f1fe0de..721452f1 100644 --- a/main.js +++ b/main.js @@ -687,27 +687,34 @@ class Zigbee extends utils.Adapter { // on activation of the 'device_query' state trigger hardware query where possible if (stateDesc.id === 'device_query') { if (this.query_device_block.indexOf(deviceId) > -1) { - this.log.warn(`Device query for '${entity.device.ieeeAddr}' blocked`); + this.log.info(`Device query for '${entity.device.ieeeAddr}' blocked`); return; } if (mappedModel) { this.query_device_block.push(deviceId); - this.log.warn(`Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' triggered`); + if (has_elevated_debug) + this.log.warn(`ELEVATED O06: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' triggered`); let t; for (const converter of mappedModel.toZigbee) { if (converter.hasOwnProperty('convertGet')) { for (const ckey of converter.key) { - t = new Date().getTime(); try { await converter.convertGet(entity.device.endpoints[0], ckey, {endpoint_name:entity.device.endpoints[0].ID.toString()}); } catch (error) { - const delta = new Date().getTime()-t; - this.log.warn(`Failed to read state (1)'${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} ' after ${delta} ms from query with '${error && error.message ? error.message : 'no error message'}('${error && error.stack ? error.stack : 'no call stack'})`); + if (has_elevated_debug) { + this.log.warn(`ELEVATED OE02.1 Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' from query with '${error && error.message ? error.message : 'no error message'}`); + } + else + this.log.info(`failed to read state ${JSON.stringify(ckey)} of ${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} after device query`); } } } } - this.log.warn(`Device query for '${entity.device.ieeeAddr}' complete`); + if (has_elevated_debug) + this.log.warn(`ELEVATED O07: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`); + else + this.log.info(`Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`); + const idToRemove = deviceId; setTimeout(() => { const idx = this.query_device_block.indexOf(idToRemove); From 375cdcf4c9c3aaa5b0bdcda69b400f2fadd6e450 Mon Sep 17 00:00:00 2001 From: asgothian <45667167+asgothian@users.noreply.github.com> Date: Sun, 12 Jan 2025 19:07:24 +0100 Subject: [PATCH 15/15] Lint Lint --- lib/zigbeecontroller.js | 14 +++++++------- main.js | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/zigbeecontroller.js b/lib/zigbeecontroller.js index 0de3be55..e6d0a3bd 100644 --- a/lib/zigbeecontroller.js +++ b/lib/zigbeecontroller.js @@ -390,7 +390,7 @@ class ZigbeeController extends EventEmitter { getDevice(key) { try { return this.herdsman.getDeviceByIeeeAddr(key); - } + } catch { return undefined; } @@ -399,7 +399,7 @@ class ZigbeeController extends EventEmitter { getDevicesByType(type) { try { return this.herdsman.getDevicesByType(type); - } + } catch { return undefined; } @@ -408,7 +408,7 @@ class ZigbeeController extends EventEmitter { getDeviceByNetworkAddress(networkAddress) { try { return this.herdsman.getDeviceByNetworkAddress(networkAddress); - } + } catch { return undefined; } @@ -480,7 +480,7 @@ class ZigbeeController extends EventEmitter { name: key.type === 'Coordinator' ? 'Coordinator' : key.ieeeAddr, }; } - } + } catch { return undefined; } @@ -488,7 +488,7 @@ class ZigbeeController extends EventEmitter { } async incMsgHandler(message) { - try { + try { this.debug('incoming msg', message); const device = await this.herdsman.getDeviceByIeeeAddr(message.srcaddr); if (!device) { @@ -503,7 +503,7 @@ class ZigbeeController extends EventEmitter { this.event('msg', device.ieeeAddr, message, { modelId: device.modelId }); - } + } catch { return; } @@ -883,7 +883,7 @@ class ZigbeeController extends EventEmitter { callback && callback(undefined, result); } } - catch (error) + catch (error) { this.log.error(`error sending ${type} ${cmd} to endpoint: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`) } diff --git a/main.js b/main.js index 721452f1..a1c9700c 100644 --- a/main.js +++ b/main.js @@ -629,10 +629,10 @@ class Zigbee extends utils.Adapter { let isGroup = false; const has_elevated_debug = this.stController.checkDebugDevice(deviceId) - if (has_elevated_debug) - { - let stateNames = []; - stateList.forEach( state => stateNames.push(state.id)); + if (has_elevated_debug) + { + const stateNames = []; + stateList.forEach( state => stateNames.push(state.id)); this.log.warn(`ELEVATED O03: Publishing to ${deviceId} of model ${model} ${stateNames.join(', ')}`); } else @@ -704,7 +704,7 @@ class Zigbee extends utils.Adapter { if (has_elevated_debug) { this.log.warn(`ELEVATED OE02.1 Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' from query with '${error && error.message ? error.message : 'no error message'}`); } - else + else this.log.info(`failed to read state ${JSON.stringify(ckey)} of ${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} after device query`); } } @@ -712,7 +712,7 @@ class Zigbee extends utils.Adapter { } if (has_elevated_debug) this.log.warn(`ELEVATED O07: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`); - else + else this.log.info(`Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`); const idToRemove = deviceId;