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/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..d56cde37 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; @@ -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/statescontroller.js b/lib/statescontroller.js index e16c75db..951a1873 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'); } @@ -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) { 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 c5c8271a..e6d0a3bd 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')}`); } } @@ -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; } @@ -369,7 +379,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'); } @@ -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; + 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 + }); } - // We can't handle devices without modelId. - if (!device.modelId) { - this.debug('Message without 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) { @@ -894,7 +935,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 {}; } @@ -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) { diff --git a/main.js b/main.js index b95d9b35..a1c9700c 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) + { + const 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,11 @@ class Zigbee extends utils.Adapter { try { const entity = await this.zbController.resolveEntity(deviceId); - this.log.debug(`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; } @@ -682,25 +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.debug(`Device query for '${entity.device.ieeeAddr}' started`); + 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) { 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) { - this.log.warn(`Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after query with '${JSON.stringify(error)}'`); - + 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.debug(`Device query for '${entity.device.ieeeAddr}' done`); + 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); @@ -715,6 +729,7 @@ class Zigbee extends utils.Adapter { } let converter = undefined; + let msgCnt = 1; for (const c of mappedModel.toZigbee) { if (!c.hasOwnProperty('convertSet')) continue; @@ -724,13 +739,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; @@ -738,7 +754,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; } } @@ -804,7 +820,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); @@ -824,7 +840,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 : ''}`); } }