From 0cf7b45981cfe4840986121574c88f6437be8b15 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Tue, 2 Apr 2024 22:30:13 +0200 Subject: [PATCH] feat: Improve logging (#989) * feat: Improve logging * feat: Improve logging * Finer log levels for base classes. * Lower z2m dups to `debug`. Fixup GP. Fix tests. * Lower a few more z2m dups to `debug`. * Refactored to use namespacing directly. * change prefix * updates * fix tests * Reduce `ember` NCP counters logging footprint. * Add tests for unset logger. --------- Co-authored-by: Nerivec <62446222+Nerivec@users.noreply.github.com> --- package.json | 6 +- src/adapter/adapter.ts | 36 +- src/adapter/deconz/adapter/deconzAdapter.ts | 132 ++++---- src/adapter/deconz/driver/driver.ts | 88 ++--- src/adapter/deconz/driver/frameParser.ts | 87 ++--- src/adapter/deconz/driver/parser.ts | 12 +- src/adapter/deconz/driver/writer.ts | 6 +- src/adapter/ember/adapter/emberAdapter.ts | 316 +++++++++--------- src/adapter/ember/adapter/oneWaitress.ts | 4 +- src/adapter/ember/adapter/requestQueue.ts | 18 +- src/adapter/ember/adapter/tokensManager.ts | 55 +-- src/adapter/ember/ezsp/ezsp.ts | 297 ++++++++-------- src/adapter/ember/uart/ash.ts | 148 ++++---- src/adapter/ember/uart/parser.ts | 6 +- src/adapter/ember/uart/queues.ts | 4 +- src/adapter/ember/uart/writer.ts | 7 +- src/adapter/ezsp/adapter/backup.ts | 7 +- src/adapter/ezsp/adapter/ezspAdapter.ts | 49 ++- src/adapter/ezsp/driver/driver.ts | 147 ++++---- src/adapter/ezsp/driver/ezsp.ts | 132 +++++--- src/adapter/ezsp/driver/multicast.ts | 26 +- src/adapter/ezsp/driver/parser.ts | 10 +- src/adapter/ezsp/driver/types/basic.ts | 2 +- src/adapter/ezsp/driver/types/named.ts | 4 +- src/adapter/ezsp/driver/types/struct.ts | 4 +- src/adapter/ezsp/driver/uart.ts | 92 ++--- src/adapter/ezsp/driver/writer.ts | 6 +- src/adapter/z-stack/adapter/adapter-backup.ts | 52 +-- src/adapter/z-stack/adapter/manager.ts | 112 +++---- src/adapter/z-stack/adapter/zStackAdapter.ts | 52 ++- src/adapter/z-stack/unpi/parser.ts | 12 +- src/adapter/z-stack/unpi/writer.ts | 8 +- src/adapter/z-stack/znp/znp.ts | 43 +-- src/adapter/zigate/adapter/zigateAdapter.ts | 109 +++--- src/adapter/zigate/debug.ts | 16 - src/adapter/zigate/driver/frame.ts | 15 +- src/adapter/zigate/driver/ziGateObject.ts | 13 +- src/adapter/zigate/driver/zigate.ts | 48 ++- src/controller/controller.ts | 116 +++---- src/controller/database.ts | 8 +- src/controller/greenPower.ts | 66 ++-- src/controller/helpers/requestQueue.ts | 37 +- src/controller/logger-stub.ts | 7 - src/controller/model/device.ts | 102 +++--- src/controller/model/endpoint.ts | 32 +- src/controller/model/group.ts | 19 +- src/controller/touchlink.ts | 42 +-- src/index.ts | 4 + src/utils/logger.ts | 17 + src/zcl/buffaloZcl.ts | 9 +- test/adapter/z-stack/adapter.test.ts | 100 +++--- test/controller.test.ts | 181 ++++------ test/utils.test.ts | 35 ++ 53 files changed, 1434 insertions(+), 1522 deletions(-) delete mode 100644 src/adapter/zigate/debug.ts delete mode 100644 src/controller/logger-stub.ts create mode 100644 src/utils/logger.ts diff --git a/package.json b/package.json index c60443fbb7..1a24e80c19 100644 --- a/package.json +++ b/package.json @@ -77,9 +77,9 @@ "scripts": { "build": "./node_modules/.bin/tsc", "start": "./node_modules/.bin/tsc -w", - "test": "jest test", - "test-with-coverage": "jest test --coverage --collectCoverageFrom 'src/**/*.ts'", - "test-watch": "jest test --watch", + "test": "jest test --silent", + "test-with-coverage": "jest test --silent --coverage --collectCoverageFrom 'src/**/*.ts'", + "test-watch": "jest test --silent --watch", "eslint": "node_modules/.bin/eslint . --ext .ts --max-warnings=0", "docs": "typedoc --tsconfig typedoc-tsconfig.json", "clean": "rimraf temp coverage dist", diff --git a/src/adapter/adapter.ts b/src/adapter/adapter.ts index 188b0930a1..f8b8c23b3c 100644 --- a/src/adapter/adapter.ts +++ b/src/adapter/adapter.ts @@ -2,12 +2,11 @@ import * as TsType from './tstype'; import {ZclDataPayload} from './events'; import events from 'events'; import {ZclFrame, FrameType, Direction} from '../zcl'; -import Debug from "debug"; -import {LoggerStub} from "../controller/logger-stub"; import * as Models from "../models"; import Bonjour, {Service} from 'bonjour-service'; +import {logger} from '../utils/logger'; -const debug = Debug("zigbee-herdsman:adapter"); +const NS = 'zh:adapter'; abstract class Adapter extends events.EventEmitter { public readonly greenPowerGroup = 0x0b84; @@ -15,18 +14,14 @@ abstract class Adapter extends events.EventEmitter { protected adapterOptions: TsType.AdapterOptions; protected serialPortOptions: TsType.SerialPortOptions; protected backupPath: string; - protected logger?: LoggerStub; - protected constructor( - networkOptions: TsType.NetworkOptions, serialPortOptions: TsType.SerialPortOptions, backupPath: string, - adapterOptions: TsType.AdapterOptions, logger?: LoggerStub) - { + protected constructor(networkOptions: TsType.NetworkOptions, serialPortOptions: TsType.SerialPortOptions, backupPath: string, + adapterOptions: TsType.AdapterOptions) { super(); this.networkOptions = networkOptions; this.adapterOptions = adapterOptions; this.serialPortOptions = serialPortOptions; this.backupPath = backupPath; - this.logger = logger; } /** @@ -38,7 +33,6 @@ abstract class Adapter extends events.EventEmitter { serialPortOptions: TsType.SerialPortOptions, backupPath: string, adapterOptions: TsType.AdapterOptions, - logger?: LoggerStub, ): Promise { const {ZStackAdapter} = await import('./z-stack/adapter'); const {DeconzAdapter} = await import('./deconz/adapter'); @@ -68,11 +62,11 @@ abstract class Adapter extends events.EventEmitter { let adapter: AdapterImplementation = adapters[0]; if (!serialPortOptions.path) { - debug('No path provided, auto detecting path'); + logger.debug('No path provided, auto detecting path', NS); for (const candidate of adapters) { const path = await candidate.autoDetectPath(); if (path) { - debug(`Auto detected path '${path}' from adapter '${candidate.name}'`); + logger.debug(`Auto detected path '${path}' from adapter '${candidate.name}'`, NS); serialPortOptions.path = path; adapter = candidate; break; @@ -93,7 +87,7 @@ abstract class Adapter extends events.EventEmitter { const bj = new Bonjour(); const mdnsTimeout = 2000; // timeout for mdns scan - logger.info(`Starting mdns discovery for coordinator: ${mdnsDevice}`); + logger.info(`Starting mdns discovery for coordinator: ${mdnsDevice}`, NS); await new Promise((resolve, reject) => { bj.findOne({type: mdnsDevice}, mdnsTimeout, function (service: Service) { if (service) { @@ -103,10 +97,10 @@ abstract class Adapter extends events.EventEmitter { const mdnsAdapter = (service.txt.radio_type == 'znp' ? 'zstack' : service.txt.radio_type) as TsType.SerialPortOptions['adapter']; const mdnsBaud = parseInt(service.txt.baud_rate); - logger.info(`Coordinator Ip: ${mdnsIp}`); - logger.info(`Coordinator Port: ${mdnsPort}`); - logger.info(`Coordinator Radio: ${mdnsAdapter}`); - logger.info(`Coordinator Baud: ${mdnsBaud}\n`); + logger.info(`Coordinator Ip: ${mdnsIp}`, NS); + logger.info(`Coordinator Port: ${mdnsPort}`, NS); + logger.info(`Coordinator Radio: ${mdnsAdapter}`, NS); + logger.info(`Coordinator Baud: ${mdnsBaud}\n`, NS); bj.destroy(); serialPortOptions.path = `tcp://${mdnsIp}:${mdnsPort}`; serialPortOptions.adapter = mdnsAdapter; @@ -116,7 +110,7 @@ abstract class Adapter extends events.EventEmitter { && serialPortOptions.adapter !== 'auto') { adapter = adapterLookup[serialPortOptions.adapter]; resolve( - new adapter(networkOptions, serialPortOptions, backupPath, adapterOptions, logger) + new adapter(networkOptions, serialPortOptions, backupPath, adapterOptions) ); } else { reject(new Error(`Adapter ${serialPortOptions.adapter} is not supported.`)); @@ -142,17 +136,17 @@ abstract class Adapter extends events.EventEmitter { // Determine adapter to use for (const candidate of adapters) { if (await candidate.isValidPath(serialPortOptions.path)) { - debug(`Path '${serialPortOptions.path}' is valid for '${candidate.name}'`); + logger.debug(`Path '${serialPortOptions.path}' is valid for '${candidate.name}'`, NS); adapter = candidate; break; } } } catch (error) { - debug(`Failed to validate path: '${error}'`); + logger.debug(`Failed to validate path: '${error}'`, NS); } } - return new adapter(networkOptions, serialPortOptions, backupPath, adapterOptions, logger); + return new adapter(networkOptions, serialPortOptions, backupPath, adapterOptions); } public abstract start(): Promise; diff --git a/src/adapter/deconz/adapter/deconzAdapter.ts b/src/adapter/deconz/adapter/deconzAdapter.ts index 9b9ae27f39..2e1527d336 100644 --- a/src/adapter/deconz/adapter/deconzAdapter.ts +++ b/src/adapter/deconz/adapter/deconzAdapter.ts @@ -5,9 +5,7 @@ import { DeviceType, ActiveEndpoints, SimpleDescriptor, LQI, RoutingTable, Backup as BackupType, NetworkParameters, StartResult, LQINeighbor, RoutingTableEntry, AdapterOptions, } from '../../tstype'; -import Debug from "debug"; import Adapter from '../../adapter'; -const debug = Debug("zigbee-herdsman:deconz:adapter"); import Driver from '../driver/driver'; import {ZclFrame, FrameType, Direction, Foundation} from '../../../zcl'; import * as Events from '../../events'; @@ -17,9 +15,10 @@ import processFrame from '../driver/frameParser'; import {Queue, Waitress, Wait} from '../../../utils'; import PARAM from '../driver/constants'; import { Command, WaitForDataRequest, ApsDataRequest, ReceivedDataResponse, DataStateResponse, gpDataInd } from '../driver/constants'; -import {LoggerStub} from "../../../controller/logger-stub"; import * as Models from "../../../models"; +import {logger} from '../../../utils/logger'; +const NS = 'zh:deconz'; var frameParser = require('../driver/frameParser'); interface WaitressMatcher { @@ -43,10 +42,9 @@ class DeconzAdapter extends Adapter { private waitress: Waitress; private TX_OPTIONS = 0x00; // No APS ACKS - public constructor(networkOptions: NetworkOptions, - serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions, logger?: LoggerStub) { + public constructor(networkOptions: NetworkOptions, serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions) { - super(networkOptions, serialPortOptions, backupPath, adapterOptions, logger); + super(networkOptions, serialPortOptions, backupPath, adapterOptions); const concurrent = this.adapterOptions && this.adapterOptions.concurrent ? this.adapterOptions.concurrent : 2; @@ -156,10 +154,10 @@ class DeconzAdapter extends Adapter { } await this.driver.writeParameterRequest(PARAM.PARAM.Network.PERMIT_JOIN, seconds); - debug("PERMIT_JOIN - " + seconds + " seconds"); + logger.debug("PERMIT_JOIN - " + seconds + " seconds", NS); } catch (error) { const msg = "PERMIT_JOIN FAILED - " + error; - debug(msg); + logger.debug(msg, NS); // try again this.permitJoin(seconds, networkAddress); //return Promise.reject(new Error(msg)); // do not reject @@ -187,7 +185,7 @@ class DeconzAdapter extends Adapter { this.fwVersion = {type: type, meta: meta}; return {type: type, meta: meta}; } catch (error) { - debug("Get coordinator version Error: " + error); + logger.debug("Get coordinator version Error: " + error, NS); } } } @@ -268,11 +266,11 @@ class DeconzAdapter extends Adapter { } } - debug("LQI RESPONSE - addr: 0x" + networkAddress.toString(16) + " status: " + response.status + " read " + (response.tableListCount + response.startIndex) + "/" + response.tableEntrys + " entrys"); + logger.debug("LQI RESPONSE - addr: 0x" + networkAddress.toString(16) + " status: " + response.status + " read " + (response.tableListCount + response.startIndex) + "/" + response.tableEntrys + " entrys", NS); return response; } catch (error) { const msg = "LQI REQUEST FAILED - addr: 0x" + networkAddress.toString(16) + " " + error; - debug(msg); + logger.debug(msg, NS); return Promise.reject(new Error(msg)); } }; @@ -362,11 +360,11 @@ class DeconzAdapter extends Adapter { } } - debug("ROUTING_TABLE RESPONSE - addr: 0x" + networkAddress.toString(16) + " status: " + response.status + " read " + (response.tableListCount + response.startIndex) + "/" + response.tableEntrys + " entrys"); + logger.debug("ROUTING_TABLE RESPONSE - addr: 0x" + networkAddress.toString(16) + " status: " + response.status + " read " + (response.tableListCount + response.startIndex) + "/" + response.tableEntrys + " entrys", NS); return response; } catch (error) { const msg = "ROUTING_TABLE REQUEST FAILED - addr: 0x" + networkAddress.toString(16) + " " + error; - debug(msg); + logger.debug(msg, NS); return Promise.reject(new Error(msg)); } }; @@ -417,11 +415,11 @@ class DeconzAdapter extends Adapter { const type: DeviceType = (logicaltype === 1) ? 'Router' : (logicaltype === 2) ? 'EndDevice' : (logicaltype === 0) ? 'Coordinator' : 'Unknown'; const manufacturer = buf.readUInt16LE(7); - debug("RECEIVING NODE_DESCRIPTOR - addr: 0x" + networkAddress.toString(16) + " type: " + type + " manufacturer: 0x" + manufacturer.toString(16)); + logger.debug("RECEIVING NODE_DESCRIPTOR - addr: 0x" + networkAddress.toString(16) + " type: " + type + " manufacturer: 0x" + manufacturer.toString(16), NS); return {manufacturerCode: manufacturer, type}; } catch (error) { const msg = "RECEIVING NODE_DESCRIPTOR FAILED - addr: 0x" + networkAddress.toString(16) + " " + error; - debug(msg); + logger.debug(msg, NS); return Promise.reject(new Error(msg)); } } @@ -460,11 +458,11 @@ class DeconzAdapter extends Adapter { for (let i = 5; i < (epCount + 5); i++) { epList.push(buf.readUInt8(i)); } - debug("ACTIVE_ENDPOINTS - addr: 0x" + networkAddress.toString(16) + " EP list: " + epList); + logger.debug("ACTIVE_ENDPOINTS - addr: 0x" + networkAddress.toString(16) + " EP list: " + epList, NS); return {endpoints: epList}; } catch (error) { const msg = "READING ACTIVE_ENDPOINTS FAILED - addr: 0x" + networkAddress.toString(16) + " " + error; - debug(msg); + logger.debug(msg, NS); return Promise.reject(new Error(msg)); } } @@ -520,17 +518,17 @@ class DeconzAdapter extends Adapter { inputClusters: inClusters, outputClusters: outClusters } - debug("RECEIVING SIMPLE_DESCRIPTOR - addr: 0x" + networkAddress.toString(16) + " EP:" + simpleDesc.endpointID + " inClusters: " + inClusters + " outClusters: " + outClusters); + logger.debug("RECEIVING SIMPLE_DESCRIPTOR - addr: 0x" + networkAddress.toString(16) + " EP:" + simpleDesc.endpointID + " inClusters: " + inClusters + " outClusters: " + outClusters, NS); return simpleDesc; } catch (error) { const msg = "RECEIVING SIMPLE_DESCRIPTOR FAILED - addr: 0x" + networkAddress.toString(16) + " " + error; - debug(msg); + logger.debug(msg, NS); return Promise.reject(new Error(msg)); } } private async checkCoordinatorSimpleDescriptor(skip: boolean): Promise { - debug("checking coordinator simple descriptor"); + logger.debug("checking coordinator simple descriptor", NS); var simpleDesc: any = null; if (skip === false) { try { @@ -542,15 +540,15 @@ class DeconzAdapter extends Adapter { this.checkCoordinatorSimpleDescriptor(false); return; } - debug("EP: " + simpleDesc.endpointID); - debug("profile ID: " + simpleDesc.profileID); - debug("device ID: " + simpleDesc.deviceID); + logger.debug("EP: " + simpleDesc.endpointID, NS); + logger.debug("profile ID: " + simpleDesc.profileID, NS); + logger.debug("device ID: " + simpleDesc.deviceID, NS); for (let i = 0; i < simpleDesc.inputClusters.length; i++) { - debug("input cluster: 0x" + simpleDesc.inputClusters[i].toString(16)); + logger.debug("input cluster: 0x" + simpleDesc.inputClusters[i].toString(16), NS); } for (let o = 0; o < simpleDesc.outputClusters.length; o++) { - debug("output cluster: 0x" + simpleDesc.outputClusters[o].toString(16)); + logger.debug("output cluster: 0x" + simpleDesc.outputClusters[o].toString(16), NS); } let ok = true; @@ -559,7 +557,7 @@ class DeconzAdapter extends Adapter { !simpleDesc.inputClusters.includes(0x19) || !simpleDesc.inputClusters.includes(0x0501) || !simpleDesc.outputClusters.includes(0x01) || !simpleDesc.outputClusters.includes(0x20) || !simpleDesc.outputClusters.includes(0x500) || !simpleDesc.outputClusters.includes(0x502)) { - debug("missing cluster"); + logger.debug("missing cluster", NS); ok = false; } @@ -569,17 +567,17 @@ class DeconzAdapter extends Adapter { } } - debug("setting new simple descriptor"); + logger.debug("setting new simple descriptor", NS); try { //[ sd1 ep proId devId vers #inCl iCl1 iCl2 iCl3 iCl4 iCl5 #outC oCl1 oCl2 oCl3 oCl4 ] const sd = [ 0x00, 0x01, 0x04, 0x01, 0x05, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x06, 0x0A, 0x00, 0x19, 0x00, 0x01, 0x05, 0x04, 0x01, 0x00, 0x20, 0x00, 0x00, 0x05, 0x02, 0x05]; const sd1 = sd.reverse(); await this.driver.writeParameterRequest(PARAM.PARAM.STK.Endpoint, sd1); } catch (error) { - debug("error setting simple descriptor - try again"); + logger.debug("error setting simple descriptor - try again", NS); this.checkCoordinatorSimpleDescriptor(true); return; } - debug("success setting simple descriptor"); + logger.debug("success setting simple descriptor", NS); } public waitFor( @@ -604,8 +602,8 @@ class DeconzAdapter extends Adapter { const request: ApsDataRequest = {}; let pay = zclFrame.toBuffer(); - //console.log("zclFramte.toBuffer:"); - //console.log(pay); + //logger.info("zclFramte.toBuffer:", NS); + //logger.info(pay, NS); request.requestId = transactionID; request.destAddrMode = PARAM.PARAM.addressMode.NWK_ADDR; @@ -623,16 +621,16 @@ class DeconzAdapter extends Adapter { const command = zclFrame.getCommand(); this.driver.enqueueSendDataRequest(request) .then(result => { - debug(`sendZclFrameToEndpoint - message send with transSeq Nr.: ${zclFrame.Header.transactionSequenceNumber}`); - debug(command.hasOwnProperty('response') + ", " + zclFrame.Header.frameControl.disableDefaultResponse + ", " + disableResponse + ", " + request.timeout); + logger.debug(`sendZclFrameToEndpoint - message send with transSeq Nr.: ${zclFrame.Header.transactionSequenceNumber}`, NS); + logger.debug(command.hasOwnProperty('response') + ", " + zclFrame.Header.frameControl.disableDefaultResponse + ", " + disableResponse + ", " + request.timeout, NS); if (!command.hasOwnProperty('response') || zclFrame.Header.frameControl.disableDefaultResponse || !disableResponse) { - debug(`resolve request (${zclFrame.Header.transactionSequenceNumber})`); + logger.debug(`resolve request (${zclFrame.Header.transactionSequenceNumber})`, NS); return Promise.resolve(); } }) .catch(error => { - debug(`sendZclFrameToEndpoint ERROR (${zclFrame.Header.transactionSequenceNumber})`); - debug(error); + logger.debug(`sendZclFrameToEndpoint ERROR (${zclFrame.Header.transactionSequenceNumber})`, NS); + logger.debug(error, NS); //return Promise.reject(new Error("sendZclFrameToEndpoint ERROR " + error)); }); try { @@ -655,10 +653,10 @@ class DeconzAdapter extends Adapter { wasBroadcast: data.srcAddrMode === 0x01 || data.srcAddrMode === 0xF, destinationEndpoint: data.destEndpoint, }; - debug(`response received (${zclFrame.Header.transactionSequenceNumber})`); + logger.debug(`response received (${zclFrame.Header.transactionSequenceNumber})`, NS); return response; } else { - debug(`no response expected (${zclFrame.Header.transactionSequenceNumber})`); + logger.debug(`no response expected (${zclFrame.Header.transactionSequenceNumber})`, NS); return null; } @@ -672,10 +670,10 @@ class DeconzAdapter extends Adapter { const request: ApsDataRequest = {}; let pay = zclFrame.toBuffer(); - debug("zclFrame to group - zclFrame.payload:"); - debug(zclFrame.Payload); - //console.log("zclFramte.toBuffer:"); - //console.log(pay); + logger.debug("zclFrame to group - zclFrame.payload:", NS); + logger.debug(zclFrame.Payload, NS); + //logger.info("zclFramte.toBuffer:", NS); + //logger.info(pay, NS); request.requestId = transactionID; request.destAddrMode = PARAM.PARAM.addressMode.GROUP_ADDR; @@ -689,10 +687,10 @@ class DeconzAdapter extends Adapter { request.radius = PARAM.PARAM.txRadius.UNLIMITED; try { - debug(`sendZclFrameToGroup - message send`); + logger.debug(`sendZclFrameToGroup - message send`, NS); return this.driver.enqueueSendDataRequest(request) as Promise; } catch (error) { - //debug(`sendZclFrameToGroup ERROR: ${error}`); + //logger.debug(`sendZclFrameToGroup ERROR: ${error}`, NS); throw new Error(error); } } @@ -702,8 +700,8 @@ class DeconzAdapter extends Adapter { const request: ApsDataRequest = {}; let pay = zclFrame.toBuffer(); - debug("zclFrame to all - zclFrame.payload:"); - debug(zclFrame.Payload); + logger.debug("zclFrame to all - zclFrame.payload:", NS); + logger.debug(zclFrame.Payload, NS); request.requestId = transactionID; request.destAddrMode = PARAM.PARAM.addressMode.NWK_ADDR; @@ -718,10 +716,10 @@ class DeconzAdapter extends Adapter { request.radius = PARAM.PARAM.txRadius.UNLIMITED; try { - debug(`sendZclFrameToAll - message send`); + logger.debug(`sendZclFrameToAll - message send`, NS); return this.driver.enqueueSendDataRequest(request) as Promise; } catch (error) { - //debug(`sendZclFrameToAll ERROR: ${error}`); + //logger.debug(`sendZclFrameToAll ERROR: ${error}`, NS); throw new Error(error); } } @@ -767,12 +765,12 @@ class DeconzAdapter extends Adapter { try { const d = await this.waitForData(destinationNetworkAddress, 0, 0x8021); const data = d.asduPayload; - debug("BIND RESPONSE - addr: 0x" + destinationNetworkAddress.toString(16) + " status: " + data[1]); + logger.debug("BIND RESPONSE - addr: 0x" + destinationNetworkAddress.toString(16) + " status: " + data[1], NS); if (data[1] !== 0) { throw new Error("status: " + data[1]); } } catch (error) { - debug("BIND FAILED - addr: 0x" + destinationNetworkAddress.toString(16) + " " + error); + logger.debug("BIND FAILED - addr: 0x" + destinationNetworkAddress.toString(16) + " " + error, NS); throw new Error(error); } } @@ -819,12 +817,12 @@ class DeconzAdapter extends Adapter { try { const d = await this.waitForData(destinationNetworkAddress, 0, 0x8022); const data = d.asduPayload; - debug("UNBIND RESPONSE - addr: 0x" + destinationNetworkAddress.toString(16) + " status: " + data[1]); + logger.debug("UNBIND RESPONSE - addr: 0x" + destinationNetworkAddress.toString(16) + " status: " + data[1], NS); if (data[1] !== 0) { throw new Error("status: " + data[1]); } } catch (error) { - debug("UNBIND FAILED - addr: 0x" + destinationNetworkAddress.toString(16) + " " + error); + logger.debug("UNBIND FAILED - addr: 0x" + destinationNetworkAddress.toString(16) + " " + error, NS); throw new Error(error); } } @@ -856,7 +854,7 @@ class DeconzAdapter extends Adapter { try { const d = await this.waitForData(networkAddress, 0, 0x8034); const data = d.asduPayload; - debug("REMOVE_DEVICE - addr: 0x" + networkAddress.toString(16) + " status: " + data[1]); + logger.debug("REMOVE_DEVICE - addr: 0x" + networkAddress.toString(16) + " status: " + data[1], NS); const payload: Events.DeviceLeavePayload = { networkAddress: networkAddress, ieeeAddr: ieeeAddr, @@ -866,7 +864,7 @@ class DeconzAdapter extends Adapter { } this.emit(Events.Events.deviceLeave, payload); } catch (error) { - debug("REMOVE_DEVICE FAILED - addr: 0x" + networkAddress.toString(16) + " " + error); + logger.debug("REMOVE_DEVICE FAILED - addr: 0x" + networkAddress.toString(16) + " " + error, NS); throw new Error(error); } } @@ -889,7 +887,7 @@ class DeconzAdapter extends Adapter { // check current channel against configuration.yaml if (this.networkOptions.channelList[0] !== channel) { - debug("Channel in configuration.yaml (" + this.networkOptions.channelList[0] + ") differs from current channel (" + channel + "). Changing channel."); + logger.debug("Channel in configuration.yaml (" + this.networkOptions.channelList[0] + ") differs from current channel (" + channel + "). Changing channel.", NS); let setChannelMask = 0; switch (this.networkOptions.channelList[0]) { @@ -950,47 +948,47 @@ class DeconzAdapter extends Adapter { await this.sleep(500); changed = true; } catch (error) { - debug("Could not set channel: " + error); + logger.debug("Could not set channel: " + error, NS); } } // check current panid against configuration.yaml if (this.networkOptions.panID !== panid) { - debug("panid in configuration.yaml (" + this.networkOptions.panID + ") differs from current panid (" + panid + "). Changing panid."); + logger.debug("panid in configuration.yaml (" + this.networkOptions.panID + ") differs from current panid (" + panid + "). Changing panid.", NS); try { await this.driver.writeParameterRequest(PARAM.PARAM.Network.PAN_ID, this.networkOptions.panID); await this.sleep(500); changed = true; } catch (error) { - debug("Could not set panid: " + error); + logger.debug("Could not set panid: " + error, NS); } } // check current extended_panid against configuration.yaml if (this.driver.generalArrayToString(this.networkOptions.extendedPanID, 8) !== expanid) { - debug("extended panid in configuration.yaml (" + this.driver.macAddrArrayToString(this.networkOptions.extendedPanID) + ") differs from current extended panid (" + expanid + "). Changing extended panid."); + logger.debug("extended panid in configuration.yaml (" + this.driver.macAddrArrayToString(this.networkOptions.extendedPanID) + ") differs from current extended panid (" + expanid + "). Changing extended panid.", NS); try { await this.driver.writeParameterRequest(PARAM.PARAM.Network.APS_EXT_PAN_ID, this.networkOptions.extendedPanID); await this.sleep(500); changed = true; } catch (error) { - debug("Could not set extended panid: " + error); + logger.debug("Could not set extended panid: " + error, NS); } } // check current network key against configuration.yaml if (this.driver.generalArrayToString(this.networkOptions.networkKey, 16) !== networkKey) { - debug("network key in configuration.yaml (hidden) differs from current network key (" + networkKey + "). Changing network key."); + logger.debug("network key in configuration.yaml (hidden) differs from current network key (" + networkKey + "). Changing network key.", NS); try { await this.driver.writeParameterRequest(PARAM.PARAM.Network.NETWORK_KEY, this.networkOptions.networkKey); await this.sleep(500); changed = true; } catch (error) { - debug("Could not set network key: " + error); + logger.debug("Could not set network key: " + error, NS); } } @@ -1013,7 +1011,7 @@ class DeconzAdapter extends Adapter { }; } catch (error) { const msg = "get network parameters Error:" + error; - debug(msg); + logger.debug(msg, NS); return Promise.reject(new Error(msg)); } } @@ -1109,7 +1107,7 @@ class DeconzAdapter extends Adapter { try { frame = ZclFrame.fromBuffer(resp.clusterId, Buffer.from(resp.asduPayload)); } catch (error) { - debug("could not parse zclFrame: " + error); + logger.debug("could not parse zclFrame: " + error, NS); } } } @@ -1121,12 +1119,12 @@ class DeconzAdapter extends Adapter { req.profileId === resp.profileId) { if (frame !== null && req.transactionSequenceNumber !== null && req.transactionSequenceNumber !== undefined) { if (req.transactionSequenceNumber === frame.Header.transactionSequenceNumber) { - debug("resolve data request with transSeq Nr.: " + req.transactionSequenceNumber); + logger.debug("resolve data request with transSeq Nr.: " + req.transactionSequenceNumber, NS); this.openRequestsQueue.splice(i, 1); req.resolve(resp); } } else { - debug("resolve data request without a transSeq Nr."); + logger.debug("resolve data request without a transSeq Nr.", NS); this.openRequestsQueue.splice(i, 1); req.resolve(resp); } @@ -1137,7 +1135,7 @@ class DeconzAdapter extends Adapter { // Default timeout: 60 seconds. // Comparison is negated to prevent orphans when invalid timeout is entered (resulting in NaN). if (!((now - req.ts) <= (req.timeout ?? 60000))) { - //debug("Timeout for request in openRequestsQueue addr: " + req.addr.toString(16) + " clusterId: " + req.clusterId.toString(16) + " profileId: " + req.profileId.toString(16)); + //logger.debug("Timeout for request in openRequestsQueue addr: " + req.addr.toString(16) + " clusterId: " + req.clusterId.toString(16) + " profileId: " + req.profileId.toString(16), NS); //remove from busyQueue this.openRequestsQueue.splice(i, 1); req.reject("waiting for response TIMEOUT"); diff --git a/src/adapter/deconz/driver/driver.ts b/src/adapter/deconz/driver/driver.ts index ed4293cb61..a2d29e0346 100644 --- a/src/adapter/deconz/driver/driver.ts +++ b/src/adapter/deconz/driver/driver.ts @@ -1,6 +1,5 @@ /* istanbul ignore file */ /* eslint-disable */ -import Debug from 'debug'; import events from 'events'; import Writer from './writer'; import Parser from './parser'; @@ -15,8 +14,9 @@ import { Command, Request, parameterT, ApsDataRequest, ReceivedDataResponse, Dat // @ts-ignore import slip from 'slip'; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:deconz:driver'); +const NS = 'zh:deconz:driver'; const autoDetectDefinitions = [ {manufacturer: 'dresden elektronik ingenieurtechnik GmbH', vendorId: '1cf1', productId: '0030'}, // Conbee II @@ -96,10 +96,10 @@ class Driver extends events.EventEmitter { .then(result => {}) .catch(error => { //try again - debug("try again to reset watchdog"); + logger.debug("try again to reset watchdog", NS); that.writeParameterRequest(0x26, 600) .then(result => {}) - .catch(error => {debug("warning watchdog was not reset");}); + .catch(error => {logger.debug("warning watchdog was not reset", NS);}); }); }, (1000 * 60 * 8)); // 8 minutes @@ -125,11 +125,11 @@ class Driver extends events.EventEmitter { protected catchPromise(val: any) { return Promise.resolve(val) - .catch(err => debug(`Promise was caught with reason: ${err}`)); + .catch(err => logger.debug(`Promise was caught with reason: ${err}`, NS)); } public setDelay(delay: number): void { - debug(`Set delay to ${delay}`); + logger.debug(`Set delay to ${delay}`, NS); this.DELAY = delay; this.READY_TO_SEND_TIMEOUT = delay; this.PROCESS_QUEUES = delay; @@ -174,7 +174,7 @@ class Driver extends events.EventEmitter { } private onPortClose(): void { - debug('Port closed'); + logger.debug('Port closed', NS); this.initialized = false; this.emit('close'); } @@ -185,7 +185,7 @@ class Driver extends events.EventEmitter { } public openSerialPort(baudrate: number): Promise { - debug(`Opening with ${this.path}`); + logger.debug(`Opening with ${this.path}`, NS); this.serialPort = new SerialPort({path: this.path, baudRate: baudrate, autoOpen: false}); //38400 RaspBee //115200 ConBee3 this.writer = new Writer(); @@ -205,7 +205,7 @@ class Driver extends events.EventEmitter { this.serialPort.close(); } } else { - debug('Serialport opened'); + logger.debug('Serialport opened', NS); this.initialized = true; resolve(); } @@ -215,7 +215,7 @@ class Driver extends events.EventEmitter { private async openSocketPort(): Promise { const info = SocketPortUtils.parseTcpPath(this.path); - debug(`Opening TCP socket with ${info.host}:${info.port}`); + logger.debug(`Opening TCP socket with ${info.host}:${info.port}`, NS); this.socketPort = new net.Socket(); this.socketPort.setNoDelay(true); this.socketPort.setKeepAlive(true, 15000); @@ -229,13 +229,13 @@ class Driver extends events.EventEmitter { return new Promise((resolve, reject): void => { this.socketPort.on('connect', function() { - debug('Socket connected'); + logger.debug('Socket connected', NS); }); // eslint-disable-next-line const self = this; this.socketPort.on('ready', async function() { - debug('Socket ready'); + logger.debug('Socket ready', NS); self.initialized = true; resolve(); }); @@ -243,7 +243,7 @@ class Driver extends events.EventEmitter { this.socketPort.once('close', this.onPortClose); this.socketPort.on('error', function () { - debug('Socket error'); + logger.debug('Socket error', NS); reject(new Error(`Error while opening socket`)); self.initialized = false; }); @@ -280,7 +280,7 @@ class Driver extends events.EventEmitter { public readParameterRequest(parameterId: number) : Promise { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`push read parameter request to queue. seqNr: ${seqNumber} paramId: ${parameterId}`); + //logger.debug(`push read parameter request to queue. seqNr: ${seqNumber} paramId: ${parameterId}`, NS); const ts = 0; const commandId = PARAM.PARAM.FrameType.ReadParameter; const req: Request = {commandId, parameterId, seqNumber, resolve, reject, ts}; @@ -291,7 +291,7 @@ class Driver extends events.EventEmitter { public writeParameterRequest(parameterId: number, parameter: parameterT) : Promise { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`push write parameter request to queue. seqNr: ${seqNumber} paramId: ${parameterId} parameter: ${parameter}`); + //logger.debug(`push write parameter request to queue. seqNr: ${seqNumber} paramId: ${parameterId} parameter: ${parameter}`, NS); const ts = 0; const commandId = PARAM.PARAM.FrameType.WriteParameter; const req: Request = {commandId, parameterId, parameter, seqNumber, resolve, reject, ts}; @@ -302,7 +302,7 @@ class Driver extends events.EventEmitter { public readFirmwareVersionRequest() : Promise { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`push read firmware version request to queue. seqNr: ${seqNumber}`); + //logger.debug(`push read firmware version request to queue. seqNr: ${seqNumber}`, NS); const ts = 0; const commandId = PARAM.PARAM.FrameType.ReadFirmwareVersion; const req: Request = {commandId, seqNumber, resolve, reject, ts}; @@ -330,7 +330,7 @@ class Driver extends events.EventEmitter { } else { parameterLength = this.getLengthOfParameter(parameterId); } - //debug("SEND WRITE_PARAMETER Request - parameter id: " + parameterId + " value: " + value.toString(16) + " length: " + parameterLength); + //logger.debug("SEND WRITE_PARAMETER Request - parameter id: " + parameterId + " value: " + value.toString(16) + " length: " + parameterLength, NS); const payloadLength = 1 + parameterLength; const frameLength = 7 + payloadLength; @@ -388,7 +388,7 @@ class Driver extends events.EventEmitter { private sendReadFirmwareVersionRequest(seqNumber: number) { /* command id, sequence number, 0, framelength(U16) */ const requestFrame = [PARAM.PARAM.FrameType.ReadFirmwareVersion, seqNumber, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]; - //debug(requestFrame); + //logger.debug(requestFrame, NS); this.sendRequest(requestFrame); } @@ -406,13 +406,13 @@ class Driver extends events.EventEmitter { if ( this.portType === 'serial') { this.serialPort.write(slipframe, function(err) { if (err) { - debug("Error writing serial Port: " + err.message); + logger.debug("Error writing serial Port: " + err.message, NS); } }); } else { this.socketPort.write(slipframe, function(err) { if (err) { - debug("Error writing socket Port: " + err.message); + logger.debug("Error writing socket Port: " + err.message, NS); } }); } @@ -430,23 +430,23 @@ class Driver extends events.EventEmitter { switch (req.commandId) { case PARAM.PARAM.FrameType.ReadParameter: - debug(`send read parameter request from queue. seqNr: ${req.seqNumber} paramId: ${req.parameterId}`); + logger.debug(`send read parameter request from queue. seqNr: ${req.seqNumber} paramId: ${req.parameterId}`, NS); this.sendReadParameterRequest(req.parameterId, req.seqNumber); break; case PARAM.PARAM.FrameType.WriteParameter: - debug(`send write parameter request from queue. seqNr: ${req.seqNumber} paramId: ${req.parameterId} param: ${req.parameter}`); + logger.debug(`send write parameter request from queue. seqNr: ${req.seqNumber} paramId: ${req.parameterId} param: ${req.parameter}`, NS); this.sendWriteParameterRequest(req.parameterId, req.parameter, req.seqNumber); break; case PARAM.PARAM.FrameType.ReadFirmwareVersion: - debug(`send read firmware version request from queue. seqNr: ${req.seqNumber}`); + logger.debug(`send read firmware version request from queue. seqNr: ${req.seqNumber}`, NS); this.sendReadFirmwareVersionRequest(req.seqNumber); break; case PARAM.PARAM.FrameType.ReadDeviceState: - debug(`send read device state from queue. seqNr: ${req.seqNumber}`); + logger.debug(`send read device state from queue. seqNr: ${req.seqNumber}`, NS); this.sendReadDeviceStateRequest(req.seqNumber); break; case PARAM.PARAM.NetworkState.CHANGE_NETWORK_STATE: - debug(`send change network state request from queue. seqNr: ${req.seqNumber}`); + logger.debug(`send change network state request from queue. seqNr: ${req.seqNumber}`, NS); this.sendChangeNetworkStateRequest(req.seqNumber, req.networkState); break; default: @@ -464,7 +464,7 @@ class Driver extends events.EventEmitter { const now = Date.now(); if ((now - req.ts) > 10000) { - debug(`Timeout for request - CMD: 0x${req.commandId.toString(16)} seqNr: ${req.seqNumber}`); + logger.debug(`Timeout for request - CMD: 0x${req.commandId.toString(16)} seqNr: ${req.seqNumber}`, NS); //remove from busyQueue busyQueue.splice(i, 1); timeoutCounter++; @@ -476,7 +476,7 @@ class Driver extends events.EventEmitter { req.reject("TIMEOUT"); if (timeoutCounter >= 2) { timeoutCounter = 0; - debug("too many timeouts - restart serial connecion"); + logger.debug("too many timeouts - restart serial connecion", NS); if (this.serialPort?.isOpen) { this.serialPort.close(); } @@ -492,7 +492,7 @@ class Driver extends events.EventEmitter { public changeNetworkStateRequest(networkState: number) : Promise { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`push change network state request to apsQueue. seqNr: ${seqNumber}`); + //logger.debug(`push change network state request to apsQueue. seqNr: ${seqNumber}`, NS); const ts = 0; const commandId = PARAM.PARAM.NetworkState.CHANGE_NETWORK_STATE; const req: Request = {commandId, networkState, seqNumber, resolve, reject, ts}; @@ -508,7 +508,7 @@ class Driver extends events.EventEmitter { private deviceStateRequest() { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`DEVICE_STATE Request - seqNr: ${seqNumber}`); + //logger.debug(`DEVICE_STATE Request - seqNr: ${seqNumber}`, NS); const ts = 0; const commandId = PARAM.PARAM.FrameType.ReadDeviceState; const req: Request = {commandId, seqNumber, resolve, reject, ts}; @@ -523,14 +523,14 @@ class Driver extends events.EventEmitter { this.configChanged = (currentDeviceStatus >> 4) & 0x01; this.apsRequestFreeSlots = (currentDeviceStatus >> 5) & 0x01; - debug("networkstate: " + networkState + " apsDataConfirm: " + this.apsDataConfirm + " apsDataIndication: " + this.apsDataIndication + - " configChanged: " + this.configChanged + " apsRequestFreeSlots: " + this.apsRequestFreeSlots); + logger.debug("networkstate: " + networkState + " apsDataConfirm: " + this.apsDataConfirm + " apsDataIndication: " + this.apsDataIndication + + " configChanged: " + this.configChanged + " apsRequestFreeSlots: " + this.apsRequestFreeSlots, NS); } private async handleDeviceStatus() { if (this.apsDataConfirm === 1) { try { - debug("query aps data confirm"); + logger.debug("query aps data confirm", NS); this.apsDataConfirm = 0; const x = await this.querySendDataStateRequest(); } catch (e) { @@ -541,7 +541,7 @@ class Driver extends events.EventEmitter { } if (this.apsDataIndication === 1) { try { - debug("query aps data indication"); + logger.debug("query aps data indication", NS); this.apsDataIndication = 0; const x = await this.readReceivedDataRequest(); } catch (e) { @@ -559,7 +559,7 @@ class Driver extends events.EventEmitter { private readReceivedDataRequest() : Promise { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`push read received data request to apsQueue. seqNr: ${seqNumber}`); + //logger.debug(`push read received data request to apsQueue. seqNr: ${seqNumber}`, NS); const ts = 0; const commandId = PARAM.PARAM.APS.DATA_INDICATION; const req: Request = {commandId, seqNumber, resolve, reject, ts}; @@ -571,7 +571,7 @@ class Driver extends events.EventEmitter { public enqueueSendDataRequest(request: ApsDataRequest) : Promise { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`push enqueue send data request to apsQueue. seqNr: ${seqNumber}`); + //logger.debug(`push enqueue send data request to apsQueue. seqNr: ${seqNumber}`, NS); const ts = 0; const requestId = request.requestId; const commandId = PARAM.PARAM.APS.DATA_REQUEST; @@ -584,7 +584,7 @@ class Driver extends events.EventEmitter { private querySendDataStateRequest() : Promise { const seqNumber = this.nextSeqNumber(); return new Promise((resolve, reject): void => { - //debug(`push query send data state request to apsQueue. seqNr: ${seqNumber}`); + //logger.debug(`push query send data state request to apsQueue. seqNr: ${seqNumber}`, NS); const ts = 0; const commandId = PARAM.PARAM.APS.DATA_CONFIRM; const req: Request = {commandId, seqNumber, resolve, reject, ts}; @@ -598,7 +598,7 @@ class Driver extends events.EventEmitter { } if (this.apsRequestFreeSlots !== 1) { - debug("no free slots. Delay sending of APS Request"); + logger.debug("no free slots. Delay sending of APS Request", NS); await this.sleep(1000); return; } @@ -610,7 +610,7 @@ class Driver extends events.EventEmitter { case PARAM.PARAM.APS.DATA_REQUEST: if (readyToSend === false) { // wait until last request was confirmed or given time elapsed - debug("delay sending of APS Request"); + logger.debug("delay sending of APS Request", NS); apsQueue.unshift(req); break; } else { @@ -638,7 +638,7 @@ class Driver extends events.EventEmitter { switch (req.commandId) { case PARAM.PARAM.APS.DATA_INDICATION: - //debug(`read received data request. seqNr: ${req.seqNumber}`); + //logger.debug(`read received data request. seqNr: ${req.seqNumber}`, NS); if (this.DELAY === 0) { this.sendReadReceivedDataRequest(req.seqNumber); } else { @@ -646,7 +646,7 @@ class Driver extends events.EventEmitter { } break; case PARAM.PARAM.APS.DATA_CONFIRM: - //debug(`query send data state request. seqNr: ${req.seqNumber}`); + //logger.debug(`query send data state request. seqNr: ${req.seqNumber}`, NS); if (this.DELAY === 0) { this.sendQueryDataStateRequest(req.seqNumber); } else { @@ -660,13 +660,13 @@ class Driver extends events.EventEmitter { } private sendQueryDataStateRequest(seqNumber: number) { - debug(`DATA_CONFIRM - sending data state request - SeqNr. ${seqNumber}`); + logger.debug(`DATA_CONFIRM - sending data state request - SeqNr. ${seqNumber}`, NS); const requestFrame = [PARAM.PARAM.APS.DATA_CONFIRM, seqNumber, 0x00, 0x07, 0x00, 0x00, 0x00]; this.sendRequest(requestFrame); } private sendReadReceivedDataRequest(seqNumber: number) { - debug(`DATA_INDICATION - sending read data request - SeqNr. ${seqNumber}`); + logger.debug(`DATA_INDICATION - sending read data request - SeqNr. ${seqNumber}`, NS); // payloadlength = 0, flag = none const requestFrame = [PARAM.PARAM.APS.DATA_INDICATION, seqNumber, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01]; this.sendRequest(requestFrame); @@ -696,7 +696,7 @@ class Driver extends events.EventEmitter { dest += request.destEndpoint; } - debug(`DATA_REQUEST - destAddr: 0x${dest} SeqNr. ${seqNumber} request id: ${request.requestId}`); + logger.debug(`DATA_REQUEST - destAddr: 0x${dest} SeqNr. ${seqNumber} request id: ${request.requestId}`, NS); const requestFrame = [PARAM.PARAM.APS.DATA_REQUEST, seqNumber, 0x00, frameLength & 0xff, (frameLength >> 8) & 0xff, payloadLength & 0xff, (payloadLength >> 8) & 0xff, request.requestId, 0x00, request.destAddrMode].concat( @@ -717,7 +717,7 @@ class Driver extends events.EventEmitter { timeout = req.request.timeout * 1000; // seconds * 1000 = milliseconds } if ((now - req.ts) > timeout) { - debug(`Timeout for aps request CMD: 0x${req.commandId.toString(16)} seq: ${req.seqNumber}`); + logger.debug(`Timeout for aps request CMD: 0x${req.commandId.toString(16)} seq: ${req.seqNumber}`, NS); //remove from busyQueue apsBusyQueue.splice(i, 1); req.reject(new Error("APS TIMEOUT")); diff --git a/src/adapter/deconz/driver/frameParser.ts b/src/adapter/deconz/driver/frameParser.ts index d8b8f026b6..5edf5b21b3 100644 --- a/src/adapter/deconz/driver/frameParser.ts +++ b/src/adapter/deconz/driver/frameParser.ts @@ -7,8 +7,9 @@ import { busyQueue, apsBusyQueue, readyToSend, enableRTS, disableRTS, enableRtsT import { Request, ReceivedDataResponse, DataStateResponse, Command, ParamMac, ParamPanId, ParamNwkAddr, ParamExtPanId, ParamChannel, ParamChannelMask, ParamPermitJoin, ParamNetworkKey, gpDataInd } from './constants'; import * as Events from '../../events'; import {ZclFrame} from '../../../zcl'; -import Debug from 'debug'; -const debug = Debug('zigbee-herdsman:deconz:frameParser'); +import {logger} from '../../../utils/logger'; + +const NS = 'zh:deconz:frameparser'; interface lastReceivedGpInd { srcId: number; @@ -32,15 +33,15 @@ function parseReadParameterResponse(view: DataView) : Command { result = "0" + result; } result = "0x" + result; - debug(`MAC: ${result}`); + logger.debug(`MAC: ${result}`, NS); return result; case PARAM.PARAM.Network.PAN_ID: const panId: ParamPanId = view.getUint16(8, littleEndian); - debug('PANID: ' + panId.toString(16)); + logger.debug('PANID: ' + panId.toString(16), NS); return panId; case PARAM.PARAM.Network.NWK_ADDRESS: const nwkAddr: ParamNwkAddr = view.getUint16(8, littleEndian); - debug('NWKADDR: ' + nwkAddr.toString(16)); + logger.debug('NWKADDR: ' + nwkAddr.toString(16), NS); return nwkAddr; case PARAM.PARAM.Network.EXT_PAN_ID: const extPanId: ParamExtPanId = view.getBigUint64(8, littleEndian).toString(16); @@ -49,7 +50,7 @@ function parseReadParameterResponse(view: DataView) : Command { res = "0" + res; } res = "0x" + res; - debug(`EXT_PANID: ${res}`); + logger.debug(`EXT_PANID: ${res}`, NS); return res; case PARAM.PARAM.Network.APS_EXT_PAN_ID: const apsExtPanId: ParamExtPanId = view.getBigUint64(8, littleEndian).toString(16); @@ -58,7 +59,7 @@ function parseReadParameterResponse(view: DataView) : Command { resAEPID = "0" + resAEPID; } resAEPID = "0x" + resAEPID; - debug(`APS_EXT_PANID: ${resAEPID}`); + logger.debug(`APS_EXT_PANID: ${resAEPID}`, NS); return resAEPID; case PARAM.PARAM.Network.NETWORK_KEY: const networkKey1 = view.getBigUint64(9).toString(16); @@ -71,40 +72,40 @@ function parseReadParameterResponse(view: DataView) : Command { while (res2.length < 16) { res2 = "0" + res2; } - debug('NETWORK_KEY: hidden'); + logger.debug('NETWORK_KEY: hidden', NS); return "0x"+res1+res2; case PARAM.PARAM.Network.CHANNEL: const channel: ParamChannel = view.getUint8(8); - debug('CHANNEL: ' + channel); + logger.debug('CHANNEL: ' + channel, NS); return channel; case PARAM.PARAM.Network.CHANNEL_MASK: const chMask: ParamChannelMask = view.getUint32(8, littleEndian); - debug('CHANNELMASK: ' + chMask.toString(16)); + logger.debug('CHANNELMASK: ' + chMask.toString(16), NS); return chMask; case PARAM.PARAM.Network.PERMIT_JOIN: const permitJoin: ParamPermitJoin = view.getUint8(8); - debug('PERMIT_JOIN: ' + permitJoin); + logger.debug('PERMIT_JOIN: ' + permitJoin, NS); return permitJoin; case PARAM.PARAM.Network.WATCHDOG_TTL: const ttl: ParamPermitJoin = view.getUint32(8); - debug('WATCHDOG_TTL: ' + ttl); + logger.debug('WATCHDOG_TTL: ' + ttl, NS); return ttl; default: //throw new Error(`unknown parameter id ${parameterId}`); - debug(`unknown parameter id ${parameterId}`); + logger.debug(`unknown parameter id ${parameterId}`, NS); return null; } } function parseReadFirmwareResponse(view : DataView) : number[] { const fw = [view.getUint8(5), view.getUint8(6), view.getUint8(7), view.getUint8(8)]; - debug("read firmware version response - version: " + fw); + logger.debug("read firmware version response - version: " + fw, NS); return fw; } function parseDeviceStateResponse(view : DataView) : number { const flag = view.getUint8(5); - debug("device state: " + flag.toString(2)); + logger.debug("device state: " + flag.toString(2), NS); frameParserEvents.emit('receivedDataNotification', flag); return flag; } @@ -112,7 +113,7 @@ function parseDeviceStateResponse(view : DataView) : number { function parseChangeNetworkStateResponse(view : DataView) : number { const status = view.getUint8(2); const state = view.getUint8(5); - debug("change network state - status: " + status + " new state: " + state); + logger.debug("change network state - status: " + status + " new state: " + state, NS); return state; } @@ -127,7 +128,7 @@ function parseQuerySendDataStateResponse(view : DataView) : object { if (response.status !== 0) { if (response.status !== 5) { - debug("DATA_CONFIRM RESPONSE - seqNr.: " + response.seqNr + " status: " + response.status); + logger.debug("DATA_CONFIRM RESPONSE - seqNr.: " + response.seqNr + " status: " + response.status, NS); } return null; } @@ -177,22 +178,22 @@ function parseQuerySendDataStateResponse(view : DataView) : object { // TODO timeout (at driver.ts) if (response.confirmStatus !== 0) { // reject if status is not SUCCESS - //debug("REJECT APS_REQUEST - request id: " + response.requestId + " confirm status: " + response.confirmStatus); + //logger.debug("REJECT APS_REQUEST - request id: " + response.requestId + " confirm status: " + response.confirmStatus, NS); req.reject(response.confirmStatus); } else { - //debug("RESOLVE APS_REQUEST - request id: " + response.requestId + " confirm status: " + response.confirmStatus); + //logger.debug("RESOLVE APS_REQUEST - request id: " + response.requestId + " confirm status: " + response.confirmStatus, NS); req.resolve(response.confirmStatus); } //remove from busyqueue apsBusyQueue.splice(i, 1); - debug("DATA_CONFIRM RESPONSE - destAddr: 0x" + destAddr + " request id: " + response.requestId + " confirm status: " + response.confirmStatus); + logger.debug("DATA_CONFIRM RESPONSE - destAddr: 0x" + destAddr + " request id: " + response.requestId + " confirm status: " + response.confirmStatus, NS); frameParserEvents.emit('receivedDataNotification', response.deviceState); return response; } catch (error) { - debug("DATA_CONFIRM RESPONSE - " + error); + logger.debug("DATA_CONFIRM RESPONSE - " + error, NS); return null; } } @@ -209,7 +210,7 @@ function parseReadReceivedDataResponse(view : DataView) : object { if (response.status != 0) { if (response.status !== 5) { - debug("DATA_INDICATION RESPONSE - seqNr.: " + response.seqNr + " status: " + response.status); + logger.debug("DATA_INDICATION RESPONSE - seqNr.: " + response.seqNr + " status: " + response.status, NS); } return null; } @@ -276,13 +277,13 @@ function parseReadReceivedDataResponse(view : DataView) : object { for (let l = 0; l <= (8 - newStatus.length); l++) { newStatus = "0" + newStatus; } - debug("DATA_INDICATION RESPONSE - seqNr. " + response.seqNr + " srcAddr: 0x" + srcAddr + " destAddr: 0x" + destAddr + " profile id: 0x" + response.profileId.toString(16) + " cluster id: 0x" + response.clusterId.toString(16) + " lqi: " + response.lqi); - debug("response payload: " + payload); + logger.debug("DATA_INDICATION RESPONSE - seqNr. " + response.seqNr + " srcAddr: 0x" + srcAddr + " destAddr: 0x" + destAddr + " profile id: 0x" + response.profileId.toString(16) + " cluster id: 0x" + response.clusterId.toString(16) + " lqi: " + response.lqi, NS); + logger.debug("response payload: " + payload, NS); frameParserEvents.emit('receivedDataPayload', response); frameParserEvents.emit('receivedDataNotification', response.deviceState); return response; } catch (error) { - debug("DATA_INDICATION RESPONSE - " + error); + logger.debug("DATA_INDICATION RESPONSE - " + error, NS); return null; } } @@ -292,11 +293,11 @@ function parseEnqueueSendDataResponse(view : DataView) : number { const status = view.getUint8(2); const requestId = view.getUint8(8); const deviceState = view.getUint8(7); - debug("DATA_REQUEST RESPONSE - request id: " + requestId + " status: " + status); + logger.debug("DATA_REQUEST RESPONSE - request id: " + requestId + " status: " + status, NS); frameParserEvents.emit('receivedDataNotification', deviceState); return deviceState; } catch (error) { - debug("parseEnqueueSendDataResponse - " + error); + logger.debug("parseEnqueueSendDataResponse - " + error, NS); return null; } } @@ -304,10 +305,10 @@ function parseEnqueueSendDataResponse(view : DataView) : number { function parseWriteParameterResponse(view : DataView) : number { try { const parameterId = view.getUint8(7); - debug(`write parameter response - parameter id: ${parameterId} - status: ${view.getUint8(2)}`); + logger.debug(`write parameter response - parameter id: ${parameterId} - status: ${view.getUint8(2)}`, NS); return parameterId; } catch (error) { - debug("parseWriteParameterResponse - " + error); + logger.debug("parseWriteParameterResponse - " + error, NS); return null; } } @@ -315,11 +316,11 @@ function parseWriteParameterResponse(view : DataView) : number { function parseReceivedDataNotification(view : DataView) : number { try { const deviceState = view.getUint8(5); - debug("DEVICE_STATE changed: " + deviceState.toString(2)); + logger.debug("DEVICE_STATE changed: " + deviceState.toString(2), NS); frameParserEvents.emit('receivedDataNotification', deviceState); return deviceState; } catch (error) { - debug("parseReceivedDataNotification - " + error); + logger.debug("parseReceivedDataNotification - " + error, NS); return null; } } @@ -330,7 +331,7 @@ function parseGreenPowerDataIndication(view : DataView) : object { ind.seqNr = view.getUint8(1); if (view.byteLength < 30) { - debug("GP data notification"); + logger.debug("GP data notification", NS); ind.id = 0x00; // 0 = notification, 4 = commissioning ind.rspId = 0x01; // 1 = pairing, 2 = commissioning ind.options = 0; view.getUint16(7, littleEndian); // frame ctrl field(7) ext.fcf(8) @@ -347,7 +348,7 @@ function parseGreenPowerDataIndication(view : DataView) : object { } ind.commandFrame = payload; } else { - debug("GP commissioning notification"); + logger.debug("GP commissioning notification", NS); ind.id = 0x04; // 0 = notification, 4 = commissioning ind.rspId = 0x01; // 1 = pairing, 2 = commissioning ind.options = view.getUint16(14, littleEndian); // opt(14) ext.opt(15) @@ -372,30 +373,30 @@ function parseGreenPowerDataIndication(view : DataView) : object { lastReceivedGpInd.srcId = ind.srcId; lastReceivedGpInd.commandId = ind.commandId; lastReceivedGpInd.frameCounter = ind.frameCounter; - //debug(`GP_DATA_INDICATION - src id: ${ind.srcId} cmd id: ${ind.commandId} frameCounter: ${ind.frameCounter}`); - debug(`GP_DATA_INDICATION - src id: 0x${ind.srcId.toString(16)} cmd id: 0x${ind.commandId.toString(16)} frameCounter: 0x${ind.frameCounter.toString(16)}`); + //logger.debug(`GP_DATA_INDICATION - src id: ${ind.srcId} cmd id: ${ind.commandId} frameCounter: ${ind.frameCounter}`, NS); + logger.debug(`GP_DATA_INDICATION - src id: 0x${ind.srcId.toString(16)} cmd id: 0x${ind.commandId.toString(16)} frameCounter: 0x${ind.frameCounter.toString(16)}`, NS); frameParserEvents.emit('receivedGreenPowerIndication', ind); } return ind; } catch (error) { - debug("GREEN_POWER INDICATION - " + error); + logger.debug("GREEN_POWER INDICATION - " + error, NS); return null; } } function parseMacPollCommand(view : DataView) : number { - //debug("Received command MAC_POLL"); + //logger.debug("Received command MAC_POLL", NS); return 28; } function parseBeaconRequest(view : DataView) : number { - debug("Received Beacon Request"); + logger.debug("Received Beacon Request", NS); return 31; } function parseUnknownCommand(view : DataView) : number { const id = view.getUint8(0); - debug(`received unknown command - id ${id}`); + logger.debug(`received unknown command - id ${id}`, NS); return id; } function getParserForCommandId(id: Number) : Function { @@ -432,7 +433,7 @@ function getParserForCommandId(id: Number) : Function { async function processFrame(frame: Uint8Array) : Promise { const [seqNumber, status, command, commandId] = await parseFrame(frame); - //debug(`process frame with seq: ${seqNumber} status: ${status}`); + //logger.debug(`process frame with seq: ${seqNumber} status: ${status}`, NS); let queue = busyQueue; @@ -461,17 +462,17 @@ async function processFrame(frame: Uint8Array) : Promise { queue.splice(i, 1); if (status !== 0) { // reject if status is not SUCCESS - //debug("REJECT REQUEST"); + //logger.debug("REJECT REQUEST", NS); req.reject({status}); } else { - //debug("RESOLVE REQUEST"); + //logger.debug("RESOLVE REQUEST", NS); req.resolve(command); } } function parseFrame(frame: Uint8Array) : [number, number, Command, number] { if (frame.length < MIN_BUFFER_SIZE) { - debug("received frame size to small - discard frame"); + logger.debug("received frame size to small - discard frame", NS); return [null, null, null, null]; } diff --git a/src/adapter/deconz/driver/parser.ts b/src/adapter/deconz/driver/parser.ts index 36e75a3314..ad06a7c7e0 100644 --- a/src/adapter/deconz/driver/parser.ts +++ b/src/adapter/deconz/driver/parser.ts @@ -4,9 +4,9 @@ import * as stream from 'stream'; // @ts-ignore import slip from 'slip'; import Frame from './frame'; -import Debug from "debug"; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:deconz:driver:parser'); +const NS = 'zh:deconz:driver:parser'; class Parser extends stream.Transform { private buffer: Buffer; @@ -26,18 +26,18 @@ class Parser extends stream.Transform { } private onMessage(message: Uint8Array): void { - //debug(`message received: ${message}`); + //logger.debug(`message received: ${message}`, NS); this.emit('parsed', message); } private onError(_: Uint8Array, error: string): void { - debug(`<-- error '${error}'`); + logger.debug(`<-- error '${error}'`, NS); } public _transform(chunk: Buffer, _: string, cb: Function): void { - //debug(`<-- [${[...chunk]}]`); + //logger.debug(`<-- [${[...chunk]}]`, NS); this.decoder.decode(chunk); - //debug(`<-- [${[...chunk]}]`); + //logger.debug(`<-- [${[...chunk]}]`, NS); cb(); } } diff --git a/src/adapter/deconz/driver/writer.ts b/src/adapter/deconz/driver/writer.ts index 74304bb0a0..5e436b7b2b 100644 --- a/src/adapter/deconz/driver/writer.ts +++ b/src/adapter/deconz/driver/writer.ts @@ -4,14 +4,14 @@ import * as stream from 'stream'; import Frame from './frame'; // @ts-ignore import slip from 'slip'; -import Debug from "debug"; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:deconz:driver:writer'); +const NS = 'zh:deconz:driver:writer'; class Writer extends stream.Readable { public writeFrame(frame: Frame): void { const buffer = slip.encode(frame.toBuffer()); - debug(`--> frame [${[...buffer]}]`); + logger.debug(`--> frame [${[...buffer]}]`, NS); this.push(buffer); } diff --git a/src/adapter/ember/adapter/emberAdapter.ts b/src/adapter/ember/adapter/emberAdapter.ts index cee3d0d63c..cf4c5929ec 100644 --- a/src/adapter/ember/adapter/emberAdapter.ts +++ b/src/adapter/ember/adapter/emberAdapter.ts @@ -1,12 +1,10 @@ /* istanbul ignore file */ -import Debug from "debug"; import equals from 'fast-deep-equal/es6'; import {fs} from "mz"; import SerialPortUtils from '../../serialPortUtils'; import SocketPortUtils from '../../socketPortUtils'; import {BackupUtils, RealpathSync, Wait} from "../../../utils"; import {Adapter, TsType} from "../.."; -import {LoggerStub} from "../../../controller/logger-stub"; import {Backup, UnifiedBackupStorage} from "../../../models"; import {FrameType, Direction, ZclFrame, Foundation, ManufacturerCode} from "../../../zcl"; import Cluster from "../../../zcl/definition/cluster"; @@ -59,7 +57,6 @@ import { EmberDeviceUpdate, EzspNetworkScanType, EmberIncomingMessageType, - EmberCounterType, } from "../enums"; import { EmberAesMmoHashContext, @@ -154,9 +151,10 @@ import {FIXED_ENDPOINTS} from "./endpoints"; import {aesMmoHashInit, initNetworkCache, initSecurityManagerContext} from "../utils/initters"; import {randomBytes} from "crypto"; import {EmberOneWaitress, OneWaitressEvents} from "./oneWaitress"; +import {logger} from "../../../utils/logger"; // import {EmberTokensManager} from "./tokensManager"; -const debug = Debug('zigbee-herdsman:adapter:ember:adapter'); +const NS = 'zh:ember'; export type NetworkCache = { //-- basic network info @@ -441,8 +439,8 @@ export class EmberAdapter extends Adapter { private networkCache: NetworkCache; constructor(networkOptions: TsType.NetworkOptions, serialPortOptions: TsType.SerialPortOptions, backupPath: string, - adapterOptions: TsType.AdapterOptions, logger?: LoggerStub) { - super(networkOptions, serialPortOptions, backupPath, adapterOptions, logger); + adapterOptions: TsType.AdapterOptions) { + super(networkOptions, serialPortOptions, backupPath, adapterOptions); // TODO config // XXX: 'zigbeed': 4.4.x/7.4.x not supported by multiprotocol at the moment, will need refactoring when/if support is added @@ -452,7 +450,7 @@ export class EmberAdapter extends Adapter { const delay = (typeof this.adapterOptions.delay === 'number') ? Math.min(Math.max(this.adapterOptions.delay, 5), 60) : 5; - debug(`Using delay=${delay}.`); + logger.debug(`Using delay=${delay}.`, NS); this.requestQueue = new EmberRequestQueue(delay); this.oneWaitress = new EmberOneWaitress(); @@ -484,12 +482,12 @@ export class EmberAdapter extends Adapter { switch (status) { case EmberStatus.NETWORK_UP: { this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_NETWORK_UP); - console.log(`[STACK STATUS] Network up.`); + logger.info(`[STACK STATUS] Network up.`, NS); break; } case EmberStatus.NETWORK_DOWN: { this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_NETWORK_DOWN); - console.log(`[STACK STATUS] Network down.`); + logger.info(`[STACK STATUS] Network down.`, NS); break; } case EmberStatus.NETWORK_OPENED: { @@ -499,32 +497,32 @@ export class EmberAdapter extends Adapter { const setJPstatus = (await this.emberSetJoinPolicy(EmberJoinDecision.USE_PRECONFIGURED_KEY)); if (setJPstatus !== EzspStatus.SUCCESS) { - console.error(`[ZDO] Failed set join policy with status=${EzspStatus[setJPstatus]}.`); + logger.error(`[ZDO] Failed set join policy with status=${EzspStatus[setJPstatus]}.`, NS); return EmberStatus.ERR_FATAL; } return EmberStatus.SUCCESS; }, - console.error,// no reject, just log error if any + (e) => logger.error(e, NS),// no reject, just log error if any true,// prioritize just to avoid delays if queue is busy ); - console.log(`[STACK STATUS] Network opened.`); + logger.info(`[STACK STATUS] Network opened.`, NS); break; } case EmberStatus.NETWORK_CLOSED: { this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_NETWORK_CLOSED); - console.log(`[STACK STATUS] Network closed.`); + logger.info(`[STACK STATUS] Network closed.`, NS); break; } case EmberStatus.CHANNEL_CHANGED: { this.oneWaitress.resolveEvent(OneWaitressEvents.STACK_STATUS_CHANNEL_CHANGED); // invalidate cache this.networkCache.parameters.radioChannel = INVALID_RADIO_CHANNEL; - console.log(`[STACK STATUS] Channel changed.`); + logger.info(`[STACK STATUS] Channel changed.`, NS); break; } default: { - debug(`[STACK STATUS] ${EmberStatus[status]}.`); + logger.debug(`[STACK STATUS] ${EmberStatus[status]}.`, NS); break; } } @@ -547,8 +545,8 @@ export class EmberAdapter extends Adapter { case EmberOutgoingMessageType.MULTICAST: case EmberOutgoingMessageType.MULTICAST_WITH_ALIAS: { // BC/MC not checking for message sent, avoid unnecessary waitress lookups - console.error(`Delivery of ${EmberOutgoingMessageType[type]} failed for "${indexOrDestination}" ` - + `[apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`); + logger.error(`Delivery of ${EmberOutgoingMessageType[type]} failed for "${indexOrDestination}" ` + + `[apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS); break; } default: { @@ -694,7 +692,7 @@ export class EmberAdapter extends Adapter { this.oneWaitress.resolveZCL(payload); this.emit(Events.zclData, payload); } catch (err) { - console.error(`<~x~ [GP] Failed creating ZCL payload. Skipping. ${err}`); + logger.error(`<~x~ [GP] Failed creating ZCL payload. Skipping. ${err}`, NS); return; } } @@ -731,7 +729,7 @@ export class EmberAdapter extends Adapter { if (this.manufacturerCode !== joinManufCode) { this.requestQueue.enqueue( async (): Promise => { - debug(`[WORKAROUND] Setting coordinator manufacturer code to ${ManufacturerCode[joinManufCode]}.`); + logger.debug(`[WORKAROUND] Setting coordinator manufacturer code to ${ManufacturerCode[joinManufCode]}.`, NS); await this.ezsp.ezspSetManufacturerCode(joinManufCode); this.manufacturerCode = joinManufCode; @@ -739,14 +737,14 @@ export class EmberAdapter extends Adapter { this.emit(Events.deviceJoined, payload); return EmberStatus.SUCCESS; }, - console.error,// no reject, just log error if any + (e) => logger.error(e, NS),// no reject, just log error if any true,// prioritize just to avoid delays if queue is busy ); } else { this.emit(Events.deviceJoined, payload); } } else { - console.warn(`[TRUST CENTER] Device ${newNodeId}:${newNodeEui64} was denied joining via ${parentOfNewNodeId}.`); + logger.warning(`[TRUST CENTER] Device ${newNodeId}:${newNodeEui64} was denied joining via ${parentOfNewNodeId}.`, NS); } } } @@ -757,17 +755,11 @@ export class EmberAdapter extends Adapter { // listed as per EmberCounterType const counters = (await this.ezsp.ezspReadAndClearCounters()); - let countersLogString = "[NCP COUNTERS] "; - - for (let i = 0; i < EmberCounterType.COUNT; i++) { - countersLogString += `${EmberCounterType[i]}: ${counters[i]} | `; - } - - console.log(countersLogString); + logger.info(`[NCP COUNTERS] ${counters.join(',')}`, NS); return EmberStatus.SUCCESS; }, - console.error,// no reject, just log error if any + (e) => logger.error(e, NS), // no reject, just log error if any ); } @@ -835,7 +827,7 @@ export class EmberAdapter extends Adapter { this.networkCache.status = (await this.ezsp.ezspNetworkState()); this.networkCache.eui64 = (await this.ezsp.ezspGetEui64()); - debug(`[INIT] Network Ready! ${JSON.stringify(this.networkCache)}`); + logger.debug(`[INIT] Network Ready! ${JSON.stringify(this.networkCache)}`, NS); return result; } @@ -971,7 +963,7 @@ export class EmberAdapter extends Adapter { const remainTilMTORR = (await this.ezsp.ezspSetSourceRouteDiscoveryMode(EmberSourceRouteDiscoveryMode.RESCHEDULE)); - console.log(`[CONCENTRATOR] Started source route discovery. ${remainTilMTORR}ms until next broadcast.`); + logger.info(`[CONCENTRATOR] Started source route discovery. ${remainTilMTORR}ms until next broadcast.`, NS); } /** @@ -982,7 +974,7 @@ export class EmberAdapter extends Adapter { for (const ep of FIXED_ENDPOINTS) { if (ep.networkIndex !== 0x00) { - debug(`Multi-network not currently supported. Skipping endpoint ${JSON.stringify(ep)}.`); + logger.debug(`Multi-network not currently supported. Skipping endpoint ${JSON.stringify(ep)}.`, NS); continue; } @@ -1002,12 +994,12 @@ export class EmberAdapter extends Adapter { )); if (status === EzspStatus.SUCCESS) { - debug(`Registered endpoint "${ep.endpoint}" with status=${EzspStatus[status]}.`); + logger.debug(`Registered endpoint "${ep.endpoint}" with status=${EzspStatus[status]}.`, NS); } else { throw new Error(`Failed to register endpoint "${ep.endpoint}" with status=${EzspStatus[status]}.`); } } else { - debug(`Endpoint "${ep.endpoint}" already registered.`); + logger.debug(`Endpoint "${ep.endpoint}" already registered.`, NS); } for (const multicastId of ep.multicastIds) { @@ -1023,7 +1015,7 @@ export class EmberAdapter extends Adapter { throw new Error(`Failed to register group "${multicastId}" in multicast table with status=${EmberStatus[status]}.`); } - debug(`Registered multicast table entry: ${JSON.stringify(multicastEntry)}.`); + logger.debug(`Registered multicast table entry: ${JSON.stringify(multicastEntry)}.`, NS); } } } @@ -1067,7 +1059,7 @@ export class EmberAdapter extends Adapter { }; const initStatus = (await this.ezsp.ezspNetworkInit(networkInitStruct)); - debug(`[INIT TC] Network init status=${EmberStatus[initStatus]}.`); + logger.debug(`[INIT TC] Network init status=${EmberStatus[initStatus]}.`, NS); if ((initStatus !== EmberStatus.SUCCESS) && (initStatus !== EmberStatus.NOT_JOINED)) { throw new Error(`[INIT TC] Failed network init request with status=${EmberStatus[initStatus]}.`); @@ -1085,8 +1077,8 @@ export class EmberAdapter extends Adapter { const [npStatus, nodeType, netParams] = (await this.ezsp.ezspGetNetworkParameters()); - debug(`[INIT TC] Current network config=${JSON.stringify(this.networkOptions)}`); - debug(`[INIT TC] Current NCP network: nodeType=${EmberNodeType[nodeType]} params=${JSON.stringify(netParams)}`); + logger.debug(`[INIT TC] Current network config=${JSON.stringify(this.networkOptions)}`, NS); + logger.debug(`[INIT TC] Current NCP network: nodeType=${EmberNodeType[nodeType]} params=${JSON.stringify(netParams)}`, NS); if ((npStatus === EmberStatus.SUCCESS) && (nodeType === EmberNodeType.COORDINATOR) && (this.networkOptions.panID === netParams.panId) && (equals(this.networkOptions.extendedPanID, netParams.extendedPanId))) { @@ -1100,7 +1092,7 @@ export class EmberAdapter extends Adapter { throw new Error(`[BACKUP] Failed to export Network Key with status=${SLStatus[nkStatus]}.`); } - debug(`[INIT TC] Current NCP network: networkKey=${networkKey.contents.toString('hex')}`); + logger.debug(`[INIT TC] Current NCP network: networkKey=${networkKey.contents.toString('hex')}`, NS); // config doesn't match adapter anymore if (!networkKey.contents.equals(configNetworkKey)) { @@ -1112,7 +1104,7 @@ export class EmberAdapter extends Adapter { } if (action === NetworkInitAction.LEAVE) { - console.log(`[INIT TC] NCP network does not match config. Leaving network...`); + logger.info(`[INIT TC] NCP network does not match config. Leaving network...`, NS); const leaveStatus = (await this.ezsp.ezspLeaveNetwork()); if (leaveStatus !== EmberStatus.SUCCESS) { @@ -1144,12 +1136,12 @@ export class EmberAdapter extends Adapter { action = NetworkInitAction.FORM_BACKUP; } else { // config doesn't match backup - console.log(`[INIT TC] Config does not match backup.`); + logger.info(`[INIT TC] Config does not match backup.`, NS); action = NetworkInitAction.FORM_CONFIG; } } else { // no backup - console.log(`[INIT TC] No valid backup found.`); + logger.info(`[INIT TC] No valid backup found.`, NS); action = NetworkInitAction.FORM_CONFIG; } } @@ -1160,7 +1152,7 @@ export class EmberAdapter extends Adapter { switch (action) { case NetworkInitAction.FORM_BACKUP: { - console.log(`[INIT TC] Forming from backup.`); + logger.info(`[INIT TC] Forming from backup.`, NS); const keyList: LinkKeyBackupData[] = backup.devices.map((device) => { const octets = Array.from(device.ieeeAddress.reverse()); const deviceEui64 = '0x' + octets.map(octet => octet.toString(16).padStart(2, '0')).join(""); @@ -1190,7 +1182,7 @@ export class EmberAdapter extends Adapter { break; } case NetworkInitAction.FORM_CONFIG: { - console.log(`[INIT TC] Forming from config.`); + logger.info(`[INIT TC] Forming from config.`, NS); await this.formNetwork( false,/*from config*/ configNetworkKey, @@ -1205,7 +1197,7 @@ export class EmberAdapter extends Adapter { break; } case NetworkInitAction.DONE: { - console.log(`[INIT TC] NCP network matches config.`); + logger.info(`[INIT TC] NCP network matches config.`, NS); break; } default: { @@ -1219,8 +1211,8 @@ export class EmberAdapter extends Adapter { // currently Z2M won't support the key update because of one-way config... // need to investigate handling this properly - // console.warn(`[INIT TC] Network key frame counter is reaching its limit. Scheduling broadcast to update network key. ` - // + `This may result in some devices (especially battery-powered) temporarily losing connection.`); + // logger.warning(`[INIT TC] Network key frame counter is reaching its limit. Scheduling broadcast to update network key. ` + // + `This may result in some devices (especially battery-powered) temporarily losing connection.`, NS); // // XXX: no idea here on the proper timer value, but this will block the network for several seconds on exec // // (probably have to take the behavior of sleepy-end devices into account to improve chances of reaching everyone right away?) // setTimeout(async () => { @@ -1228,9 +1220,9 @@ export class EmberAdapter extends Adapter { // await this.broadcastNetworkKeyUpdate(); // return EmberStatus.SUCCESS; - // }, console.error, true);// no reject just log error if any, will retry next start, & prioritize so we know it'll run when expected + // }, logger.error, true);// no reject just log error if any, will retry next start, & prioritize so we know it'll run when expected // }, 300000); - console.warn(`[INIT TC] Network key frame counter is reaching its limit. A new network key will have to be instaured soon.`); + logger.warning(`[INIT TC] Network key frame counter is reaching its limit. A new network key will have to be instaured soon.`, NS); } return result; @@ -1291,7 +1283,7 @@ export class EmberAdapter extends Adapter { channels: EMBER_ALL_802_15_4_CHANNELS_MASK, }; - console.log(`[INIT FORM] Forming new network with: ${JSON.stringify(netParams)}`); + logger.info(`[INIT FORM] Forming new network with: ${JSON.stringify(netParams)}`, NS); emberStatus = (await this.ezsp.ezspFormNetwork(netParams)); @@ -1307,9 +1299,9 @@ export class EmberAdapter extends Adapter { const stStatus = await this.ezsp.ezspStartWritingStackTokens(); - debug(`[INIT FORM] Start writing stack tokens status=${EzspStatus[stStatus]}.`); + logger.debug(`[INIT FORM] Start writing stack tokens status=${EzspStatus[stStatus]}.`, NS); - console.log(`[INIT FORM] New network formed!`); + logger.info(`[INIT FORM] New network formed!`, NS); } /** @@ -1369,7 +1361,7 @@ export class EmberAdapter extends Adapter { for (let i = 0; i < keyTableSize; i++) { [deviceEui64, plaintextKey, apsKeyMeta, status] = (await this.ezsp.ezspExportLinkKeyByIndex(i)); - debug(`[BACKUP] Export link key at index ${i}, status=${SLStatus[status]}.`); + logger.debug(`[BACKUP] Export link key at index ${i}, status=${SLStatus[status]}.`, NS); // only include key if we could retrieve one at index and hash it properly if (status === SLStatus.OK) { @@ -1387,12 +1379,12 @@ export class EmberAdapter extends Adapter { }); } else { // this should never happen? - console.error(`[BACKUP] Failed to hash link key at index ${i} with status=${EmberStatus[hashStatus]}. Omitting from backup.`); + logger.error(`[BACKUP] Failed to hash link key at index ${i} with status=${EmberStatus[hashStatus]}. Omitting from backup.`, NS); } } } - console.log(`[BACKUP] Retrieved ${keyList.length} link keys.`); + logger.info(`[BACKUP] Retrieved ${keyList.length} link keys.`, NS); return keyList; } @@ -1440,7 +1432,7 @@ export class EmberAdapter extends Adapter { } } - debug(`[BACKUP] Imported ${backupData.length} keys.`); + logger.debug(`[BACKUP] Imported ${backupData.length} keys.`, NS); } /** @@ -1453,13 +1445,13 @@ export class EmberAdapter extends Adapter { return new Promise((resolve, reject): void => { this.requestQueue.enqueue( async (): Promise => { - console.warn(`[TRUST CENTER] Performing a network key update. This might take a while and disrupt normal operation.`); + logger.warning(`[TRUST CENTER] Performing a network key update. This might take a while and disrupt normal operation.`, NS); // zero-filled = let stack generate new random network key let status = await this.ezsp.ezspBroadcastNextNetworkKey({contents: Buffer.alloc(EMBER_ENCRYPTION_KEY_SIZE)}); if (status !== EmberStatus.SUCCESS) { - console.error(`[TRUST CENTER] Failed to broadcast next network key with status=${EmberStatus[status]}.`); + logger.error(`[TRUST CENTER] Failed to broadcast next network key with status=${EmberStatus[status]}.`, NS); return status; } @@ -1471,7 +1463,7 @@ export class EmberAdapter extends Adapter { if (status !== EmberStatus.SUCCESS) { // XXX: Not sure how likely this is, but this is bad, probably should hard fail? - console.error(`[TRUST CENTER] Failed to broadcast network key switch with status=${EmberStatus[status]}.`); + logger.error(`[TRUST CENTER] Failed to broadcast network key switch with status=${EmberStatus[status]}.`, NS); return status; } @@ -1488,14 +1480,14 @@ export class EmberAdapter extends Adapter { * @param status */ private async onNcpNeedsResetAndInit(status: EzspStatus): Promise { - console.error(`!!! NCP FATAL ERROR reason=${EzspStatus[status]}. ATTEMPTING RESET... !!!`); + logger.error(`!!! NCP FATAL ERROR reason=${EzspStatus[status]}. ATTEMPTING RESET... !!!`, NS); try { await this.stop(); await Wait(500);// just because await this.start(); } catch (err) { - console.error(`Failed to reset and init NCP. ${err}`); + logger.error(`Failed to reset and init NCP. ${err}`, NS); this.emit(Events.disconnected); } } @@ -1569,7 +1561,7 @@ export class EmberAdapter extends Adapter { if (status === EmberStatus.SUCCESS) { this.networkCache.parameters = parameters; } else { - console.error(`Failed to get PAN ID (via network parameters) with status=${EmberStatus[status]}.`); + logger.error(`Failed to get PAN ID (via network parameters) with status=${EmberStatus[status]}.`, NS); } } @@ -1588,7 +1580,7 @@ export class EmberAdapter extends Adapter { if (status === EmberStatus.SUCCESS) { this.networkCache.parameters = parameters; } else { - console.error(`Failed to get Extended PAN ID (via network parameters) with status=${EmberStatus[status]}.`); + logger.error(`Failed to get Extended PAN ID (via network parameters) with status=${EmberStatus[status]}.`, NS); } } @@ -1607,7 +1599,7 @@ export class EmberAdapter extends Adapter { if (status === EmberStatus.SUCCESS) { this.networkCache.parameters = parameters; } else { - console.error(`Failed to get radio channel (via network parameters) with status=${EmberStatus[status]}.`); + logger.error(`Failed to get radio channel (via network parameters) with status=${EmberStatus[status]}.`, NS); } } @@ -1626,7 +1618,7 @@ export class EmberAdapter extends Adapter { )); if (status !== SLStatus.OK) { - console.error(`Failed energy scan request with status=${SLStatus[status]}.`); + logger.error(`Failed energy scan request with status=${SLStatus[status]}.`, NS); return EmberStatus.ERR_FATAL; } @@ -1670,7 +1662,7 @@ export class EmberAdapter extends Adapter { throw new Error(`NCP EZSP protocol version of ${ncpEzspProtocolVer} does not match Host version ${hostEzspProtocolVer}`); } - debug(`NCP info: EZSPVersion=${ncpEzspProtocolVer} StackType=${ncpStackType} StackVersion=${ncpStackVer}`); + logger.debug(`NCP info: EZSPVersion=${ncpEzspProtocolVer} StackType=${ncpStackType} StackVersion=${ncpStackVer}`, NS); const [status, versionStruct] = (await this.ezsp.ezspGetVersionStruct()); @@ -1686,10 +1678,10 @@ export class EmberAdapter extends Adapter { }; if (versionStruct.type !== EmberVersionType.GA) { - console.warn(`NCP is running a non-GA version (${EmberVersionType[versionStruct.type]}).`); + logger.warning(`NCP is running a non-GA version (${EmberVersionType[versionStruct.type]}).`, NS); } - debug(`NCP version info: ${JSON.stringify(this.version)}`); + logger.debug(`NCP version info: ${JSON.stringify(this.version)}`, NS); } /** @@ -1703,14 +1695,14 @@ export class EmberAdapter extends Adapter { private async emberSetEzspConfigValue(configId: EzspConfigId, value: number): Promise { const status = (await this.ezsp.ezspSetConfigurationValue(configId, value)); - debug(`[EzspConfigId] SET "${EzspConfigId[configId]}" TO "${value}" with status=${EzspStatus[status]}.`); + logger.debug(`[EzspConfigId] SET "${EzspConfigId[configId]}" TO "${value}" with status=${EzspStatus[status]}.`, NS); if (status === EzspStatus.ERROR_INVALID_ID) { // can be ZLL where not all NCPs need or support it. - console.warn(`[EzspConfigId] Unsupported configuration ID ${EzspConfigId[configId]} by NCP.`); + logger.warning(`[EzspConfigId] Unsupported configuration ID ${EzspConfigId[configId]} by NCP.`, NS); } else if (status !== EzspStatus.SUCCESS) { // don't fail in case a set value gets called "out of time" - console.error(`[EzspConfigId] Failed to SET "${EzspConfigId[configId]}" TO "${value}" with status=${EzspStatus[status]}.`); + logger.error(`[EzspConfigId] Failed to SET "${EzspConfigId[configId]}" TO "${value}" with status=${EzspStatus[status]}.`, NS); } return status; @@ -1726,7 +1718,7 @@ export class EmberAdapter extends Adapter { private async emberSetEzspValue(valueId: EzspValueId, valueLength: number, value: number[]): Promise { const status = (await this.ezsp.ezspSetValue(valueId, valueLength, value)); - debug(`[EzspValueId] SET "${EzspValueId[valueId]}" TO "${value}" with status=${EzspStatus[status]}.`); + logger.debug(`[EzspValueId] SET "${EzspValueId[valueId]}" TO "${value}" with status=${EzspStatus[status]}.`, NS); return status; } @@ -1740,7 +1732,7 @@ export class EmberAdapter extends Adapter { private async emberSetEzspPolicy(policyId: EzspPolicyId, decisionId: number): Promise { const status = (await this.ezsp.ezspSetPolicy(policyId, decisionId)); - debug(`[EzspPolicyId] SET "${EzspPolicyId[policyId]}" TO "${decisionId}" with status=${EzspStatus[status]}.`); + logger.debug(`[EzspPolicyId] SET "${EzspPolicyId[policyId]}" TO "${decisionId}" with status=${EzspStatus[status]}.`, NS); return status; } @@ -1845,7 +1837,7 @@ export class EmberAdapter extends Adapter { let apsFrame: EmberApsFrame = null; let messageTag: number = null; - debug(`Permit joining for ${duration} sec. status=${[status]}`); + logger.debug(`Permit joining for ${duration} sec. status=${[status]}`, NS); if (broadcastMgmtPermitJoin) { // `authentication`: TC significance always 1 (zb specs) @@ -1893,7 +1885,7 @@ export class EmberAdapter extends Adapter { if (status === EzspStatus.SUCCESS) { return value; } else { - debug(`Failed to get source route overhead (via extended value), status=${EzspStatus[status]}.`); + logger.debug(`Failed to get source route overhead (via extended value), status=${EzspStatus[status]}.`, NS); } return 0; @@ -2031,7 +2023,7 @@ export class EmberAdapter extends Adapter { if (destination === EMBER_BROADCAST_ADDRESS || destination === EMBER_RX_ON_WHEN_IDLE_BROADCAST_ADDRESS || destination === EMBER_SLEEPY_BROADCAST_ADDRESS) { - debug(`~~~> [ZDO BROADCAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`); + logger.debug(`~~~> [ZDO BROADCAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS); const [status, apsSequence] = (await this.ezsp.ezspSendBroadcast( destination, apsFrame, @@ -2041,10 +2033,13 @@ export class EmberAdapter extends Adapter { )); apsFrame.sequence = apsSequence; - debug(`~~~> [SENT ZDO type=BROADCAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag} status=${EmberStatus[status]}]`); + logger.debug( + `~~~> [SENT ZDO type=BROADCAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag} status=${EmberStatus[status]}]`, + NS, + ); return [status, apsFrame, messageTag]; } else { - debug(`~~~> [ZDO UNICAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`); + logger.debug(`~~~> [ZDO UNICAST apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag}]`, NS); const [status, apsSequence] = (await this.ezsp.ezspSendUnicast( EmberOutgoingMessageType.DIRECT, destination, @@ -2054,7 +2049,10 @@ export class EmberAdapter extends Adapter { )); apsFrame.sequence = apsSequence; - debug(`~~~> [SENT ZDO type=DIRECT apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag} status=${EmberStatus[status]}]`); + logger.debug( + `~~~> [SENT ZDO type=DIRECT apsFrame=${JSON.stringify(apsFrame)} messageTag=${messageTag} status=${EmberStatus[status]}]`, + NS, + ); return [status, apsFrame, messageTag]; } } @@ -2102,7 +2100,10 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeUInt8(outClusters.length); this.zdoRequestBuffalo.writeListUInt16(outClusters); - debug(`~~~> [ZDO MATCH_DESCRIPTORS_REQUEST target=${target} profile=${profile} inClusters=${inClusters} outClusters=${outClusters}]`); + logger.debug( + `~~~> [ZDO MATCH_DESCRIPTORS_REQUEST target=${target} profile=${profile} inClusters=${inClusters} outClusters=${outClusters}]`, + NS, + ); return this.sendZDORequestBuffer(target, MATCH_DESCRIPTORS_REQUEST, options); } @@ -2131,7 +2132,7 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0); this.zdoRequestBuffalo.writeUInt8(childStartIndex); - debug(`~~~> [ZDO NETWORK_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`); + logger.debug(`~~~> [ZDO NETWORK_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS); return this.sendZDORequestBuffer(EMBER_RX_ON_WHEN_IDLE_BROADCAST_ADDRESS, NETWORK_ADDRESS_REQUEST, EmberApsOption.SOURCE_EUI64); } @@ -2161,7 +2162,7 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0); this.zdoRequestBuffalo.writeUInt8(childStartIndex); - debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`); + logger.debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST target=${target} reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS); return this.sendZDORequestBuffer(target, IEEE_ADDRESS_REQUEST, options); } @@ -2181,8 +2182,8 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeUInt8(reportKids ? 1 : 0); this.zdoRequestBuffalo.writeUInt8(childStartIndex); - debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST targetNodeIdOfRequest=${targetNodeIdOfRequest} discoveryNodeId=${discoveryNodeId} ` - + `reportKids=${reportKids} childStartIndex=${childStartIndex}]`); + logger.debug(`~~~> [ZDO IEEE_ADDRESS_REQUEST targetNodeIdOfRequest=${targetNodeIdOfRequest} discoveryNodeId=${discoveryNodeId} ` + + `reportKids=${reportKids} childStartIndex=${childStartIndex}]`, NS); return this.sendZDORequestBuffer(targetNodeIdOfRequest, IEEE_ADDRESS_REQUEST, options); } @@ -2229,7 +2230,7 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeUInt16(target); this.zdoRequestBuffalo.writeUInt8(targetEndpoint); - debug(`~~~> [ZDO SIMPLE_DESCRIPTOR_REQUEST target=${target} targetEndpoint=${targetEndpoint}]`); + logger.debug(`~~~> [ZDO SIMPLE_DESCRIPTOR_REQUEST target=${target} targetEndpoint=${targetEndpoint}]`, NS); return this.sendZDORequestBuffer(target, SIMPLE_DESCRIPTOR_REQUEST, options); } @@ -2313,8 +2314,8 @@ export class EmberAdapter extends Adapter { private async emberBindRequest(target: EmberNodeId, source: EmberEUI64, sourceEndpoint: number, clusterId: number, type: number, destination: EmberEUI64, groupAddress: EmberMulticastId, destinationEndpoint: number, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO BIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} ` - + `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`); + logger.debug(`~~~> [ZDO BIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} ` + + `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`, NS); return this.emberSendZigDevBindRequest( target, BIND_REQUEST, @@ -2361,8 +2362,11 @@ export class EmberAdapter extends Adapter { private async emberUnbindRequest(target: EmberNodeId, source: EmberEUI64, sourceEndpoint: number, clusterId: number, type: number, destination: EmberEUI64, groupAddress: EmberMulticastId, destinationEndpoint: number, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO UNBIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} ` - + `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`); + logger.debug( + `~~~> [ZDO UNBIND_REQUEST target=${target} source=${source} sourceEndpoint=${sourceEndpoint} clusterId=${clusterId} type=${type} ` + + `destination=${destination} groupAddress=${groupAddress} destinationEndpoint=${destinationEndpoint}]`, + NS, + ); return this.emberSendZigDevBindRequest( target, UNBIND_REQUEST, @@ -2392,7 +2396,7 @@ export class EmberAdapter extends Adapter { */ private async emberActiveEndpointsRequest(target: EmberNodeId, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO ACTIVE_ENDPOINTS_REQUEST target=${target}]`); + logger.debug(`~~~> [ZDO ACTIVE_ENDPOINTS_REQUEST target=${target}]`, NS); return this.emberSendZigDevRequestTarget(target, ACTIVE_ENDPOINTS_REQUEST, options); } @@ -2414,7 +2418,7 @@ export class EmberAdapter extends Adapter { */ private async emberPowerDescriptorRequest(target: EmberNodeId, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO POWER_DESCRIPTOR_REQUEST target=${target}]`); + logger.debug(`~~~> [ZDO POWER_DESCRIPTOR_REQUEST target=${target}]`, NS); return this.emberSendZigDevRequestTarget(target, POWER_DESCRIPTOR_REQUEST, options); } @@ -2435,7 +2439,7 @@ export class EmberAdapter extends Adapter { */ private async emberNodeDescriptorRequest(target: EmberNodeId, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO NODE_DESCRIPTOR_REQUEST target=${target}]`); + logger.debug(`~~~> [ZDO NODE_DESCRIPTOR_REQUEST target=${target}]`, NS); return this.emberSendZigDevRequestTarget(target, NODE_DESCRIPTOR_REQUEST, options); } @@ -2458,7 +2462,7 @@ export class EmberAdapter extends Adapter { */ private async emberLqiTableRequest(target: EmberNodeId, startIndex: number, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO LQI_TABLE_REQUEST target=${target} startIndex=${startIndex}]`); + logger.debug(`~~~> [ZDO LQI_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS); return this.emberTableRequest(LQI_TABLE_REQUEST, target, startIndex, options); } @@ -2481,7 +2485,7 @@ export class EmberAdapter extends Adapter { */ private async emberRoutingTableRequest(target: EmberNodeId, startIndex: number, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO ROUTING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`); + logger.debug(`~~~> [ZDO ROUTING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS); return this.emberTableRequest(ROUTING_TABLE_REQUEST, target, startIndex, options); } @@ -2505,7 +2509,7 @@ export class EmberAdapter extends Adapter { */ private async emberBindingTableRequest(target: EmberNodeId, startIndex: number, options: EmberApsOption) : Promise<[EmberStatus, apsFrame: EmberApsFrame, messageTag: number]> { - debug(`~~~> [ZDO BINDING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`); + logger.debug(`~~~> [ZDO BINDING_TABLE_REQUEST target=${target} startIndex=${startIndex}]`, NS); return this.emberTableRequest(BINDING_TABLE_REQUEST, target, startIndex, options); } @@ -2552,7 +2556,7 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeIeeeAddr(deviceAddress); this.zdoRequestBuffalo.writeUInt8(leaveRequestFlags); - debug(`~~~> [ZDO LEAVE_REQUEST target=${target} deviceAddress=${deviceAddress} leaveRequestFlags=${leaveRequestFlags}]`); + logger.debug(`~~~> [ZDO LEAVE_REQUEST target=${target} deviceAddress=${deviceAddress} leaveRequestFlags=${leaveRequestFlags}]`, NS); return this.sendZDORequestBuffer(target, LEAVE_REQUEST, options); } @@ -2580,7 +2584,7 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeUInt8(duration); this.zdoRequestBuffalo.writeUInt8(authentication); - debug(`~~~> [ZDO PERMIT_JOINING_REQUEST target=${target} duration=${duration} authentication=${authentication}]`); + logger.debug(`~~~> [ZDO PERMIT_JOINING_REQUEST target=${target} duration=${duration} authentication=${authentication}]`, NS); return this.sendZDORequestBuffer(target, PERMIT_JOINING_REQUEST, options); } @@ -2610,7 +2614,10 @@ export class EmberAdapter extends Adapter { this.zdoRequestBuffalo.writeUInt16(manager); } - debug(`~~~> [ZDO NWK_UPDATE_REQUEST target=${target} scanChannels=${scanChannels} duration=${duration} count=${count} manager=${manager}]`); + logger.debug( + `~~~> [ZDO NWK_UPDATE_REQUEST target=${target} scanChannels=${scanChannels} duration=${duration} count=${count} manager=${manager}]`, + NS, + ); return this.sendZDORequestBuffer(target, NWK_UPDATE_REQUEST, options); } @@ -2642,7 +2649,7 @@ export class EmberAdapter extends Adapter { try { return SerialPortUtils.is(RealpathSync(path), autoDetectDefinitions); } catch (error) { - debug(`Failed to determine if path is valid: '${error}'`); + logger.debug(`Failed to determine if path is valid: '${error}'`, NS); return false; } } @@ -2654,10 +2661,10 @@ export class EmberAdapter extends Adapter { } public async start(): Promise { - console.log(`======== Ember Adapter Starting ========`); + logger.info(`======== Ember Adapter Starting ========`, NS); this.initVariables(); - debug(`Starting EZSP with stack configuration: "${this.stackConfig}".`); + logger.debug(`Starting EZSP with stack configuration: "${this.stackConfig}".`, NS); const result = await this.initEzsp(); return result; @@ -2667,7 +2674,7 @@ export class EmberAdapter extends Adapter { await this.ezsp.stop(); this.initVariables(); - console.log(`======== Ember Adapter Stopped ========`); + logger.info(`======== Ember Adapter Stopped ========`, NS); } // queued, non-InterPAN @@ -2729,7 +2736,7 @@ export class EmberAdapter extends Adapter { const [netStatus, , netParams] = (await this.ezsp.ezspGetNetworkParameters()); if (netStatus !== EmberStatus.SUCCESS) { - console.error(`[BACKUP] Failed to get network parameters.`); + logger.error(`[BACKUP] Failed to get network parameters.`, NS); return netStatus; } @@ -2740,7 +2747,7 @@ export class EmberAdapter extends Adapter { const [netKeyStatus, netKeyInfo] = (await this.ezsp.ezspGetNetworkKeyInfo()); if (netKeyStatus !== SLStatus.OK) { - console.error(`[BACKUP] Failed to get network keys info.`); + logger.error(`[BACKUP] Failed to get network keys info.`, NS); return ((netKeyStatus === SLStatus.BUSY) || (netKeyStatus === SLStatus.NOT_READY)) ? EmberStatus.NETWORK_BUSY : EmberStatus.ERR_FATAL;// allow retry on statuses that should be temporary } @@ -2760,7 +2767,7 @@ export class EmberAdapter extends Adapter { // this.ezsp, // Buffer.from(this.networkCache.eui64.substring(2/*0x*/), 'hex').reverse() // )); - // console.log(tokensBuf.toString('hex')); + // logger.info(tokensBuf.toString('hex'), NS); let context: SecManContext = initSecurityManagerContext(); context.coreKeyType = SecManKeyType.TC_LINK; @@ -2869,7 +2876,7 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed broadcast channel change to "${newChannel}" with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed broadcast channel change to "${newChannel}" with status=${EmberStatus[status]}.`, NS); return status; } @@ -2890,7 +2897,7 @@ export class EmberAdapter extends Adapter { // queued public async setTransmitPower(value: number): Promise { if (typeof value !== 'number') { - console.error(`Tried to set transmit power to non-number. Value ${value} of type ${typeof value}.`); + logger.error(`Tried to set transmit power to non-number. Value ${value} of type ${typeof value}.`, NS); return; } @@ -2900,7 +2907,7 @@ export class EmberAdapter extends Adapter { const status = await this.ezsp.ezspSetRadioPower(value); if (status !== EmberStatus.SUCCESS) { - console.error(`Failed to set transmit power to ${value} status=${EmberStatus[status]}.`); + logger.error(`Failed to set transmit power to ${value} status=${EmberStatus[status]}.`, NS); return status; } @@ -2947,7 +2954,7 @@ export class EmberAdapter extends Adapter { const [aesStatus, keyContents] = (await this.emberAesHashSimple(key)); if (aesStatus !== EmberStatus.SUCCESS) { - console.error(`[ADD INSTALL CODE] Failed AES hash for "${ieeeAddress}" with status=${EmberStatus[aesStatus]}.`); + logger.error(`[ADD INSTALL CODE] Failed AES hash for "${ieeeAddress}" with status=${EmberStatus[aesStatus]}.`, NS); return aesStatus; } @@ -2956,9 +2963,9 @@ export class EmberAdapter extends Adapter { const impStatus = (await this.ezsp.ezspImportTransientKey(ieeeAddress, {contents: keyContents}, SecManFlag.NONE)); if (impStatus == SLStatus.OK) { - debug(`[ADD INSTALL CODE] Success for "${ieeeAddress}".`); + logger.debug(`[ADD INSTALL CODE] Success for "${ieeeAddress}".`, NS); } else { - console.error(`[ADD INSTALL CODE] Failed for "${ieeeAddress}" with status=${SLStatus[impStatus]}.`); + logger.error(`[ADD INSTALL CODE] Failed for "${ieeeAddress}" with status=${SLStatus[impStatus]}.`, NS); return EmberStatus.ERR_FATAL; } @@ -3004,11 +3011,11 @@ export class EmberAdapter extends Adapter { const plaintextKey: SecManKey = {contents: Buffer.from(ZIGBEE_PROFILE_INTEROPERABILITY_LINK_KEY)}; const impKeyStatus = (await this.ezsp.ezspImportTransientKey(BLANK_EUI64, plaintextKey, SecManFlag.NONE)); - debug(`[ZDO] Pre joining import transient key status=${SLStatus[impKeyStatus]}.`); + logger.debug(`[ZDO] Pre joining import transient key status=${SLStatus[impKeyStatus]}.`, NS); return impKeyStatus === SLStatus.OK ? EmberStatus.SUCCESS : EmberStatus.ERR_FATAL; } else { if (this.manufacturerCode !== DEFAULT_MANUFACTURER_CODE) { - debug(`[WORKAROUND] Reverting coordinator manufacturer code to default.`); + logger.debug(`[WORKAROUND] Reverting coordinator manufacturer code to default.`, NS); await this.ezsp.ezspSetManufacturerCode(DEFAULT_MANUFACTURER_CODE); this.manufacturerCode = DEFAULT_MANUFACTURER_CODE; @@ -3019,7 +3026,7 @@ export class EmberAdapter extends Adapter { const setJPstatus = (await this.emberSetJoinPolicy(EmberJoinDecision.ALLOW_REJOINS_ONLY)); if (setJPstatus !== EzspStatus.SUCCESS) { - console.error(`[ZDO] Failed set join policy for with status=${EzspStatus[setJPstatus]}.`); + logger.error(`[ZDO] Failed set join policy for with status=${EzspStatus[setJPstatus]}.`, NS); return EmberStatus.ERR_FATAL; } @@ -3037,7 +3044,7 @@ export class EmberAdapter extends Adapter { const pjStatus = (await preJoining()); if (pjStatus !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${EmberStatus[pjStatus]}.`); + logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${EmberStatus[pjStatus]}.`, NS); return pjStatus; } @@ -3046,7 +3053,7 @@ export class EmberAdapter extends Adapter { const [status, apsFrame, messageTag] = (await this.emberPermitJoiningRequest(networkAddress, seconds, 1, 0)); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed permit joining request for "${networkAddress}" with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed permit joining request for "${networkAddress}" with status=${EmberStatus[status]}.`, NS); return status; } @@ -3072,7 +3079,7 @@ export class EmberAdapter extends Adapter { const pjStatus = (await preJoining()); if (pjStatus !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${EmberStatus[pjStatus]}.`); + logger.error(`[ZDO] Failed pre joining request for "${networkAddress}" with status=${EmberStatus[pjStatus]}.`, NS); return pjStatus; } @@ -3084,7 +3091,7 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed permit joining request with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed permit joining request with status=${EmberStatus[status]}.`, NS); return status; } @@ -3124,7 +3131,7 @@ export class EmberAdapter extends Adapter { const [reqStatus, apsFrame, messageTag] = (await this.emberLqiTableRequest(networkAddress, startIndex, DEFAULT_APS_OPTIONS)); if (reqStatus !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed LQI request for "${networkAddress}" (index "${startIndex}") with status=${EmberStatus[reqStatus]}.`); + logger.error(`[ZDO] Failed LQI request for "${networkAddress}" (index "${startIndex}") with status=${EmberStatus[reqStatus]}.`, NS); return [reqStatus, null, null]; } @@ -3188,8 +3195,9 @@ export class EmberAdapter extends Adapter { const [reqStatus, apsFrame, messageTag] = (await this.emberRoutingTableRequest(networkAddress, startIndex, DEFAULT_APS_OPTIONS)); if (reqStatus !== EmberStatus.SUCCESS) { - console.error( - `[ZDO] Failed routing table request for "${networkAddress}" (index "${startIndex}") with status=${EmberStatus[reqStatus]}.` + logger.error( + `[ZDO] Failed routing table request for "${networkAddress}" (index "${startIndex}") with status=${EmberStatus[reqStatus]}.`, + NS, ); return [reqStatus, null, null]; } @@ -3254,7 +3262,7 @@ export class EmberAdapter extends Adapter { const [status, apsFrame, messageTag] = (await this.emberNodeDescriptorRequest(networkAddress, DEFAULT_APS_OPTIONS)); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed node descriptor for "${networkAddress}" with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed node descriptor for "${networkAddress}" with status=${EmberStatus[status]}.`, NS); return status; } @@ -3280,9 +3288,9 @@ export class EmberAdapter extends Adapter { // always 0 before rev. 21 where field was added if (result.stackRevision < CURRENT_ZIGBEE_SPEC_REVISION) { - console.warn(`[ZDO] Node descriptor for "${networkAddress}" reports device is only compliant to revision ` + logger.warning(`[ZDO] Node descriptor for "${networkAddress}" reports device is only compliant to revision ` + `"${(result.stackRevision < 21) ? 'pre-21' : result.stackRevision}" of the ZigBee specification ` - + `(current revision: ${CURRENT_ZIGBEE_SPEC_REVISION}).`); + + `(current revision: ${CURRENT_ZIGBEE_SPEC_REVISION}).`, NS); } resolve({type, manufacturerCode: result.manufacturerCode}); @@ -3305,7 +3313,7 @@ export class EmberAdapter extends Adapter { const [status, apsFrame, messageTag] = (await this.emberActiveEndpointsRequest(networkAddress, DEFAULT_APS_OPTIONS)); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed active endpoints request for "${networkAddress}" with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed active endpoints request for "${networkAddress}" with status=${EmberStatus[status]}.`, NS); return status; } @@ -3339,8 +3347,8 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed simple descriptor request for "${networkAddress}" endpoint "${endpointID}" ` - + `with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed simple descriptor request for "${networkAddress}" endpoint "${endpointID}" ` + + `with status=${EmberStatus[status]}.`, NS); return status; } @@ -3389,8 +3397,8 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" ` - + `endpoint "${destinationEndpoint}" with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" ` + + `endpoint "${destinationEndpoint}" with status=${EmberStatus[status]}.`, NS); return status; } @@ -3427,8 +3435,8 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" ` - + `with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed bind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" ` + + `with status=${EmberStatus[status]}.`, NS); return status; } @@ -3472,8 +3480,8 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" ` - + `endpoint "${destinationEndpoint}" with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" destination "${destinationAddressOrGroup}" ` + + `endpoint "${destinationEndpoint}" with status=${EmberStatus[status]}.`, NS); return status; } @@ -3511,8 +3519,8 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" ` - + `with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed unbind request for "${destinationNetworkAddress}" group "${destinationAddressOrGroup}" ` + + `with status=${EmberStatus[status]}.`, NS); return status; } @@ -3548,8 +3556,8 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`[ZDO] Failed remove device request for "${networkAddress}" target "${ieeeAddr}" ` - + `with status=${EmberStatus[status]}.`); + logger.error(`[ZDO] Failed remove device request for "${networkAddress}" target "${ieeeAddr}" ` + + `with status=${EmberStatus[status]}.`, NS); return status; } @@ -3616,7 +3624,10 @@ export class EmberAdapter extends Adapter { } } - debug(`~~~> [ZCL to=${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.Header)}]`); + logger.debug( + `~~~> [ZCL to=${networkAddress} apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.Header)}]`, + NS, + ); // eslint-disable-next-line @typescript-eslint/no-unused-vars const [status, messageTag] = (await this.ezsp.send( EmberOutgoingMessageType.DIRECT, @@ -3628,7 +3639,7 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${EmberStatus[status]}.`); + logger.error(`~x~> [ZCL to=${networkAddress}] Failed to send request with status=${EmberStatus[status]}.`, NS); return status;// let queue handle retry based on status } @@ -3682,7 +3693,7 @@ export class EmberAdapter extends Adapter { } } - debug(`~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.Header)}]`); + logger.debug(`~~~> [ZCL GROUP apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.Header)}]`, NS); // eslint-disable-next-line @typescript-eslint/no-unused-vars const [status, messageTag] = (await this.ezsp.send( EmberOutgoingMessageType.MULTICAST, @@ -3694,7 +3705,7 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`~x~> [ZCL GROUP] Failed to send with status=${EmberStatus[status]}.`); + logger.error(`~x~> [ZCL GROUP] Failed to send with status=${EmberStatus[status]}.`, NS); return status;// let queue handle retry based on status } @@ -3738,7 +3749,7 @@ export class EmberAdapter extends Adapter { } } - debug(`~~~> [ZCL BROADCAST apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.Header)}]`); + logger.debug(`~~~> [ZCL BROADCAST apsFrame=${JSON.stringify(apsFrame)} header=${JSON.stringify(zclFrame.Header)}]`, NS); // eslint-disable-next-line @typescript-eslint/no-unused-vars const [status, messageTag] = (await this.ezsp.send( EmberOutgoingMessageType.BROADCAST, @@ -3750,7 +3761,7 @@ export class EmberAdapter extends Adapter { )); if (status !== EmberStatus.SUCCESS) { - console.error(`~x~> [ZCL BROADCAST] Failed to send with status=${EmberStatus[status]}.`); + logger.error(`~x~> [ZCL BROADCAST] Failed to send with status=${EmberStatus[status]}.`, NS); return status;// let queue handle retry based on status } @@ -3771,7 +3782,7 @@ export class EmberAdapter extends Adapter { // queued public async setChannelInterPAN(channel: number): Promise { if (typeof channel !== 'number') { - console.error(`Tried to set channel InterPAN to non-number. Channel ${channel} of type ${typeof channel}.`); + logger.error(`Tried to set channel InterPAN to non-number. Channel ${channel} of type ${typeof channel}.`, NS); return; } @@ -3783,7 +3794,7 @@ export class EmberAdapter extends Adapter { if (status !== EmberStatus.SUCCESS) { this.interpanLock = false;// XXX: ok? - console.error(`Failed to set InterPAN channel to ${channel} with status=${EmberStatus[status]}.`); + logger.error(`Failed to set InterPAN channel to ${channel} with status=${EmberStatus[status]}.`, NS); return status; } @@ -3817,11 +3828,11 @@ export class EmberAdapter extends Adapter { msgBuffalo.writeUInt16(zclFrame.Cluster.ID); msgBuffalo.writeUInt16(TOUCHLINK_PROFILE_ID); - debug(`~~~> [ZCL TOUCHLINK to=${ieeeAddress} header=${JSON.stringify(zclFrame.Header)}]`); + logger.debug(`~~~> [ZCL TOUCHLINK to=${ieeeAddress} header=${JSON.stringify(zclFrame.Header)}]`, NS); const status = (await this.ezsp.ezspSendRawMessage(Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]))); if (status !== EmberStatus.SUCCESS) { - console.error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${EmberStatus[status]}.`); + logger.error(`~x~> [ZCL TOUCHLINK to=${ieeeAddress}] Failed to send with status=${EmberStatus[status]}.`, NS); return status; } @@ -3876,11 +3887,11 @@ export class EmberAdapter extends Adapter { const data = Buffer.concat([msgBuffalo.getWritten(), zclFrame.toBuffer()]); - debug(`~~~> [ZCL TOUCHLINK BROADCAST header=${JSON.stringify(zclFrame.Header)}]`); + logger.debug(`~~~> [ZCL TOUCHLINK BROADCAST header=${JSON.stringify(zclFrame.Header)}]`, NS); const status = (await this.ezsp.ezspSendRawMessage(data)); if (status !== EmberStatus.SUCCESS) { - console.error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${EmberStatus[status]}.`); + logger.error(`~x~> [ZCL TOUCHLINK BROADCAST] Failed to send with status=${EmberStatus[status]}.`, NS); return status; } @@ -3910,8 +3921,9 @@ export class EmberAdapter extends Adapter { const status = (await this.ezsp.ezspSetLogicalAndRadioChannel(this.networkOptions.channelList[0])); if (status !== EmberStatus.SUCCESS) { - console.error( - `Failed to restore InterPAN channel to ${this.networkOptions.channelList[0]} with status=${EmberStatus[status]}.` + logger.error( + `Failed to restore InterPAN channel to ${this.networkOptions.channelList[0]} with status=${EmberStatus[status]}.`, + NS, ); return status; } @@ -3933,7 +3945,7 @@ export class EmberAdapter extends Adapter { private checkInterpanLock(): void { if (this.interpanLock) { - console.error(`[INTERPAN MODE] Cannot execute non-InterPAN commands.`); + logger.error(`[INTERPAN MODE] Cannot execute non-InterPAN commands.`, NS); // will be caught by request queue and rejected internally. throw new Error(EzspStatus[EzspStatus.ERROR_INVALID_CALL]); diff --git a/src/adapter/ember/adapter/oneWaitress.ts b/src/adapter/ember/adapter/oneWaitress.ts index 709d85791d..d9b0d37db7 100644 --- a/src/adapter/ember/adapter/oneWaitress.ts +++ b/src/adapter/ember/adapter/oneWaitress.ts @@ -4,7 +4,9 @@ import {ZclDataPayload} from "../../events"; import {TOUCHLINK_PROFILE_ID} from "../consts"; import {EmberApsFrame, EmberNodeId} from "../types"; import {EmberZdoStatus} from "../zdo"; +import {logger} from '../../../utils/logger'; +const NS = 'zh:ember:waitress'; /** Events specific to OneWaitress usage. */ export enum OneWaitressEvents { @@ -130,7 +132,7 @@ export class EmberOneWaitress { } else if (status === EmberZdoStatus.ZDP_NO_ENTRY) { // XXX: bypassing fail here since Z2M seems to trigger ZDO remove-type commands without checking current state // Z2M also fails with ZCL payload NOT_FOUND though. This should be removed once upstream fixes that. - console.log(`[ZDO] Received status ZDP_NO_ENTRY for "${sender}" cluster "${apsFrame.clusterId}". Ignoring.`); + logger.info(`[ZDO] Received status ZDP_NO_ENTRY for "${sender}" cluster "${apsFrame.clusterId}". Ignoring.`, NS); waiter.resolve(payload); } else { waiter.reject(new Error(`[ZDO] Failed response by NCP for "${sender}" cluster "${apsFrame.clusterId}" ` diff --git a/src/adapter/ember/adapter/requestQueue.ts b/src/adapter/ember/adapter/requestQueue.ts index 88fd039bbe..668cbb37e8 100644 --- a/src/adapter/ember/adapter/requestQueue.ts +++ b/src/adapter/ember/adapter/requestQueue.ts @@ -1,8 +1,8 @@ /* istanbul ignore file */ -import Debug from "debug"; +import {logger} from "../../../utils/logger"; import {EmberStatus, EzspStatus} from "../enums"; -const debug = Debug('zigbee-herdsman:adapter:ember:queue'); +const NS = 'zh:ember:queue'; interface EmberRequestQueueEntry { /** @@ -51,7 +51,7 @@ export class EmberRequestQueue { public stopDispatching(): void { clearInterval(this.dispatchHandler); - debug(`Dispatching stopped; queue=${this.queue.length} priorityQueue=${this.priorityQueue.length}`); + logger.debug(`Dispatching stopped; queue=${this.queue.length} priorityQueue=${this.priorityQueue.length}`, NS); } /** @@ -61,7 +61,7 @@ export class EmberRequestQueue { public startDispatching(): void { this.dispatchHandler = setInterval(this.dispatch.bind(this), this.dispatchInterval); - debug(`Dispatching started.`); + logger.debug(`Dispatching started.`, NS); } /** @@ -77,7 +77,7 @@ export class EmberRequestQueue { * @returns new length of the queue. */ public enqueue(func: () => Promise, reject: (reason: Error) => void, prioritize: boolean = false): number { - debug(`Status queue=${this.queue.length} priorityQueue=${this.priorityQueue.length}.`); + logger.debug(`Status queue=${this.queue.length} priorityQueue=${this.priorityQueue.length}.`, NS); return (prioritize ? this.priorityQueue : this.queue).push({ sendAttempts: 0, func, @@ -118,10 +118,10 @@ export class EmberRequestQueue { const status: EmberStatus = (await entry.func()); if ((status === EmberStatus.MAX_MESSAGE_LIMIT_REACHED) || (status === EmberStatus.NETWORK_BUSY)) { - debug(`Dispatching deferred: NCP busy.`); + logger.debug(`Dispatching deferred: NCP busy.`, NS); this.defer(NETWORK_BUSY_DEFER_MSEC); } else if (status === EmberStatus.NETWORK_DOWN) { - debug(`Dispatching deferred: Network not ready`); + logger.debug(`Dispatching deferred: Network not ready`, NS); this.defer(NETWORK_DOWN_DEFER_MSEC); } else { // success @@ -133,10 +133,10 @@ export class EmberRequestQueue { } } catch (err) {// message is EzspStatus string from ezsp${x} commands, except for stuff rejected by OneWaitress, but that's never "retry" if (err.message === EzspStatus[EzspStatus.NO_TX_SPACE]) { - debug(`Dispatching deferred: Host busy.`); + logger.debug(`Dispatching deferred: Host busy.`, NS); this.defer(NETWORK_BUSY_DEFER_MSEC); } else if (err.message === EzspStatus[EzspStatus.NOT_CONNECTED]) { - debug(`Dispatching deferred: Network not ready`); + logger.debug(`Dispatching deferred: Network not ready`, NS); this.defer(NETWORK_DOWN_DEFER_MSEC); } else { (fromPriorityQueue ? this.priorityQueue : this.queue).shift(); diff --git a/src/adapter/ember/adapter/tokensManager.ts b/src/adapter/ember/adapter/tokensManager.ts index ed6fbe6ba5..408aeffd15 100644 --- a/src/adapter/ember/adapter/tokensManager.ts +++ b/src/adapter/ember/adapter/tokensManager.ts @@ -1,5 +1,4 @@ /* istanbul ignore file */ -import Debug from "debug"; import {initSecurityManagerContext} from "../utils/initters"; import {BLANK_EUI64} from "../consts"; import {EMBER_ENCRYPTION_KEY_SIZE, EUI64_SIZE} from "../ezsp/consts"; @@ -7,8 +6,9 @@ import {EmberStatus, EzspStatus, SLStatus, SecManFlag, SecManKeyType} from "../e import {EzspValueId} from "../ezsp/enums"; import {EmberTokenData, SecManKey} from "../types"; import {Ezsp} from "../ezsp/ezsp"; +import {logger} from "../../../utils/logger"; -const debug = Debug('zigbee-herdsman:adapter:ember:adapter:tokens'); +const NS = 'zh:ember:tokens'; /* eslint-disable @typescript-eslint/no-unused-vars */ //------------------------------------------------------------------------------ @@ -341,7 +341,7 @@ export class EmberTokensManager { * @return Saved tokens buffer or null. */ public static async saveTokens(ezsp: Ezsp, localEui64: Buffer): Promise { - console.log(`[TOKENS] Saving tokens...`); + logger.info(`[TOKENS] Saving tokens...`, NS); const tokenCount = (await ezsp.ezspGetTokenCount()); if (tokenCount) { @@ -350,7 +350,7 @@ export class EmberTokensManager { // Don't compile for scripted test or any non-host code due to linker issues. const hasSecureStorage: boolean = (await EmberTokensManager.ncpUsesPSAKeyStorage(ezsp)); - debug(`[TOKENS] Saving ${tokenCount} tokens, ${hasSecureStorage ? "with" : "without"} secure storage.`); + logger.debug(`[TOKENS] Saving ${tokenCount} tokens, ${hasSecureStorage ? "with" : "without"} secure storage.`, NS); for (let i = 0; i < tokenCount; i++) { const [tiStatus, tokenInfo] = (await ezsp.ezspGetTokenInfo(i)); @@ -372,13 +372,15 @@ export class EmberTokensManager { await EmberTokensManager.saveKeysToData(ezsp, tokenData, tokenInfo.nvm3Key, arrayIndex); // ensure the token data was retrieved properly, length should match the size announced by the token info - console.assert( - tokenData.data.length === tokenInfo.size, - `[TOKENS] Mismatch in token data size; got ${tokenData.data.length}, expected ${tokenInfo.size}.` - ); + if (tokenData.data.length !== tokenInfo.size) { + logger.error( + `[TOKENS] Mismatch in token data size; got ${tokenData.data.length}, expected ${tokenInfo.size}.`, + NS, + ); + } } - // debug(`[TOKENS] TOKEN nvm3Key=${DEBUG_TOKEN_STRINGS[tokenInfo.nvm3Key]} size=${tokenInfo.size} ` - // + `arraySize=${tokenInfo.arraySize} token=${tokenData.data.toString('hex')}`); + // logger.debug(`[TOKENS] TOKEN nvm3Key=${DEBUG_TOKEN_STRINGS[tokenInfo.nvm3Key]} size=${tokenInfo.size} ` + // + `arraySize=${tokenInfo.arraySize} token=${tokenData.data.toString('hex')}`, NS); // Check the Key to see if the token to save is restoredEui64, in that case // check if it is blank, then save the node EUI64 in its place, else save the value @@ -388,19 +390,19 @@ export class EmberTokensManager { && (tokenData.data === BLANK_EUI64_BUF)) { // Special case : Save the node EUI64 on the restoredEui64 token while saving. tokenData.data.set(localEui64); - debug(`[TOKENS] Saved node EUI64 in place of blank RESTORED EUI64.`); + logger.debug(`[TOKENS] Saved node EUI64 in place of blank RESTORED EUI64.`, NS); } outputToken.set(tokenData.data, writeOffset); writeOffset += tokenData.size; } else { - console.error(`[TOKENS] Failed to get token data at index ${arrayIndex} with status=${EmberStatus[tdStatus]}.`); + logger.error(`[TOKENS] Failed to get token data at index ${arrayIndex} with status=${EmberStatus[tdStatus]}.`, NS); } } chunks.push(outputToken); } else { - console.error(`[TOKENS] Failed to get token info at index ${i} with status=${EmberStatus[tiStatus]}.`); + logger.error(`[TOKENS] Failed to get token info at index ${i} with status=${EmberStatus[tiStatus]}.`, NS); } } @@ -408,7 +410,7 @@ export class EmberTokensManager { } else { // ezspGetTokenCount == 0 OR (ezspGetTokenInfo|ezspGetTokenData|ezspSetTokenData return LIBRARY_NOT_PRESENT) // ezspTokenFactoryReset will do nothing. - console.error(`[TOKENS] Saving tokens not supported by NCP (not NVM3-based).`); + logger.error(`[TOKENS] Saving tokens not supported by NCP (not NVM3-based).`, NS); } return null; @@ -428,13 +430,13 @@ export class EmberTokensManager { throw new Error(`[TOKENS] Restore tokens buffer empty.`); } - console.log(`[TOKENS] Restoring tokens...`); + logger.info(`[TOKENS] Restoring tokens...`, NS); let readOffset: number = 0; const inTokenCount = inBuffer.readUInt8(readOffset++); const hasSecureStorage: boolean = (await EmberTokensManager.ncpUsesPSAKeyStorage(ezsp)); - debug(`[TOKENS] Restoring ${inTokenCount} tokens, ${hasSecureStorage ? "with" : "without"} secure storage.`); + logger.debug(`[TOKENS] Restoring ${inTokenCount} tokens, ${hasSecureStorage ? "with" : "without"} secure storage.`, NS); for (let i = 0; i < inTokenCount; i++) { const [tiStatus, tokenInfo] = (await ezsp.ezspGetTokenInfo(i)); @@ -458,15 +460,14 @@ export class EmberTokensManager { const status = (await ezsp.ezspSetTokenData(nvm3Key, arrayIndex, tokenData)) as EmberStatus; - console.assert( - status === EmberStatus.SUCCESS, - `[TOKENS] Failed to set token data for key "${nvm3Key}" with status=${EmberStatus[status]}.` - ); + if (status !== EmberStatus.SUCCESS) { + logger.error(`[TOKENS] Failed to set token data for key "${nvm3Key}" with status=${EmberStatus[status]}.`, NS); + } readOffset += tokenData.size; } } else { - console.error(`[TOKENS] Failed to get token info at index ${i} with status=${EmberStatus[tiStatus]}.`); + logger.error(`[TOKENS] Failed to get token info at index ${i} with status=${EmberStatus[tiStatus]}.`, NS); } } @@ -746,7 +747,7 @@ export class EmberTokensManager { throw new Error(`[TOKENS] Restore tokens buffer empty.`); } - console.log(`[TOKENS] Restoring tokens to Zigbeed...`); + logger.info(`[TOKENS] Restoring tokens to Zigbeed...`, NS); let readOffset: number = 0; const inTokenCount = inBuffer.readUInt8(readOffset++); @@ -766,10 +767,12 @@ export class EmberTokensManager { const creator = EmberTokensManager.getCreatorFromNvm3Key(nvm3Key);// uint16_t const status = (await ezsp.ezspSetTokenData(creator, arrayIndex, tokenData)); - console.assert( - status === EmberStatus.SUCCESS, - `[TOKENS] Failed to set Zigbeed token data for key "${nvm3Key}" creator "${creator}" with status=${EmberStatus[status]}.` - ); + if (status !== EmberStatus.SUCCESS) { + logger.error( + `[TOKENS] Failed to set Zigbeed token data for key "${nvm3Key}" creator "${creator}" with status=${EmberStatus[status]}.`, + NS, + ); + } readOffset += tokenData.size; } diff --git a/src/adapter/ember/ezsp/ezsp.ts b/src/adapter/ember/ezsp/ezsp.ts index 10d9bbf948..c08af01c58 100644 --- a/src/adapter/ember/ezsp/ezsp.ts +++ b/src/adapter/ember/ezsp/ezsp.ts @@ -1,5 +1,4 @@ /* istanbul ignore file */ -import Debug from "debug"; import EventEmitter from "events"; import {SerialPortOptions} from "../../tstype"; import Cluster from "../../../zcl/definition/cluster"; @@ -181,8 +180,9 @@ import { WILDCARD_PROFILE_ID } from "../consts"; import {FIXED_ENDPOINTS} from "../adapter/endpoints"; +import {logger} from "../../../utils/logger"; -const debug = Debug('zigbee-herdsman:adapter:ember:ezsp'); +const NS = 'zh:ember:ezsp'; /** @@ -335,7 +335,7 @@ export class Ezsp extends EventEmitter { } public async start(): Promise { - console.log(`======== EZSP starting ========`); + logger.info(`======== EZSP starting ========`, NS); this.initVariables(); @@ -352,7 +352,7 @@ export class Ezsp extends EventEmitter { status = await this.ash.start(); if (status === EzspStatus.SUCCESS) { - console.log(`======== EZSP started ========`); + logger.info(`======== EZSP started ========`, NS); this.registerHandlers(); return status; } @@ -375,7 +375,7 @@ export class Ezsp extends EventEmitter { clearInterval(this.tickHandle); this.initVariables(); - console.log(`======== EZSP stopped ========`); + logger.info(`======== EZSP stopped ========`, NS); } /** @@ -418,14 +418,14 @@ export class Ezsp extends EventEmitter { if (status === EzspStatus.ERROR_QUEUE_FULL) { this.counterErrQueueFull += 1; - console.error(`NCP Queue full (counter: ${this.counterErrQueueFull}). ${lastFrameStr}`); + logger.error(`NCP Queue full (counter: ${this.counterErrQueueFull}). ${lastFrameStr}`, NS); } else if (status === EzspStatus.ERROR_OVERFLOW) { - console.error( - `The NCP has run out of buffers, causing general malfunction. Remediate network congestion, if present. ` - + lastFrameStr + logger.error( + `The NCP has run out of buffers, causing general malfunction. Remediate network congestion, if present. ${lastFrameStr}`, + NS, ); } else { - console.error(`ERROR Transaction failure; status=${EzspStatus[status]}. ${lastFrameStr}`); + logger.error(`ERROR Transaction failure; status=${EzspStatus[status]}. ${lastFrameStr}`, NS); } // Do not reset if this is a decryption failure, as we ignored the packet @@ -468,7 +468,7 @@ export class Ezsp extends EventEmitter { private startCommand(command: number): void { if (this.sendingCommand) { - console.error(`[SEND COMMAND] Cannot send second one before processing response from first one.`); + logger.error(`[SEND COMMAND] Cannot send second one before processing response from first one.`, NS); throw new Error(EzspStatus[EzspStatus.ERROR_INVALID_CALL]); } @@ -516,7 +516,7 @@ export class Ezsp extends EventEmitter { */ private async sendCommand(): Promise { if (!this.checkConnection()) { - debug("[SEND COMMAND] NOT CONNECTED"); + logger.debug(`[SEND COMMAND] NOT CONNECTED`, NS); return EzspStatus.NOT_CONNECTED; } @@ -549,7 +549,7 @@ export class Ezsp extends EventEmitter { let status: EzspStatus; - debug(`===> ${this.frameToString}`); + logger.debug(`===> ${this.frameToString}`, NS); try { status = await (new Promise((resolve, reject: (reason: Error) => void): void => { @@ -578,7 +578,7 @@ export class Ezsp extends EventEmitter { throw new Error(EzspStatus[status]); } } catch (err) { - debug(`=x=> ${this.frameToString} Error: ${err}`); + logger.debug(`=x=> ${this.frameToString} Error: ${err}`, NS); this.ezspErrorHandler(status); } @@ -607,7 +607,7 @@ export class Ezsp extends EventEmitter { // While we are waiting for a response to a command, we use the asynch callback flag to ignore asynchronous callbacks. // This allows our caller to assume that no callbacks will appear between sending a command and receiving its response. if (this.waitingForResponse && (buffer.data[EZSP_FRAME_CONTROL_INDEX] & EZSP_FRAME_CONTROL_ASYNCH_CB)) { - debug(`Skipping async callback while waiting for response to command.`); + logger.debug(`Skipping async callback while waiting for response to command.`, NS); if (this.ash.rxFree.length === 0) { dropBuffer = buffer; @@ -620,7 +620,7 @@ export class Ezsp extends EventEmitter { this.frameLength = buffer.len; - debug(`<=== ${this.frameToString}`);// raw=${this.frameContents.subarray(0, this.frameLength).toString('hex')}`); + logger.debug(`<=== ${this.frameToString}`, NS); this.ash.rxFree.freeBuffer(buffer); @@ -634,7 +634,7 @@ export class Ezsp extends EventEmitter { this.ash.rxQueue.removeEntry(dropBuffer); this.ash.rxFree.freeBuffer(dropBuffer); - debug(`ERROR Host receive queue full. Dropping received callback: ${dropBuffer.data.toString('hex')}`); + logger.debug(`ERROR Host receive queue full. Dropping received callback: ${dropBuffer.data.toString('hex')}`, NS); this.ezspErrorHandler(EzspStatus.ERROR_QUEUE_FULL); } @@ -687,7 +687,7 @@ export class Ezsp extends EventEmitter { } if (status !== EzspStatus.SUCCESS) { - debug(`[RESPONSE RECEIVED] ERROR ${EzspStatus[status]}`); + logger.debug(`[RESPONSE RECEIVED] ERROR ${EzspStatus[status]}`, NS); this.ezspErrorHandler(status); } @@ -1134,7 +1134,10 @@ export class Ezsp extends EventEmitter { apsFrame.sequence = apsSequence; // NOTE: match `~~~>` from adapter since this is just a wrapper for it - debug(`~~~> [SENT type=${EmberOutgoingMessageType[type]} apsSequence=${apsSequence} messageTag=${messageTag} status=${EmberStatus[status]}]`); + logger.debug( + `~~~> [SENT type=${EmberOutgoingMessageType[type]} apsSequence=${apsSequence} messageTag=${messageTag} status=${EmberStatus[status]}]`, + NS, + ); return [status, messageTag]; } @@ -1753,7 +1756,7 @@ export class Ezsp extends EventEmitter { * Indicates that there are currently no pending callbacks. */ ezspNoCallbacks(): void { - debug(`ezspNoCallbacks(): callback called`); + logger.debug(`ezspNoCallbacks(): callback called`, NS); } /** @@ -1898,7 +1901,7 @@ export class Ezsp extends EventEmitter { * @param tokenAddress uint16_t The address of the stack token that has changed. */ ezspStackTokenChangedHandler(tokenAddress: number): void { - debug(`ezspStackTokenChangedHandler(): callback called with: [tokenAddress=${tokenAddress}]`); + logger.debug(`ezspStackTokenChangedHandler(): callback called with: [tokenAddress=${tokenAddress}]`, NS); } /** @@ -1983,7 +1986,7 @@ export class Ezsp extends EventEmitter { * @param timerId uint8_t Which timer generated the callback (0 or 1). */ ezspTimerHandler(timerId: number): void { - debug(`ezspTimerHandler(): callback called with: [timerId=${timerId}]`); + logger.debug(`ezspTimerHandler(): callback called with: [timerId=${timerId}]`, NS); } /** @@ -2050,7 +2053,7 @@ export class Ezsp extends EventEmitter { * @param type Type of Counter */ ezspCounterRolloverHandler(type: EmberCounterType): void { - debug(`ezspCounterRolloverHandler(): callback called with: [type=${EmberCounterType[type]}]`); + logger.debug(`ezspCounterRolloverHandler(): callback called with: [type=${EmberCounterType[type]}]`, NS); } /** @@ -2153,7 +2156,7 @@ export class Ezsp extends EventEmitter { * @param payload uint8_t * The payload of the custom frame. */ ezspCustomFrameHandler(payloadLength: number, payload: number[]): void { - debug(`ezspCustomFrameHandler(): callback called with: [payloadLength=${payloadLength}], [payload=${payload}]`); + logger.debug(`ezspCustomFrameHandler(): callback called with: [payloadLength=${payloadLength}], [payload=${payload}]`, NS); } /** @@ -2319,7 +2322,7 @@ export class Ezsp extends EventEmitter { * @param status Stack status */ ezspStackStatusHandler(status: EmberStatus): void { - debug(`ezspStackStatusHandler(): callback called with: [status=${EmberStatus[status]}]`); + logger.debug(`ezspStackStatusHandler(): callback called with: [status=${EmberStatus[status]}]`, NS); this.emit(EzspEvents.STACK_STATUS, status); } @@ -2368,8 +2371,8 @@ export class Ezsp extends EventEmitter { * @param maxRssiValue int8_t The maximum RSSI value found on the channel. */ ezspEnergyScanResultHandler(channel: number, maxRssiValue: number): void { - debug(`ezspEnergyScanResultHandler(): callback called with: [channel=${channel}], [maxRssiValue=${maxRssiValue}]`); - console.log(`Energy scan for channel ${channel} reports max RSSI value at ${maxRssiValue}.`); + logger.debug(`ezspEnergyScanResultHandler(): callback called with: [channel=${channel}], [maxRssiValue=${maxRssiValue}]`, NS); + logger.info(`Energy scan for channel ${channel} reports max RSSI value at ${maxRssiValue}.`, NS); } /** @@ -2381,8 +2384,8 @@ export class Ezsp extends EventEmitter { * @param lastHopRssi int8_t The energy level (in units of dBm) observed during the reception. */ ezspNetworkFoundHandler(networkFound: EmberZigbeeNetwork, lastHopLqi: number, lastHopRssi: number): void { - debug(`ezspNetworkFoundHandler(): callback called with: [networkFound=${networkFound}], ` - + `[lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}]`); + logger.debug(`ezspNetworkFoundHandler(): callback called with: [networkFound=${networkFound}], ` + + `[lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}]`, NS); } /** @@ -2394,7 +2397,7 @@ export class Ezsp extends EventEmitter { * error conditions signify a failure to scan on the channel specified. */ ezspScanCompleteHandler(channel: number, status: EmberStatus): void { - debug(`ezspScanCompleteHandler(): callback called with: [channel=${channel}], [status=${EmberStatus[status]}]`); + logger.debug(`ezspScanCompleteHandler(): callback called with: [channel=${channel}], [status=${EmberStatus[status]}]`, NS); } /** @@ -2405,7 +2408,7 @@ export class Ezsp extends EventEmitter { * @param channel uint8_t The channel that the unused panID was found on. */ ezspUnusedPanIdFoundHandler(panId: EmberPanId, channel: number): void { - debug(`ezspUnusedPanIdFoundHandler(): callback called with: [panId=${panId}], [channel=${channel}]`); + logger.debug(`ezspUnusedPanIdFoundHandler(): callback called with: [panId=${panId}], [channel=${channel}]`, NS); } /** @@ -2618,8 +2621,8 @@ export class Ezsp extends EventEmitter { * @param childType The node type of the child. */ ezspChildJoinHandler(index: number, joining: boolean, childId: EmberNodeId, childEui64: EmberEUI64, childType: EmberNodeType): void { - debug(`ezspChildJoinHandler(): callback called with: [index=${index}], [joining=${joining}], ` - + `[childId=${childId}], [childEui64=${childEui64}], [childType=${childType}]`); + logger.debug(`ezspChildJoinHandler(): callback called with: [index=${index}], [joining=${joining}], ` + + `[childId=${childId}], [childEui64=${childEui64}], [childType=${childType}]`, NS); } /** @@ -3389,8 +3392,8 @@ export class Ezsp extends EventEmitter { */ ezspDutyCycleHandler(channelPage: number, channel: number, state: EmberDutyCycleState, totalDevices: number, arrayOfDeviceDutyCycles: EmberPerDeviceDutyCycle[]): void { - debug(`ezspDutyCycleHandler(): callback called with: [channelPage=${channelPage}], [channel=${channel}], ` - + `[state=${state}], [totalDevices=${totalDevices}], [arrayOfDeviceDutyCycles=${arrayOfDeviceDutyCycles}]`); + logger.debug(`ezspDutyCycleHandler(): callback called with: [channelPage=${channelPage}], [channel=${channel}], ` + + `[state=${state}], [totalDevices=${totalDevices}], [arrayOfDeviceDutyCycles=${arrayOfDeviceDutyCycles}]`, NS); } /** @@ -3655,8 +3658,8 @@ export class Ezsp extends EventEmitter { * @param policyDecision EMBER_SUCCESS if the binding was added to the table and any other status if not. */ ezspRemoteSetBindingHandler(entry: EmberBindingTableEntry, index: number, policyDecision: EmberStatus): void { - debug(`ezspRemoteSetBindingHandler(): callback called with: [entry=${entry}], [index=${index}], ` - + `[policyDecision=${EmberStatus[policyDecision]}]`); + logger.debug(`ezspRemoteSetBindingHandler(): callback called with: [entry=${entry}], [index=${index}], ` + + `[policyDecision=${EmberStatus[policyDecision]}]`, NS); } /** @@ -3669,7 +3672,7 @@ export class Ezsp extends EventEmitter { * @param policyDecision EMBER_SUCCESS if the binding was removed from the table and any other status if not. */ ezspRemoteDeleteBindingHandler(index: number, policyDecision: EmberStatus): void { - debug(`ezspRemoteDeleteBindingHandler(): callback called with: [index=${index}], [policyDecision=${EmberStatus[policyDecision]}]`); + logger.debug(`ezspRemoteDeleteBindingHandler(): callback called with: [index=${index}], [policyDecision=${EmberStatus[policyDecision]}]`, NS); } //----------------------------------------------------------------------------- @@ -3951,9 +3954,12 @@ export class Ezsp extends EventEmitter { */ ezspMessageSentHandler(type: EmberOutgoingMessageType, indexOrDestination: number, apsFrame: EmberApsFrame, messageTag: number, status: EmberStatus, messageContents: Buffer): void { - debug(`ezspMessageSentHandler(): callback called with: [type=${EmberOutgoingMessageType[type]}], [indexOrDestination=${indexOrDestination}], ` + logger.debug( + `ezspMessageSentHandler(): callback called with: [type=${EmberOutgoingMessageType[type]}], [indexOrDestination=${indexOrDestination}], ` + `[apsFrame=${JSON.stringify(apsFrame)}], [messageTag=${messageTag}], [status=${EmberStatus[status]}], ` - + `[messageContents=${messageContents.toString('hex')}]`); + + `[messageContents=${messageContents.toString('hex')}]`, + NS, + ); if (status === EmberStatus.DELIVERY_FAILED) { // no ACK was received from the destination @@ -4050,7 +4056,7 @@ export class Ezsp extends EventEmitter { * - EMBER_MAC_NO_ACK_RECEIVED - The poll message was sent but not acknowledged by the parent. */ ezspPollCompleteHandler(status: EmberStatus): void { - debug(`ezspPollCompleteHandler(): callback called with: [status=${EmberStatus[status]}]`); + logger.debug(`ezspPollCompleteHandler(): callback called with: [status=${EmberStatus[status]}]`, NS); } /** @@ -4060,7 +4066,7 @@ export class Ezsp extends EventEmitter { * @param transmitExpected True if transmit is expected, false otherwise. */ ezspPollHandler(childId: EmberNodeId, transmitExpected: boolean): void { - debug(`ezspPollHandler(): callback called with: [childId=${childId}], [transmitExpected=${transmitExpected}]`); + logger.debug(`ezspPollHandler(): callback called with: [childId=${childId}], [transmitExpected=${transmitExpected}]`, NS); } /** @@ -4072,7 +4078,7 @@ export class Ezsp extends EventEmitter { * @param senderEui64 The EUI64 of the sender */ ezspIncomingSenderEui64Handler(senderEui64: EmberEUI64): void { - debug(`ezspIncomingSenderEui64Handler(): callback called with: [senderEui64=${senderEui64}]`); + logger.debug(`ezspIncomingSenderEui64Handler(): callback called with: [senderEui64=${senderEui64}]`, NS); } /** @@ -4091,9 +4097,12 @@ export class Ezsp extends EventEmitter { */ ezspIncomingMessageHandler(type: EmberIncomingMessageType, apsFrame: EmberApsFrame, lastHopLqi: number, lastHopRssi: number, sender: EmberNodeId, bindingIndex: number, addressIndex: number, messageContents: Buffer): void { - debug(`ezspIncomingMessageHandler(): callback called with: [type=${EmberIncomingMessageType[type]}], [apsFrame=${JSON.stringify(apsFrame)}], ` + logger.debug( + `ezspIncomingMessageHandler(): callback called with: [type=${EmberIncomingMessageType[type]}], [apsFrame=${JSON.stringify(apsFrame)}], ` + `[lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}], [sender=${sender}], [bindingIndex=${bindingIndex}], ` - + `[addressIndex=${addressIndex}], [messageContents=${messageContents.toString('hex')}]`); + + `[addressIndex=${addressIndex}], [messageContents=${messageContents.toString('hex')}]`, + NS, + ); if (apsFrame.profileId === ZDO_PROFILE_ID) { const zdoBuffalo = new EzspBuffalo(messageContents, ZDO_MESSAGE_OVERHEAD);// set pos to skip `transaction sequence number` @@ -4103,7 +4112,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO IEEE_ADDRESS_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO IEEE_ADDRESS_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { // 64-bit address for the remote device @@ -4131,9 +4140,9 @@ export class Ezsp extends EventEmitter { assocDevList = zdoBuffalo.readListUInt16({length: assocDevCount}); } - debug(`<=== [ZDO IEEE_ADDRESS_RESPONSE status=${EmberZdoStatus[status]} eui64=${eui64} nodeId=${nodeId} startIndex=${startIndex} ` - + `assocDevList=${assocDevList}]`); - debug(`<=== [ZDO IEEE_ADDRESS_RESPONSE] Support not implemented upstream`); + logger.debug(`<=== [ZDO IEEE_ADDRESS_RESPONSE status=${EmberZdoStatus[status]} eui64=${eui64} nodeId=${nodeId} ` + + `startIndex=${startIndex} assocDevList=${assocDevList}]`, NS); + logger.debug(`<=== [ZDO IEEE_ADDRESS_RESPONSE] Support not implemented upstream`, NS); const payload: IEEEAddressResponsePayload = {eui64, nodeId, assocDevList}; @@ -4145,7 +4154,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO NETWORK_ADDRESS_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO NETWORK_ADDRESS_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { // 64-bit address for the remote device @@ -4173,8 +4182,8 @@ export class Ezsp extends EventEmitter { assocDevList = zdoBuffalo.readListUInt16({length: assocDevCount}); } - debug(`<=== [ZDO NETWORK_ADDRESS_RESPONSE status=${EmberZdoStatus[status]} eui64=${eui64} nodeId=${nodeId} ` - + `startIndex=${startIndex} assocDevList=${assocDevList}]`); + logger.debug(`<=== [ZDO NETWORK_ADDRESS_RESPONSE status=${EmberZdoStatus[status]} eui64=${eui64} nodeId=${nodeId} ` + + `startIndex=${startIndex} assocDevList=${assocDevList}]`, NS); const payload: NetworkAddressResponsePayload = {eui64, nodeId, assocDevList}; @@ -4186,15 +4195,18 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO MATCH_DESCRIPTORS_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO MATCH_DESCRIPTORS_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { const nodeId = zdoBuffalo.readUInt16(); const endpointCount = zdoBuffalo.readUInt8(); const endpointList = zdoBuffalo.readListUInt8({length: endpointCount}); - debug(`<=== [ZDO MATCH_DESCRIPTORS_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} endpointList=${endpointList}]`); - debug(`<=== [ZDO MATCH_DESCRIPTORS_RESPONSE] Support not implemented upstream`); + logger.debug( + `<=== [ZDO MATCH_DESCRIPTORS_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} endpointList=${endpointList}]`, + NS, + ); + logger.debug(`<=== [ZDO MATCH_DESCRIPTORS_RESPONSE] Support not implemented upstream`, NS); const payload: MatchDescriptorsResponsePayload = {nodeId, endpointList}; @@ -4206,7 +4218,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO SIMPLE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO SIMPLE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { const nodeId = zdoBuffalo.readUInt16(); @@ -4222,9 +4234,9 @@ export class Ezsp extends EventEmitter { const outClusterCount = zdoBuffalo.readUInt8(); const outClusterList = zdoBuffalo.readListUInt16({length: outClusterCount}); - debug(`<=== [ZDO SIMPLE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} endpoint=${endpoint} ` + logger.debug(`<=== [ZDO SIMPLE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} endpoint=${endpoint} ` + `profileId=${profileId} deviceId=${deviceId} deviceVersion=${deviceVersion} inClusterList=${inClusterList} ` - + `outClusterList=${outClusterList}]`); + + `outClusterList=${outClusterList}]`, NS); const payload: SimpleDescriptorResponsePayload = { nodeId, @@ -4243,7 +4255,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO NODE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO NODE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { const nodeId = zdoBuffalo.readUInt16(); @@ -4298,9 +4310,9 @@ export class Ezsp extends EventEmitter { // eslint-disable-next-line @typescript-eslint/no-unused-vars const descCapFlags = zdoBuffalo.readUInt8(); - debug(`<=== [ZDO NODE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} logicalType=${logicalType} ` + logger.debug(`<=== [ZDO NODE_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} logicalType=${logicalType} ` + `freqBand=${freqBand} macCapFlags=${byteToBits(macCapFlags)} manufacturerCode=${manufacturerCode} maxBufSize=${maxBufSize} ` - + `maxIncTxSize=${maxIncTxSize} stackRevision=${stackRevision} maxOutTxSize=${maxOutTxSize}]`); + + `maxIncTxSize=${maxIncTxSize} stackRevision=${stackRevision} maxOutTxSize=${maxOutTxSize}]`, NS); const payload: NodeDescriptorResponsePayload = { nodeId, @@ -4318,7 +4330,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO POWER_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO POWER_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { const nodeId = zdoBuffalo.readUInt16(); @@ -4342,10 +4354,10 @@ export class Ezsp extends EventEmitter { // All other values reserved const [currentPowerSource, currentPowerSourceLevel] = lowHighBits(zdoBuffalo.readUInt8()); - debug(`<=== [ZDO POWER_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} ` + logger.debug(`<=== [ZDO POWER_DESCRIPTOR_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} ` + `currentPowerMode=${currentPowerMode} availPowerSources=${availPowerSources} currentPowerSource=${currentPowerSource} ` - + `currentPowerSourceLevel=${currentPowerSourceLevel}]`); - debug(`<=== [ZDO POWER_DESCRIPTOR_RESPONSE] Support not implemented upstream`); + + `currentPowerSourceLevel=${currentPowerSourceLevel}]`, NS); + logger.debug(`<=== [ZDO POWER_DESCRIPTOR_RESPONSE] Support not implemented upstream`, NS); const payload: PowerDescriptorResponsePayload = { nodeId, @@ -4363,14 +4375,17 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO ACTIVE_ENDPOINTS_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO ACTIVE_ENDPOINTS_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { const nodeId = zdoBuffalo.readUInt16(); const endpointCount = zdoBuffalo.readUInt8(); const endpointList = zdoBuffalo.readListUInt8({length: endpointCount}); - debug(`<=== [ZDO ACTIVE_ENDPOINTS_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} endpointList=${endpointList}]`); + logger.debug( + `<=== [ZDO ACTIVE_ENDPOINTS_RESPONSE status=${EmberZdoStatus[status]} nodeId=${nodeId} endpointList=${endpointList}]`, + NS, + ); const payload: ActiveEndpointsResponsePayload = {nodeId, endpointList}; @@ -4382,7 +4397,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO LQI_TABLE_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO LQI_TABLE_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { // 0x00-0xFF, total number of neighbor table entries within the remote device @@ -4419,8 +4434,8 @@ export class Ezsp extends EventEmitter { }); } - debug(`<=== [ZDO LQI_TABLE_RESPONSE status=${EmberZdoStatus[status]} neighborTableEntries=${neighborTableEntries} ` - + `startIndex=${startIndex} entryCount=${entryCount} entryList=${JSON.stringify(entryList)}]`); + logger.debug(`<=== [ZDO LQI_TABLE_RESPONSE status=${EmberZdoStatus[status]} neighborTableEntries=${neighborTableEntries} ` + + `startIndex=${startIndex} entryCount=${entryCount} entryList=${JSON.stringify(entryList)}]`, NS); const payload: LQITableResponsePayload = {neighborTableEntries, entryList}; @@ -4432,7 +4447,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO ROUTING_TABLE_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO ROUTING_TABLE_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { // 0x00-0xFF, total number of routing table entries within the remote device @@ -4461,8 +4476,8 @@ export class Ezsp extends EventEmitter { }); } - debug(`<=== [ZDO ROUTING_TABLE_RESPONSE status=${EmberZdoStatus[status]} routingTableEntries=${routingTableEntries} ` - + `startIndex=${startIndex} entryCount=${entryCount} entryList=${JSON.stringify(entryList)}]`); + logger.debug(`<=== [ZDO ROUTING_TABLE_RESPONSE status=${EmberZdoStatus[status]} routingTableEntries=${routingTableEntries} ` + + `startIndex=${startIndex} entryCount=${entryCount} entryList=${JSON.stringify(entryList)}]`, NS); const payload: RoutingTableResponsePayload = {routingTableEntries, entryList}; @@ -4474,7 +4489,7 @@ export class Ezsp extends EventEmitter { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); if (status !== EmberZdoStatus.ZDP_SUCCESS) { - debug(`<=== [ZDO BINDING_TABLE_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO BINDING_TABLE_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { const bindingTableEntries = zdoBuffalo.readUInt8(); @@ -4500,9 +4515,9 @@ export class Ezsp extends EventEmitter { }); } - debug(`<=== [ZDO BINDING_TABLE_RESPONSE status=${EmberZdoStatus[status]} bindingTableEntries=${bindingTableEntries} ` - + `startIndex=${startIndex} entryCount=${entryCount} entryList=${JSON.stringify(entryList)}]`); - debug(`<=== [ZDO BINDING_TABLE_RESPONSE] Support not implemented upstream`); + logger.debug(`<=== [ZDO BINDING_TABLE_RESPONSE status=${EmberZdoStatus[status]} bindingTableEntries=${bindingTableEntries} ` + + `startIndex=${startIndex} entryCount=${entryCount} entryList=${JSON.stringify(entryList)}]`, NS); + logger.debug(`<=== [ZDO BINDING_TABLE_RESPONSE] Support not implemented upstream`, NS); const payload: BindingTableResponsePayload = {bindingTableEntries, entryList}; @@ -4513,28 +4528,28 @@ export class Ezsp extends EventEmitter { case BIND_RESPONSE: { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); - debug(`<=== [ZDO BIND_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO BIND_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame); break; } case UNBIND_RESPONSE:{ const status: EmberZdoStatus = zdoBuffalo.readUInt8(); - debug(`<=== [ZDO UNBIND_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO UNBIND_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame); break; } case LEAVE_RESPONSE: { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); - debug(`<=== [ZDO LEAVE_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO LEAVE_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame); break; } case PERMIT_JOINING_RESPONSE: { const status: EmberZdoStatus = zdoBuffalo.readUInt8(); - debug(`<=== [ZDO PERMIT_JOINING_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO PERMIT_JOINING_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame); break; } @@ -4544,7 +4559,7 @@ export class Ezsp extends EventEmitter { /** @see MACCapabilityFlags */ const capabilities = zdoBuffalo.readUInt8(); - debug(`<=== [ZDO END_DEVICE_ANNOUNCE nodeId=${nodeId} eui64=${eui64} capabilities=${byteToBits(capabilities)}]`); + logger.debug(`<=== [ZDO END_DEVICE_ANNOUNCE nodeId=${nodeId} eui64=${eui64} capabilities=${byteToBits(capabilities)}]`, NS); const payload: EndDeviceAnnouncePayload = {nodeId, eui64, capabilities: getMacCapFlags(capabilities)}; @@ -4557,7 +4572,7 @@ export class Ezsp extends EventEmitter { if (status !== EmberZdoStatus.ZDP_SUCCESS) { // status should always be NOT_SUPPORTED here - debug(`<=== [ZDO PARENT_ANNOUNCE_RESPONSE status=${EmberZdoStatus[status]}]`); + logger.debug(`<=== [ZDO PARENT_ANNOUNCE_RESPONSE status=${EmberZdoStatus[status]}]`, NS); this.emit(EzspEvents.ZDO_RESPONSE, status, sender, apsFrame, null); } else { const numberOfChildren = zdoBuffalo.readUInt8(); @@ -4569,9 +4584,9 @@ export class Ezsp extends EventEmitter { children.push(childEui64); } - debug(`<=== [ZDO PARENT_ANNOUNCE_RESPONSE status=${EmberZdoStatus[status]} numberOfChildren=${numberOfChildren} ` - + `children=${children}]`); - debug(`<=== [ZDO PARENT_ANNOUNCE_RESPONSE] Support not implemented upstream`); + logger.debug(`<=== [ZDO PARENT_ANNOUNCE_RESPONSE status=${EmberZdoStatus[status]} numberOfChildren=${numberOfChildren} ` + + `children=${children}]`, NS); + logger.debug(`<=== [ZDO PARENT_ANNOUNCE_RESPONSE] Support not implemented upstream`, NS); const payload: ParentAnnounceResponsePayload = {children}; @@ -4579,7 +4594,7 @@ export class Ezsp extends EventEmitter { } } default: { - console.log(`<=== [ZDO clusterId=${apsFrame.clusterId} sender=${sender}] Support not implemented upstream.`); + logger.info(`<=== [ZDO clusterId=${apsFrame.clusterId} sender=${sender}] Support not implemented upstream.`, NS); break; } } @@ -4619,7 +4634,7 @@ export class Ezsp extends EventEmitter { * for this discovery arrive, but the callback is made only once. */ ezspIncomingManyToOneRouteRequestHandler(source: EmberNodeId, longId: EmberEUI64, cost: number): void { - debug(`ezspIncomingManyToOneRouteRequestHandler(): callback called with: [source=${source}], [longId=${longId}], [cost=${cost}]`); + logger.debug(`ezspIncomingManyToOneRouteRequestHandler(): callback called with: [source=${source}], [longId=${longId}], [cost=${cost}]`, NS); } /** @@ -4648,7 +4663,7 @@ export class Ezsp extends EventEmitter { * @param target The short id of the remote node. */ ezspIncomingRouteErrorHandler(status: EmberStatus, target: EmberNodeId): void { - debug(`ezspIncomingRouteErrorHandler(): callback called with: [status=${EmberStatus[status]}], [target=${target}]`); + logger.debug(`ezspIncomingRouteErrorHandler(): callback called with: [status=${EmberStatus[status]}], [target=${target}]`, NS); // NOTE: This can trigger immediately after removal of a device with status MAC_INDIRECT_TIMEOUT } @@ -4666,8 +4681,8 @@ export class Ezsp extends EventEmitter { * @param target The short ID of the remote node */ ezspIncomingNetworkStatusHandler(errorCode: EmberStackError, target: EmberNodeId): void { - debug(`ezspIncomingNetworkStatusHandler(): callback called with: [errorCode=${EmberStackError[errorCode]}], [target=${target}]`); - console.log(`Received network/route error ${EmberStackError[errorCode]} for "${target}".`); + logger.debug(`ezspIncomingNetworkStatusHandler(): callback called with: [errorCode=${EmberStackError[errorCode]}], [target=${target}]`, NS); + logger.warning(`Received network/route error ${EmberStackError[errorCode]} for "${target}".`, NS); } /** @@ -4683,8 +4698,8 @@ export class Ezsp extends EventEmitter { */ ezspIncomingRouteRecordHandler(source: EmberNodeId, sourceEui: EmberEUI64, lastHopLqi: number, lastHopRssi: number, relayCount: number, relayList: number[]): void { - debug(`ezspIncomingRouteRecordHandler(): callback called with: [source=${source}], [sourceEui=${sourceEui}], ` - + `[lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}], [relayCount=${relayCount}], [relayList=${relayList}]`); + logger.debug(`ezspIncomingRouteRecordHandler(): callback called with: [source=${source}], [sourceEui=${sourceEui}], ` + + `[lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}], [relayCount=${relayCount}], [relayList=${relayList}]`, NS); // XXX: could at least trigger a `Events.lastSeenChanged` but this is not currently being listened to at the adapter level } @@ -5045,8 +5060,8 @@ export class Ezsp extends EventEmitter { * @param id The short id for which a conflict was detected */ ezspIdConflictHandler(id: EmberNodeId): void { - debug(`ezspIdConflictHandler(): callback called with: [id=${id}]`); - console.error(`An ID conflict was detected for network address "${id}". Corresponding devices removed from the network.`); + logger.debug(`ezspIdConflictHandler(): callback called with: [id=${id}]`, NS); + logger.error(`An ID conflict was detected for network address "${id}". Corresponding devices removed from the network.`, NS); // XXX: this is currently causing more problems than not doing it, so disabled for now. // devices should rejoin on ID conflict anyway, so the database isn't out of sync for very long. @@ -5128,8 +5143,8 @@ export class Ezsp extends EventEmitter { * @param messageContents uint8_t * The raw message that was received. */ ezspMacPassthroughMessageHandler(messageType: EmberMacPassthroughType, lastHopLqi: number, lastHopRssi: number, messageContents: Buffer): void { - debug(`ezspMacPassthroughMessageHandler(): callback called with: [messageType=${messageType}], [lastHopLqi=${lastHopLqi}], ` - + `[lastHopRssi=${lastHopRssi}], [messageContents=${messageContents.toString('hex')}]`); + logger.debug(`ezspMacPassthroughMessageHandler(): callback called with: [messageType=${messageType}], [lastHopLqi=${lastHopLqi}], ` + + `[lastHopRssi=${lastHopRssi}], [messageContents=${messageContents.toString('hex')}]`, NS); } /** @@ -5145,9 +5160,9 @@ export class Ezsp extends EventEmitter { */ ezspMacFilterMatchMessageHandler(filterIndexMatch: number, legacyPassthroughType: EmberMacPassthroughType, lastHopLqi: number, lastHopRssi: number, messageContents: Buffer): void { - debug(`ezspMacFilterMatchMessageHandler(): callback called with: [filterIndexMatch=${filterIndexMatch}], ` + logger.debug(`ezspMacFilterMatchMessageHandler(): callback called with: [filterIndexMatch=${filterIndexMatch}], ` + `[legacyPassthroughType=${legacyPassthroughType}], [lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}], ` - + `[messageContents=${messageContents.toString('hex')}]`); + + `[messageContents=${messageContents.toString('hex')}]`, NS); // TODO: needs triple-checking, this is only valid for InterPAN messages const msgBuffalo = new EzspBuffalo(messageContents, 0); @@ -5165,7 +5180,7 @@ export class Ezsp extends EventEmitter { // eslint-disable-next-line @typescript-eslint/no-unused-vars destAddress = msgBuffalo.readUInt16(); } else { - debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN macFrameControl "${macFrameControl}".`); + logger.debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN macFrameControl "${macFrameControl}".`, NS); return; } @@ -5176,7 +5191,7 @@ export class Ezsp extends EventEmitter { let remainingLength = msgBuffalo.getBufferLength() - msgBuffalo.getPosition(); if (remainingLength < (STUB_NWK_SIZE + MIN_STUB_APS_SIZE)) { - debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN length "${remainingLength}".`); + logger.debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN length "${remainingLength}".`, NS); return; } @@ -5184,7 +5199,7 @@ export class Ezsp extends EventEmitter { remainingLength -= 2;// read 2 more bytes before APS stuff if (nwkFrameControl !== STUB_NWK_FRAME_CONTROL) { - debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN nwkFrameControl "${nwkFrameControl}".`); + logger.debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN nwkFrameControl "${nwkFrameControl}".`, NS); return; } @@ -5192,7 +5207,7 @@ export class Ezsp extends EventEmitter { if ((apsFrameControl & ~(INTERPAN_APS_FRAME_DELIVERY_MODE_MASK) & ~(INTERPAN_APS_FRAME_SECURITY)) !== INTERPAN_APS_FRAME_CONTROL_NO_DELIVERY_MODE) { - debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN apsFrameControl "${apsFrameControl}".`); + logger.debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN apsFrameControl "${apsFrameControl}".`, NS); return; } @@ -5203,14 +5218,14 @@ export class Ezsp extends EventEmitter { case EmberInterpanMessageType.UNICAST: case EmberInterpanMessageType.BROADCAST: { if (remainingLength < INTERPAN_APS_UNICAST_BROADCAST_SIZE) { - debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN length "${remainingLength}".`); + logger.debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN length "${remainingLength}".`, NS); return; } break; } case EmberInterpanMessageType.MULTICAST: { if (remainingLength < INTERPAN_APS_MULTICAST_SIZE) { - debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN length "${remainingLength}".`); + logger.debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN length "${remainingLength}".`, NS); return; } @@ -5218,7 +5233,7 @@ export class Ezsp extends EventEmitter { break; } default: { - debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN messageType "${messageType}".`); + logger.debug(`ezspMacFilterMatchMessageHandler INVALID InterPAN messageType "${messageType}".`, NS); return; } } @@ -5239,7 +5254,7 @@ export class Ezsp extends EventEmitter { * @param status EMBER_SUCCESS if the transmission was successful, or EMBER_DELIVERY_FAILED if not */ ezspRawTransmitCompleteHandler(status: EmberStatus): void { - debug(`ezspRawTransmitCompleteHandler(): callback called with: [status=${EmberStatus[status]}]`); + logger.debug(`ezspRawTransmitCompleteHandler(): callback called with: [status=${EmberStatus[status]}]`, NS); } /** @@ -5395,7 +5410,7 @@ export class Ezsp extends EventEmitter { */ // NOTE: added for good measure if (context.coreKeyType === SecManKeyType.INTERNAL) { - console.assert(false, `ezspImportKey cannot use INTERNAL key type.`); + logger.error(`ezspImportKey cannot use INTERNAL key type.`, NS); return [null, SLStatus.INVALID_PARAMETER]; } @@ -5460,7 +5475,7 @@ export class Ezsp extends EventEmitter { */ // NOTE: added for good measure if (context.coreKeyType === SecManKeyType.INTERNAL) { - console.assert(false, `ezspImportKey cannot use INTERNAL key type.`); + logger.error(`ezspImportKey cannot use INTERNAL key type.`, NS); return SLStatus.INVALID_PARAMETER; } @@ -5487,7 +5502,7 @@ export class Ezsp extends EventEmitter { * @param sequenceNumber uint8_t The sequence number of the new network key. */ ezspSwitchNetworkKeyHandler(sequenceNumber: number): void { - debug(`ezspSwitchNetworkKeyHandler(): callback called with: [sequenceNumber=${sequenceNumber}]`); + logger.debug(`ezspSwitchNetworkKeyHandler(): callback called with: [sequenceNumber=${sequenceNumber}]`, NS); } /** @@ -5644,7 +5659,7 @@ export class Ezsp extends EventEmitter { * @param status This is the status indicating what was established or why the key establishment failed. */ ezspZigbeeKeyEstablishmentHandler(partner: EmberEUI64, status: EmberKeyStatus): void { - debug(`ezspZigbeeKeyEstablishmentHandler(): callback called with: [partner=${partner}], [status=${EmberKeyStatus[status]}]`); + logger.debug(`ezspZigbeeKeyEstablishmentHandler(): callback called with: [partner=${partner}], [status=${EmberKeyStatus[status]}]`, NS); // NOTE: For security reasons, any valid `partner` (not wildcard) that return with a status=TC_REQUESTER_VERIFY_KEY_TIMEOUT // are kicked off the network for posing a risk, unless HA devices allowed (as opposed to Z3) // and always if status=TC_REQUESTER_VERIFY_KEY_FAILURE @@ -6025,9 +6040,9 @@ export class Ezsp extends EventEmitter { */ ezspTrustCenterJoinHandler(newNodeId: EmberNodeId, newNodeEui64: EmberEUI64, status: EmberDeviceUpdate, policyDecision: EmberJoinDecision, parentOfNewNodeId: EmberNodeId): void { - debug(`ezspTrustCenterJoinHandler(): callback called with: [newNodeId=${newNodeId}], [newNodeEui64=${newNodeEui64}], ` + logger.debug(`ezspTrustCenterJoinHandler(): callback called with: [newNodeId=${newNodeId}], [newNodeEui64=${newNodeEui64}], ` + `[status=${EmberDeviceUpdate[status]}], [policyDecision=${EmberJoinDecision[policyDecision]}], ` - + `[parentOfNewNodeId=${parentOfNewNodeId}]`); + + `[parentOfNewNodeId=${parentOfNewNodeId}]`, NS); // NOTE: this is mostly just passing stuff up to Z2M, so use only one emit for all, let adapter do the rest, no parsing needed this.emit(EzspEvents.TRUST_CENTER_JOIN, newNodeId, newNodeEui64, status, policyDecision, parentOfNewNodeId); } @@ -6188,7 +6203,10 @@ export class Ezsp extends EventEmitter { * @param ephemeralPublicKey EmberPublicKeyData * The generated ephemeral public key. */ ezspGenerateCbkeKeysHandler(status: EmberStatus, ephemeralPublicKey: EmberPublicKeyData): void { - debug(`ezspGenerateCbkeKeysHandler(): callback called with: [status=${EmberStatus[status]}], [ephemeralPublicKey=${ephemeralPublicKey}]`); + logger.debug( + `ezspGenerateCbkeKeysHandler(): callback called with: [status=${EmberStatus[status]}], [ephemeralPublicKey=${ephemeralPublicKey}]`, + NS, + ); } /** @@ -6229,8 +6247,8 @@ export class Ezsp extends EventEmitter { * @param responderSmac EmberSmacData * The calculated value of the responder's SMAC */ ezspCalculateSmacsHandler(status: EmberStatus, initiatorSmac: EmberSmacData, responderSmac: EmberSmacData): void { - debug(`ezspCalculateSmacsHandler(): callback called with: [status=${EmberStatus[status]}], [initiatorSmac=${initiatorSmac}], ` - + `[responderSmac=${responderSmac}]`); + logger.debug(`ezspCalculateSmacsHandler(): callback called with: [status=${EmberStatus[status]}], [initiatorSmac=${initiatorSmac}], ` + + `[responderSmac=${responderSmac}]`, NS); } /** @@ -6261,8 +6279,8 @@ export class Ezsp extends EventEmitter { * @param ephemeralPublicKey EmberPublicKey283k1Data * The generated ephemeral public key. */ ezspGenerateCbkeKeysHandler283k1(status: EmberStatus, ephemeralPublicKey: EmberPublicKey283k1Data): void { - debug(`ezspGenerateCbkeKeysHandler283k1(): callback called with: [status=${EmberStatus[status]}], ` - + `[ephemeralPublicKey=${ephemeralPublicKey}]`); + logger.debug(`ezspGenerateCbkeKeysHandler283k1(): callback called with: [status=${EmberStatus[status]}], ` + + `[ephemeralPublicKey=${ephemeralPublicKey}]`, NS); } /** @@ -6304,8 +6322,8 @@ export class Ezsp extends EventEmitter { * @param responderSmac EmberSmacData * The calculated value of the responder's SMAC */ ezspCalculateSmacsHandler283k1(status: EmberStatus, initiatorSmac: EmberSmacData, responderSmac: EmberSmacData): void { - debug(`ezspCalculateSmacsHandler283k1(): callback called with: [status=${EmberStatus[status]}], [initiatorSmac=${initiatorSmac}], ` - + `[responderSmac=${responderSmac}]`); + logger.debug(`ezspCalculateSmacsHandler283k1(): callback called with: [status=${EmberStatus[status]}], [initiatorSmac=${initiatorSmac}], ` + + `[responderSmac=${responderSmac}]`, NS); } /** @@ -6450,7 +6468,10 @@ export class Ezsp extends EventEmitter { * @param messageContents uint8_t *The message and attached which includes the original message and the appended signature. */ ezspDsaSignHandler(status: EmberStatus, messageContents: Buffer): void { - debug(`ezspDsaSignHandler(): callback called with: [status=${EmberStatus[status]}], [messageContents=${messageContents.toString('hex')}]`); + logger.debug( + `ezspDsaSignHandler(): callback called with: [status=${EmberStatus[status]}], [messageContents=${messageContents.toString('hex')}]`, + NS, + ); } /** @@ -6489,7 +6510,7 @@ export class Ezsp extends EventEmitter { * @param status The result of the DSA verification operation. */ ezspDsaVerifyHandler(status: EmberStatus): void { - debug(`ezspDsaVerifyHandler(): callback called with: [status=${EmberStatus[status]}]`); + logger.debug(`ezspDsaVerifyHandler(): callback called with: [status=${EmberStatus[status]}]`, NS); } /** @@ -6791,8 +6812,8 @@ export class Ezsp extends EventEmitter { * @param packetContents uint8_t * The received packet (last 2 bytes are not FCS / CRC and may be discarded) */ ezspMfglibRxHandler(linkQuality: number, rssi: number, packetLength: number, packetContents: number[]): void { - debug(`ezspMfglibRxHandler(): callback called with: [linkQuality=${linkQuality}], [rssi=${rssi}], ` - + `[packetLength=${packetLength}], [packetContents=${packetContents}]`); + logger.debug(`ezspMfglibRxHandler(): callback called with: [linkQuality=${linkQuality}], [rssi=${rssi}], ` + + `[packetLength=${packetLength}], [packetContents=${packetContents}]`, NS); // gecko_sdk_4.4.0\protocol\zigbee\app\framework\plugin\manufacturing-library-cli\manufacturing-library-cli-host.c } @@ -6891,8 +6912,8 @@ export class Ezsp extends EventEmitter { * @param messageContents uint8_t *The bootload message that was sent. */ ezspIncomingBootloadMessageHandler(longId: EmberEUI64, lastHopLqi: number, lastHopRssi: number, messageContents: Buffer): void { - debug(`ezspIncomingBootloadMessageHandler(): callback called with: [longId=${longId}], [lastHopLqi=${lastHopLqi}], ` - + `[lastHopRssi=${lastHopRssi}], [messageContents=${messageContents.toString('hex')}]`); + logger.debug(`ezspIncomingBootloadMessageHandler(): callback called with: [longId=${longId}], [lastHopLqi=${lastHopLqi}], ` + + `[lastHopRssi=${lastHopRssi}], [messageContents=${messageContents.toString('hex')}]`, NS); } /** @@ -6905,8 +6926,8 @@ export class Ezsp extends EventEmitter { * @param messageContents uint8_t * The message that was sent. */ ezspBootloadTransmitCompleteHandler(status: EmberStatus, messageContents: Buffer): void { - debug(`ezspBootloadTransmitCompleteHandler(): callback called with: [status=${EmberStatus[status]}], ` - + `[messageContents=${messageContents.toString('hex')}]`); + logger.debug(`ezspBootloadTransmitCompleteHandler(): callback called with: [status=${EmberStatus[status]}], ` + + `[messageContents=${messageContents.toString('hex')}]`, NS); } /** @@ -7056,8 +7077,8 @@ export class Ezsp extends EventEmitter { */ ezspZllNetworkFoundHandler(networkInfo: EmberZllNetwork, isDeviceInfoNull: boolean, deviceInfo: EmberZllDeviceInfoRecord, lastHopLqi: number, lastHopRssi: number): void { - debug(`ezspZllNetworkFoundHandler(): callback called with: [networkInfo=${networkInfo}], [isDeviceInfoNull=${isDeviceInfoNull}], ` - + `[deviceInfo=${deviceInfo}], [lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}]`); + logger.debug(`ezspZllNetworkFoundHandler(): callback called with: [networkInfo=${networkInfo}], [isDeviceInfoNull=${isDeviceInfoNull}], ` + + `[deviceInfo=${deviceInfo}], [lastHopLqi=${lastHopLqi}], [lastHopRssi=${lastHopRssi}]`, NS); } /** @@ -7066,7 +7087,7 @@ export class Ezsp extends EventEmitter { * @param status Status of the operation. */ ezspZllScanCompleteHandler(status: EmberStatus): void { - debug(`ezspZllScanCompleteHandler(): callback called with: [status=${EmberStatus[status]}]`); + logger.debug(`ezspZllScanCompleteHandler(): callback called with: [status=${EmberStatus[status]}]`, NS); } /** @@ -7078,8 +7099,8 @@ export class Ezsp extends EventEmitter { * @param lastHopRssi int8_t The energy level (in units of dBm) observed during reception. */ ezspZllAddressAssignmentHandler(addressInfo: EmberZllAddressAssignment, lastHopLqi: number, lastHopRssi: number): void { - debug(`ezspZllAddressAssignmentHandler(): callback called with: [addressInfo=${addressInfo}], [lastHopLqi=${lastHopLqi}], ` - + `[lastHopRssi=${lastHopRssi}]`); + logger.debug(`ezspZllAddressAssignmentHandler(): callback called with: [addressInfo=${addressInfo}], [lastHopLqi=${lastHopLqi}], ` + + `[lastHopRssi=${lastHopRssi}]`, NS); } /** @@ -7088,7 +7109,7 @@ export class Ezsp extends EventEmitter { * @param networkInfo EmberZllNetwork * Information about the network. */ ezspZllTouchLinkTargetHandler(networkInfo: EmberZllNetwork): void { - debug(`ezspZllTouchLinkTargetHandler(): callback called with: [networkInfo=${networkInfo}]`); + logger.debug(`ezspZllTouchLinkTargetHandler(): callback called with: [networkInfo=${networkInfo}]`, NS); } /** @@ -7540,7 +7561,7 @@ export class Ezsp extends EventEmitter { * @param gpepHandle uint8_t The handle of the GPDF. */ ezspDGpSentHandler(status: EmberStatus, gpepHandle: number): void { - debug(`ezspDGpSentHandler(): callback called with: [status=${EmberStatus[status]}], [gpepHandle=${gpepHandle}]`); + logger.debug(`ezspDGpSentHandler(): callback called with: [status=${EmberStatus[status]}], [gpepHandle=${gpepHandle}]`, NS); } /** @@ -7564,15 +7585,15 @@ export class Ezsp extends EventEmitter { ezspGpepIncomingMessageHandler(status: EmberStatus, gpdLink: number, sequenceNumber: number, addr: EmberGpAddress, gpdfSecurityLevel: EmberGpSecurityLevel, gpdfSecurityKeyType: EmberGpKeyType, autoCommissioning: boolean, bidirectionalInfo: number, gpdSecurityFrameCounter: number, gpdCommandId: number, mic: number, proxyTableIndex: number, gpdCommandPayload: Buffer): void { - debug(`ezspGpepIncomingMessageHandler(): callback called with: [status=${EmberStatus[status]}], [gpdLink=${gpdLink}], ` + logger.debug(`ezspGpepIncomingMessageHandler(): callback called with: [status=${EmberStatus[status]}], [gpdLink=${gpdLink}], ` + `[sequenceNumber=${sequenceNumber}], [addr=${JSON.stringify(addr)}], [gpdfSecurityLevel=${EmberGpSecurityLevel[gpdfSecurityLevel]}], ` + `[gpdfSecurityKeyType=${EmberGpKeyType[gpdfSecurityKeyType]}], [autoCommissioning=${autoCommissioning}], ` + `[bidirectionalInfo=${bidirectionalInfo}], [gpdSecurityFrameCounter=${gpdSecurityFrameCounter}], [gpdCommandId=${gpdCommandId}], ` - + `[mic=${mic}], [proxyTableIndex=${proxyTableIndex}], [gpdCommandPayload=${gpdCommandPayload.toString('hex')}]`); + + `[mic=${mic}], [proxyTableIndex=${proxyTableIndex}], [gpdCommandPayload=${gpdCommandPayload.toString('hex')}]`, NS); if (addr.applicationId === EmberGpApplicationId.IEEE_ADDRESS) { // XXX: don't bother parsing for upstream for now, since it will be rejected - console.error(`<=== [GP] Received IEEE address type in message. Support not implemented upstream. Dropping.`); + logger.error(`<=== [GP] Received IEEE address type in message. Support not implemented upstream. Dropping.`, NS); return; } diff --git a/src/adapter/ember/uart/ash.ts b/src/adapter/ember/uart/ash.ts index b17a0de7d2..656130114a 100644 --- a/src/adapter/ember/uart/ash.ts +++ b/src/adapter/ember/uart/ash.ts @@ -1,5 +1,4 @@ /* istanbul ignore file */ -import Debug from "debug"; import {EventEmitter} from "stream"; import {Socket} from "net"; import SocketPortUtils from "../../socketPortUtils"; @@ -44,8 +43,9 @@ import {EzspBuffer, EzspFreeList, EzspQueue} from "./queues"; import {AshWriter} from "./writer"; import {AshParser} from "./parser"; import {Wait} from "../../../utils"; +import {logger} from "../../../utils/logger"; -const debug = Debug('zigbee-herdsman:adapter:ember:uart:ash'); +const NS = 'zh:ember:uart:ash'; /** ASH get rflag in control byte */ @@ -490,7 +490,7 @@ export class UartAsh extends EventEmitter { // enable software flow control if RTS/CTS not enabled in config if (!serialOpts.rtscts) { - debug(`RTS/CTS config is off, enabling software flow control.`); + logger.debug(`RTS/CTS config is off, enabling software flow control.`, NS); serialOpts.xon = true; serialOpts.xoff = true; } @@ -501,7 +501,7 @@ export class UartAsh extends EventEmitter { serialOpts.binding = this.portOptions.binding; } - debug(`Opening serial port with ${JSON.stringify(serialOpts)}`); + logger.debug(`Opening serial port with ${JSON.stringify(serialOpts)}`, NS); this.serialPort = new SerialPort(serialOpts); this.writer = new AshWriter({highWaterMark: CONFIG_HIGHWATER_MARK}); @@ -513,7 +513,7 @@ export class UartAsh extends EventEmitter { try { await this.serialPort.asyncOpen(); - debug(`Serial port opened: ${JSON.stringify(await this.serialPort.asyncGet())}`); + logger.debug(`Serial port opened: ${JSON.stringify(await this.serialPort.asyncGet())}`, NS); this.serialPort.once('close', this.onPortClose.bind(this)); this.serialPort.on('error', this.onPortError.bind(this)); @@ -524,7 +524,7 @@ export class UartAsh extends EventEmitter { } } else { const info = SocketPortUtils.parseTcpPath(this.portOptions.path); - debug(`Opening TCP socket with ${info.host}:${info.port}`); + logger.debug(`Opening TCP socket with ${info.host}:${info.port}`, NS); this.socketPort = new Socket(); this.socketPort.setNoDelay(true); @@ -545,10 +545,10 @@ export class UartAsh extends EventEmitter { }; this.socketPort.on('connect', () => { - debug('Socket connected'); + logger.debug('Socket connected', NS); }); this.socketPort.on('ready', async (): Promise => { - debug('Socket ready'); + logger.debug('Socket ready', NS); this.socketPort.removeListener('error', openError); this.socketPort.once('close', this.onPortClose.bind(this)); this.socketPort.on('error', this.onPortError.bind(this)); @@ -567,7 +567,7 @@ export class UartAsh extends EventEmitter { * @param err A boolean for Socket, an Error for serialport */ private async onPortClose(err: boolean | Error): Promise { - console.log(`Port closed. Error? ${err ?? 'no'}`); + logger.info(`Port closed. Error? ${err ?? 'no'}`, NS); } /** @@ -575,7 +575,7 @@ export class UartAsh extends EventEmitter { * @param error */ private async onPortError(error: Error): Promise { - console.log(`Port error: ${error}`); + logger.info(`Port error: ${error}`, NS); this.emit(AshEvents.fatalError, EzspStatus.ERROR_SERIAL_INIT); } @@ -591,7 +591,7 @@ export class UartAsh extends EventEmitter { if (this.flags & Flag.CONNECTED) { this.counters.rxCancelled += 1; - console.warn(`Frame(s) in progress cancelled in [${buffer.toString('hex')}]`); + logger.warning(`Frame(s) in progress cancelled in [${buffer.toString('hex')}]`, NS); } // get rid of everything up to the CAN flag and start reading frame from there, no need to loop through bytes in vain @@ -601,7 +601,7 @@ export class UartAsh extends EventEmitter { if (!buffer.length) { // skip any CANCEL that results in empty frame (have yet to see one, but just in case...) // shouldn't happen for any other reason, unless receiving bad stuff from port? - debug(`Received empty frame. Skipping.`); + logger.debug(`Received empty frame. Skipping.`, NS); return; } @@ -609,12 +609,12 @@ export class UartAsh extends EventEmitter { if ((status !== EzspStatus.SUCCESS) && (status !== EzspStatus.ASH_IN_PROGRESS) && (status !== EzspStatus.NO_RX_DATA)) { if (this.flags & Flag.CONNECTED) { - console.error(`Error while parsing received frame, status=${EzspStatus[status]}.`); + logger.error(`Error while parsing received frame, status=${EzspStatus[status]}.`, NS); // if we're connected (not in reset) and get here, we need to reset this.emit(AshEvents.fatalError, EzspStatus.HOST_FATAL_ERROR); return; } else { - debug(`Error while parsing received frame in NOT_CONNECTED state (flags=${this.flags}), status=${EzspStatus[status]}.`); + logger.debug(`Error while parsing received frame in NOT_CONNECTED state (flags=${this.flags}), status=${EzspStatus[status]}.`, NS); } } } @@ -632,7 +632,7 @@ export class UartAsh extends EventEmitter { return EzspStatus.ERROR_INVALID_CALL; } - console.log(`======== ASH starting ========`); + logger.info(`======== ASH starting ========`, NS); try { if (this.serialPort != null) { @@ -641,7 +641,7 @@ export class UartAsh extends EventEmitter { // XXX: Socket equiv? } } catch (err) { - console.error(`Error while flushing before start: ${err}`); + logger.error(`Error while flushing before start: ${err}`, NS); } this.sendExec(); @@ -650,7 +650,7 @@ export class UartAsh extends EventEmitter { // NOTE: on average, this seems to take around 1000ms when successful for (let i = 0; i < CONFIG_TIME_RST; i += CONFIG_TIME_RST_CHECK) { if ((this.flags & Flag.CONNECTED)) { - console.log(`======== ASH started ========`); + logger.info(`======== ASH started ========`, NS); return EzspStatus.SUCCESS; } else if ((this.hostError !== EzspStatus.NO_ERROR) || (this.ncpError !== EzspStatus.NO_ERROR)) { @@ -658,7 +658,7 @@ export class UartAsh extends EventEmitter { break; } - debug(`Waiting for RSTACK... ${i}/${CONFIG_TIME_RST}`); + logger.debug(`Waiting for RSTACK... ${i}/${CONFIG_TIME_RST}`, NS); await Wait(CONFIG_TIME_RST_CHECK); } @@ -675,7 +675,7 @@ export class UartAsh extends EventEmitter { await this.closePort(); this.initVariables(); - console.log(`======== ASH stopped ========`); + logger.info(`======== ASH stopped ========`, NS); } /** @@ -687,9 +687,9 @@ export class UartAsh extends EventEmitter { try { await this.serialPort.asyncFlushAndClose(); - debug(`Serial port closed.`); + logger.debug(`Serial port closed.`, NS); } catch (err) { - console.error(`Failed to close serial port ${err}.`); + logger.error(`Failed to close serial port ${err}.`, NS); } this.serialPort.removeAllListeners(); @@ -697,7 +697,7 @@ export class UartAsh extends EventEmitter { this.socketPort.destroy(); this.socketPort.removeAllListeners(); - debug(`Socket port closed.`); + logger.debug(`Socket port closed.`, NS); } } @@ -716,7 +716,7 @@ export class UartAsh extends EventEmitter { return EzspStatus.ERROR_INVALID_CALL; } - console.log(`======== ASH NCP reset ========`); + logger.info(`======== ASH NCP reset ========`, NS); this.initVariables(); @@ -732,7 +732,7 @@ export class UartAsh extends EventEmitter { return EzspStatus.SUCCESS; } catch (err) { - console.error(`Failed to init port with error ${err}`); + logger.error(`Failed to init port with error ${err}`, NS); this.hostError = status; @@ -815,7 +815,7 @@ export class UartAsh extends EventEmitter { this.adjustAckPeriod(true); - debug(`Timer expired waiting for ACK for ${expectedFrm}, current=${this.ackRx}`); + logger.debug(`Timer expired waiting for ACK for ${expectedFrm}, current=${this.ackRx}`, NS); if (++this.timeouts >= ASH_MAX_TIMEOUTS) { this.hostDisconnect(EzspStatus.ASH_ERROR_TIMEOUTS); @@ -885,16 +885,16 @@ export class UartAsh extends EventEmitter { len = 1; this.flags &= ~(Flag.RST | Flag.NAK | Flag.ACK); this.sendState = SendState.SHFRAME; - debug(`---> [FRAME type=RST]`); + logger.debug(`---> [FRAME type=RST]`, NS); } else if (this.flags & (Flag.NAK | Flag.ACK)) { if (this.flags & Flag.NAK) { this.txSHBuffer[0] = AshFrameType.NAK + (this.frmRx << ASH_ACKNUM_BIT); this.flags &= ~(Flag.NRTX | Flag.NAK | Flag.ACK); - debug(`---> [FRAME type=NAK frmRx=${this.frmRx}]`); + logger.debug(`---> [FRAME type=NAK frmRx=${this.frmRx}]`, NS); } else { this.txSHBuffer[0] = AshFrameType.ACK + (this.frmRx << ASH_ACKNUM_BIT); this.flags &= ~(Flag.NRTX | Flag.ACK); - debug(`---> [FRAME type=ACK frmRx=${this.frmRx}]`); + logger.debug(`---> [FRAME type=ACK frmRx=${this.frmRx}]`, NS); } if (this.flags & Flag.NR) { @@ -913,7 +913,7 @@ export class UartAsh extends EventEmitter { len = buffer.len + 1; this.txSHBuffer[0] = AshFrameType.DATA | (this.frmReTx << ASH_FRMNUM_BIT) | (this.frmRx << ASH_ACKNUM_BIT) | ASH_RFLAG_MASK; this.sendState = SendState.RETX_DATA; - debug(`---> [FRAME type=DATA_RETX frmReTx=${this.frmReTx} frmRx=${this.frmRx}]`); + logger.debug(`---> [FRAME type=DATA_RETX frmReTx=${this.frmReTx} frmRx=${this.frmRx}]`, NS); } else if (this.ackTx != this.frmRx) { // An ACK should be generated this.flags |= Flag.ACK; @@ -927,7 +927,7 @@ export class UartAsh extends EventEmitter { this.txSHBuffer[0] = AshFrameType.DATA | (this.frmTx << ASH_FRMNUM_BIT) | (this.frmRx << ASH_ACKNUM_BIT); this.sendState = SendState.TX_DATA; - debug(`---> [FRAME type=DATA frmTx=${this.frmTx} frmRx=${this.frmRx}]`); + logger.debug(`---> [FRAME type=DATA frmTx=${this.frmTx} frmRx=${this.frmRx}]`, NS); } else { // Otherwise there's nothing to send this.writer.writeFlush(); @@ -1026,30 +1026,30 @@ export class UartAsh extends EventEmitter { this.counters.rxCrcErrors += 1; this.rejectFrame(); - console.error(`Received frame with CRC error`); + logger.error(`Received frame with CRC error`, NS); return EzspStatus.NO_RX_DATA; case EzspStatus.ASH_COMM_ERROR: this.counters.rxCommErrors += 1; this.rejectFrame(); - console.error(`Received frame with comm error`); + logger.error(`Received frame with comm error`, NS); return EzspStatus.NO_RX_DATA; case EzspStatus.ASH_TOO_SHORT: this.counters.rxTooShort += 1; this.rejectFrame(); - console.error(`Received frame shorter than minimum`); + logger.error(`Received frame shorter than minimum`, NS); return EzspStatus.NO_RX_DATA; case EzspStatus.ASH_TOO_LONG: this.counters.rxTooLong += 1; this.rejectFrame(); - console.error(`Received frame longer than maximum`); + logger.error(`Received frame longer than maximum`, NS); return EzspStatus.NO_RX_DATA; case EzspStatus.ASH_ERROR_XON_XOFF: return this.hostDisconnect(status); default: - console.error(`Unhandled error while receiving frame, status=${EzspStatus[status]}.`); + logger.error(`Unhandled error while receiving frame, status=${EzspStatus[status]}.`, NS); return this.hostDisconnect(EzspStatus.HOST_FATAL_ERROR); } @@ -1071,7 +1071,7 @@ export class UartAsh extends EventEmitter { const frameTypeStr = AshFrameType[frameType]; - debug(`<--- [FRAME type=${frameTypeStr}]`); + logger.debug(`<--- [FRAME type=${frameTypeStr}]`, NS); this.countFrame(false); // Process frames received while not in the connected state - @@ -1099,11 +1099,11 @@ export class UartAsh extends EventEmitter { this.flags = Flag.CONNECTED | Flag.ACK; - console.log(`======== ASH connected ========`); + logger.info(`======== ASH connected ========`, NS); return EzspStatus.SUCCESS; } else if (frameType === AshFrameType.ERROR) { - console.error(`Received ERROR from NCP while connecting, with code=${NcpFailedCode[this.rxSHBuffer[2]]}.`); + logger.error(`Received ERROR from NCP while connecting, with code=${NcpFailedCode[this.rxSHBuffer[2]]}.`, NS); return this.ncpDisconnect(EzspStatus.ASH_NCP_FATAL_ERROR); } @@ -1114,12 +1114,12 @@ export class UartAsh extends EventEmitter { if ((frameType === AshFrameType.DATA) || (frameType === AshFrameType.ACK) || (frameType === AshFrameType.NAK) ) { ackNum = ashGetACKNum(this.rxSHBuffer[0]); - debug(`<--- [FRAME type=${frameTypeStr} ackNum=${ackNum}]`); + logger.debug(`<--- [FRAME type=${frameTypeStr} ackNum=${ackNum}]`, NS); if (!withinRange(this.ackRx, ackNum, this.frmTx)) { this.counters.rxBadAckNumber += 1; - debug(`<-x- [FRAME type=${frameTypeStr} ackNum=${ackNum}] Invalid ACK num; not within <${this.ackRx}-${this.frmTx}>`); + logger.debug(`<-x- [FRAME type=${frameTypeStr} ackNum=${ackNum}] Invalid ACK num; not within <${this.ackRx}-${this.frmTx}>`, NS); frameType = AshFrameType.INVALID; } else if (ackNum !== this.ackRx) { @@ -1159,7 +1159,7 @@ export class UartAsh extends EventEmitter { // valid frame but no memory? this.counters.rxNoBuffer += 1; - debug(`<-x- ${frameStr} No buffer available`); + logger.debug(`<-x- ${frameStr} No buffer available`, NS); this.rejectFrame(); @@ -1177,7 +1177,7 @@ export class UartAsh extends EventEmitter { this.randomizeBuffer(this.rxDataBuffer.data, this.rxDataBuffer.len);// IN/OUT data this.rxQueue.addTail(this.rxDataBuffer);// add frame to receive queue - debug(`<--- ${frameStr} Added to rxQueue`); + logger.debug(`<--- ${frameStr} Added to rxQueue`, NS); this.counters.rxData += this.rxDataBuffer.len; @@ -1196,7 +1196,7 @@ export class UartAsh extends EventEmitter { if ((this.flags & Flag.REJ) === 0) { this.counters.rxOutOfSequence += 1; - debug(`<-x- ${frameStr} Out of sequence: expected ${this.frmRx}; got ${frmNum}.`); + logger.debug(`<-x- ${frameStr} Out of sequence: expected ${this.frmRx}; got ${frmNum}.`, NS); } this.rejectFrame(); @@ -1213,17 +1213,17 @@ export class UartAsh extends EventEmitter { break; case AshFrameType.RSTACK: // unexpected ncp reset - console.error(`Received unexpected reset from NCP, with reason=${NcpFailedCode[this.rxSHBuffer[2]]}.`); + logger.error(`Received unexpected reset from NCP, with reason=${NcpFailedCode[this.rxSHBuffer[2]]}.`, NS); this.ncpError = EzspStatus.ASH_NCP_FATAL_ERROR; return this.hostDisconnect(EzspStatus.ASH_ERROR_NCP_RESET); case AshFrameType.ERROR: // ncp error - console.error(`Received ERROR from NCP, with code=${NcpFailedCode[this.rxSHBuffer[2]]}.`); + logger.error(`Received ERROR from NCP, with code=${NcpFailedCode[this.rxSHBuffer[2]]}.`, NS); return this.ncpDisconnect(EzspStatus.ASH_NCP_FATAL_ERROR); case AshFrameType.INVALID: // reject invalid frames - debug(`<-x- [FRAME type=${frameTypeStr}] Rejecting. ${this.rxSHBuffer.toString('hex')}`); + logger.debug(`<-x- [FRAME type=${frameTypeStr}] Rejecting. ${this.rxSHBuffer.toString('hex')}`, NS); this.rejectFrame(); break; @@ -1369,12 +1369,12 @@ export class UartAsh extends EventEmitter { if (this.rxFree.length < CONFIG_NR_LOW_LIMIT) { this.flags |= Flag.NR; - debug(`NOT READY - Signaling NCP`); + logger.warning(`NOT READY - Signaling NCP`, NS); } else if (this.rxFree.length > CONFIG_NR_HIGH_LIMIT) { this.flags &= ~Flag.NR; this.stopNrTimer(); // needed?? - // debug(`READY - Signaling NCP`);// spams-a-lot + // logger.debug(`READY - Signaling NCP`, NS);// spams-a-lot } // Force an ACK (or possibly NAK) if we need to send an updated nFlag @@ -1410,7 +1410,7 @@ export class UartAsh extends EventEmitter { this.flags = 0; this.hostError = error; - console.error(`ASH disconnected: ${EzspStatus[error]} | NCP status: ${EzspStatus[this.ncpError]}`); + logger.error(`ASH disconnected: ${EzspStatus[error]} | NCP status: ${EzspStatus[this.ncpError]}`, NS); return EzspStatus.HOST_FATAL_ERROR; } @@ -1424,7 +1424,7 @@ export class UartAsh extends EventEmitter { this.flags = 0; this.ncpError = error; - console.error(`ASH disconnected | NCP status: ${EzspStatus[this.ncpError]}`); + logger.error(`ASH disconnected | NCP status: ${EzspStatus[this.ncpError]}`, NS); return EzspStatus.ASH_NCP_FATAL_ERROR; } @@ -1500,13 +1500,13 @@ export class UartAsh extends EventEmitter { } } else { this.counters.rxBadControl += 1; - debug(`Frame illegal control ${control}.`);// EzspStatus.ASH_BAD_CONTROL + logger.debug(`Frame illegal control ${control}.`, NS);// EzspStatus.ASH_BAD_CONTROL return AshFrameType.INVALID; } this.counters.rxBadLength += 1; - debug(`Frame illegal length ${len} for control ${control}.`);// EzspStatus.ASH_BAD_LENGTH + logger.debug(`Frame illegal length ${len} for control ${control}.`, NS);// EzspStatus.ASH_BAD_LENGTH return AshFrameType.INVALID; } @@ -1888,29 +1888,25 @@ export class UartAsh extends EventEmitter { * Prints counters in a nicely formatted table. */ private printCounters(): void { - console.table({ - "Total frames": {"Received": this.counters.rxAllFrames, "Transmitted": this.counters.txAllFrames}, - "Cancelled": {"Received": this.counters.rxCancelled, "Transmitted": this.counters.txCancelled}, - "DATA frames": {"Received": this.counters.rxDataFrames, "Transmitted": this.counters.txDataFrames}, - "DATA bytes": {"Received": this.counters.rxData, "Transmitted": this.counters.txData}, - "Retry frames": {"Received": this.counters.rxReDataFrames, "Transmitted": this.counters.txReDataFrames}, - "ACK frames": {"Received": this.counters.rxAckFrames, "Transmitted": this.counters.txAckFrames}, - "NAK frames": {"Received": this.counters.rxNakFrames, "Transmitted": this.counters.txNakFrames}, - "nRdy frames": {"Received": this.counters.rxN1Frames, "Transmitted": this.counters.txN1Frames}, - }); - - console.table({ - "CRC errors": {"Received": this.counters.rxCrcErrors}, - "Comm errors": {"Received": this.counters.rxCommErrors}, - "Length < minimum": {"Received": this.counters.rxTooShort}, - "Length > maximum": {"Received": this.counters.rxTooLong}, - "Bad controls": {"Received": this.counters.rxBadControl}, - "Bad lengths": {"Received": this.counters.rxBadLength}, - "Bad ACK numbers": {"Received": this.counters.rxBadAckNumber}, - "Out of buffers": {"Received": this.counters.rxNoBuffer}, - "Retry dupes": {"Received": this.counters.rxDuplicates}, - "Out of sequence": {"Received": this.counters.rxOutOfSequence}, - "ACK timeouts": {"Received": this.counters.rxAckTimeouts}, - }); + logger.info(`Total frames: RX=${this.counters.rxAllFrames}, TX=${this.counters.txAllFrames}`, NS); + logger.info(`Cancelled : RX=${this.counters.rxCancelled}, TX=${this.counters.txCancelled}`, NS); + logger.info(`DATA frames : RX=${this.counters.rxDataFrames}, TX=${this.counters.txDataFrames}`, NS); + logger.info(`DATA bytes : RX=${this.counters.rxData}, TX=${this.counters.txData}`, NS); + logger.info(`Retry frames: RX=${this.counters.rxReDataFrames}, TX=${this.counters.txReDataFrames}`, NS); + logger.info(`ACK frames : RX=${this.counters.rxAckFrames}, TX=${this.counters.txAckFrames}`, NS); + logger.info(`NAK frames : RX=${this.counters.rxNakFrames}, TX=${this.counters.txNakFrames}`, NS); + logger.info(`nRdy frames : RX=${this.counters.rxN1Frames}, TX=${this.counters.txN1Frames}`, NS); + + logger.info(`CRC errors : RX=${this.counters.rxCrcErrors}`, NS); + logger.info(`Comm errors : RX=${this.counters.rxCommErrors}`, NS); + logger.info(`Length < minimum: RX=${this.counters.rxTooShort}`, NS); + logger.info(`Length > maximum: RX=${this.counters.rxTooLong}`, NS); + logger.info(`Bad controls : RX=${this.counters.rxBadControl}`, NS); + logger.info(`Bad lengths : RX=${this.counters.rxBadLength}`, NS); + logger.info(`Bad ACK numbers : RX=${this.counters.rxBadAckNumber}`, NS); + logger.info(`Out of buffers : RX=${this.counters.rxNoBuffer}`, NS); + logger.info(`Retry dupes : RX=${this.counters.rxDuplicates}`, NS); + logger.info(`Out of sequence : RX=${this.counters.rxOutOfSequence}`, NS); + logger.info(`ACK timeouts : RX=${this.counters.rxAckTimeouts}`, NS); } } diff --git a/src/adapter/ember/uart/parser.ts b/src/adapter/ember/uart/parser.ts index f470fae900..e3746fc1b6 100644 --- a/src/adapter/ember/uart/parser.ts +++ b/src/adapter/ember/uart/parser.ts @@ -1,9 +1,9 @@ /* istanbul ignore file */ -import Debug from "debug"; import {Transform, TransformCallback, TransformOptions} from "stream"; import {AshReservedByte} from "./enums"; +import {logger} from "../../../utils/logger"; -const debug = Debug('zigbee-herdsman:adapter:ember:uart:ash:parser'); +const NS = 'zh:ember:uart:ash:parser'; export class AshParser extends Transform { private buffer: Buffer; @@ -23,7 +23,7 @@ export class AshParser extends Transform { const frame = data.subarray(0, position + 1); setImmediate((): void => { - debug(`<<<< [FRAME raw=${frame.toString('hex')}]`); + logger.debug(`<<<< [FRAME raw=${frame.toString('hex')}]`, NS); this.push(frame); }); diff --git a/src/adapter/ember/uart/queues.ts b/src/adapter/ember/uart/queues.ts index 7acd382f0f..5c17e337b2 100644 --- a/src/adapter/ember/uart/queues.ts +++ b/src/adapter/ember/uart/queues.ts @@ -1,6 +1,8 @@ /* istanbul ignore file */ +import {logger} from "../../../utils/logger"; import {EZSP_MAX_FRAME_LENGTH} from "../ezsp/consts"; +const NS = 'zh:ember:uart:queues'; /** * Buffer to hold a DATA frame. @@ -231,7 +233,7 @@ export class EzspFreeList { buf.data = Buffer.alloc(EZSP_MAX_FRAME_LENGTH); const e = new Error(); - console.assert(false, `Pre-allocated buffer had improper size and had to be re-allocated. ${e.stack}`); + logger.error(`Pre-allocated buffer had improper size and had to be re-allocated. ${e.stack}`, NS); } else { // (void) memset(buffer->data, 0, EZSP_MAX_FRAME_LENGTH); buf.data.fill(0); diff --git a/src/adapter/ember/uart/writer.ts b/src/adapter/ember/uart/writer.ts index c577f94127..289a54b9a4 100644 --- a/src/adapter/ember/uart/writer.ts +++ b/src/adapter/ember/uart/writer.ts @@ -1,9 +1,8 @@ /* istanbul ignore file */ -import Debug from "debug"; import {Readable, ReadableOptions} from "stream"; +import {logger} from "../../../utils/logger"; -const debug = Debug('zigbee-herdsman:adapter:ember:uart:ash:writer'); - +const NS = 'zh:ember:uart:ash:writer'; export class AshWriter extends Readable { private bytesToWrite: number[]; @@ -18,7 +17,7 @@ export class AshWriter extends Readable { const buffer = Buffer.from(this.bytesToWrite); this.bytesToWrite = []; - debug(`>>>> [FRAME raw=${buffer.toString('hex')}]`); + logger.debug(`>>>> [FRAME raw=${buffer.toString('hex')}]`, NS); // this.push(buffer); this.emit('data', buffer); diff --git a/src/adapter/ezsp/adapter/backup.ts b/src/adapter/ezsp/adapter/backup.ts index e260952908..8fb278e74e 100644 --- a/src/adapter/ezsp/adapter/backup.ts +++ b/src/adapter/ezsp/adapter/backup.ts @@ -1,5 +1,4 @@ /* istanbul ignore file */ -import Debug from "debug"; import {Driver} from '../driver'; import * as Models from "../../../models"; import { @@ -12,11 +11,13 @@ import { import {channelsMask2list} from '../driver/utils'; import {fs} from "mz"; import {BackupUtils} from "../../../utils"; +import {logger} from '../../../utils/logger'; + +const NS = 'zh:ezsp:backup'; export class EZSPAdapterBackup { private driver: Driver; private defaultPath: string; - private debug = Debug("zigbee-herdsman:adapter:ezsp:backup"); public constructor(driver: Driver, path: string) { this.driver = driver; @@ -24,7 +25,7 @@ export class EZSPAdapterBackup { } public async createBackup(): Promise { - this.debug("creating backup"); + logger.debug("creating backup", NS); const version: number = await this.driver.ezsp.version(); const linkResult = await this.driver.getKey(EmberKeyType.TRUST_CENTER_LINK_KEY); const netParams = await this.driver.ezsp.execCommand('getNetworkParameters'); diff --git a/src/adapter/ezsp/adapter/ezspAdapter.ts b/src/adapter/ezsp/adapter/ezspAdapter.ts index 3224e8227b..879a7d7471 100644 --- a/src/adapter/ezsp/adapter/ezspAdapter.ts +++ b/src/adapter/ezsp/adapter/ezspAdapter.ts @@ -4,10 +4,8 @@ import { ActiveEndpoints, SimpleDescriptor, LQI, RoutingTable, NetworkParameters, StartResult, LQINeighbor, RoutingTableEntry, AdapterOptions } from '../../tstype'; -import Debug from "debug"; import Adapter from '../../adapter'; -const debug = Debug("zigbee-herdsman:adapter:ezsp:debg"); import {Driver, EmberIncomingMessage} from '../driver'; import {EmberZDOCmd, uint16_t, EmberEUI64, EmberStatus} from '../driver/types'; import {ZclFrame, FrameType, Direction, Foundation} from '../../../zcl'; @@ -17,8 +15,9 @@ import * as Models from "../../../models"; import SerialPortUtils from '../../serialPortUtils'; import SocketPortUtils from '../../socketPortUtils'; import {EZSPZDOResponseFrameData} from '../driver/ezsp'; -import {LoggerStub} from "../../../controller/logger-stub"; +import {logger} from '../../../utils/logger'; +const NS = 'zh:ezsp'; const autoDetectDefinitions = [ {manufacturer: 'ITEAD', vendorId: '1a86', productId: '55d4'}, // Sonoff ZBDongle-E @@ -43,9 +42,8 @@ class EZSPAdapter extends Adapter { public constructor(networkOptions: NetworkOptions, - serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions, - logger?: LoggerStub) { - super(networkOptions, serialPortOptions, backupPath, adapterOptions, logger); + serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions) { + super(networkOptions, serialPortOptions, backupPath, adapterOptions); this.waitress = new Waitress( this.waitressValidator, this.waitressTimeoutFormatter @@ -54,11 +52,10 @@ class EZSPAdapter extends Adapter { this.closing = false; const concurrent = adapterOptions && adapterOptions.concurrent ? adapterOptions.concurrent : 8; - debug(`Adapter concurrent: ${concurrent}`); + logger.debug(`Adapter concurrent: ${concurrent}`, NS); this.queue = new Queue(concurrent); - this.driver = new Driver(this.serialPortOptions, this.networkOptions, this.greenPowerGroup, - backupPath, this.logger); + this.driver = new Driver(this.serialPortOptions, this.networkOptions, this.greenPowerGroup, backupPath); this.driver.on('close', this.onDriverClose.bind(this)); this.driver.on('deviceJoined', this.handleDeviceJoin.bind(this)); this.driver.on('deviceLeft', this.handleDeviceLeft.bind(this)); @@ -66,7 +63,7 @@ class EZSPAdapter extends Adapter { } private async processMessage(frame: EmberIncomingMessage): Promise { - debug(`processMessage: ${JSON.stringify(frame)}`); + logger.debug(`processMessage: ${JSON.stringify(frame)}`, NS); if (frame.apsFrame.profileId == 0) { if ( frame.apsFrame.clusterId == EmberZDOCmd.Device_annce && @@ -76,7 +73,7 @@ class EZSPAdapter extends Adapter { [nwk, rst] = uint16_t.deserialize(uint16_t, frame.message.subarray(1)); [ieee, rst] = EmberEUI64.deserialize(EmberEUI64, rst as Buffer); ieee = new EmberEUI64(ieee); - debug("ZDO Device announce: %s, %s", nwk, ieee.toString()); + logger.debug(`ZDO Device announce: ${nwk}, ${ieee.toString()}`, NS); this.driver.handleNodeJoined(nwk, ieee); } } else if (frame.apsFrame.profileId == 260 || frame.apsFrame.profileId == 0xFFFF) { @@ -143,7 +140,7 @@ class EZSPAdapter extends Adapter { this.waitress.resolve(payload); this.emit(Events.Events.zclData, payload); } else { - debug(`Ignoring GP frame because clusterId is not greenPower`); + logger.debug(`Ignoring GP frame because clusterId is not greenPower`, NS); } } this.emit('event', frame); @@ -152,7 +149,7 @@ class EZSPAdapter extends Adapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any private async handleDeviceJoin(arr: any[]): Promise { const [nwk, ieee] = arr; - debug('Device join request received: %s %s', nwk, ieee.toString('hex')); + logger.debug(`Device join request received: ${nwk} ${ieee.toString('hex')}`, NS); const payload: Events.DeviceJoinedPayload = { networkAddress: nwk, ieeeAddr: `0x${ieee.toString('hex')}`, @@ -168,7 +165,7 @@ class EZSPAdapter extends Adapter { // eslint-disable-next-line @typescript-eslint/no-explicit-any private handleDeviceLeft(arr: any[]): void { const [nwk, ieee] = arr; - debug('Device left network request received: %s %s', nwk, ieee); + logger.debug(`Device left network request received: ${nwk} ${ieee}`, NS); const payload: Events.DeviceLeavePayload = { networkAddress: nwk, @@ -190,7 +187,7 @@ class EZSPAdapter extends Adapter { } public async onDriverClose(): Promise { - debug(`onDriverClose()`); + logger.debug(`onDriverClose()`, NS); if (!this.closing) { this.emit(Events.Events.disconnected); @@ -206,7 +203,7 @@ class EZSPAdapter extends Adapter { try { return SerialPortUtils.is(RealpathSync(path), autoDetectDefinitions); } catch (error) { - debug(`Failed to determine if path is valid: '${error}'`); + logger.debug(`Failed to determine if path is valid: '${error}'`, NS); return false; } } @@ -383,11 +380,11 @@ class EZSPAdapter extends Adapter { return this.queue.execute(async () => { this.checkInterpanLock(); try { - debug(`Requesting 'Node Descriptor' for '${networkAddress}'`); + logger.debug(`Requesting 'Node Descriptor' for '${networkAddress}'`, NS); const result = await this.nodeDescriptorInternal(networkAddress); return result; } catch (error) { - debug(`Node descriptor request for '${networkAddress}' failed (${error}), retry`); + logger.debug(`Node descriptor request for '${networkAddress}' failed (${error}), retry`, NS); throw error; } }); @@ -406,7 +403,7 @@ class EZSPAdapter extends Adapter { } public async activeEndpoints(networkAddress: number): Promise { - debug(`Requesting 'Active endpoints' for '${networkAddress}'`); + logger.debug(`Requesting 'Active endpoints' for '${networkAddress}'`, NS); return this.queue.execute(async () => { const endpoints = await this.driver.zdoRequest( networkAddress, EmberZDOCmd.Active_EP_req, EmberZDOCmd.Active_EP_rsp, @@ -417,7 +414,7 @@ class EZSPAdapter extends Adapter { } public async simpleDescriptor(networkAddress: number, endpointID: number): Promise { - debug(`Requesting 'Simple Descriptor' for '${networkAddress}' endpoint ${endpointID}`); + logger.debug(`Requesting 'Simple Descriptor' for '${networkAddress}' endpoint ${endpointID}`, NS); return this.queue.execute(async () => { this.checkInterpanLock(); const descriptor = await this.driver.zdoRequest( @@ -456,8 +453,8 @@ class EZSPAdapter extends Adapter { if (ieeeAddr == null) { ieeeAddr = `0x${this.driver.ieee.toString()}`; } - debug('sendZclFrameToEndpointInternal %s:%i/%i (%i,%i,%i), timeout=%i', - ieeeAddr, networkAddress, endpoint, responseAttempt, dataRequestAttempt, this.queue.count(), timeout); + logger.debug(`sendZclFrameToEndpointInternal ${ieeeAddr}:${networkAddress}/${endpoint} ` + + `(${responseAttempt},${dataRequestAttempt},${this.queue.count()}), timeout=${timeout}`, NS); let response = null; const command = zclFrame.getCommand(); if (command.hasOwnProperty('response') && disableResponse === false) { @@ -492,7 +489,7 @@ class EZSPAdapter extends Adapter { const result = await response.start().promise; return result; } catch (error) { - debug('Response timeout (%s:%d,%d)', ieeeAddr, networkAddress, responseAttempt); + logger.debug(`Response timeout (${ieeeAddr}:${networkAddress},${responseAttempt})`, NS); if (responseAttempt < 1 && !disableRecovery) { return this.sendZclFrameToEndpointInternal( ieeeAddr, networkAddress, endpoint, sourceEndpoint, zclFrame, timeout, disableResponse, @@ -657,7 +654,7 @@ class EZSPAdapter extends Adapter { public async sendZclFrameInterPANToIeeeAddr(zclFrame: ZclFrame, ieeeAddr: string): Promise { return this.queue.execute(async () => { - debug(`sendZclFrameInterPANToIeeeAddr to ${ieeeAddr}`); + logger.debug(`sendZclFrameInterPANToIeeeAddr to ${ieeeAddr}`, NS); try { const frame = this.driver.makeEmberIeeeRawFrame(); frame.ieeeFrameControl = 0xcc21; @@ -679,7 +676,7 @@ class EZSPAdapter extends Adapter { public async sendZclFrameInterPANBroadcast(zclFrame: ZclFrame, timeout: number): Promise { return this.queue.execute(async () => { - debug(`sendZclFrameInterPANBroadcast`); + logger.debug(`sendZclFrameInterPANBroadcast`, NS); const command = zclFrame.getCommand(); if (!command.hasOwnProperty('response')) { throw new Error(`Command '${command.name}' has no response, cannot wait for response`); @@ -721,7 +718,7 @@ class EZSPAdapter extends Adapter { } public async setTransmitPower(value: number): Promise { - debug(`setTransmitPower to ${value}`); + logger.debug(`setTransmitPower to ${value}`, NS); return this.queue.execute(async () => { await this.driver.setRadioPower(value); }); diff --git a/src/adapter/ezsp/driver/driver.ts b/src/adapter/ezsp/driver/driver.ts index e8b256c254..29985e5512 100644 --- a/src/adapter/ezsp/driver/driver.ts +++ b/src/adapter/ezsp/driver/driver.ts @@ -24,16 +24,12 @@ import { } from './types/named'; import {Multicast} from './multicast'; import {Waitress, Wait} from '../../../utils'; -import Debug from "debug"; import equals from 'fast-deep-equal/es6'; import {ParamsDesc} from './commands'; import {EZSPAdapterBackup} from '../adapter/backup'; -import {LoggerStub} from "../../../controller/logger-stub"; +import {logger} from '../../../utils/logger'; -const debug = { - error: Debug('zigbee-herdsman:adapter:ezsp:erro'), - log: Debug('zigbee-herdsman:adapter:ezsp:driv'), -}; +const NS = 'zh:ezsp:driver'; interface AddEndpointParameters { endpoint?: number, @@ -97,18 +93,14 @@ export class Driver extends EventEmitter { private transactionID = 1; private serialOpt: TsType.SerialPortOptions; public backupMan: EZSPAdapterBackup; - private logger: LoggerStub; - constructor(serialOpt: TsType.SerialPortOptions, nwkOpt: TsType.NetworkOptions, greenPowerGroup: number, - backupPath: string, logger: LoggerStub) { + constructor(serialOpt: TsType.SerialPortOptions, nwkOpt: TsType.NetworkOptions, greenPowerGroup: number, backupPath: string) { super(); this.nwkOpt = nwkOpt; this.serialOpt = serialOpt; this.greenPowerGroup = greenPowerGroup; - this.waitress = new Waitress( - this.waitressValidator, this.waitressTimeoutFormatter); - this.logger = logger; + this.waitress = new Waitress(this.waitressValidator, this.waitressTimeoutFormatter); this.backupMan = new EZSPAdapterBackup(this, backupPath); } @@ -118,42 +110,42 @@ export class Driver extends EventEmitter { * @returns */ public async reset(): Promise { - debug.log(`Reset connection.`); + logger.info(`Reset connection.`, NS); try { // don't emit 'close' on stop since we don't want this to bubble back up as 'disconnected' to the controller. await this.stop(false); } catch (err) { - debug.error(`Stop error ${err.stack}`); + logger.error(`Stop error ${err.stack}`, NS); } try { await Wait(1000); - debug.log(`Startup again.`); + logger.info(`Startup again.`, NS); await this.startup(); } catch (err) { - debug.error(`Reset error ${err.stack}`); + logger.error(`Reset error ${err.stack}`, NS); try { // here we let emit await this.stop(); } catch (stopErr) { - debug.error(`Failed to stop after failed reset ${stopErr.stack}`); + logger.error(`Failed to stop after failed reset ${stopErr.stack}`, NS); } } } private async onEzspReset(): Promise { - debug.log('onEzspReset()'); + logger.info('onEzspReset()', NS); await this.reset(); } private onEzspClose(): void { - debug.log('onEzspClose()'); + logger.info('onEzspClose()', NS); this.emit('close'); } public async stop(emitClose: boolean = true): Promise { - debug.log('Stopping driver'); + logger.info('Stopping driver', NS); if (this.ezsp) { return this.ezsp.close(emitClose); @@ -170,7 +162,7 @@ export class Driver extends EventEmitter { try { await this.ezsp.connect(this.serialOpt); } catch (error) { - debug.error(`EZSP could not connect: ${error.cause ?? error}`); + logger.error(`EZSP could not connect: ${error.cause ?? error}`, NS); throw error; } @@ -186,7 +178,7 @@ export class Driver extends EventEmitter { await this.ezsp.setValue(EzspValueId.VALUE_CCA_THRESHOLD, 0); await this.ezsp.setSourceRouting(); //const count = await ezsp.getConfigurationValue(EzspConfigId.CONFIG_APS_UNICAST_MESSAGE_COUNT); - //debug.log("APS_UNICAST_MESSAGE_COUNT is set to %s", count); + //logger.info("APS_UNICAST_MESSAGE_COUNT is set to %s", count, NS); await this.addEndpoint({ inputClusters: [0x0000, 0x0003, 0x0006, 0x000A, 0x0019, 0x001A, 0x0300], outputClusters: [0x0000, 0x0003, 0x0004, 0x0005, 0x0006, 0x0008, 0x0020, @@ -212,7 +204,7 @@ export class Driver extends EventEmitter { [special, verInfo] = uint8_t.deserialize(uint8_t, verInfo); /* eslint-enable prefer-const */ const vers = `${major}.${minor}.${patch}.${special} build ${build}`; - debug.log(`EmberZNet version: ${vers}`); + logger.info(`EmberZNet version: ${vers}`, NS); this.version = { product: this.ezsp.ezspV, majorrel: `${major}`, @@ -227,49 +219,54 @@ export class Driver extends EventEmitter { const res = await this.ezsp.execCommand('networkState'); - debug.log(`Network state ${res.status}`); + logger.info(`Network state ${res.status}`, NS); if (res.status == EmberNetworkStatus.JOINED_NETWORK) { - debug.log(`Leaving current network and forming new network`); + logger.info(`Leaving current network and forming new network`, NS); const st = await this.ezsp.leaveNetwork(); - console.assert(st == EmberStatus.NETWORK_DOWN, `leaveNetwork returned unexpected status: ${st}`); + if (st != EmberStatus.NETWORK_DOWN) { + logger.error(`leaveNetwork returned unexpected status: ${st}`, NS); + } } if (restore) { // restore - debug.log("Restore network from backup"); + logger.info("Restore network from backup", NS); await this.formNetwork(true); result = 'restored'; } else { // reset - debug.log("Form network"); + logger.info("Form network", NS); await this.formNetwork(false); result = 'reset'; } } const state = (await this.ezsp.execCommand('networkState')).status; - debug.log(`Network state ${state}`); + logger.info(`Network state ${state}`, NS); const netParams = await this.ezsp.execCommand('getNetworkParameters'); - console.assert(netParams.status == EmberStatus.SUCCESS, - `Command (getNetworkParameters) returned unexpected state: ${netParams.status}`); + + if (netParams.status != EmberStatus.SUCCESS) { + logger.error(`Command (getNetworkParameters) returned unexpected state: ${netParams.status}`, NS); + } + this.networkParams = netParams.parameters; - debug.log("Node type: %s, Network parameters: %s", netParams.nodeType, this.networkParams); + logger.info(`Node type: ${netParams.nodeType}, Network parameters: ${this.networkParams}`, NS); const nwk = (await this.ezsp.execCommand('getNodeId')).nodeId; const ieee = (await this.ezsp.execCommand('getEui64')).eui64; this.ieee = new EmberEUI64(ieee); - debug.log('Network ready'); + logger.info('Network ready', NS); this.ezsp.on('frame', this.handleFrame.bind(this)); this.handleNodeJoined(nwk, this.ieee); - debug.log(`EZSP nwk=${nwk}, IEEE=0x${this.ieee}`); + logger.info(`EZSP nwk=${nwk}, IEEE=0x${this.ieee}`, NS); const linkResult = await this.getKey(EmberKeyType.TRUST_CENTER_LINK_KEY); - debug.log(`TRUST_CENTER_LINK_KEY: ${JSON.stringify(linkResult)}`); + logger.info(`TRUST_CENTER_LINK_KEY: ${JSON.stringify(linkResult)}`, NS); const netResult = await this.getKey(EmberKeyType.CURRENT_NETWORK_KEY); - debug.log(`CURRENT_NETWORK_KEY: ${JSON.stringify(netResult)}`); + logger.info(`CURRENT_NETWORK_KEY: ${JSON.stringify(netResult)}`, NS); await Wait(1000); await this.ezsp.execCommand('setManufacturerCode', {code: DEFAULT_MFG_ID}); @@ -287,7 +284,7 @@ export class Driver extends EventEmitter { valid = valid && (await this.ezsp.networkInit()); const netParams = await this.ezsp.execCommand('getNetworkParameters'); const networkParams = netParams.parameters; - debug.log("Current Node type: %s, Network parameters: %s", netParams.nodeType, networkParams); + logger.info(`Current Node type: ${netParams.nodeType}, Network parameters: ${networkParams}`, NS); valid = valid && (netParams.status == EmberStatus.SUCCESS); valid = valid && (netParams.nodeType == EmberNodeType.COORDINATOR); valid = valid && (options.panID == networkParams.panId); @@ -404,7 +401,7 @@ export class Driver extends EventEmitter { } case (frameName === 'macFilterMatchMessageHandler'): { const [rawFrame, data] = EmberIeeeRawFrame.deserialize(EmberIeeeRawFrame, frame.message); - debug.log(`macFilterMatchMessageHandler frame message: ${rawFrame}`); + logger.info(`macFilterMatchMessageHandler frame message: ${rawFrame}`, NS); this.emit('incomingMessage', { messageType: null, apsFrame: rawFrame, @@ -419,7 +416,7 @@ export class Driver extends EventEmitter { break; } case (frameName === 'stackStatusHandler'): { - debug.log(`stackStatusHandler: ${EmberStatus.valueToName(EmberStatus, frame.status)}`); + logger.info(`stackStatusHandler: ${EmberStatus.valueToName(EmberStatus, frame.status)}`, NS); break; } // case (frameName === 'childJoinHandler'): { @@ -444,15 +441,16 @@ export class Driver extends EventEmitter { // <=== Application frame 155 (zigbeeKeyEstablishmentHandler) received: 2ebd08feff9ffd9006 +2ms // <=== Application frame 155 (zigbeeKeyEstablishmentHandler) parsed: 144,253,159,255,254,8,189,46,6 +2ms // Unhandled frame zigbeeKeyEstablishmentHandler - debug.log(`Unhandled frame ${frameName}`); + logger.info(`Unhandled frame ${frameName}`, NS); } } private handleRouteRecord(nwk: number, ieee: EmberEUI64 | number[], lqi: number, rssi: number, relays: number): void { // todo - debug.log( - `handleRouteRecord: nwk=${nwk}, ieee=${ieee.toString()}, lqi=${lqi}, rssi=${rssi}, relays=${relays}` + logger.info( + `handleRouteRecord: nwk=${nwk}, ieee=${ieee.toString()}, lqi=${lqi}, rssi=${rssi}, relays=${relays}`, + NS, ); this.setNode(nwk, ieee); @@ -464,7 +462,7 @@ export class Driver extends EventEmitter { private handleRouteError(status: EmberStatus, nwk: number): void { // todo - debug.log(`handleRouteError: nwk=${nwk}, status=${status}`); + logger.info(`handleRouteError: nwk=${nwk}, status=${status}`, NS); //this.waitress.reject({address: nwk, payload: null, frame: null}, 'Route error'); // const ieee = await this.networkIdToEUI64(nwk); // this.eui64ToRelays.set(ieee.toString(), null); @@ -481,7 +479,7 @@ export class Driver extends EventEmitter { // "target":50564 // } // https://docs.silabs.com/d/zigbee-stack-api/7.4.0/message#ember-incoming-network-status-handler - debug.log(`handleNetworkStatus: nwk=${nwk}, errorCode=${errorCode}`); + logger.info(`handleNetworkStatus: nwk=${nwk}, errorCode=${errorCode}`, NS); } private handleNodeLeft(nwk: number, ieee: EmberEUI64 | number[]): void { @@ -508,7 +506,7 @@ export class Driver extends EventEmitter { for(const rec of IEEE_PREFIX_MFG_ID) { if ((Buffer.from((ieee as EmberEUI64).value)).indexOf(Buffer.from(rec.prefix)) == 0) { // set ManufacturerCode - debug.log(`handleNodeJoined: change ManufacturerCode for ieee ${ieee} to ${rec.mfgId}`); + logger.info(`handleNodeJoined: change ManufacturerCode for ieee ${ieee} to ${rec.mfgId}`, NS); // eslint-disable-next-line @typescript-eslint/no-floating-promises this.resetMfgId(rec.mfgId); break; @@ -574,7 +572,7 @@ export class Driver extends EventEmitter { if ([EmberStatus.MAX_MESSAGE_LIMIT_REACHED, EmberStatus.NO_BUFFERS, EmberStatus.NETWORK_BUSY] .includes(sendResult.status)) { // need to repeat after pause - debug.log(`Request send status ${sendResult.status}. Attempt to repeat the request`); + logger.info(`Request send status ${sendResult.status}. Attempt to repeat the request`, NS); await Wait(delay); } else { @@ -582,7 +580,7 @@ export class Driver extends EventEmitter { break; } } catch (e) { - debug.error(`Request error ${e}: ${e.stack}`); + logger.error(`Request error ${e}: ${e.stack}`, NS); break; } } @@ -608,7 +606,7 @@ export class Driver extends EventEmitter { await this.ezsp.execCommand('sendRawMessage', {message: msgData}); return true; } catch (e) { - debug.error(`Request error ${e}: ${e.stack}`); + logger.error(`Request error ${e}: ${e.stack}`, NS); return false; } } @@ -620,7 +618,7 @@ export class Driver extends EventEmitter { await this.ezsp.execCommand('sendRawMessage', {message: msgData}); return true; } catch (e) { - debug.error(`Request error ${e}: ${e.stack}`); + logger.error(`Request error ${e}: ${e.stack}`, NS); return false; } } @@ -676,7 +674,7 @@ export class Driver extends EventEmitter { const requestName = EmberZDOCmd.valueName(EmberZDOCmd, requestCmd); const responseName = EmberZDOCmd.valueName(EmberZDOCmd, responseCmd); - debug.log(`ZDO ${requestName} params: ${JSON.stringify(params)}`); + logger.info(`ZDO ${requestName} params: ${JSON.stringify(params)}`, NS); const frame = this.makeApsFrame(requestCmd as number, false); const payload = this.makeZDOframe(requestCmd as number, {transId: frame.sequence, ...params}); @@ -691,16 +689,16 @@ export class Driver extends EventEmitter { const response = await waiter.start().promise; - debug.log(`${responseName} frame: ${JSON.stringify(response.payload)}`); + logger.info(`${responseName} frame: ${JSON.stringify(response.payload)}`, NS); const result = new EZSPZDOResponseFrameData(responseCmd as number, response.payload); - debug.log(`${responseName} parsed: ${JSON.stringify(result)}`); + logger.info(`${responseName} parsed: ${JSON.stringify(result)}`, NS); return result; } catch (e) { this.waitress.remove(waiter.ID); - debug.error(`zdoRequest error: ${e} ${e.stack}`); + logger.error(`zdoRequest error: ${e} ${e.stack}`, NS); throw e; } @@ -770,7 +768,7 @@ export class Driver extends EventEmitter { inputClusterList: inputClusters, outputClusterList: outputClusters, }); - debug.log(`Ezsp adding endpoint: ${JSON.stringify(res)}`); + logger.info(`Ezsp adding endpoint: ${JSON.stringify(res)}`, NS); } public waitFor(address: number, clusterId: number, sequence: number, timeout = 10000) @@ -898,9 +896,11 @@ export class Driver extends EventEmitter { smc.flags = 0; smc.psaKeyAlgPermission = 0; const keyInfo = await this.ezsp.execCommand('exportKey', {context: smc}); - console.assert(keyInfo.status === SLStatus.SL_STATUS_OK, - `exportKey(${EmberKeyType.valueToName(EmberKeyType, keyType)}) ` - + `returned unexpected SL status: ${keyInfo.status}`); + + if (keyInfo.status !== SLStatus.SL_STATUS_OK) { + logger.error(`exportKey(${EmberKeyType.valueToName(EmberKeyType, keyType)}) ` + + `returned unexpected SL status: ${keyInfo.status}`, NS); + } return keyInfo; } } @@ -910,10 +910,9 @@ export class Driver extends EventEmitter { throw new Error(`getNetKeyInfo(): Invalid call on EZSP < 13.`); } else { const keyInfo = await this.ezsp.execCommand('getNetworkKeyInfo'); - console.assert( - keyInfo.status === SLStatus.SL_STATUS_OK, - `getNetworkKeyInfo() returned unexpected SL status: ${keyInfo.status}` - ); + if (keyInfo.status !== SLStatus.SL_STATUS_OK) { + logger.error(`getNetworkKeyInfo() returned unexpected SL status: ${keyInfo.status}`, NS); + } return keyInfo; } @@ -928,8 +927,8 @@ export class Driver extends EventEmitter { //valid = valid && (await this.ezsp.networkInit()); const netParams = await this.ezsp.execCommand('getNetworkParameters'); const networkParams = netParams.parameters; - debug.log("Current Node type: %s, Network parameters: %s", netParams.nodeType, networkParams); - debug.log("Backuped network parameters: %s", backup.networkOptions); + logger.info(`Current Node type: ${netParams.nodeType}, Network parameters: ${networkParams}`, NS); + logger.info(`Backuped network parameters: ${backup.networkOptions}`, NS); const networkKey = await this.getKey(EmberKeyType.CURRENT_NETWORK_KEY); let netKey: Buffer = null; if (this.ezsp.ezspV < 13) { @@ -944,19 +943,19 @@ export class Driver extends EventEmitter { valid = valid && (Buffer.from(networkParams.extendedPanId).equals(backup.networkOptions.extendedPanId)); valid = valid && (Buffer.from(netKey).equals(backup.networkOptions.networkKey)); if (valid) { - this.logger.error(`Configuration is not consistent with adapter backup!`); - this.logger.error(`- PAN ID: configured=${options.panID}, adapter=${networkParams.panId}, backup=${backup.networkOptions.panId}`); - this.logger.error(`- Extended PAN ID: configured=${Buffer.from(options.extendedPanID).toString("hex")}, `+ + logger.error(`Configuration is not consistent with adapter backup!`, NS); + logger.error(`- PAN ID: configured=${options.panID}, adapter=${networkParams.panId}, backup=${backup.networkOptions.panId}`, NS); + logger.error(`- Extended PAN ID: configured=${Buffer.from(options.extendedPanID).toString("hex")}, `+ `adapter=${Buffer.from(networkParams.extendedPanId).toString("hex")}, `+ - `backup=${Buffer.from(networkParams.extendedPanId).toString("hex")}`); - this.logger.error(`- Channel: configured=${options.channelList}, adapter=${networkParams.radioChannel}, `+ - `backup=${backup.logicalChannel}`); - this.logger.error(`- Network key: configured=${Buffer.from(options.networkKey).toString("hex")}, `+ + `backup=${Buffer.from(networkParams.extendedPanId).toString("hex")}`, NS); + logger.error(`- Channel: configured=${options.channelList}, adapter=${networkParams.radioChannel}, `+ + `backup=${backup.logicalChannel}`, NS); + logger.error(`- Network key: configured=${Buffer.from(options.networkKey).toString("hex")}, `+ `adapter=${Buffer.from(netKey).toString("hex")}, `+ - `backup=${backup.networkOptions.networkKey.toString("hex")}`); - this.logger.error(`Please update configuration to prevent further issues.`); - this.logger.error(`If you wish to re-commission your network, please remove coordinator backup.`); - this.logger.error(`Re-commissioning your network will require re-pairing of all devices!`); + `backup=${backup.networkOptions.networkKey.toString("hex")}`, NS); + logger.error(`Please update configuration to prevent further issues.`, NS); + logger.error(`If you wish to re-commission your network, please remove coordinator backup.`, NS); + logger.error(`Re-commissioning your network will require re-pairing of all devices!`, NS); throw new Error("startup failed - configuration-adapter mismatch - see logs above for more information"); } valid = true; diff --git a/src/adapter/ezsp/driver/ezsp.ts b/src/adapter/ezsp/driver/ezsp.ts index 32b68da86c..7998f49023 100644 --- a/src/adapter/ezsp/driver/ezsp.ts +++ b/src/adapter/ezsp/driver/ezsp.ts @@ -25,14 +25,11 @@ import { import {EventEmitter} from 'events'; import {EmberApsFrame, EmberNetworkParameters} from './types/struct'; import {Queue, Waitress, Wait} from '../../../utils'; -import Debug from "debug"; import {SerialPortOptions} from '../../tstype'; +import {logger} from '../../../utils/logger'; -const debug = { - error: Debug('zigbee-herdsman:adapter:ezsp:erro'), - log: Debug('zigbee-herdsman:adapter:ezsp:ezsp'), -}; +const NS = 'zh:ezsp:ezsp'; const MAX_SERIAL_CONNECT_ATTEMPTS = 4; @@ -156,7 +153,7 @@ export class EZSPFrameData { try { frm = new EZSPFrameData(frameName, isRequest, params); } catch (error) { - debug.error(`Frame ${frameName} parsing error: ${error.stack}`); + logger.error(`Frame ${frameName} parsing error: ${error.stack}`, NS); return true; } return false; @@ -356,11 +353,11 @@ export class Ezsp extends EventEmitter { await this.serialDriver.connect(options); break; } catch (error) { - debug.error(`Connection attempt ${i} error: ${error.stack}`); + logger.error(`Connection attempt ${i} error: ${error.stack}`, NS); if (i < MAX_SERIAL_CONNECT_ATTEMPTS) { await Wait(SERIAL_CONNECT_NEW_ATTEMPT_MIN_DELAY * i); - debug.log(`Next attempt ${i+1}`); + logger.info(`Next attempt ${i+1}`, NS); } lastError = error; @@ -390,20 +387,20 @@ export class Ezsp extends EventEmitter { } private onSerialReset(): void { - debug.log('onSerialReset()'); + logger.info('onSerialReset()', NS); this.inResetingProcess = true; this.emit('reset'); } private onSerialClose(): void { - debug.log('onSerialClose()'); + logger.info('onSerialClose()', NS); if (!this.inResetingProcess) { this.emit('close'); } } public async close(emitClose: boolean): Promise { - debug.log('Closing Ezsp'); + logger.info('Closing Ezsp', NS); clearTimeout(this.watchdogTimer); this.queue.clear(); @@ -419,7 +416,7 @@ export class Ezsp extends EventEmitter { * @param data */ private onFrameReceived(data: Buffer): void { - debug.log(`<== Frame: ${data.toString('hex')}`); + logger.info(`<== Frame: ${data.toString('hex')}`, NS); let frameId: number; const sequence = data[0]; @@ -442,11 +439,11 @@ export class Ezsp extends EventEmitter { const frm = EZSPFrameData.createFrame(this.ezspV, frameId, false, data); if (!frm) { - debug.error(`Unparsed frame 0x${frameId.toString(16)}. Skipped`); + logger.error(`Unparsed frame 0x${frameId.toString(16)}. Skipped`, NS); return; } - debug.log(`<== 0x${frameId.toString(16)}: ${JSON.stringify(frm)}`); + logger.info(`<== 0x${frameId.toString(16)}: ${JSON.stringify(frm)}`, NS); const handled = this.waitress.resolve({ frameId, @@ -469,7 +466,7 @@ export class Ezsp extends EventEmitter { const result = await this.execCommand("version", {desiredProtocolVersion: version}); if ((result.protocolVersion !== version)) { - debug.log("Switching to eszp version %d", result.protocolVersion); + logger.info(`Switching to eszp version ${result.protocolVersion}`, NS); await this.execCommand("version", {desiredProtocolVersion: result.protocolVersion}); } @@ -481,11 +478,11 @@ export class Ezsp extends EventEmitter { const waiter = this.waitFor("stackStatusHandler", null); const result = await this.execCommand("networkInit"); - debug.log('network init result: ', JSON.stringify(result)); + logger.info(`Network init result: ${JSON.stringify(result)}`, NS); if ((result.status !== EmberStatus.SUCCESS)) { this.waitress.remove(waiter.ID); - debug.log("Failure to init network"); + logger.info("Failure to init network", NS); return false; } @@ -498,19 +495,20 @@ export class Ezsp extends EventEmitter { const waiter = this.waitFor("stackStatusHandler", null); const result = await this.execCommand("leaveNetwork"); - debug.log('network init result', JSON.stringify(result)); + logger.info(`Network init result: ${JSON.stringify(result)}`, NS); if ((result.status !== EmberStatus.SUCCESS)) { this.waitress.remove(waiter.ID); - debug.log("Failure to leave network"); + logger.info("Failure to leave network", NS); throw new Error(("Failure to leave network: " + JSON.stringify(result))); } const response = await waiter.start().promise; if ((response.payload.status !== EmberStatus.NETWORK_DOWN)) { - debug.log("Wrong network status: " + JSON.stringify(response.payload)); - throw new Error(("Wrong network status: " + JSON.stringify(response.payload))); + const msg = `Wrong network status: ${JSON.stringify(response.payload)}`; + logger.info(msg, NS); + throw new Error(msg); } return response.payload.status; @@ -518,19 +516,25 @@ export class Ezsp extends EventEmitter { async setConfigurationValue(configId: number, value: number): Promise { const configName = EzspConfigId.valueToName(EzspConfigId, configId); - debug.log(`Set ${configName} = ${value}`); + logger.info(`Set ${configName} = ${value}`, NS); const ret = await this.execCommand('setConfigurationValue', {configId: configId, value: value}); - console.assert(ret.status === EmberStatus.SUCCESS, - `Command (setConfigurationValue(${configName}, ${value})) returned unexpected state: ${JSON.stringify(ret)}`); + + if (ret.status !== EmberStatus.SUCCESS) { + logger.error(`Command (setConfigurationValue(${configName}, ${value})) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + } async getConfigurationValue(configId: number): Promise { const configName = EzspConfigId.valueToName(EzspConfigId, configId); - debug.log(`Get ${configName}`); + logger.info(`Get ${configName}`, NS); const ret = await this.execCommand('getConfigurationValue', {configId: configId}); - console.assert(ret.status === EmberStatus.SUCCESS, - `Command (getConfigurationValue(${configName})) returned unexpected state: ${JSON.stringify(ret)}`); - debug.log(`Got ${configName} = ${ret.value}`); + + if (ret.status !== EmberStatus.SUCCESS) { + logger.error(`Command (getConfigurationValue(${configName})) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + + logger.info(`Got ${configName} = ${ret.value}`, NS); return ret.value; } @@ -541,51 +545,69 @@ export class Ezsp extends EventEmitter { async setMulticastTableEntry(index: number, entry: t.EmberMulticastTableEntry): Promise { const ret = await this.execCommand('setMulticastTableEntry', {index: index, value: entry}); - console.assert(ret.status === EmberStatus.SUCCESS, - `Command (setMulticastTableEntry) returned unexpected state: ${JSON.stringify(ret)}`); + + if (ret.status !== EmberStatus.SUCCESS) { + logger.error(`Command (setMulticastTableEntry) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + return ret.status; } async setInitialSecurityState(entry: t.EmberInitialSecurityState): Promise{ const ret = await this.execCommand('setInitialSecurityState', {state: entry}); - console.assert(ret.success === EmberStatus.SUCCESS, - `Command (setInitialSecurityState) returned unexpected state: ${JSON.stringify(ret)}`); + + if (ret.success !== EmberStatus.SUCCESS) { + logger.error(`Command (setInitialSecurityState) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + return ret.success; } async getCurrentSecurityState(): Promise { const ret = await this.execCommand('getCurrentSecurityState'); - console.assert(ret.status === EmberStatus.SUCCESS, - `Command (getCurrentSecurityState) returned unexpected state: ${JSON.stringify(ret)}`); + + if (ret.status !== EmberStatus.SUCCESS) { + logger.error(`Command (getCurrentSecurityState) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + return ret; } async setValue(valueId: t.EzspValueId, value: number): Promise { const valueName = t.EzspValueId.valueToName(t.EzspValueId, valueId); - debug.log(`Set ${valueName} = ${value}`); + logger.info(`Set ${valueName} = ${value}`, NS); const ret = await this.execCommand('setValue', {valueId, value}); - console.assert(ret.status === EmberStatus.SUCCESS, - `Command (setValue(${valueName}, ${value})) returned unexpected state: ${JSON.stringify(ret)}`); + + if (ret.status !== EmberStatus.SUCCESS) { + logger.error(`Command (setValue(${valueName}, ${value})) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + return ret; } async getValue(valueId: t.EzspValueId): Promise { const valueName = t.EzspValueId.valueToName(t.EzspValueId, valueId); - debug.log(`Get ${valueName}`); + logger.info(`Get ${valueName}`, NS); const ret = await this.execCommand('getValue', {valueId}); - console.assert(ret.status === EmberStatus.SUCCESS, - `Command (getValue(${valueName})) returned unexpected state: ${JSON.stringify(ret)}`); - debug.log(`Got ${valueName} = ${ret.value}`); + + if (ret.status !== EmberStatus.SUCCESS) { + logger.error(`Command (getValue(${valueName})) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + + logger.info(`Got ${valueName} = ${ret.value}`, NS); return ret.value; } async setPolicy(policyId: EzspPolicyId, value: number): Promise { const policyName = EzspPolicyId.valueToName(EzspPolicyId, policyId); - debug.log(`Set ${policyName} = ${value}`); + logger.info(`Set ${policyName} = ${value}`, NS); const ret = await this.execCommand('setPolicy', {policyId: policyId, decisionId: value}); - console.assert(ret.status === EmberStatus.SUCCESS, - `Command (setPolicy(${policyName}, ${value})) returned unexpected state: ${JSON.stringify(ret)}`); + + if (ret.status !== EmberStatus.SUCCESS) { + logger.error(`Command (setPolicy(${policyName}, ${value})) returned unexpected state: ${JSON.stringify(ret)}`, NS); + } + return ret; } @@ -596,7 +618,7 @@ export class Ezsp extends EventEmitter { try { await this.setConfigurationValue(confName, value); } catch (error) { - debug.error(`setConfigurationValue(${confName}, ${value}) error: ${error} ${error.stack}`); + logger.error(`setConfigurationValue(${confName}, ${value}) error: ${error} ${error.stack}`, NS); } } } @@ -609,7 +631,7 @@ export class Ezsp extends EventEmitter { try { await this.setPolicy(policy, value); } catch (error) { - debug.error(`setPolicy(${policy}, ${value}) error: ${error} ${error.stack}`); + logger.error(`setPolicy(${policy}, ${value}) error: ${error} ${error.stack}`, NS); } } } @@ -622,7 +644,7 @@ export class Ezsp extends EventEmitter { private makeFrame(name: string, params: ParamsDesc, seq: number): Buffer { const frmData = new EZSPFrameData(name, true, params); - debug.log(`==> ${JSON.stringify(frmData)}`); + logger.info(`==> ${JSON.stringify(frmData)}`, NS); const frame = [(seq & 255)]; @@ -642,7 +664,7 @@ export class Ezsp extends EventEmitter { } public async execCommand(name: string, params: ParamsDesc = null): Promise { - debug.log(`==> ${name}: ${JSON.stringify(params)}`); + logger.info(`==> ${name}: ${JSON.stringify(params)}`, NS); if (!this.serialDriver.isInitialized()) { throw new Error('Connection not initialized'); @@ -673,7 +695,7 @@ export class Ezsp extends EventEmitter { if ((v.status !== EmberStatus.SUCCESS)) { this.waitress.remove(waiter.ID); - debug.error("Failure forming network: " + JSON.stringify(v)); + logger.error("Failure forming network: " + JSON.stringify(v), NS); throw new Error(("Failure forming network: " + JSON.stringify(v))); } @@ -681,7 +703,7 @@ export class Ezsp extends EventEmitter { const response = await waiter.start().promise; if ((response.payload.status !== EmberStatus.NETWORK_UP)) { - debug.error("Wrong network status: " + JSON.stringify(response.payload)); + logger.error("Wrong network status: " + JSON.stringify(response.payload), NS); throw new Error(("Wrong network status: " + JSON.stringify(response.payload))); } @@ -721,10 +743,10 @@ export class Ezsp extends EventEmitter { maxHops: 0, }); - debug.log("Set concentrator type: %s", JSON.stringify(res)); + logger.info(`Set concentrator type: ${JSON.stringify(res)}`, NS); if (res.status != EmberStatus.SUCCESS) { - debug.log("Couldn't set concentrator type %s: %s", true, JSON.stringify(res)); + logger.info(`Couldn't set concentrator ${JSON.stringify(res)}`, NS); } if (this.ezspV >= 8) { @@ -762,17 +784,17 @@ export class Ezsp extends EventEmitter { } private async watchdogHandler(): Promise { - debug.log(`Time to watchdog ... ${this.failures}`); + logger.info(`Time to watchdog ... ${this.failures}`, NS); if (this.inResetingProcess) { - debug.log('The reset process is in progress...'); + logger.info('The reset process is in progress...', NS); return; } try { await this.execCommand('nop'); } catch (error) { - debug.error(`Watchdog heartbeat timeout ${error.stack}`); + logger.error(`Watchdog heartbeat timeout ${error.stack}`, NS); if (!this.inResetingProcess) { this.failures += 1; diff --git a/src/adapter/ezsp/driver/multicast.ts b/src/adapter/ezsp/driver/multicast.ts index b1a29bad70..c73398c45a 100644 --- a/src/adapter/ezsp/driver/multicast.ts +++ b/src/adapter/ezsp/driver/multicast.ts @@ -1,13 +1,11 @@ /* istanbul ignore file */ +import {logger} from '../../../utils/logger'; import {Driver} from './driver'; import {EzspConfigId} from './types'; import {EmberStatus} from './types/named'; import {EmberMulticastTableEntry} from './types/struct'; -import Debug from "debug"; -const debug = { - log: Debug('zigbee-herdsman:adapter:ezsp:cast'), -}; +const NS = 'zh:ezsp:cast'; export class Multicast { @@ -30,7 +28,7 @@ export class Multicast { ); for (let i = 0; i < size; i++) { const entry = await this.driver.ezsp.getMulticastTableEntry(i); - debug.log("MulticastTableEntry[%s] = %s", i, entry); + logger.info(`MulticastTableEntry[${i}] = ${entry}`, NS); if (entry.endpoint !== 0) { this._multicast[entry.multicastId] = [entry, i]; } else { @@ -52,7 +50,7 @@ export class Multicast { public async subscribe(group_id: number, endpoint: number): Promise { if (this._multicast.hasOwnProperty(group_id)) { - debug.log("%s is already subscribed", group_id); + logger.info(`${group_id} is already subscribed`, NS); return EmberStatus.SUCCESS; } @@ -64,26 +62,16 @@ export class Multicast { entry.networkIndex = 0; const status = await this.driver.ezsp.setMulticastTableEntry(idx, entry); if (status !== EmberStatus.SUCCESS) { - debug.log( - "Set MulticastTableEntry #%s for %s multicast id: %s", - idx, - entry.multicastId, - status, - ); + logger.info(`Set MulticastTableEntry #${idx} for ${entry.multicastId} multicast id: ${status}`, NS); this._available.push(idx); return status; } this._multicast[entry.multicastId] = [entry, idx]; - debug.log( - "Set MulticastTableEntry #%s for %s multicast id: %s", - idx, - entry.multicastId, - status, - ); + logger.info(`Set MulticastTableEntry #${idx} for ${entry.multicastId} multicast id: ${status}`, NS); return status; } catch (e) { - debug.log("No more available slots MulticastId subscription"); + logger.info("No more available slots MulticastId subscription", NS); return EmberStatus.INDEX_OUT_OF_RANGE; } } diff --git a/src/adapter/ezsp/driver/parser.ts b/src/adapter/ezsp/driver/parser.ts index abfa71037d..0a2dc5a69f 100644 --- a/src/adapter/ezsp/driver/parser.ts +++ b/src/adapter/ezsp/driver/parser.ts @@ -1,10 +1,10 @@ /* istanbul ignore file */ import * as stream from 'stream'; import * as consts from './consts'; -import Debug from "debug"; import Frame from './frame'; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:adapter:ezsp:uart'); +const NS = 'zh:ezsp:uart'; export class Parser extends stream.Transform { private tail: Buffer[]; @@ -20,7 +20,7 @@ export class Parser extends stream.Transform { public _transform(chunk: Buffer, _: string, cb: () => void): void { if (this.flagXONXOFF && (chunk.indexOf(consts.XON) >= 0 || chunk.indexOf(consts.XOFF) >= 0)) { // XXX: should really throw, but just assert for now to flag potential problematic setups - console.assert(false, `Host driver did not remove XON/XOFF from input stream. Driver not setup for XON/XOFF?`); + logger.error(`Host driver did not remove XON/XOFF from input stream. Driver not setup for XON/XOFF?`, NS); } if (chunk.indexOf(consts.CANCEL) >= 0) { @@ -33,7 +33,7 @@ export class Parser extends stream.Transform { chunk = chunk.subarray(chunk.indexOf(consts.FLAG) + 1); } - debug(`<-- [${chunk.toString('hex')}]`); + logger.debug(`<-- [${chunk.toString('hex')}]`, NS); let delimiterPlace = chunk.indexOf(consts.FLAG); @@ -50,7 +50,7 @@ export class Parser extends stream.Transform { } } catch (error) { - debug(`<-- error ${error.stack}`); + logger.debug(`<-- error ${error.stack}`, NS); } chunk = chunk.subarray(delimiterPlace + 1); diff --git a/src/adapter/ezsp/driver/types/basic.ts b/src/adapter/ezsp/driver/types/basic.ts index d563c37bda..f3573fb9d2 100644 --- a/src/adapter/ezsp/driver/types/basic.ts +++ b/src/adapter/ezsp/driver/types/basic.ts @@ -108,7 +108,7 @@ export class LVBytes { export abstract class List { /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/ static serialize(cls: any, value: any[]): Buffer { - console.assert(((cls._length === null) || (cls.length === cls._length))); + // console.assert(((cls._length === null) || (cls.length === cls._length))); return Buffer.from(value.map(i => i.serialize(cls, i))); } diff --git a/src/adapter/ezsp/driver/types/named.ts b/src/adapter/ezsp/driver/types/named.ts index 780dac32cb..9842ad932e 100644 --- a/src/adapter/ezsp/driver/types/named.ts +++ b/src/adapter/ezsp/driver/types/named.ts @@ -3,7 +3,7 @@ import * as basic from './basic'; import {fixed_list} from './basic'; -console.assert(basic.uint8_t); +// console.assert(basic.uint8_t); export class NcpResetCode extends basic.uint8_t { //Reset and Error Codes for NCP @@ -68,7 +68,7 @@ export class EmberEUI64 extends fixed_list(8, basic.uint8_t) { if (value instanceof EmberEUI64) { value = (value as EmberEUI64).value as number[]; } - console.assert(cls._length === value.length); + // console.assert(cls._length === value.length); /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/ const val = Buffer.from(value).reverse().map(i => basic.uint8_t.serialize(basic.uint8_t, i)[0]); return Buffer.from(val); diff --git a/src/adapter/ezsp/driver/types/struct.ts b/src/adapter/ezsp/driver/types/struct.ts index b95e8433ea..cd610f2faa 100644 --- a/src/adapter/ezsp/driver/types/struct.ts +++ b/src/adapter/ezsp/driver/types/struct.ts @@ -9,7 +9,7 @@ export class EzspStruct { /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/ return Buffer.concat(cls._fields.map((field: any[]) => { const value = obj[field[0]]; - console.assert(field[1]); + // console.assert(field[1]); return field[1].serialize(field[1], value); })); } @@ -649,7 +649,7 @@ export class EmberMultiAddress extends EzspStruct { /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/ return Buffer.concat(fields.map((field: any[]) => { const value = obj[field[0]]; - console.assert(field[1]); + // console.assert(field[1]); return field[1].serialize(field[1], value); })); } diff --git a/src/adapter/ezsp/driver/uart.ts b/src/adapter/ezsp/driver/uart.ts index 9af5f06597..adf8791dc3 100644 --- a/src/adapter/ezsp/driver/uart.ts +++ b/src/adapter/ezsp/driver/uart.ts @@ -7,11 +7,11 @@ import {Queue, Waitress, Wait} from '../../../utils'; import {Writer} from './writer'; import {Parser} from './parser'; import {Frame as NpiFrame, FrameType} from './frame'; -import Debug from "debug"; import {SerialPortOptions} from '../../tstype'; import wait from '../../../utils/wait'; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:adapter:ezsp:uart'); +const NS = 'zh:ezsp:uart'; enum NcpResetCode { @@ -80,12 +80,12 @@ export class SerialDriver extends EventEmitter { // enable software flow control if RTS/CTS not enabled in config if (!options.rtscts) { - debug(`RTS/CTS config is off, enabling software flow control.`); + logger.debug(`RTS/CTS config is off, enabling software flow control.`, NS); options.xon = true; options.xoff = true; } - debug(`Opening SerialPort with ${JSON.stringify(options)}`); + logger.debug(`Opening SerialPort with ${JSON.stringify(options)}`, NS); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this.serialPort = new SerialPort(options); @@ -99,7 +99,7 @@ export class SerialDriver extends EventEmitter { try { await this.serialPort.asyncOpen(); - debug('Serialport opened'); + logger.debug('Serialport opened', NS); this.serialPort.once('close', this.onPortClose.bind(this)); this.serialPort.on('error', this.onPortError.bind(this)); @@ -121,7 +121,7 @@ export class SerialDriver extends EventEmitter { private async openSocketPort(path: string): Promise { const info = SocketPortUtils.parseTcpPath(path); - debug(`Opening TCP socket with ${info.host}:${info.port}`); + logger.debug(`Opening TCP socket with ${info.host}:${info.port}`, NS); this.socketPort = new net.Socket(); this.socketPort.setNoDelay(true); @@ -142,10 +142,10 @@ export class SerialDriver extends EventEmitter { }; this.socketPort.on('connect', () => { - debug('Socket connected'); + logger.debug('Socket connected', NS); }); this.socketPort.on('ready', async (): Promise => { - debug('Socket ready'); + logger.debug('Socket ready', NS); this.socketPort.removeListener('error', openError); this.socketPort.once('close', this.onPortClose.bind(this)); this.socketPort.on('error', this.onPortError.bind(this)); @@ -190,13 +190,13 @@ export class SerialDriver extends EventEmitter { break; default: this.rejectCondition = true; - debug(`UNKNOWN FRAME RECEIVED: ${frame}`); + logger.debug(`UNKNOWN FRAME RECEIVED: ${frame}`, NS); } } catch (error) { this.rejectCondition = true; - debug(error); - debug(`Error while parsing to NpiFrame '${error.stack}'`); + logger.debug(error, NS); + logger.debug(`Error while parsing to NpiFrame '${error.stack}'`, NS); } // We send NAK only if the rejectCondition was set in the current processing @@ -211,17 +211,17 @@ export class SerialDriver extends EventEmitter { const frmNum = (frame.control & 0x70) >> 4; const reTx = (frame.control & 0x08) >> 3; - debug(`<-- DATA (${frmNum},${frame.control & 0x07},${reTx}): ${frame}`); + logger.debug(`<-- DATA (${frmNum},${frame.control & 0x07},${reTx}): ${frame}`, NS); // Expected package {recvSeq}, but received {frmNum} // This happens when the chip sends us a reTx packet, but we are waiting for the next one if (this.recvSeq != frmNum) { if (reTx) { // if the reTx flag is set, then this is a packet replay - debug(`Unexpected DATA packet sequence ${frmNum} | ${this.recvSeq}: packet replay`); + logger.debug(`Unexpected DATA packet sequence ${frmNum} | ${this.recvSeq}: packet replay`, NS); } else { // otherwise, the sequence of packets is out of order - skip or send NAK is needed - debug(`Unexpected DATA packet sequence ${frmNum} | ${this.recvSeq}: reject condition`); + logger.debug(`Unexpected DATA packet sequence ${frmNum} | ${this.recvSeq}: reject condition`, NS); this.rejectCondition = true; return; } @@ -231,7 +231,7 @@ export class SerialDriver extends EventEmitter { this.recvSeq = (frmNum + 1) & 7; // next - debug(`--> ACK (${this.recvSeq})`); + logger.debug(`--> ACK (${this.recvSeq})`, NS); this.writer.sendACK(this.recvSeq); @@ -240,7 +240,7 @@ export class SerialDriver extends EventEmitter { if (reTx && !handled) { // if the package is resent and did not expect it, // then will skip it - already processed it earlier - debug(`Skipping the packet as repeated (${this.recvSeq})`); + logger.debug(`Skipping the packet as repeated (${this.recvSeq})`, NS); return; } @@ -255,7 +255,7 @@ export class SerialDriver extends EventEmitter { // next number after the last accepted frame this.ackSeq = frame.control & 0x07; - debug(`<-- ACK (${this.ackSeq}): ${frame}`); + logger.debug(`<-- ACK (${this.ackSeq}): ${frame}`, NS); const handled = this.waitress.resolve({sequence: this.ackSeq}); @@ -263,7 +263,7 @@ export class SerialDriver extends EventEmitter { // Packet confirmation received for {ackSeq}, but was expected {sendSeq} // This happens when the chip has not yet received of the packet {sendSeq} from us, // but has already sent us the next one. - debug(`Unexpected packet sequence ${this.ackSeq} | ${this.sendSeq}`); + logger.debug(`Unexpected packet sequence ${this.ackSeq} | ${this.sendSeq}`, NS); } return handled; @@ -273,20 +273,20 @@ export class SerialDriver extends EventEmitter { /* Handle negative acknowledgment frame */ const nakNum = frame.control & 0x07; - debug(`<-- NAK (${nakNum}): ${frame}`); + logger.debug(`<-- NAK (${nakNum}): ${frame}`, NS); const handled = this.waitress.reject({sequence: nakNum}, 'Recv NAK frame'); if (!handled) { // send NAK - debug(`NAK Unexpected packet sequence ${nakNum}`); + logger.debug(`NAK Unexpected packet sequence ${nakNum}`, NS); } else { - debug(`NAK Expected packet sequence ${nakNum}`); + logger.debug(`NAK Expected packet sequence ${nakNum}`, NS); } } private handleRST(frame: NpiFrame): void { - debug(`<-- RST: ${frame}`); + logger.debug(`<-- RST: ${frame}`, NS); } private handleRSTACK(frame: NpiFrame): void { @@ -294,7 +294,7 @@ export class SerialDriver extends EventEmitter { let code; this.rejectCondition = false; - debug(`<-- RSTACK ${frame}`); + logger.debug(`<-- RSTACK ${frame}`, NS); try { code = NcpResetCode[frame.buffer[2]]; @@ -302,7 +302,7 @@ export class SerialDriver extends EventEmitter { code = NcpResetCode.ERROR_UNKNOWN_EM3XX_ERROR; } - debug(`RSTACK Version: ${frame.buffer[1]} Reason: ${code.toString()} frame: ${frame}`); + logger.debug(`RSTACK Version: ${frame.buffer[1]} Reason: ${code.toString()} frame: ${frame}`, NS); if (NcpResetCode[code].toString() !== NcpResetCode.RESET_SOFTWARE.toString()) { return; @@ -312,18 +312,18 @@ export class SerialDriver extends EventEmitter { } private async handleError(frame: NpiFrame): Promise { - debug(`<-- Error ${frame}`); + logger.debug(`<-- Error ${frame}`, NS); try { // send reset await this.reset(); } catch (error) { - debug(`Failed to reset on Error Frame: ${error}`); + logger.debug(`Failed to reset on Error Frame: ${error}`, NS); } } async reset(): Promise { - debug('Uart reseting'); + logger.debug('Uart reseting', NS); this.parser.reset(); this.queue.clear(); this.sendSeq = 0; @@ -331,19 +331,19 @@ export class SerialDriver extends EventEmitter { return this.queue.execute(async (): Promise => { try { - debug(`--> Write reset`); + logger.debug(`--> Write reset`, NS); const waiter = this.waitFor(-1, 10000); this.rejectCondition = false; this.writer.sendReset(); - debug(`-?- waiting reset`); + logger.debug(`-?- waiting reset`, NS); await waiter.start().promise; - debug(`-+- waiting reset success`); + logger.debug(`-+- waiting reset success`, NS); await wait(2000); } catch (e) { - debug(`--> Error: ${e}`); + logger.debug(`--> Error: ${e}`, NS); this.emit('reset'); @@ -353,7 +353,7 @@ export class SerialDriver extends EventEmitter { } public async close(emitClose: boolean): Promise { - debug('Closing UART'); + logger.debug('Closing UART', NS); this.queue.clear(); if (this.initialized) { @@ -380,11 +380,11 @@ export class SerialDriver extends EventEmitter { } private onPortError(error: Error): void { - debug(`Port error: ${error}`); + logger.debug(`Port error: ${error}`, NS); } private onPortClose(err: boolean | Error): void { - debug(`Port closed. Error? ${err}`); + logger.debug(`Port closed. Error? ${err}`, NS); // on error: serialport passes an Error object (in case of disconnect) // net.Socket passes a boolean (in case of a transmission error) @@ -412,28 +412,28 @@ export class SerialDriver extends EventEmitter { try { const waiter = this.waitFor(nextSeq); - debug(`--> DATA (${seq},${ackSeq},0): ${data.toString('hex')}`); + logger.debug(`--> DATA (${seq},${ackSeq},0): ${data.toString('hex')}`, NS); this.writer.sendData(randData, seq, 0, ackSeq); - debug(`-?- waiting (${nextSeq})`); + logger.debug(`-?- waiting (${nextSeq})`, NS); await waiter.start().promise; - debug(`-+- waiting (${nextSeq}) success`); + logger.debug(`-+- waiting (${nextSeq}) success`, NS); } catch (e1) { - debug(`--> Error: ${e1}`); - debug(`-!- break waiting (${nextSeq})`); - debug(`Can't send DATA frame (${seq},${ackSeq},0): ${data.toString('hex')}`); + logger.debug(`--> Error: ${e1}`, NS); + logger.debug(`-!- break waiting (${nextSeq})`, NS); + logger.debug(`Can't send DATA frame (${seq},${ackSeq},0): ${data.toString('hex')}`, NS); try { await Wait(500); const waiter = this.waitFor(nextSeq); - debug(`->> DATA (${seq},${ackSeq},1): ${data.toString('hex')}`); + logger.debug(`->> DATA (${seq},${ackSeq},1): ${data.toString('hex')}`, NS); this.writer.sendData(randData, seq, 1, ackSeq); - debug(`-?- rewaiting (${nextSeq})`); + logger.debug(`-?- rewaiting (${nextSeq})`, NS); await waiter.start().promise; - debug(`-+- rewaiting (${nextSeq}) success`); + logger.debug(`-+- rewaiting (${nextSeq}) success`, NS); } catch (e2) { - debug(`--> Error: ${e2}`); - debug(`-!- break rewaiting (${nextSeq})`); - debug(`Can't resend DATA frame (${seq},${ackSeq},1): ${data.toString('hex')}`); + logger.debug(`--> Error: ${e2}`, NS); + logger.debug(`-!- break rewaiting (${nextSeq})`, NS); + logger.debug(`Can't resend DATA frame (${seq},${ackSeq},1): ${data.toString('hex')}`, NS); if (this.initialized) { this.emit('reset'); } diff --git a/src/adapter/ezsp/driver/writer.ts b/src/adapter/ezsp/driver/writer.ts index e657461f8f..51d9508925 100644 --- a/src/adapter/ezsp/driver/writer.ts +++ b/src/adapter/ezsp/driver/writer.ts @@ -2,13 +2,13 @@ import * as stream from 'stream'; import * as consts from './consts'; import {crc16ccitt} from './utils'; -import Debug from "debug"; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:adapter:ezsp:uart'); +const NS = 'zh:ezsp:uart'; export class Writer extends stream.Readable { public writeBuffer(buffer: Buffer): void { - debug(`--> [${buffer.toString('hex')}]`); + logger.debug(`--> [${buffer.toString('hex')}]`, NS); this.push(buffer); } diff --git a/src/adapter/z-stack/adapter/adapter-backup.ts b/src/adapter/z-stack/adapter/adapter-backup.ts index d77db2af86..47aec3cdcc 100644 --- a/src/adapter/z-stack/adapter/adapter-backup.ts +++ b/src/adapter/z-stack/adapter/adapter-backup.ts @@ -1,5 +1,4 @@ /* eslint-disable max-len */ -import Debug from "debug"; import {Znp} from "../znp"; import * as Models from "../../../models"; import * as Structs from "../structs"; @@ -11,6 +10,9 @@ import {NvItemsIds, NvSystemIds} from "../constants/common"; import {Subsystem} from "../unpi/constants"; import {ZnpVersion} from "./tstype"; import {AddressManagerUser, SecurityManagerAuthenticationOption} from "../structs"; +import {logger} from "../../../utils/logger"; + +const NS = 'zh:zstack:backup'; /** * Class providing ZNP adapter backup and restore procedures based mostly on NV memory manipulation. @@ -20,7 +22,6 @@ export class AdapterBackup { private znp: Znp; private nv: AdapterNvMemory; private defaultPath: string; - private debug = Debug("zigbee-herdsman:adapter:zStack:startup:backup"); public constructor(znp: Znp, nv: AdapterNvMemory, path: string) { this.znp = znp; @@ -59,7 +60,7 @@ export class AdapterBackup { * Creates a new backup from connected ZNP adapter and returns it in internal backup model format. */ public async createBackup(ieeeAddressesInDatabase: string[]): Promise { - this.debug("creating backup"); + logger.debug("creating backup", NS); const version: ZnpVersion = await this.getAdapterVersion(); /* get adapter ieee address */ @@ -68,14 +69,14 @@ export class AdapterBackup { throw new Error("Failed to read adapter IEEE address"); } const ieeeAddress = Buffer.from(ieeeAddressResponse.payload.extaddress.split("0x")[1], "hex"); - this.debug("fetched adapter ieee address"); + logger.debug("fetched adapter ieee address", NS); /* get adapter nib */ const nib = await this.nv.readItem(NvItemsIds.NIB, 0, Structs.nib); if (!nib) { throw new Error("Cannot backup - adapter not commissioned"); } - this.debug("fetched adapter nib"); + logger.debug("fetched adapter nib", NS); /* get adapter active key information */ let activeKeyInfo; @@ -90,23 +91,23 @@ export class AdapterBackup { if (!activeKeyInfo) { throw new Error("Cannot backup - missing active key info"); } - this.debug("fetched adapter active key information"); + logger.debug("fetched adapter active key information", NS); /* get adapter security data */ const preconfiguredKeyEnabled = await this.nv.readItem(NvItemsIds.PRECFGKEYS_ENABLE, 0); - this.debug("fetched adapter pre-configured key"); + logger.debug("fetched adapter pre-configured key", NS); const addressManagerTable = await this.getAddressManagerTable(version); - this.debug(`fetched adapter address manager table (capacity=${addressManagerTable?.capacity || 0}, used=${addressManagerTable?.usedCount || 0})`); + logger.debug(`fetched adapter address manager table (capacity=${addressManagerTable?.capacity || 0}, used=${addressManagerTable?.usedCount || 0})`, NS); const securityManagerTable = await this.getSecurityManagerTable(); - this.debug(`fetched adapter security manager table (capacity=${securityManagerTable?.usedCount || 0}, used=${securityManagerTable?.usedCount || 0})`); + logger.debug(`fetched adapter security manager table (capacity=${securityManagerTable?.usedCount || 0}, used=${securityManagerTable?.usedCount || 0})`, NS); const apsLinkKeyDataTable = await this.getApsLinkKeyDataTable(version); - this.debug(`fetched adapter aps link key data table (capacity=${apsLinkKeyDataTable?.usedCount || 0}, used=${apsLinkKeyDataTable?.usedCount || 0})`); + logger.debug(`fetched adapter aps link key data table (capacity=${apsLinkKeyDataTable?.usedCount || 0}, used=${apsLinkKeyDataTable?.usedCount || 0})`, NS); const tclkSeed = version === ZnpVersion.zStack12 ? null : await this.nv.readItem(NvItemsIds.TCLK_SEED, 0, Structs.nwkKey); - this.debug("fetched adapter tclk seed"); + logger.debug("fetched adapter tclk seed", NS); const tclkTable = await this.getTclkTable(version); - this.debug(`fetched adapter tclk table (capacity=${tclkTable?.usedCount || 0}, used=${tclkTable?.usedCount || 0})`); + logger.debug(`fetched adapter tclk table (capacity=${tclkTable?.usedCount || 0}, used=${tclkTable?.usedCount || 0})`, NS); const secMaterialTable = await this.getNetworkSecurityMaterialTable(version); - this.debug(`fetched adapter network security material table (capacity=${secMaterialTable?.usedCount || 0}, used=${secMaterialTable?.usedCount || 0})`); + logger.debug(`fetched adapter network security material table (capacity=${secMaterialTable?.usedCount || 0}, used=${secMaterialTable?.usedCount || 0})`, NS); /* examine network security material table */ const genericExtendedPanId = Buffer.alloc(8, 0xff); @@ -206,13 +207,14 @@ export class AdapterBackup { d.linkKey && ieeeAddressesInDatabase.includes(`0x${d.ieeeAddress.toString("hex")}`) && !backup.devices.find((dd) => d.ieeeAddress.equals(dd.ieeeAddress))); const missingStr = missing.map((d) => `0x${d.ieeeAddress.toString('hex')}`).join(', '); - this.debug( + logger.debug( `Following devices with link key are missing from new backup but present in old backup and database, ` + - `adding them back: ${missingStr}` + `adding them back: ${missingStr}`, + NS, ); backup.devices = [...backup.devices, ...missing]; } catch (error) { - this.debug(`Failed to read old backup, not checking for missing routers: ${error}`); + logger.debug(`Failed to read old backup, not checking for missing routers: ${error}`, NS); } return backup; @@ -224,7 +226,7 @@ export class AdapterBackup { * @param backup Backup to restore to connected adapter. */ public async restoreBackup(backup: Models.Backup): Promise { - this.debug("restoring backup"); + logger.debug("restoring backup", NS); const version: ZnpVersion = await this.getAdapterVersion(); /* istanbul ignore next */ if (version === ZnpVersion.zStack12) { @@ -253,12 +255,12 @@ export class AdapterBackup { const currentApsLinkKeyDataTable = await this.getApsLinkKeyDataTable(version); const currentTclkTable = await this.getTclkTable(version); const currentNwkSecMaterialTable = await this.getNetworkSecurityMaterialTable(version); - this.debug(`got target adapter table sizes:`); - this.debug(` - address manager table: ${currentAddressManagerTable.capacity}`); - this.debug(` - security manager table: ${currentSecurityManagerTable.capacity}`); - this.debug(` - aps link key data table: ${currentApsLinkKeyDataTable.capacity}`); - this.debug(` - tclk table: ${currentTclkTable.capacity}`); - this.debug(` - network security material table: ${currentNwkSecMaterialTable.capacity}`); + logger.debug(`got target adapter table sizes:`, NS); + logger.debug(` - address manager table: ${currentAddressManagerTable.capacity}`, NS); + logger.debug(` - security manager table: ${currentSecurityManagerTable.capacity}`, NS); + logger.debug(` - aps link key data table: ${currentApsLinkKeyDataTable.capacity}`, NS); + logger.debug(` - tclk table: ${currentTclkTable.capacity}`, NS); + logger.debug(` - network security material table: ${currentNwkSecMaterialTable.capacity}`, NS); /* prepare table structures */ const addressManagerTable = Structs.addressManagerTable(currentAddressManagerTable.capacity); @@ -315,7 +317,7 @@ export class AdapterBackup { tclkEntry.rxFrmCntr = device.linkKey.rxCounter; tclkEntry.txFrmCntr = device.linkKey.txCounter + 2500; linkKeyProcessed = true; - this.debug(`successfully recovered link key for ${device.ieeeAddress.toString("hex")} using tclk seed (shift=${recoveredSeedShift})`); + logger.debug(`successfully recovered link key for ${device.ieeeAddress.toString("hex")} using tclk seed (shift=${recoveredSeedShift})`, NS); } } @@ -340,7 +342,7 @@ export class AdapterBackup { sme.authenticationOption = SecurityManagerAuthenticationOption.AuthenticatedCBCK; linkKeyProcessed = true; - this.debug(`successfully recovered link key for ${device.ieeeAddress.toString("hex")} using aps key data table`); + logger.debug(`successfully recovered link key for ${device.ieeeAddress.toString("hex")} using aps key data table`, NS); } } } diff --git a/src/adapter/z-stack/adapter/manager.ts b/src/adapter/z-stack/adapter/manager.ts index 8911b9a6a3..db2c2f486c 100644 --- a/src/adapter/z-stack/adapter/manager.ts +++ b/src/adapter/z-stack/adapter/manager.ts @@ -1,6 +1,5 @@ /* eslint-disable max-len */ import {Znp} from "../znp"; -import Debug from "debug"; import {ZnpVersion} from "./tstype"; import {TsType} from "../../"; import {DevStates, NvItemsIds, ZnpCommandStatus} from "../constants/common"; @@ -16,7 +15,9 @@ import * as UnpiConstants from "../unpi/constants"; import * as crypto from "crypto"; import {Wait} from "../../../utils"; import {Endpoints} from "./endpoints"; -import {LoggerStub} from "../../../controller/logger-stub"; +import {logger} from "../../../utils/logger"; + +const NS = 'zh:adapter:zstack:manager'; /** * Startup strategy is internally used to determine required startup method. @@ -35,19 +36,12 @@ export class ZnpAdapterManager { private znp: Znp; private options: ZStackModels.StartupOptions; private nwkOptions: Models.NetworkOptions; - private logger: LoggerStub; - private debug = { - startup: Debug("zigbee-herdsman:adapter:zStack:startup"), - strategy: Debug("zigbee-herdsman:adapter:zStack:startup:strategy"), - commissioning: Debug("zigbee-herdsman:adapter:zStack:startup:commissioning") - }; - - public constructor(znp: Znp, options: ZStackModels.StartupOptions, logger: LoggerStub) { + + public constructor(znp: Znp, options: ZStackModels.StartupOptions) { this.znp = znp; this.options = options; this.nv = new AdapterNvMemory(this.znp); this.backup = new AdapterBackup(this.znp, this.nv, this.options.backupPath); - this.logger = logger; } /** @@ -55,13 +49,13 @@ export class ZnpAdapterManager { * and network is ready to process frames. */ public async start(): Promise { - this.debug.startup(`beginning znp startup`); + logger.debug(`beginning znp startup`, NS); this.nwkOptions = await this.parseConfigNetworkOptions(this.options.networkOptions); await this.nv.init(); /* determine startup strategy */ const strategy = await this.determineStrategy(); - this.debug.startup(`determined startup strategy: ${strategy}`); + logger.debug(`determined startup strategy: ${strategy}`, NS); /* perform coordinator startup based on determined strategy */ let result: TsType.StartResult; @@ -73,7 +67,7 @@ export class ZnpAdapterManager { } case "restoreBackup": { if (this.options.version === ZnpVersion.zStack12) { - this.debug.startup(`performing recommissioning instead of restore for z-stack 1.2`); + logger.debug(`performing recommissioning instead of restore for z-stack 1.2`, NS); await this.beginCommissioning(this.nwkOptions); await this.beginStartup(); } else { @@ -110,7 +104,7 @@ export class ZnpAdapterManager { * [this GitHub issue comment](https://github.com/Koenkk/zigbee-herdsman/issues/286#issuecomment-761029689). */ private async determineStrategy(): Promise { - this.debug.strategy("determining znp startup strategy"); + logger.debug("determining znp startup strategy", NS); /* acquire data from adapter */ const hasConfiguredNvId = this.options.version === ZnpVersion.zStack12 ? NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK1 : NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3; @@ -176,75 +170,75 @@ export class ZnpAdapterManager { /* Determine startup strategy */ if (!hasConfigured || !hasConfigured.isConfigured() || !nib) { /* Adapter is not configured or not commissioned */ - this.debug.strategy("(stage-1) adapter is not configured / not commissioned"); + logger.debug("(stage-1) adapter is not configured / not commissioned", NS); if (configMatchesBackup) { /* Adapter backup is available and matches configuration */ - this.debug.strategy("(stage-2) configuration matches backup"); + logger.debug("(stage-2) configuration matches backup", NS); checkRestoreVersionCompatibility(); return "restoreBackup"; } else { /* Adapter backup is either not available or does not match configuration */ if (!backup) { - this.debug.strategy("(stage-2) adapter backup does not exist"); + logger.debug("(stage-2) adapter backup does not exist", NS); } else { - this.debug.strategy("(stage-2) configuration does not match backup"); + logger.debug("(stage-2) configuration does not match backup", NS); } return "startCommissioning"; } } else { /* Adapter is configured and commissioned */ - this.debug.strategy("(stage-1) adapter is configured"); + logger.debug("(stage-1) adapter is configured", NS); if (configMatchesAdapter) { /* Warn if EPID is reversed (backward-compat) */ if (isExtendedPanIdReversed) { - this.debug.strategy("(stage-2) extended pan id is reversed"); - this.logger.warn(`Extended PAN ID is reversed (expected=${this.nwkOptions.extendedPanId.toString("hex")}, actual=${nib.extendedPANID.toString("hex")})`); + logger.debug("(stage-2) extended pan id is reversed", NS); + logger.warning(`Extended PAN ID is reversed (expected=${this.nwkOptions.extendedPanId.toString("hex")}, actual=${nib.extendedPANID.toString("hex")})`, NS); } /* Configuration matches adapter state - regular startup */ - this.debug.strategy("(stage-2) adapter state matches configuration"); + logger.debug("(stage-2) adapter state matches configuration", NS); return "startup"; } else { /* Configuration does not match adapter state */ - this.debug.strategy("(stage-2) adapter state does not match configuration"); + logger.debug("(stage-2) adapter state does not match configuration", NS); if (backup) { /* Backup is present */ - this.debug.strategy("(stage-3) got adapter backup"); + logger.debug("(stage-3) got adapter backup", NS); if (backupMatchesAdapter) { /* Backup matches adapter state */ - this.debug.strategy("(stage-4) adapter state matches backup"); - this.logger.error(`Configuration is not consistent with adapter state/backup!`); - this.logger.error(`- PAN ID: configured=${this.nwkOptions.panId}, adapter=${nib.nwkPanId}`); - this.logger.error(`- Extended PAN ID: configured=${this.nwkOptions.extendedPanId.toString("hex")}, adapter=${nib.extendedPANID.toString("hex")}`); - this.logger.error(`- Network Key: configured=${this.nwkOptions.networkKey.toString("hex")}, adapter=${activeKeyInfo.key.toString("hex")}`); - this.logger.error(`- Channel List: configured=${this.nwkOptions.channelList.toString()}, adapter=${Utils.unpackChannelList(nib.channelList).toString()}`); - this.logger.error(`Please update configuration to prevent further issues.`); - this.logger.error(`If you wish to re-commission your network, please remove coordinator backup at ${this.options.backupPath}.`); - this.logger.error(`Re-commissioning your network will require re-pairing of all devices!`); + logger.debug("(stage-4) adapter state matches backup", NS); + logger.error(`Configuration is not consistent with adapter state/backup!`, NS); + logger.error(`- PAN ID: configured=${this.nwkOptions.panId}, adapter=${nib.nwkPanId}`, NS); + logger.error(`- Extended PAN ID: configured=${this.nwkOptions.extendedPanId.toString("hex")}, adapter=${nib.extendedPANID.toString("hex")}`, NS); + logger.error(`- Network Key: configured=${this.nwkOptions.networkKey.toString("hex")}, adapter=${activeKeyInfo.key.toString("hex")}`, NS); + logger.error(`- Channel List: configured=${this.nwkOptions.channelList.toString()}, adapter=${Utils.unpackChannelList(nib.channelList).toString()}`, NS); + logger.error(`Please update configuration to prevent further issues.`, NS); + logger.error(`If you wish to re-commission your network, please remove coordinator backup at ${this.options.backupPath}.`, NS); + logger.error(`Re-commissioning your network will require re-pairing of all devices!`, NS); if (this.options.adapterOptions.forceStartWithInconsistentAdapterConfiguration) { - this.logger.error(`Running despite adapter configuration mismatch as configured. Please update the adapter to compatible firmware and recreate your network as soon as possible.`); + logger.error(`Running despite adapter configuration mismatch as configured. Please update the adapter to compatible firmware and recreate your network as soon as possible.`, NS); return "startup"; } else { throw new Error("startup failed - configuration-adapter mismatch - see logs above for more information"); } } else { /* Backup does not match adapter state */ - this.debug.strategy("(stage-4) adapter state does not match backup"); + logger.debug("(stage-4) adapter state does not match backup", NS); if (configMatchesBackup) { /* Adapter backup matches configuration */ - this.debug.strategy("(stage-5) adapter backup matches configuration"); + logger.debug("(stage-5) adapter backup matches configuration", NS); checkRestoreVersionCompatibility(); return "restoreBackup"; } else { /* Adapter backup does not match configuration */ - this.debug.strategy("(stage-5) adapter backup does not match configuration"); + logger.debug("(stage-5) adapter backup does not match configuration", NS); return "startCommissioning"; } } } else { /* Configuration mismatches adapter and no backup is available */ - this.debug.strategy("(stage-3) configuration-adapter mismatch (no backup)"); + logger.debug("(stage-3) configuration-adapter mismatch (no backup)", NS); return "startCommissioning"; } } @@ -257,13 +251,13 @@ export class ZnpAdapterManager { private async beginStartup(): Promise { const deviceInfo = await this.znp.request(Subsystem.UTIL, 'getDeviceInfo', {}); if (deviceInfo.payload.devicestate !== DevStates.ZB_COORD) { - this.debug.startup("starting adapter as coordinator"); + logger.debug("starting adapter as coordinator", NS); const started = this.znp.waitFor(UnpiConstants.Type.AREQ, Subsystem.ZDO, 'stateChangeInd', {state: 9}, 60000); await this.znp.request(Subsystem.ZDO, 'startupFromApp', {startdelay: 100}, null, null, [ZnpCommandStatus.SUCCESS, ZnpCommandStatus.FAILURE]); await started.start().promise; - this.debug.startup("adapter successfully started in coordinator mode"); + logger.debug("adapter successfully started in coordinator mode", NS); } else { - this.debug.startup("adapter is already running in coordinator mode"); + logger.debug("adapter is already running in coordinator mode", NS); } } @@ -287,12 +281,12 @@ export class ZnpAdapterManager { }; /* commission provisioning network */ - this.debug.commissioning("commissioning random provisioning network:"); - this.debug.commissioning(` - panId: ${provisioningNwkOptions.panId}`); - this.debug.commissioning(` - extendedPanId: ${provisioningNwkOptions.extendedPanId.toString("hex")}`); - this.debug.commissioning(` - channelList: ${provisioningNwkOptions.channelList.join(", ")}`); - this.debug.commissioning(` - networkKey: ${provisioningNwkOptions.networkKey.toString("hex")}`); - this.debug.commissioning(` - networkKeyDistribute: ${provisioningNwkOptions.networkKeyDistribute}`); + logger.debug("commissioning random provisioning network:", NS); + logger.debug(` - panId: ${provisioningNwkOptions.panId}`, NS); + logger.debug(` - extendedPanId: ${provisioningNwkOptions.extendedPanId.toString("hex")}`, NS); + logger.debug(` - channelList: ${provisioningNwkOptions.channelList.join(", ")}`, NS); + logger.debug(` - networkKey: ${provisioningNwkOptions.networkKey.toString("hex")}`, NS); + logger.debug(` - networkKeyDistribute: ${provisioningNwkOptions.networkKeyDistribute}`, NS); await this.beginCommissioning(provisioningNwkOptions, false, false); /* perform NV restore */ @@ -302,7 +296,7 @@ export class ZnpAdapterManager { await this.updateCommissioningNvItems(this.nwkOptions); /* settle & reset adapter */ - this.debug.commissioning("giving adapter some time to settle"); + logger.debug("giving adapter some time to settle", NS); await Wait(1000); await this.resetAdapter(); @@ -332,7 +326,7 @@ export class ZnpAdapterManager { /* commission the network as per parameters */ await this.updateCommissioningNvItems(nwkOptions); - this.debug.commissioning("beginning network commissioning"); + logger.debug("beginning network commissioning", NS); if ([ZnpVersion.zStack30x, ZnpVersion.zStack3x0].includes(this.options.version)) { /* configure channel */ await this.znp.request(Subsystem.APP_CNF, "bdbSetChannel", {isPrimary: 0x1, channel: Utils.packChannelList(nwkOptions.channelList)}); @@ -352,7 +346,7 @@ export class ZnpAdapterManager { } /* wait for NIB to settle (takes different amount of time of different platforms */ - this.debug.commissioning("waiting for NIB to settle"); + logger.debug("waiting for NIB to settle", NS); let reads = 0; let nib: ReturnType = null; do { @@ -370,7 +364,7 @@ export class ZnpAdapterManager { throw new Error(`network commissioning failed - panId collision detected (expected=${nwkOptions.panId}, actual=${extNwkInfo.payload.panid})`); } - this.debug.commissioning("network commissioned"); + logger.debug("network commissioned", NS); /* write configuration flag */ if (writeConfiguredFlag) { @@ -391,7 +385,7 @@ export class ZnpAdapterManager { channelList.channelList = Utils.packChannelList(options.channelList); const extendedPanIdReversed = Buffer.from(options.extendedPanId).reverse(); - this.debug.commissioning(`setting network commissioning parameters`); + logger.debug(`setting network commissioning parameters`, NS); await this.nv.updateItem(NvItemsIds.STARTUP_OPTION, Buffer.from([0x00])); await this.nv.updateItem(NvItemsIds.LOGICAL_TYPE, Buffer.from([ZnpConstants.ZDO.deviceLogicalType.COORDINATOR])); @@ -436,9 +430,9 @@ export class ZnpAdapterManager { for (const endpoint of Endpoints) { if (activeEp.payload.activeeplist.includes(endpoint.endpoint)) { - this.debug.startup(`endpoint '${endpoint.endpoint}' already registered`); + logger.debug(`endpoint '${endpoint.endpoint}' already registered`, NS); } else { - this.debug.startup(`registering endpoint '${endpoint.endpoint}'`); + logger.debug(`registering endpoint '${endpoint.endpoint}'`, NS); await this.znp.request(Subsystem.AF, 'register', endpoint); } } @@ -461,16 +455,16 @@ export class ZnpAdapterManager { * Internal method to reset the adapter. */ private async resetAdapter(): Promise { - this.debug.startup("adapter reset requested"); + logger.debug("adapter reset requested", NS); await this.znp.request(Subsystem.SYS, 'resetReq', {type: ZnpConstants.SYS.resetType.SOFT}); - this.debug.startup("adapter reset successful"); + logger.debug("adapter reset successful", NS); } /** * Internal method to reset adapter config and data. */ private async clearAdapter(): Promise { - this.debug.startup("clearing adapter using startup option 3"); + logger.debug("clearing adapter using startup option 3", NS); await this.nv.writeItem(NvItemsIds.STARTUP_OPTION, Buffer.from([0x03])); await this.resetAdapter(); await this.nv.writeItem(NvItemsIds.STARTUP_OPTION, Buffer.from([0x00])); @@ -508,7 +502,7 @@ export class ZnpAdapterManager { * Writes ZNP `hasConfigured` flag to NV memory. This flag indicates the adapter has been configured. */ private async writeConfigurationFlag(): Promise { - this.debug.commissioning("writing configuration flag to adapter NV memory"); + logger.debug("writing configuration flag to adapter NV memory", NS); await this.nv.writeItem(this.options.version === ZnpVersion.zStack12 ? NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK1 : NvItemsIds.ZNP_HAS_CONFIGURED_ZSTACK3, Buffer.from([0x55])); } } diff --git a/src/adapter/z-stack/adapter/zStackAdapter.ts b/src/adapter/z-stack/adapter/zStackAdapter.ts index 64f76421fd..f66921c484 100644 --- a/src/adapter/z-stack/adapter/zStackAdapter.ts +++ b/src/adapter/z-stack/adapter/zStackAdapter.ts @@ -11,14 +11,13 @@ import {Constants as UnpiConstants} from '../unpi'; import {ZclFrame, FrameType, Direction, Foundation} from '../../../zcl'; import {Queue, Waitress, Wait} from '../../../utils'; import * as Constants from '../constants'; -import Debug from "debug"; import debounce from 'debounce'; -import {LoggerStub} from "../../../controller/logger-stub"; import {ZnpAdapterManager} from "./manager"; import * as Models from "../../../models"; import assert from 'assert'; +import {logger} from '../../../utils/logger'; -const debug = Debug("zigbee-herdsman:adapter:zStack:adapter"); +const NS = "zh:zstack"; const Subsystem = UnpiConstants.Subsystem; const Type = UnpiConstants.Type; const {ZnpCommandStatus, AddressMode} = Constants.COMMON; @@ -68,10 +67,8 @@ class ZStackAdapter extends Adapter { private interpanEndpointRegistered: boolean; private waitress: Waitress; - public constructor(networkOptions: NetworkOptions, - serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions, logger?: LoggerStub) { - - super(networkOptions, serialPortOptions, backupPath, adapterOptions, logger); + public constructor(networkOptions: NetworkOptions, serialPortOptions: SerialPortOptions, backupPath: string, adapterOptions: AdapterOptions) { + super(networkOptions, serialPortOptions, backupPath, adapterOptions); this.znp = new Znp(this.serialPortOptions.path, this.serialPortOptions.baudRate, this.serialPortOptions.rtscts); this.transactionID = 0; @@ -109,7 +106,7 @@ class ZStackAdapter extends Adapter { try { this.version = (await this.znp.request(Subsystem.SYS, 'version', {})).payload; } catch (e) { - debug(`Failed to get zStack version, assuming 1.2`); + logger.debug(`Failed to get zStack version, assuming 1.2`, NS); this.version = {"transportrev":2, "product":0, "majorrel":2, "minorrel":0, "maintrel":0, "revision":""}; } @@ -117,11 +114,11 @@ class ZStackAdapter extends Adapter { this.adapterOptions.concurrent : (this.version.product === ZnpVersion.zStack3x0 ? 16 : 2); - debug(`Adapter concurrent: ${concurrent}`); + logger.debug(`Adapter concurrent: ${concurrent}`, NS); this.queue = new Queue(concurrent); - debug(`Detected znp version '${ZnpVersion[this.version.product]}' (${JSON.stringify(this.version)})`); + logger.debug(`Detected znp version '${ZnpVersion[this.version.product]}' (${JSON.stringify(this.version)})`, NS); this.adapterManager = new ZnpAdapterManager( this.znp, { @@ -131,7 +128,6 @@ class ZStackAdapter extends Adapter { networkOptions: this.networkOptions, adapterOptions: this.adapterOptions, }, - this.logger ); const startResult = this.adapterManager.start(); @@ -257,7 +253,7 @@ class ZStackAdapter extends Adapter { * NOTE: There are cases where multiple nwkAddrRsp are recevied with different network addresses, * this is currently not handled, the first nwkAddrRsp is taken. */ - debug("Request network address of '%s'", ieeeAddr); + logger.debug(`Request network address of '${ieeeAddr}'`, NS); const response = this.znp.waitFor(UnpiConstants.Type.AREQ, Subsystem.ZDO, 'nwkAddrRsp', {ieeeaddr: ieeeAddr}); await this.znp.request(Subsystem.ZDO, 'nwkAddrReq', {ieeeaddr: ieeeAddr, reqtype: 0, startindex: 0}); const result = await response.start().promise; @@ -273,7 +269,7 @@ class ZStackAdapter extends Adapter { } private async discoverRoute(networkAddress: number, wait=true): Promise { - debug('Discovering route to %d', networkAddress); + logger.debug(`Discovering route to ${networkAddress}`, NS); const payload = {dstAddr: networkAddress, options: 0, radius: Constants.AF.DEFAULT_RADIUS}; await this.znp.request(Subsystem.ZDO, 'extRouteDisc', payload); @@ -289,7 +285,7 @@ class ZStackAdapter extends Adapter { const result = await this.nodeDescriptorInternal(networkAddress); return result; } catch (error) { - debug(`Node descriptor request for '${networkAddress}' failed (${error}), retry`); + logger.debug(`Node descriptor request for '${networkAddress}' failed (${error}), retry`, NS); // Doing a route discovery after simple descriptor request fails makes it succeed sometimes. // https://github.com/Koenkk/zigbee2mqtt/issues/3276 await this.discoverRoute(networkAddress); @@ -367,8 +363,8 @@ class ZStackAdapter extends Adapter { dataRequestAttempt: number, checkedNetworkAddress: boolean, discoveredRoute: boolean, assocRemove: boolean, assocRestore: {ieeeadr: string, nwkaddr: number, noderelation: number} ): Promise { - debug('sendZclFrameToEndpointInternal %s:%i/%i (%i,%i,%i)', - ieeeAddr, networkAddress, endpoint, responseAttempt, dataRequestAttempt, this.queue.count()); + logger.debug(`sendZclFrameToEndpointInternal ${ieeeAddr}:${networkAddress}/${endpoint} ` + + `(${responseAttempt},${dataRequestAttempt},${this.queue.count()})`, NS); let response = null; const command = zclFrame.getCommand(); if (command.hasOwnProperty('response') && disableResponse === false) { @@ -391,7 +387,7 @@ class ZStackAdapter extends Adapter { if (dataConfirmResult !== ZnpCommandStatus.SUCCESS) { // In case dataConfirm timesout (= null) or gives an error, try to recover - debug('Data confirm error (%s:%d,%d,%d)', ieeeAddr, networkAddress, dataConfirmResult, dataRequestAttempt); + logger.debug(`Data confirm error (${ieeeAddr}:${networkAddress},${dataConfirmResult},${dataRequestAttempt})`, NS); if (response !== null) response.cancel(); /** @@ -400,7 +396,7 @@ class ZStackAdapter extends Adapter { * Re-add the device to the assoc table, otherwise we will never be able to reach it anymore. */ if (assocRemove && assocRestore && this.supportsAssocAdd()) { - debug('assocAdd(%s)', assocRestore.ieeeadr); + logger.debug(`assocAdd(${assocRestore.ieeeadr})`, NS); await this.znp.request(Subsystem.UTIL, 'assocAdd', assocRestore); assocRestore = null; } @@ -464,7 +460,7 @@ class ZStackAdapter extends Adapter { * z-stack-firmware firmware version. In case it's not supported by the coordinator we will * automatically timeout after 60000ms. */ - debug('assocRemove(%s)', ieeeAddr); + logger.debug(`assocRemove(${ieeeAddr})`, NS); await this.znp.request(Subsystem.UTIL, 'assocRemove', {ieeeadr: ieeeAddr}); } else if (!discoveredRoute && dataRequestAttempt >= 1) { discoveredRoute = true; @@ -475,14 +471,16 @@ class ZStackAdapter extends Adapter { checkedNetworkAddress = true; const actualNetworkAddress = await this.requestNetworkAddress(ieeeAddr); if (networkAddress !== actualNetworkAddress) { - debug(`Failed because request was done with wrong network address`); + logger.debug(`Failed because request was done with wrong network address`, NS); discoveredRoute = true; networkAddress = actualNetworkAddress; await this.discoverRoute(actualNetworkAddress); - } else {debug('Network address did not change');} + } else { + logger.debug('Network address did not change', NS); + } } catch {} } else { - debug('Wait 2000ms'); + logger.debug('Wait 2000ms', NS); await Wait(2000); } @@ -499,7 +497,7 @@ class ZStackAdapter extends Adapter { const result = await response.start().promise; return result; } catch (error) { - debug('Response timeout (%s:%d,%d)', ieeeAddr, networkAddress, responseAttempt); + logger.debug(`Response timeout (${ieeeAddr}:${networkAddress},${responseAttempt})`, NS); if (responseAttempt < 1 && !disableRecovery) { // No response could be because the radio of the end device is turned off: // Sometimes the coordinator does not properly set the PENDING flag. @@ -507,12 +505,12 @@ class ZStackAdapter extends Adapter { const match = await this.znp.request( Subsystem.UTIL, 'assocGetWithAddress',{extaddr: ieeeAddr, nwkaddr: networkAddress} ); - debug(`Response timeout recovery: Node relation ${ - match.payload.noderelation} (${ieeeAddr} / ${match.payload.nwkaddr})`); + logger.debug(`Response timeout recovery: Node relation ${ + match.payload.noderelation} (${ieeeAddr} / ${match.payload.nwkaddr})`, NS); if (this.supportsAssocAdd() && this.supportsAssocRemove() && match.payload.nwkaddr !== 0xFFFE && match.payload.noderelation == 1 ) { - debug(`Response timeout recovery: Rewrite association table entry (${ieeeAddr})`); + logger.debug(`Response timeout recovery: Rewrite association table entry (${ieeeAddr})`, NS); await this.znp.request(Subsystem.UTIL, 'assocRemove', {ieeeadr: ieeeAddr}); await this.znp.request(Subsystem.UTIL, 'assocAdd', {ieeeadr: ieeeAddr, nwkaddr: networkAddress, noderelation: match.payload.noderelation} @@ -814,7 +812,7 @@ class ZStackAdapter extends Adapter { /* istanbul ignore else */ if (object.command === 'leaveInd') { if (object.payload.rejoin) { - debug(`Device leave: Got leave indication with rejoin=true, nothing to do`); + logger.debug(`Device leave: Got leave indication with rejoin=true, nothing to do`, NS); } else { const payload: Events.DeviceLeavePayload = { networkAddress: object.payload.srcaddr, diff --git a/src/adapter/z-stack/unpi/parser.ts b/src/adapter/z-stack/unpi/parser.ts index 04351b274f..8f8db8aca9 100644 --- a/src/adapter/z-stack/unpi/parser.ts +++ b/src/adapter/z-stack/unpi/parser.ts @@ -1,9 +1,9 @@ import * as stream from 'stream'; import {DataStart, SOF, MinMessageLength, PositionDataLength} from './constants'; import Frame from './frame'; -import Debug from "debug"; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:adapter:zStack:unpi:parser'); +const NS = 'zh:zstack:unpi:parser'; class Parser extends stream.Transform { private buffer: Buffer; @@ -14,14 +14,14 @@ class Parser extends stream.Transform { } public _transform(chunk: Buffer, _: string, cb: () => void): void { - debug(`<-- [${[...chunk]}]`); + logger.debug(`<-- [${[...chunk]}]`, NS); this.buffer = Buffer.concat([this.buffer, chunk]); this.parseNext(); cb(); } private parseNext(): void { - debug(`--- parseNext [${[...this.buffer]}]`); + logger.debug(`--- parseNext [${[...this.buffer]}]`, NS); if (this.buffer.length !== 0 && this.buffer.readUInt8(0) !== SOF) { // Buffer doesn't start with SOF, skip till SOF. @@ -41,10 +41,10 @@ class Parser extends stream.Transform { try { const frame = Frame.fromBuffer(dataLength, fcsPosition, frameBuffer); - debug(`--> parsed ${frame}`); + logger.debug(`--> parsed ${frame}`, NS); this.emit('parsed', frame); } catch (error) { - debug(`--> error ${error.stack}`); + logger.debug(`--> error ${error.stack}`, NS); } this.buffer = this.buffer.slice(frameLength, this.buffer.length); diff --git a/src/adapter/z-stack/unpi/writer.ts b/src/adapter/z-stack/unpi/writer.ts index bf8bd8f331..4bc22ef2e7 100644 --- a/src/adapter/z-stack/unpi/writer.ts +++ b/src/adapter/z-stack/unpi/writer.ts @@ -1,18 +1,18 @@ import * as stream from 'stream'; import Frame from './frame'; -import Debug from "debug"; +import {logger} from '../../../utils/logger'; -const debug = Debug('zigbee-herdsman:adapter:zStack:unpi:writer'); +const NS = 'zh:zstack:unpi:writer'; class Writer extends stream.Readable { public writeFrame(frame: Frame): void { const buffer = frame.toBuffer(); - debug(`--> frame [${[...buffer]}]`); + logger.debug(`--> frame [${[...buffer]}]`, NS); this.push(buffer); } public writeBuffer(buffer: Buffer): void { - debug(`--> buffer [${[...buffer]}]`); + logger.debug(`--> buffer [${[...buffer]}]`, NS); this.push(buffer); } diff --git a/src/adapter/z-stack/znp/znp.ts b/src/adapter/z-stack/znp/znp.ts index b43c3f62c3..577b10fc46 100755 --- a/src/adapter/z-stack/znp/znp.ts +++ b/src/adapter/z-stack/znp/znp.ts @@ -19,7 +19,7 @@ import {Subsystem, Type} from '../unpi/constants'; import net from 'net'; import events from 'events'; import Equals from 'fast-deep-equal/es6'; -import Debug from "debug"; +import {logger} from '../../../utils/logger'; const {COMMON: {ZnpCommandStatus}, Utils: {statusDescription}} = Constants; @@ -29,14 +29,7 @@ const timeouts = { default: 10000, }; -const debug = { - error: Debug('zigbee-herdsman:adapter:zStack:znp:error'), - timeout: Debug('zigbee-herdsman:adapter:zStack:znp:timeout'), - log: Debug('zigbee-herdsman:adapter:zStack:znp:log'), - SREQ: Debug('zigbee-herdsman:adapter:zStack:znp:SREQ'), - AREQ: Debug('zigbee-herdsman:adapter:zStack:znp:AREQ'), - SRSP: Debug('zigbee-herdsman:adapter:zStack:znp:SRSP'), -}; +const NS = 'zh:zstack:znp'; interface WaitressMatcher { type: Type; @@ -82,13 +75,13 @@ class Znp extends events.EventEmitter { private log(type: Type, message: string): void { if (type === Type.SRSP) { - debug.SRSP(message); + logger.debug(`SRSP: ${message}`, NS); } else if (type === Type.AREQ) { - debug.AREQ(message); + logger.debug(`AREQ: ${message}`, NS); } else { /* istanbul ignore else */ if (type === Type.SREQ) { - debug.SREQ(message); + logger.debug(`SREQ: ${message}`, NS); } else { throw new Error(`Unknown type '${type}'`); } @@ -104,7 +97,7 @@ class Znp extends events.EventEmitter { this.waitress.resolve(object); this.emit('received', object); } catch (error) { - debug.error(`Error while parsing to ZpiObject '${error.stack}'`); + logger.error(`Error while parsing to ZpiObject '${error.stack}'`, NS); } } @@ -113,11 +106,11 @@ class Znp extends events.EventEmitter { } private onPortError(error: Error): void { - debug.error(`Port error: ${error}`); + logger.error(`Port error: ${error}`, NS); } private onPortClose(): void { - debug.log('Port closed'); + logger.info('Port closed', NS); this.initialized = false; this.emit('close'); } @@ -129,7 +122,7 @@ class Znp extends events.EventEmitter { private async openSerialPort(): Promise { const options = {path: this.path, baudRate: this.baudRate, rtscts: this.rtscts, autoOpen: false}; - debug.log(`Opening SerialPort with ${JSON.stringify(options)}`); + logger.info(`Opening SerialPort with ${JSON.stringify(options)}`, NS); this.serialPort = new SerialPort(options); this.unpiWriter = new UnpiWriter(); @@ -143,7 +136,7 @@ class Znp extends events.EventEmitter { try { await this.serialPort.asyncOpen(); - debug.log('Serialport opened'); + logger.info('Serialport opened', NS); this.serialPort.once('close', this.onPortClose.bind(this)); this.serialPort.once('error', this.onPortError.bind(this)); @@ -164,7 +157,7 @@ class Znp extends events.EventEmitter { private async openSocketPort(): Promise { const info = SocketPortUtils.parseTcpPath(this.path); - debug.log(`Opening TCP socket with ${info.host}:${info.port}`); + logger.info(`Opening TCP socket with ${info.host}:${info.port}`, NS); this.socketPort = new net.Socket(); this.socketPort.setNoDelay(true); @@ -179,13 +172,13 @@ class Znp extends events.EventEmitter { return new Promise((resolve, reject): void => { this.socketPort.on('connect', function() { - debug.log('Socket connected'); + logger.info('Socket connected', NS); }); // eslint-disable-next-line const self = this; this.socketPort.on('ready', async function() { - debug.log('Socket ready'); + logger.info('Socket ready', NS); await self.skipBootloader(); self.initialized = true; resolve(); @@ -194,7 +187,7 @@ class Znp extends events.EventEmitter { this.socketPort.once('close', this.onPortClose.bind(this)); this.socketPort.on('error', function () { - debug.log('Socket error'); + logger.info('Socket error', NS); reject(new Error(`Error while opening socket`)); self.initialized = false; }); @@ -211,13 +204,13 @@ class Znp extends events.EventEmitter { // Send magic byte: https://github.com/Koenkk/zigbee2mqtt/issues/1343 to bootloader // and give ZNP 1 second to start. try { - debug.log('Writing CC2530/CC2531 skip bootloader payload'); + logger.info('Writing CC2530/CC2531 skip bootloader payload', NS); this.unpiWriter.writeBuffer(Buffer.from([0xef])); await Wait(1000); await this.request(Subsystem.SYS, 'ping', {capabilities: 1}, null, 250); } catch (error) { // Skip bootloader on some CC2652 devices (e.g. zzh-p) - debug.log('Skip bootloader for CC2652/CC1352'); + logger.info('Skip bootloader for CC2652/CC1352', NS); if (this.serialPort) { await this.setSerialPortOptions({dtr: false, rts: false}); await Wait(150); @@ -247,7 +240,7 @@ class Znp extends events.EventEmitter { try { return SerialPortUtils.is(RealpathSync(path), autoDetectDefinitions); } catch (error) { - debug.error(`Failed to determine if path is valid: '${error}'`); + logger.error(`Failed to determine if path is valid: '${error}'`, NS); return false; } } @@ -264,7 +257,7 @@ class Znp extends events.EventEmitter { } public async close(): Promise { - debug.log('closing'); + logger.info('closing', NS); this.queue.clear(); if (this.initialized) { diff --git a/src/adapter/zigate/adapter/zigateAdapter.ts b/src/adapter/zigate/adapter/zigateAdapter.ts index a5a51d9731..2927c4d6bd 100644 --- a/src/adapter/zigate/adapter/zigateAdapter.ts +++ b/src/adapter/zigate/adapter/zigateAdapter.ts @@ -7,7 +7,6 @@ import Adapter from '../../adapter'; import {Direction, Foundation, FrameType, ZclFrame} from '../../../zcl'; import {Queue, Wait, Waitress} from '../../../utils'; import Driver from '../driver/zigate'; -import {Debug} from "../debug"; import { ADDRESS_MODE, coordinatorEndpoints, @@ -19,10 +18,10 @@ import { import {RawAPSDataRequestPayload} from "../driver/commandType"; import ZiGateObject from "../driver/ziGateObject"; import {Buffalo} from "../../../buffalo"; -import {LoggerStub} from "../../../controller/logger-stub"; import * as Models from "../../../models"; +import {logger} from '../../../utils/logger'; -const debug = Debug('adapter'); +const NS = 'zh:zigate'; const default_bind_group = 901; // https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/lib/constants.js#L3 interface WaitressMatcher { address: number | string; @@ -46,14 +45,9 @@ class ZiGateAdapter extends Adapter { private closing: boolean; private queue: Queue; - public constructor(networkOptions: TsType.NetworkOptions, - serialPortOptions: TsType.SerialPortOptions, - backupPath: string, - adapterOptions: TsType.AdapterOptions, - logger?: LoggerStub - ) { - - super(networkOptions, serialPortOptions, backupPath, adapterOptions, logger); + public constructor(networkOptions: TsType.NetworkOptions, serialPortOptions: TsType.SerialPortOptions, backupPath: string, + adapterOptions: TsType.AdapterOptions) { + super(networkOptions, serialPortOptions, backupPath, adapterOptions); this.joinPermitted = false; this.driver = new Driver(serialPortOptions.path, serialPortOptions); @@ -75,7 +69,7 @@ class ZiGateAdapter extends Adapter { let startResult: TsType.StartResult = 'resumed'; try { await this.driver.open(); - debug.log("Connected to ZiGate adapter successfully."); + logger.info("Connected to ZiGate adapter successfully.", NS); const resetResponse = await this.driver.sendCommand(ZiGateCommandCode.Reset, {}, 5000) if (resetResponse.code === ZiGateMessageCode.RestartNonFactoryNew) { @@ -103,7 +97,7 @@ class ZiGateAdapter extends Adapter { const concurrent = this.adapterOptions && this.adapterOptions.concurrent ? this.adapterOptions.concurrent : 2; - debug.log(`Adapter concurrent: ${concurrent}`); + logger.debug(`Adapter concurrent: ${concurrent}`, NS); this.queue = new Queue(concurrent); return startResult; // 'resumed' | 'reset' | 'restored' @@ -115,7 +109,7 @@ class ZiGateAdapter extends Adapter { } public async getCoordinator(): Promise { - debug.log('getCoordinator'); + logger.debug('getCoordinator', NS); const networkResponse: any = await this.driver.sendCommand(ZiGateCommandCode.GetNetworkState); // @TODO deal hardcoded endpoints, made by analogy with deconz @@ -126,12 +120,12 @@ class ZiGateAdapter extends Adapter { ieeeAddr: networkResponse.payload.extendedAddress, endpoints: coordinatorEndpoints }; - debug.log('getCoordinator %o', response) + logger.debug(`getCoordinator ${JSON.stringify(response)}`, NS); return response; }; public async getCoordinatorVersion(): Promise { - debug.log('getCoordinatorVersion'); + logger.debug('getCoordinatorVersion', NS); return this.driver.sendCommand(ZiGateCommandCode.GetVersion, {}) .then((result) => { const meta = { @@ -149,7 +143,7 @@ class ZiGateAdapter extends Adapter { return Promise.resolve(version) }) .catch((e) => { - debug.error(e); + logger.error(e, NS); return Promise.reject(new Error("" + e)) }); }; @@ -171,7 +165,7 @@ class ZiGateAdapter extends Adapter { } public async reset(type: 'soft' | 'hard'): Promise { - debug.log('reset %s', type); + logger.debug(`reset ${type}`, NS); if (type === 'soft') { await this.driver.sendCommand(ZiGateCommandCode.Reset, {}, 5000); @@ -182,7 +176,7 @@ class ZiGateAdapter extends Adapter { }; public async getNetworkParameters(): Promise { - debug.log('getNetworkParameters'); + logger.debug('getNetworkParameters', NS); return this.driver.sendCommand(ZiGateCommandCode.GetNetworkState, {}, 10000) .then((NetworkStateResponse) => { const resultPayload: TsType.NetworkParameters = { @@ -216,7 +210,7 @@ class ZiGateAdapter extends Adapter { }; public async setTransmitPower(value: number): Promise { - debug.log('setTransmitPower, %o', arguments); + logger.debug(`setTransmitPower, ${JSON.stringify(arguments)}`, NS); return this.driver.sendCommand(ZiGateCommandCode.SetTXpower, {value: value}) .then(() => Promise.resolve()).catch(() => Promise.reject(new Error("Set transmitpower failed"))); }; @@ -224,7 +218,7 @@ class ZiGateAdapter extends Adapter { public async lqi(networkAddress: number): Promise { return this.queue.execute(async (): Promise => { - debug.log('lqi, %o', arguments) + logger.debug(`lqi, ${JSON.stringify(arguments)}`, NS); const neighbors: LQINeighbor[] = []; @@ -274,13 +268,13 @@ class ZiGateAdapter extends Adapter { } } - debug.log("LQI RESPONSE - addr: " + networkAddress.toString(16) + " status: " + logger.debug("LQI RESPONSE - addr: " + networkAddress.toString(16) + " status: " + response.status + " read " + (response.tableListCount + response.startIndex) - + "/" + response.tableEntrys + " entrys"); + + "/" + response.tableEntrys + " entrys", NS); return response; } catch (error) { const msg = "LQI REQUEST FAILED - addr: 0x" + networkAddress.toString(16) + " " + error; - debug.log(msg); + logger.error(msg, NS); return Promise.reject(new Error(msg)); } }; @@ -301,13 +295,13 @@ class ZiGateAdapter extends Adapter { // @TODO public routingTable(networkAddress: number): Promise { - debug.log('RoutingTable, %o', arguments) + logger.debug(`RoutingTable, ${JSON.stringify(arguments)}`, NS); return; }; public async nodeDescriptor(networkAddress: number): Promise { return this.queue.execute(async () => { - debug.log('nodeDescriptor, \n %o', arguments) + logger.debug(`nodeDescriptor, \n ${JSON.stringify(arguments)}`, NS); try { const nodeDescriptorResponse = await this.driver.sendCommand( @@ -334,13 +328,13 @@ class ZiGateAdapter extends Adapter { } const manufacturer = buf.readUInt16LE(7); - debug.log("RECEIVING NODE_DESCRIPTOR - addr: 0x" + networkAddress.toString(16) - + " type: " + type + " manufacturer: 0x" + manufacturer.toString(16)); + logger.debug("RECEIVING NODE_DESCRIPTOR - addr: 0x" + networkAddress.toString(16) + + " type: " + type + " manufacturer: 0x" + manufacturer.toString(16), NS); return {manufacturerCode: manufacturer, type}; } catch (error) { const msg = "RECEIVING NODE_DESCRIPTOR FAILED - addr: 0x" + networkAddress.toString(16) + " " + error; - debug.error(msg); + logger.error(msg, NS); return Promise.reject(new Error(msg)); } }, networkAddress); @@ -348,7 +342,7 @@ class ZiGateAdapter extends Adapter { public async activeEndpoints(networkAddress: number): Promise { return this.queue.execute(async () => { - debug.log('ActiveEndpoints request'); + logger.debug('ActiveEndpoints request', NS); const payload = { targetShortAddress: networkAddress } @@ -365,11 +359,11 @@ class ZiGateAdapter extends Adapter { endpoints: epList } - debug.log('ActiveEndpoints response: %o', payloadAE); + logger.debug(`ActiveEndpoints response: ${JSON.stringify(payloadAE)}`, NS); return payloadAE; } catch (error) { - debug.error("RECEIVING ActiveEndpoints FAILED, %o", error); + logger.error(`RECEIVING ActiveEndpoints FAILED, ${error}`, NS); return Promise.reject(new Error("RECEIVING ActiveEndpoints FAILED " + error)); } }, networkAddress); @@ -377,7 +371,7 @@ class ZiGateAdapter extends Adapter { public async simpleDescriptor(networkAddress: number, endpointID: number): Promise { return this.queue.execute(async () => { - debug.log('SimpleDescriptor request: %o', arguments) + logger.debug(`SimpleDescriptor request: ${JSON.stringify(arguments)}`, NS); try { const payload = { @@ -418,7 +412,7 @@ class ZiGateAdapter extends Adapter { } catch (error) { const msg = "RECEIVING SIMPLE_DESCRIPTOR FAILED - addr: 0x" + networkAddress.toString(16) + " EP:" + endpointID + " " + error; - debug.error(msg); + logger.error(msg, NS); return Promise.reject(new Error(msg)); } @@ -431,7 +425,7 @@ class ZiGateAdapter extends Adapter { destinationEndpoint?: number ): Promise { return this.queue.execute(async () => { - debug.log('bind %o', arguments); + logger.debug(`bind ${JSON.stringify(arguments)}`, NS); let payload = { targetExtendedAddress: sourceIeeeAddress, targetEndpoint: sourceEndpoint, @@ -450,11 +444,11 @@ class ZiGateAdapter extends Adapter { let data = result.payload.payload; if (data[1] === 0) { - debug.log('Bind %s success', sourceIeeeAddress); + logger.debug(`Bind ${sourceIeeeAddress} success`, NS); return Promise.resolve(); } else { const msg = `Bind ${sourceIeeeAddress} failed`; - debug.error(msg); + logger.error(msg, NS); return Promise.reject(new Error(msg)); } }, destinationNetworkAddress); @@ -466,7 +460,7 @@ class ZiGateAdapter extends Adapter { destinationEndpoint: number ): Promise { return this.queue.execute(async () => { - debug.log('unbind %o', arguments); + logger.debug(`unbind ${JSON.stringify(arguments)}`, NS); let payload = { targetExtendedAddress: sourceIeeeAddress, targetEndpoint: sourceEndpoint, @@ -486,11 +480,11 @@ class ZiGateAdapter extends Adapter { let data = result.payload.payload; if (data[1] === 0) { - debug.log('Unbind %s success', sourceIeeeAddress); + logger.debug(`Unbind ${sourceIeeeAddress} success`, NS); return Promise.resolve(); } else { const msg = `Unbind ${sourceIeeeAddress} failed`; - debug.error(msg); + logger.error(msg, NS); return Promise.reject(new Error(msg)); } }, destinationNetworkAddress); @@ -529,8 +523,7 @@ class ZiGateAdapter extends Adapter { disableResponse: boolean, disableRecovery: boolean, responseAttempt: number, dataRequestAttempt: number, checkedNetworkAddress: boolean, discoveredRoute: boolean, ): Promise { - debug.info('sendZclFrameToEndpointInternal %s:%i/%i (%i,%i,%i)', - ieeeAddr, networkAddress, endpoint, responseAttempt, dataRequestAttempt, this.queue.count()); + logger.debug(`sendZclFrameToEndpointInternal ${ieeeAddr}:${networkAddress}/${endpoint} (${responseAttempt},${dataRequestAttempt},${this.queue.count()})`, NS); let response = null; const data = zclFrame.toBuffer(); @@ -584,7 +577,7 @@ class ZiGateAdapter extends Adapter { // @todo discover route } catch (error) { - debug.error('Response error %s (%s:%d,%d)', error.toString(), ieeeAddr, networkAddress, responseAttempt); + logger.error(`Response error ${error.toString()} (${ieeeAddr}:${networkAddress},${responseAttempt})`, NS); if (responseAttempt < 1 && !disableRecovery) { return this.sendZclFrameToEndpointInternal( ieeeAddr, networkAddress, endpoint, sourceEndpoint, zclFrame, timeout, disableResponse, @@ -603,7 +596,7 @@ class ZiGateAdapter extends Adapter { public async sendZclFrameToAll(endpoint: number, zclFrame: ZclFrame, sourceEndpoint: number): Promise { return this.queue.execute(async () => { if (sourceEndpoint !== 0x01 /*&& sourceEndpoint !== 242*/) { // @todo on zigate firmware without gp causes hang - debug.error('source endpoint %d, not supported', sourceEndpoint); + logger.error(`source endpoint ${sourceEndpoint}, not supported`, NS); return; } @@ -620,7 +613,7 @@ class ZiGateAdapter extends Adapter { dataLength: data.length, data: data, } - debug.log('sendZclFrameToAll %o', payload) + logger.debug(`sendZclFrameToAll ${JSON.stringify(payload)}`, NS); await this.driver.sendCommand(ZiGateCommandCode.RawAPSDataRequest, payload, undefined, {}, true); await Wait(200); @@ -629,7 +622,7 @@ class ZiGateAdapter extends Adapter { public async sendZclFrameToGroup(groupID: number, zclFrame: ZclFrame, sourceEndpoint?: number): Promise { return this.queue.execute(async () => { - debug.log('sendZclFrameToGroup %o', arguments); + logger.debug(`sendZclFrameToGroup ${JSON.stringify(arguments)}`, NS); const data = zclFrame.toBuffer(); const payload: RawAPSDataRequestPayload = { addressMode: ADDRESS_MODE.group, //nwk @@ -643,7 +636,7 @@ class ZiGateAdapter extends Adapter { dataLength: data.length, data: data, } - debug.log('sendZclFrameToGroup: \n %o', payload); + logger.debug(`sendZclFrameToGroup: \n ${JSON.stringify(payload)}`, NS); await this.driver.sendCommand(ZiGateCommandCode.RawAPSDataRequest, payload, undefined, {}, true); await Wait(200); @@ -654,13 +647,13 @@ class ZiGateAdapter extends Adapter { * Supplementary functions */ private async initNetwork(): Promise { - debug.log(`Set channel mask ${this.networkOptions.channelList} key`); + logger.debug(`Set channel mask ${this.networkOptions.channelList} key`, NS); await this.driver.sendCommand( ZiGateCommandCode.SetChannelMask, {channelMask: channelsToMask(this.networkOptions.channelList)}, ); - debug.log(`Set security key`); + logger.debug(`Set security key`, NS); await this.driver.sendCommand( ZiGateCommandCode.SetSecurityStateKey, { @@ -673,7 +666,7 @@ class ZiGateAdapter extends Adapter { try { // The block is wrapped in trapping because if the network is already created, the firmware does not accept the new key. - debug.log('Set EPanID %h', this.networkOptions.extendedPanID.toString()); + logger.debug(`Set EPanID ${this.networkOptions.extendedPanID.toString()}`, NS); await this.driver.sendCommand(ZiGateCommandCode.SetExtendedPANID, { panId: this.networkOptions.extendedPanID, }); @@ -681,7 +674,7 @@ class ZiGateAdapter extends Adapter { await this.driver.sendCommand(ZiGateCommandCode.StartNetwork, {}); } catch (e) { // @TODO Depending on the type of error, output clear text to the user - debug.error("%o", e); + logger.error(e, NS); } return Promise.resolve(); } @@ -690,7 +683,7 @@ class ZiGateAdapter extends Adapter { networkAddress: number, endpoint: number, frameType: FrameType, direction: Direction, transactionSequenceNumber: number, clusterID: number, commandIdentifier: number, timeout: number, ): { promise: Promise; cancel: () => void } { - debug.log('waitForInternal %o', arguments) + logger.debug(`waitForInternal ${JSON.stringify(arguments)}`, NS); const payload = { address: networkAddress, endpoint, @@ -718,24 +711,24 @@ class ZiGateAdapter extends Adapter { * InterPAN !!! not implemented */ public async setChannelInterPAN(channel: number): Promise { - debug.log('setChannelInterPAN', arguments) + logger.debug(`setChannelInterPAN ${JSON.stringify(arguments)}`, NS); return Promise.reject("Not supported"); }; public async sendZclFrameInterPANToIeeeAddr(zclFrame: ZclFrame, ieeeAddress: string): Promise { - debug.log('sendZclFrameInterPANToIeeeAddr', arguments) + logger.debug(`sendZclFrameInterPANToIeeeAddr ${JSON.stringify(arguments)}`, NS); return Promise.reject("Not supported"); }; public async sendZclFrameInterPANBroadcast( zclFrame: ZclFrame, timeout: number ): Promise { - debug.log('sendZclFrameInterPANBroadcast', arguments) + logger.debug(`sendZclFrameInterPANBroadcast ${JSON.stringify(arguments)}`, NS); return Promise.reject("Not supported"); }; public restoreChannelInterPAN(): Promise { - debug.log('restoreChannelInterPAN', arguments) + logger.debug(`restoreChannelInterPAN ${JSON.stringify(arguments)}`, NS); return Promise.reject("Not supported"); }; @@ -764,7 +757,7 @@ class ZiGateAdapter extends Adapter { this.waitress.resolve(payload); this.emit(Events.Events.zclData, payload) } else { - debug.error('msg not zclFrame', data.zclFrame); + logger.error(`msg not zclFrame ${JSON.stringify(data.zclFrame)}`, NS); } } @@ -784,7 +777,7 @@ class ZiGateAdapter extends Adapter { } private leaveIndicationListener(data: { ziGateObject: ZiGateObject }): void { - debug.log('LeaveIndication %o', data); + logger.debug(`LeaveIndication ${JSON.stringify(data)}`, NS); const payload: Events.DeviceLeavePayload = { networkAddress: data.ziGateObject.payload.extendedAddress, ieeeAddr: data.ziGateObject.payload.extendedAddress diff --git a/src/adapter/zigate/debug.ts b/src/adapter/zigate/debug.ts deleted file mode 100644 index c64bfe61eb..0000000000 --- a/src/adapter/zigate/debug.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* istanbul ignore file */ -/* eslint-disable */ -import debug from 'debug'; - -const adapterDebug = debug('zigbee-herdsman:adapter:zigate'); - -const Debug = (suffix: string): { log: debug.Debugger, error: debug.Debugger , info: debug.Debugger} => { - const extendDebug = adapterDebug.extend(suffix); - return { - log: extendDebug.extend('log'), - info: extendDebug.extend('info'), - error: extendDebug.extend('error'), - }; -}; - -export {Debug}; diff --git a/src/adapter/zigate/driver/frame.ts b/src/adapter/zigate/driver/frame.ts index 920f155f81..fef14e8d66 100644 --- a/src/adapter/zigate/driver/frame.ts +++ b/src/adapter/zigate/driver/frame.ts @@ -1,8 +1,9 @@ /* istanbul ignore file */ /* eslint-disable */ -import {Debug} from '../debug'; -const debug = Debug('driver:frame'); +import {logger} from "../../../utils/logger"; + +const NS = 'zh:zigate:frame'; enum ZiGateFrameChunkSize { UInt8 = 1, @@ -79,12 +80,12 @@ export default class ZiGateFrame { constructor(frame?: Buffer) { if (frame !== undefined) { const decodedFrame = decodeFrame(frame); - // debug.log(`decoded frame >>> %o`, decodedFrame); + // logger.debug(`decoded frame >>> %o`, decodedFrame, NS); // Due to ZiGate incoming frames with erroneous msg length this.msgLengthOffset = -1; if (!ZiGateFrame.isValid(frame)) { - debug.error('Provided frame is not a valid ZiGate frame.'); + logger.error('Provided frame is not a valid ZiGate frame.', NS); return; } @@ -92,13 +93,13 @@ export default class ZiGateFrame { try { if(this.readMsgCode() !== 0x8001) - debug.log(`%o`, this); + logger.info(`${JSON.stringify(this)}`, NS); } catch (e) { - debug.error(e) + logger.error(e, NS); } if (this.readChecksum() !== this.calcChecksum()) { - debug.error(`Provided frame has an invalid checksum.`); + logger.error(`Provided frame has an invalid checksum.`, NS); return; } } diff --git a/src/adapter/zigate/driver/ziGateObject.ts b/src/adapter/zigate/driver/ziGateObject.ts index 41bfd1602f..b2f4237b29 100755 --- a/src/adapter/zigate/driver/ziGateObject.ts +++ b/src/adapter/zigate/driver/ziGateObject.ts @@ -5,13 +5,13 @@ import BuffaloZiGate, {BuffaloZiGateOptions} from './buffaloZiGate'; import {ZiGateCommandCode, ZiGateMessageCode, ZiGateObjectPayload} from "./constants"; import {ZiGateMessage, ZiGateMessageParameter} from "./messageType"; import {ZiGateCommand, ZiGateCommandParameter, ZiGateCommandType} from "./commandType"; -import {Debug} from '../debug'; +import {logger} from '../../../utils/logger'; type ZiGateCode = ZiGateCommandCode | ZiGateMessageCode; type ZiGateParameter = ZiGateCommandParameter | ZiGateMessageParameter; -const debug = Debug('driver:ziGateObject'); +const NS = 'zh:zigate:object'; const BufferAndListTypes = [ 'BUFFER', 'BUFFER8', 'BUFFER16', @@ -111,17 +111,14 @@ class ZiGateObject { try { result[parameter.name] = buffalo.read(parameter.parameterType, options); } catch (e) { - debug.error(e.stack); + logger.error(e.stack, NS); } } if (buffalo.isMore()) { let bufferString = buffalo.getBuffer().toString('hex'); - debug.error( - "Last bytes of data were not parsed \x1b[32m%s\x1b[31m%s\x1b[0m ", - bufferString.slice(0, (buffalo.getPosition() * 2)).replace(/../g, "$& "), - bufferString.slice(buffalo.getPosition() * 2).replace(/../g, "$& ") - ) + logger.error(`Last bytes of data were not parsed \x1b[32m${bufferString.slice(0, (buffalo.getPosition() * 2)).replace(/../g, "$& ")}` + + `\x1b[31m${bufferString.slice(buffalo.getPosition() * 2).replace(/../g, "$& ")}\x1b[0m `, NS); } return result; diff --git a/src/adapter/zigate/driver/zigate.ts b/src/adapter/zigate/driver/zigate.ts index 358a380632..6696c598ab 100644 --- a/src/adapter/zigate/driver/zigate.ts +++ b/src/adapter/zigate/driver/zigate.ts @@ -3,7 +3,6 @@ import {DelimiterParser} from '@serialport/parser-delimiter' import {EventEmitter} from 'events'; -import {Debug} from '../debug'; import {SerialPort} from '../../serialPort'; import SerialPortUtils from "../../serialPortUtils"; import SocketPortUtils from "../../socketPortUtils"; @@ -17,8 +16,9 @@ import Waitress from "../../../utils/waitress"; import {equal, ZiGateResponseMatcher, ZiGateResponseMatcherRule} from "./commandType"; import ZiGateFrame from "./frame"; import {Buffalo} from "../../../buffalo"; +import {logger} from '../../../utils/logger'; -const debug = Debug('driver'); +const NS = 'zh:zigate:driver'; const autoDetectDefinitions = [ {manufacturer: 'zigate_PL2303', vendorId: '067b', productId: '2303'}, @@ -87,20 +87,18 @@ export default class ZiGate extends EventEmitter { const waitersId: number[] = []; return await this.queue.execute(async () => { try { - debug.log( + logger.debug( 'Send command \x1b[32m>>>> ' + ZiGateCommandCode[code] + ' 0x' + zeroPad(code) - + ' <<<<\x1b[0m \nPayload: %o', - payload - ); + + ` <<<<\x1b[0m \nPayload: ${JSON.stringify(payload)}`, NS); const ziGateObject = ZiGateObject.createRequest(code, payload); const frame = ziGateObject.toZiGateFrame(); - debug.log('%o', frame); + logger.debug(`${JSON.stringify(frame)}`, NS); const sendBuffer = frame.toBuffer(); - debug.log('<-- send command ', sendBuffer); - debug.log(`DisableResponse: ${disableResponse}`); + logger.debug(`<-- send command ${sendBuffer.toString('hex')}`, NS); + logger.debug(`DisableResponse: ${disableResponse}`, NS); if (!disableResponse && Array.isArray(ziGateObject.command.response)) { ziGateObject.command.response.forEach((rules) => { @@ -143,7 +141,7 @@ export default class ZiGate extends EventEmitter { } return Promise.race(waiters); } catch (e) { - debug.error('sendCommand error:', e); + logger.error(`sendCommand error ${e}`, NS); return Promise.reject(new Error('sendCommand error: ' + e)); } }); @@ -165,7 +163,7 @@ export default class ZiGate extends EventEmitter { } public async close(): Promise { - debug.info('closing'); + logger.info('closing', NS); this.queue.clear(); if (this.initialized) { @@ -214,7 +212,7 @@ export default class ZiGate extends EventEmitter { try { await this.serialPort.asyncOpen(); - debug.log('Serialport opened'); + logger.debug('Serialport opened', NS); this.serialPort.once('close', this.onPortClose.bind(this)); this.serialPort.once('error', this.onPortError.bind(this)); @@ -233,7 +231,7 @@ export default class ZiGate extends EventEmitter { private async openSocketPort(): Promise { const info = SocketPortUtils.parseTcpPath(this.path); - debug.log(`Opening TCP socket with ${info.host}:${info.port}`); + logger.debug(`Opening TCP socket with ${info.host}:${info.port}`, NS); this.socketPort = new net.Socket(); this.socketPort.setNoDelay(true); @@ -248,14 +246,14 @@ export default class ZiGate extends EventEmitter { this.portWrite = this.socketPort; return new Promise((resolve, reject): void => { this.socketPort.on('connect', function () { - debug.log('Socket connected'); + logger.debug('Socket connected', NS); }); // eslint-disable-next-line const self = this; this.socketPort.on('ready', async function () { - debug.log('Socket ready'); + logger.debug('Socket ready', NS); self.initialized = true; resolve(); }); @@ -263,7 +261,7 @@ export default class ZiGate extends EventEmitter { this.socketPort.once('close', this.onPortClose.bind(this)); this.socketPort.on('error', (error) => { - debug.log('Socket error', error); + logger.error(`Socket error ${error}`, NS); // reject(new Error(`Error while opening socket`)); reject(); self.initialized = false; @@ -274,18 +272,18 @@ export default class ZiGate extends EventEmitter { } private onPortError(error: Error): void { - debug.error(`Port error: ${error}`); + logger.error(`Port error: ${error}`, NS); } private onPortClose(): void { - debug.log('Port closed'); + logger.debug('Port closed', NS); this.initialized = false; this.emit('close'); } private onSerialData(buffer: Buffer): void { try { - // debug.log(`--- parseNext `, buffer); + // logger.debug(`--- parseNext `, buffer, NS); const frame = new ZiGateFrame(buffer); if (!(frame instanceof ZiGateFrame)) return; // @Todo fix @@ -293,11 +291,11 @@ export default class ZiGate extends EventEmitter { const code = frame.readMsgCode(); const msgName = (ZiGateMessageCode[code] ? ZiGateMessageCode[code] : '') + ' 0x' + zeroPad(code); - debug.log(`--> parsed frame \x1b[1;34m>>>> ${msgName} <<<<\x1b[0m `); + logger.debug(`--> parsed frame \x1b[1;34m>>>> ${msgName} <<<<\x1b[0m `, NS); try { const ziGateObject = ZiGateObject.fromZiGateFrame(frame); - debug.log('%o', ziGateObject.payload); + logger.debug(`${JSON.stringify(ziGateObject.payload)}`, NS); this.waitress.resolve(ziGateObject); switch (code) { @@ -320,13 +318,13 @@ export default class ZiGate extends EventEmitter { ); this.emit('received', {ziGateObject, zclFrame}); } catch (error) { - debug.error("could not parse zclFrame: " + error); + logger.error("could not parse zclFrame: " + error, NS); this.emit('receivedRaw', {ziGateObject}); } break; default: - debug.error("not implemented profile: " + ziGateObject.payload.profileID); + logger.error("not implemented profile: " + ziGateObject.payload.profileID, NS); } break; case ZiGateMessageCode.LeaveIndication: @@ -338,11 +336,11 @@ export default class ZiGate extends EventEmitter { } } catch (error) { - debug.error('Parsing error: %o', error) + logger.error(`Parsing error: ${error}`, NS); } } catch (error) { - debug.error(`Error while parsing Frame '${error.stack}'`); + logger.error(`Error while parsing Frame '${error.stack}'`, NS); } } diff --git a/src/controller/controller.ts b/src/controller/controller.ts index bc550cb345..40e73bfe93 100644 --- a/src/controller/controller.ts +++ b/src/controller/controller.ts @@ -5,7 +5,6 @@ import {Entity, Device} from './model'; import {ZclFrameConverter} from './helpers'; import * as Events from './events'; import {KeyValue, DeviceType, GreenPowerEvents, GreenPowerDeviceJoinedPayload} from './tstype'; -import Debug from "debug"; import fs from 'fs'; import {Utils as ZclUtils, FrameControl} from '../zcl'; import Touchlink from './touchlink'; @@ -17,7 +16,9 @@ import assert from 'assert'; // @ts-ignore import mixin from 'mixin-deep'; import Group from './model/group'; -import {LoggerStub} from "./logger-stub"; +import {logger} from '../utils/logger'; + +const NS = 'zh:controller'; interface Options { network: AdapterTsType.NetworkOptions; @@ -38,7 +39,7 @@ async function catcho(func: () => Promise, errorMessage: string): Promise< try { await func(); } catch (error) { - debug.error(`${errorMessage}: ${error}`); + logger.error(`${errorMessage}: ${error}`, NS); } } @@ -58,11 +59,6 @@ const DefaultOptions: Options = { acceptJoiningDeviceHandler: null, }; -const debug = { - error: Debug('zigbee-herdsman:controller:error'), - log: Debug('zigbee-herdsman:controller:log'), -}; - /** * @noInheritDoc */ @@ -83,18 +79,16 @@ class Controller extends events.EventEmitter { private touchlink: Touchlink; private stopping: boolean; private networkParametersCached: AdapterTsType.NetworkParameters; - private logger?: LoggerStub; /** * Create a controller * * To auto detect the port provide `null` for `options.serialPort.path` */ - public constructor(options: Options, logger?: LoggerStub) { + public constructor(options: Options) { super(); this.stopping = false; this.options = mixin(JSON.parse(JSON.stringify(DefaultOptions)), options); - this.logger = logger; // Validate options for (const channel of this.options.network.channelList) { @@ -112,8 +106,7 @@ class Controller extends events.EventEmitter { } if (this.options.network.panID >= 0xFFFF || this.options.network.panID <= 0) { - throw new Error(`PanID must have a value of 0x0001 (1) - 0xFFFE (65534), ` + - `got ${this.options.network.panID}.`); + throw new Error(`PanID must have a value of 0x0001 (1) - 0xFFFE (65534), got ${this.options.network.panID}.`); } } @@ -126,11 +119,10 @@ class Controller extends events.EventEmitter { Entity.injectDatabase(this.database); // Adapter (create and inject) - this.adapter = await Adapter.create(this.options.network, - this.options.serialPort, this.options.backupPath, this.options.adapter, this.logger); - debug.log(`Starting with options '${JSON.stringify(this.options)}'`); + this.adapter = await Adapter.create(this.options.network, this.options.serialPort, this.options.backupPath, this.options.adapter); + logger.debug(`Starting with options '${JSON.stringify(this.options)}'`, NS); const startResult = await this.adapter.start(); - debug.log(`Started with result '${startResult}'`); + logger.debug(`Started with result '${startResult}'`, NS); // Check if we have to change the channel, only do this when adapter `resumed` because: // - `getNetworkParameters` might be return wrong info because it needs to propogate after backup restore @@ -146,7 +138,7 @@ class Controller extends events.EventEmitter { Entity.injectAdapter(this.adapter); // log injection - debug.log(`Injected database: ${this.database != null}, adapter: ${this.adapter != null}`); + logger.debug(`Injected database: ${this.database != null}, adapter: ${this.adapter != null}`, NS); this.greenPower = new GreenPower(this.adapter); this.greenPower.on(GreenPowerEvents.deviceJoined, this.onDeviceJoinedGreenPower.bind(this)); @@ -165,7 +157,7 @@ class Controller extends events.EventEmitter { fs.copyFileSync(this.options.databasePath, this.options.databaseBackupPath); } - debug.log('Clearing database...'); + logger.debug('Clearing database...', NS); for (const group of Group.all()) { group.removeFromDatabase(); } @@ -182,7 +174,7 @@ class Controller extends events.EventEmitter { // Add coordinator to the database if it is not there yet. const coordinator = await this.adapter.getCoordinator(); if (Device.byType('Coordinator').length === 0) { - debug.log('No coordinator in database, querying...'); + logger.debug('No coordinator in database, querying...', NS); Device.create( 'Coordinator', coordinator.ieeeAddr, coordinator.networkAddress, coordinator.manufacturerID, undefined, undefined, undefined, true, coordinator.endpoints @@ -192,7 +184,7 @@ class Controller extends events.EventEmitter { // Update coordinator ieeeAddr if changed, can happen due to e.g. reflashing const databaseCoordinator = Device.byType('Coordinator')[0]; if (databaseCoordinator.ieeeAddr !== coordinator.ieeeAddr) { - debug.log(`Coordinator address changed, updating to '${coordinator.ieeeAddr}'`); + logger.info(`Coordinator address changed, updating to '${coordinator.ieeeAddr}'`, NS); databaseCoordinator.changeIeeeAddress(coordinator.ieeeAddr); } @@ -283,7 +275,7 @@ class Controller extends events.EventEmitter { const data: Events.PermitJoinChangedPayload = {permitted: true, reason, timeout: this.permitJoinTimeout}; this.emit(Events.Events.permitJoinChanged, data); } else { - debug.log('Disable joining'); + logger.debug('Disable joining', NS); await this.greenPower.permitJoin(0, null); await this.adapter.permitJoin(0, null); const data: Events.PermitJoinChangedPayload = {permitted: false, reason, timeout: this.permitJoinTimeout}; @@ -338,13 +330,13 @@ class Controller extends events.EventEmitter { public async backup(): Promise { this.databaseSave(); if (this.options.backupPath && await this.adapter.supportsBackup()) { - debug.log('Creating coordinator backup'); + logger.debug('Creating coordinator backup', NS); const backup = await this.adapter.backup(Device.all().map((d) => d.ieeeAddr)); const unifiedBackup = await BackupUtils.toUnifiedBackup(backup); const tmpBackupPath = this.options.backupPath + '.tmp'; fs.writeFileSync(tmpBackupPath, JSON.stringify(unifiedBackup, null, 2)); fs.renameSync(tmpBackupPath, this.options.backupPath); - debug.log(`Wrote coordinator backup to '${this.options.backupPath}'`); + logger.info(`Wrote coordinator backup to '${this.options.backupPath}'`, NS); } } @@ -430,7 +422,7 @@ class Controller extends events.EventEmitter { * Broadcast a network-wide channel change. */ private async changeChannel(): Promise { - debug.log(`Broadcasting change channel to '${this.options.network.channelList[0]}'.`); + logger.info(`Broadcasting change channel to '${this.options.network.channelList[0]}'.`, NS); await this.adapter.changeChannel(this.options.network.channelList[0]); this.networkParametersCached = null;// invalidate cache @@ -444,11 +436,11 @@ class Controller extends events.EventEmitter { } private onNetworkAddress(payload: AdapterEvents.NetworkAddressPayload): void { - debug.log(`Network address '${payload.ieeeAddr}'`); + logger.debug(`Network address '${payload.ieeeAddr}'`, NS); const device = Device.byIeeeAddr(payload.ieeeAddr); if (!device) { - debug.log(`Network address is from unknown device '${payload.ieeeAddr}'`); + logger.debug(`Network address is from unknown device '${payload.ieeeAddr}'`, NS); return; } @@ -456,7 +448,7 @@ class Controller extends events.EventEmitter { {device, reason: 'networkAddress'} as Events.LastSeenChangedPayload); if (device.networkAddress !== payload.networkAddress) { - debug.log(`Device '${payload.ieeeAddr}' got new networkAddress '${payload.networkAddress}'`); + logger.debug(`Device '${payload.ieeeAddr}' got new networkAddress '${payload.networkAddress}'`, NS); device.networkAddress = payload.networkAddress; device.save(); @@ -466,11 +458,11 @@ class Controller extends events.EventEmitter { } private onDeviceAnnounce(payload: AdapterEvents.DeviceAnnouncePayload): void { - debug.log(`Device announce '${payload.ieeeAddr}'`); + logger.debug(`Device announce '${payload.ieeeAddr}'`, NS); const device = Device.byIeeeAddr(payload.ieeeAddr); if (!device) { - debug.log(`Device announce is from unknown device '${payload.ieeeAddr}'`); + logger.debug(`Device announce is from unknown device '${payload.ieeeAddr}'`, NS); return; } @@ -480,7 +472,7 @@ class Controller extends events.EventEmitter { device.implicitCheckin(); if (device.networkAddress !== payload.networkAddress) { - debug.log(`Device '${payload.ieeeAddr}' announced with new networkAddress '${payload.networkAddress}'`); + logger.debug(`Device '${payload.ieeeAddr}' announced with new networkAddress '${payload.networkAddress}'`, NS); device.networkAddress = payload.networkAddress; device.save(); } @@ -490,15 +482,15 @@ class Controller extends events.EventEmitter { } private onDeviceLeave(payload: AdapterEvents.DeviceLeavePayload): void { - debug.log(`Device leave '${payload.ieeeAddr}'`); + logger.debug(`Device leave '${payload.ieeeAddr}'`, NS); const device = payload.ieeeAddr ? Device.byIeeeAddr(payload.ieeeAddr) : Device.byNetworkAddress(payload.networkAddress); if (!device) { - debug.log(`Device leave is from unknown or already deleted device '${payload.ieeeAddr ?? payload.networkAddress}'`); + logger.debug(`Device leave is from unknown or already deleted device '${payload.ieeeAddr ?? payload.networkAddress}'`, NS); return; } - debug.log(`Removing device from database '${device.ieeeAddr}'`); + logger.debug(`Removing device from database '${device.ieeeAddr}'`, NS); device.removeFromDatabase(); const data: Events.DeviceLeavePayload = {ieeeAddr: device.ieeeAddr}; @@ -506,7 +498,7 @@ class Controller extends events.EventEmitter { } private async onAdapterDisconnected(): Promise { - debug.log(`Adapter disconnected'`); + logger.debug(`Adapter disconnected`, NS); await catcho(() => this.adapter.stop(), 'Failed to stop adapter on disconnect'); @@ -514,7 +506,7 @@ class Controller extends events.EventEmitter { } private async onDeviceJoinedGreenPower(payload: GreenPowerDeviceJoinedPayload): Promise { - debug.log(`Green power device '${JSON.stringify(payload)}' joined`); + logger.debug(`Green power device '${JSON.stringify(payload)}' joined`, NS); // Green power devices don't have an ieeeAddr, the sourceID is unique and static so use this. let ieeeAddr = payload.sourceID.toString(16); @@ -525,8 +517,8 @@ class Controller extends events.EventEmitter { let device = Device.byIeeeAddr(ieeeAddr, true); if (!device) { - debug.log(`New green power device '${ieeeAddr}' joined`); - debug.log(`Creating device '${ieeeAddr}'`); + logger.debug(`New green power device '${ieeeAddr}' joined`, NS); + logger.debug(`Creating device '${ieeeAddr}'`, NS); device = Device.create( 'GreenPower', ieeeAddr, payload.networkAddress, null, undefined, undefined, modelID, true, [], @@ -538,7 +530,7 @@ class Controller extends events.EventEmitter { const deviceInterviewPayload: Events.DeviceInterviewPayload = {status: 'successful', device}; this.selfAndDeviceEmit(device, Events.Events.deviceInterview, deviceInterviewPayload); } else if (device.isDeleted) { - debug.log(`Deleted green power device '${ieeeAddr}' joined`); + logger.debug(`Deleted green power device '${ieeeAddr}' joined, undeleting`, NS); device.undelete(true); @@ -555,38 +547,38 @@ class Controller extends events.EventEmitter { } private async onDeviceJoined(payload: AdapterEvents.DeviceJoinedPayload): Promise { - debug.log(`Device '${payload.ieeeAddr}' joined`); + logger.debug(`Device '${payload.ieeeAddr}' joined`, NS); if (this.options.acceptJoiningDeviceHandler) { if (!(await this.options.acceptJoiningDeviceHandler(payload.ieeeAddr))) { - debug.log(`Device '${payload.ieeeAddr}' rejected by handler, removing it`); + logger.debug(`Device '${payload.ieeeAddr}' rejected by handler, removing it`, NS); await catcho(() => this.adapter.removeDevice(payload.networkAddress, payload.ieeeAddr), 'Failed to remove rejected device'); return; } else { - debug.log(`Device '${payload.ieeeAddr}' accepted by handler`); + logger.debug(`Device '${payload.ieeeAddr}' accepted by handler`, NS); } } let device = Device.byIeeeAddr(payload.ieeeAddr, true); if (!device) { - debug.log(`New device '${payload.ieeeAddr}' joined`); - debug.log(`Creating device '${payload.ieeeAddr}'`); + logger.debug(`New device '${payload.ieeeAddr}' joined`, NS); + logger.debug(`Creating device '${payload.ieeeAddr}'`, NS); device = Device.create( 'Unknown', payload.ieeeAddr, payload.networkAddress, undefined, undefined, undefined, undefined, false, [] ); this.selfAndDeviceEmit(device, Events.Events.deviceJoined, {device} as Events.DeviceJoinedPayload); } else if (device.isDeleted) { - debug.log(`Delete device '${payload.ieeeAddr}' joined, undeleting`); + logger.debug(`Deleted device '${payload.ieeeAddr}' joined, undeleting`, NS); device.undelete(); this.selfAndDeviceEmit(device, Events.Events.deviceJoined, {device} as Events.DeviceJoinedPayload); } if (device.networkAddress !== payload.networkAddress) { - debug.log( - `Device '${payload.ieeeAddr}' is already in database with different networkAddress, ` + - `updating networkAddress` + logger.debug( + `Device '${payload.ieeeAddr}' is already in database with different network address, updating network address`, + NS, ); device.networkAddress = payload.networkAddress; device.save(); @@ -599,23 +591,23 @@ class Controller extends events.EventEmitter { if (!device.interviewCompleted && !device.interviewing) { const payloadStart: Events.DeviceInterviewPayload = {status: 'started', device}; - debug.log(`Interview '${device.ieeeAddr}' start`); + logger.info(`Interview for '${device.ieeeAddr}' started`, NS); this.selfAndDeviceEmit(device, Events.Events.deviceInterview, payloadStart); try { await device.interview(); - debug.log(`Succesfully interviewed '${device.ieeeAddr}'`); + logger.info(`Succesfully interviewed '${device.ieeeAddr}'`, NS); const event: Events.DeviceInterviewPayload = {status: 'successful', device}; this.selfAndDeviceEmit(device, Events.Events.deviceInterview, event); } catch (error) { - debug.error(`Interview failed for '${device.ieeeAddr} with error '${error}'`); + logger.error(`Interview failed for '${device.ieeeAddr} with error '${error}'`, NS); const event: Events.DeviceInterviewPayload = {status: 'failed', device}; this.selfAndDeviceEmit(device, Events.Events.deviceInterview, event); } } else { - debug.log( - `Not interviewing '${payload.ieeeAddr}', completed '${device.interviewCompleted}', ` + - `in progress '${device.interviewing}'` + logger.debug( + `Not interviewing '${payload.ieeeAddr}', completed '${device.interviewCompleted}', in progress '${device.interviewing}'`, + NS, ); } } @@ -633,7 +625,7 @@ class Controller extends events.EventEmitter { if (dataType === 'zcl') { delete logDataPayload.frame.Cluster; } - debug.log(`Received '${dataType}' data '${JSON.stringify(logDataPayload)}'`); + logger.debug(`Received '${dataType}' data '${JSON.stringify(logDataPayload)}'`, NS); let gpDevice = null; @@ -664,15 +656,12 @@ class Controller extends events.EventEmitter { * The group ID attribute of these message defines the network address of the end device. */ if (device?.manufacturerName === 'LUMI' && device?.type == 'Router' && dataPayload.groupID) { - debug.log(`Handling re-transmitted Xiaomi message ${device.networkAddress} -> ${dataPayload.groupID}`); + logger.debug(`Handling re-transmitted Xiaomi message ${device.networkAddress} -> ${dataPayload.groupID}`, NS); device = Device.byNetworkAddress(dataPayload.groupID); } if (!device) { - debug.log( - `'${dataType}' data is from unknown device with address '${dataPayload.address}', ` + - `skipping...` - ); + logger.debug(`'${dataType}' data is from unknown device with address '${dataPayload.address}', skipping...`, NS); return; } @@ -685,9 +674,10 @@ class Controller extends events.EventEmitter { let endpoint = device.getEndpoint(dataPayload.endpoint); if (!endpoint) { - debug.log( + logger.debug( `'${dataType}' data is from unknown endpoint '${dataPayload.endpoint}' from device with ` + - `network address '${dataPayload.address}', creating it...` + `network address '${dataPayload.address}', creating it...`, + NS, ); endpoint = device.createEndpoint(dataPayload.endpoint); } @@ -734,7 +724,7 @@ class Controller extends events.EventEmitter { type = Events.CommandsLookup[command.name]; data = dataPayload.frame.Payload; } else { - debug.log(`Skipping command '${command.name}' because it is missing from the lookup`); + logger.debug(`Skipping command '${command.name}' because it is missing from the lookup`, NS); } } } diff --git a/src/controller/database.ts b/src/controller/database.ts index 1cddbadb39..f4ae731cca 100644 --- a/src/controller/database.ts +++ b/src/controller/database.ts @@ -1,10 +1,8 @@ import fs from 'fs'; -import Debug from "debug"; import {DatabaseEntry, EntityType} from './tstype'; +import {logger} from '../utils/logger'; -const debug = { - log: Debug('zigbee-herdsman:controller:database:log'), -}; +const NS = 'zh:controller:database'; class Database { private entries: {[id: number]: DatabaseEntry}; @@ -78,7 +76,7 @@ class Database { } public write(): void { - debug.log(`Writing database to '${this.path}'`); + logger.debug(`Writing database to '${this.path}'`, NS); const lines = []; for (const DatabaseEntry of Object.values(this.entries)) { const json = JSON.stringify(DatabaseEntry); diff --git a/src/controller/greenPower.ts b/src/controller/greenPower.ts index 2b99149645..a0f326855e 100644 --- a/src/controller/greenPower.ts +++ b/src/controller/greenPower.ts @@ -4,12 +4,9 @@ import crypto from 'crypto'; import ZclTransactionSequenceNumber from './helpers/zclTransactionSequenceNumber'; import events from 'events'; import {GreenPowerEvents, GreenPowerDeviceJoinedPayload} from './tstype'; -import Debug from "debug"; +import {logger} from '../utils/logger'; -const debug = { - info: Debug('zigbee-herdsman:controller:greenpower'), - error: Debug('zigbee-herdsman:controller:greenpower'), -}; +const NS = 'zh:controller:greenpower'; const zigBeeLinkKey = Buffer.from([ 0x5A, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6C, 0x6C, 0x69, 0x61, 0x6E, 0x63, 0x65, 0x30, 0x39 @@ -49,7 +46,7 @@ class GreenPower extends events.EventEmitter { /* eslint-disable-next-line @typescript-eslint/no-explicit-any*/ private async sendPairingCommand(payload: any, dataPayload: AdapterEvents.ZclDataPayload): Promise { - debug.info("Payload.Options: " + payload.options + " wasBroadcast: " + dataPayload.wasBroadcast); + logger.debug(`Payload.Options: ${payload.options} wasBroadcast: ${dataPayload.wasBroadcast}`, NS); // Set sink address based on communication mode switch ((payload.options >> 5) & 3) { @@ -66,7 +63,7 @@ class GreenPower extends events.EventEmitter { break; /* istanbul ignore next */ default: - debug.error("Unhandled applicationID: " + (payload.options & 7)); + logger.error(`Unhandled applicationID: ${(payload.options & 7)}`, NS); return; } @@ -83,8 +80,7 @@ class GreenPower extends events.EventEmitter { if (dataPayload.wasBroadcast) { return this.adapter.sendZclFrameToAll(242, frame, 242); } else { - return this.adapter.sendZclFrameToEndpoint(null, - dataPayload.frame.Payload.gppNwkAddr, 242, frame, 10000, false, false, 242); + return this.adapter.sendZclFrameToEndpoint(null, dataPayload.frame.Payload.gppNwkAddr, 242, frame, 10000, false, false, 242); } } @@ -95,28 +91,28 @@ class GreenPower extends events.EventEmitter { switch(dataPayload.frame.Payload.commandID) { /* istanbul ignore next */ case undefined: - debug.error("GP Undefined Command"); + logger.error(`Received undefined command from '${dataPayload.address}'`, NS); break; case 0xE0: // GP Commissioning - debug.info("GP Commissioning"); - + logger.info(`Received commissioning from '${dataPayload.address}'`, NS); + /* istanbul ignore if */ if (typeof dataPayload.address !== 'number') { - debug.info("Warning: commissioning request with string type address"); + logger.error(`Commissioning request with string type address unsupported for '${dataPayload.address}'`, NS); break; } - + const rxOnCap = dataPayload.frame.Payload.commandFrame.options & 0b10; - + const key = this.encryptSecurityKey( dataPayload.frame.Payload.srcID, dataPayload.frame.Payload.commandFrame.securityKey ); - + // RX capable GPD needs GP Commissioning Reply if (rxOnCap) { - debug.info("RxOnCap set -> supports bidirectional communication"); + logger.debug("RxOnCap set -> supports bidirectional communication", NS); // NOTE: currently encryption is disabled for RX capable GPDs - + const networkParameters = await this.adapter.getNetworkParameters(); // Commissioning reply payload = { @@ -132,19 +128,19 @@ class GreenPower extends events.EventEmitter { // keyMic: dataPayload.frame.Payload.commandFrame.keyMic, } }; - + const frame = Zcl.ZclFrame.create( Zcl.FrameType.SPECIFIC, Zcl.Direction.SERVER_TO_CLIENT, true, null, ZclTransactionSequenceNumber.next(), 'response', 33, payload ); await this.adapter.sendZclFrameToAll(242, frame, 242); - + payload = { options: 0b0000000110101000, // Disable encryption srcID: dataPayload.frame.Payload.srcID, deviceID: dataPayload.frame.Payload.commandFrame.deviceID, }; - + await this.sendPairingCommand(payload, dataPayload); } else { // Communication mode: @@ -154,7 +150,7 @@ class GreenPower extends events.EventEmitter { if (dataPayload.wasBroadcast) { opt = 0b1110010101001000; } - + payload = { options: opt, srcID: dataPayload.frame.Payload.srcID, @@ -163,30 +159,24 @@ class GreenPower extends events.EventEmitter { gpdKey: [...key], }; - + await this.sendPairingCommand(payload, dataPayload); } - + const eventData: GreenPowerDeviceJoinedPayload = { sourceID: dataPayload.frame.Payload.srcID, deviceID: dataPayload.frame.Payload.commandFrame.deviceID, networkAddress: dataPayload.frame.Payload.srcID & 0xFFFF, }; this.emit(GreenPowerEvents.deviceJoined, eventData); - + break; - /* istanbul ignore next */ case 0xE2: // GP Success - debug.info("GP Success"); - if (typeof dataPayload.address !== 'number') { - debug.info("Warning: commissioning request with string type address"); - break; - } - + logger.debug(`Received success from '${dataPayload.address}'`, NS); break; case 0xE3: // GP Channel Request - debug.info("GP Channel Request"); + logger.debug(`Received channel request from '${dataPayload.address}'`, NS); const networkParameters = await this.adapter.getNetworkParameters(); // Channel notification payload = { @@ -201,24 +191,24 @@ class GreenPower extends events.EventEmitter { options: networkParameters.channel - 11, } }; - + const frame = Zcl.ZclFrame.create( Zcl.FrameType.SPECIFIC, Zcl.Direction.SERVER_TO_CLIENT, true, null, ZclTransactionSequenceNumber.next(), 'response', 33, payload ); - + await this.adapter.sendZclFrameToAll(242, frame, 242); break; /* istanbul ignore next */ case 0xA1: // GP Manufacturer-specific Attribute Reporting break; default: - debug.info("Unhandled Zigbee GreenPower command: 0x" + - dataPayload.frame.Payload.commandID.toString(16)); + // NOTE: this is spammy because it logs everything that is handed back to Controller without special processing here + logger.debug(`Received unhandled command '0x${dataPayload.frame.Payload.commandID.toString(16)}' from '${dataPayload.address}'`, NS); } } catch (error) { /* istanbul ignore next */ - debug.error(`onZclGreenPowerData failed with error '${error}'`); + logger.error(error, NS); } } diff --git a/src/controller/helpers/requestQueue.ts b/src/controller/helpers/requestQueue.ts index 4436d57258..69328bf133 100755 --- a/src/controller/helpers/requestQueue.ts +++ b/src/controller/helpers/requestQueue.ts @@ -1,12 +1,9 @@ +import {logger} from '../../utils/logger'; import * as Zcl from '../../zcl'; import {Endpoint} from '../model'; import Request from './request'; -import Debug from "debug"; -const debug = { - info: Debug('zigbee-herdsman:helpers:requestQueue'), - error: Debug('zigbee-herdsman:helpers:requestQeue'), -}; +const NS = 'zh:controller:requestqueue'; type Mutable = { -readonly [P in keyof T ]: T[P] }; @@ -30,7 +27,7 @@ class RequestQueue extends Set { if (this.size === 0) return; if (!fastPolling && this.sendInProgress) { - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): sendPendingRequests already in progress`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): sendPendingRequests already in progress`, NS); return; } this.sendInProgress = true; @@ -39,26 +36,24 @@ class RequestQueue extends Set { const now = Date.now(); for (const request of this) { if (now > request.expires) { - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): discard after timeout. ` + - `Size before: ${this.size}`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): discard after timeout. Size before: ${this.size}`, NS); request.reject(); this.delete(request); } } - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): send pending requests (` + - `${this.size}, ${fastPolling})`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): send pending requests (${this.size}, ${fastPolling})`, NS); for (const request of this) { if (fastPolling || request.sendPolicy !== 'bulk') { try { const result = await request.send(); - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): send success`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): send success`, NS); request.resolve(result); this.delete(request); } catch (error) { - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): send failed, expires in ` + - `${(request.expires - now) / 1000} seconds`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): send failed, expires in ` + + `${(request.expires - now) / 1000} seconds`, NS); } } } @@ -66,8 +61,7 @@ class RequestQueue extends Set { } public async queue(request: Request): Promise { - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): Sending when active. ` + - `Expires: ${request.expires}`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): Sending when active. Expires: ${request.expires}`, NS); return new Promise((resolve, reject): void => { request.addCallbacks(resolve, reject); this.add(request); @@ -83,8 +77,8 @@ class RequestQueue extends Set { const payload = newRequest.frame.Payload; const commandID = newRequest.frame.getCommand().ID; - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): ZCL ${newRequest.frame.getCommand().name} ` + - `command, filter requests. Before: ${this.size}`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): ZCL ${newRequest.frame.getCommand().name} ` + + `command, filter requests. Before: ${this.size}`, NS); for (const request of this) { if( request?.frame?.Cluster?.ID === undefined || typeof request.frame.getCommand !== 'function') { @@ -98,7 +92,7 @@ class RequestQueue extends Set { /* istanbul ignore else */ if (newRequest.sendPolicy === 'keep-payload' && JSON.stringify(request.frame.Payload) === JSON.stringify(payload)) { - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): Merge duplicate request`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): Merge duplicate request`, NS); this.delete(request); newRequest.moveCallbacks(request); } @@ -107,7 +101,7 @@ class RequestQueue extends Set { const filteredPayload = request.frame.Payload.filter((oldEl: {attrId: number}) => !payload.find((newEl: {attrId: number}) => oldEl.attrId === newEl.attrId)); if (filteredPayload.length == 0) { - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): Remove & reject request`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): Remove & reject request`, NS); if( JSON.stringify(request.frame.Payload) === JSON.stringify(payload)) { newRequest.moveCallbacks(request); } else { @@ -117,13 +111,12 @@ class RequestQueue extends Set { } else if (newRequest.sendPolicy !== 'keep-cmd-undiv') { // remove all duplicate attributes if we shall not write undivided (request.frame as Mutable).Payload = filteredPayload; - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): ` - + `Remove commands from request`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): Remove commands from request`, NS); } } } } - debug.info(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): After: ${this.size}`); + logger.debug(`Request Queue (${this.deviceIeeeAddress}/${this.ID}): After: ${this.size}`, NS); } } diff --git a/src/controller/logger-stub.ts b/src/controller/logger-stub.ts deleted file mode 100644 index baeded3b49..0000000000 --- a/src/controller/logger-stub.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -export interface LoggerStub { - error: (message: string, ...meta: any[]) => void; - warn: (message: string, ...meta: any[]) => void; - info: (message: string, ...meta: any[]) => void; - debug: (message: string, ...meta: any[]) => void; -} diff --git a/src/controller/model/device.ts b/src/controller/model/device.ts index 13b5ac5e03..aa93d4feac 100755 --- a/src/controller/model/device.ts +++ b/src/controller/model/device.ts @@ -4,20 +4,17 @@ import ZclTransactionSequenceNumber from '../helpers/zclTransactionSequenceNumbe import Endpoint from './endpoint'; import Entity from './entity'; import {Wait} from '../../utils'; -import Debug from "debug"; import * as Zcl from '../../zcl'; import assert from 'assert'; import {ZclFrameConverter} from '../helpers'; +import {logger} from '../../utils/logger'; /** * @ignore */ const OneJanuary2000 = new Date('January 01, 2000 00:00:00 UTC+00:00').getTime(); -const debug = { - error: Debug('zigbee-herdsman:controller:device:error'), - log: Debug('zigbee-herdsman:controller:device:log'), -}; +const NS = 'zh:controller:device'; interface LQI { neighbors: { @@ -225,7 +222,7 @@ class Device extends Entity { // Respond to enroll requests if (frame.isSpecific() && frame.isCluster('ssIasZone') && frame.isCommand('enrollReq')) { - debug.log(`IAS - '${this.ieeeAddr}' responding to enroll response`); + logger.debug(`IAS - '${this.ieeeAddr}' responding to enroll response`, NS); const payload = {enrollrspcode: 0, zoneid: 23}; await endpoint.command('ssIasZone', 'enrollRsp', payload, {disableDefaultResponse: true}); } @@ -262,7 +259,7 @@ class Device extends Entity { await endpoint.readResponse(frame.Cluster.ID, frame.Header.transactionSequenceNumber, response, {srcEndpoint: dataPayload.destinationEndpoint}); } catch (error) { - debug.error(`Read response to ${this.ieeeAddr} failed`); + logger.error(`Read response to ${this.ieeeAddr} failed`, NS); } } @@ -276,7 +273,7 @@ class Device extends Entity { startFastPolling: true, fastPollTimeout: 0, }; - debug.log(`check-in from ${this.ieeeAddr}: accepting fast-poll`); + logger.debug(`check-in from ${this.ieeeAddr}: accepting fast-poll`, NS); await endpoint.command(frame.Cluster.ID, 'checkinRsp', payload, {sendPolicy: 'immediate'}); // This is a good time to read the checkin interval if we haven't stored it previously @@ -285,25 +282,24 @@ class Device extends Entity { await endpoint.read('genPollCtrl', ['checkinInterval'], {sendPolicy: 'immediate'}); this._checkinInterval = pollPeriod.checkinInterval / 4; // convert to seconds this.resetPendingRequestTimeout(); - debug.log(`Request Queue (${ - this.ieeeAddr}): default expiration timeout set to ${this.pendingRequestTimeout}`); + logger.debug(`Request Queue (${this.ieeeAddr}): default expiration timeout set to ${this.pendingRequestTimeout}`, NS); } await Promise.all(this.endpoints.map(async e => e.sendPendingRequests(true))); // We *must* end fast-poll when we're done sending things. Otherwise // we cause undue power-drain. - debug.log(`check-in from ${this.ieeeAddr}: stopping fast-poll`); + logger.debug(`check-in from ${this.ieeeAddr}: stopping fast-poll`, NS); await endpoint.command(frame.Cluster.ID, 'fastPollStop', {}, {sendPolicy: 'immediate'}); } else { const payload = { startFastPolling: false, fastPollTimeout: 0, }; - debug.log(`check-in from ${this.ieeeAddr}: declining fast-poll`); + logger.debug(`check-in from ${this.ieeeAddr}: declining fast-poll`, NS); await endpoint.command(frame.Cluster.ID, 'checkinRsp', payload, {sendPolicy: 'immediate'}); } } catch (error) { /* istanbul ignore next */ - debug.error(`Handling of poll check-in form ${this.ieeeAddr} failed`); + logger.error(`Handling of poll check-in from ${this.ieeeAddr} failed`, NS); } } @@ -331,7 +327,7 @@ class Device extends Entity { await endpoint.defaultResponse( frame.getCommand().ID, 0, frame.Cluster.ID, frame.Header.transactionSequenceNumber, {direction}); } catch (error) { - debug.error(`Default response to ${this.ieeeAddr} failed`); + logger.error(`Default response to ${this.ieeeAddr} failed`, NS); } } } @@ -364,7 +360,7 @@ class Device extends Entity { pendingRequestTimeout = entry.checkinInterval * 1000; // milliseconds } } - debug.log (`Request Queue (${ieeeAddr}): default expiration timeout set to ${pendingRequestTimeout}`); + logger.debug(`Request Queue (${ieeeAddr}): default expiration timeout set to ${pendingRequestTimeout}`, NS); return new Device( entry.id, entry.type, ieeeAddr, networkAddress, entry.manufId, endpoints, @@ -471,23 +467,23 @@ class Device extends Entity { public async interview(): Promise { if (this.interviewing) { const message = `Interview - interview already in progress for '${this.ieeeAddr}'`; - debug.log(message); + logger.debug(message, NS); throw new Error(message); } let error; this._interviewing = true; - debug.log(`Interview - start device '${this.ieeeAddr}'`); + logger.debug(`Interview - start device '${this.ieeeAddr}'`, NS); try { await this.interviewInternal(); - debug.log(`Interview - completed for device '${this.ieeeAddr}'`); + logger.debug(`Interview - completed for device '${this.ieeeAddr}'`, NS); this._interviewCompleted = true; } catch (e) { if (this.interviewQuirks()) { - debug.log(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${e}')`); + logger.debug(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${e}')`, NS); } else { - debug.log(`Interview - failed for device '${this.ieeeAddr}' with error '${e.stack}'`); + logger.debug(`Interview - failed for device '${this.ieeeAddr}' with error '${e.stack}'`, NS); error = e; } } finally { @@ -501,7 +497,7 @@ class Device extends Entity { } private interviewQuirks(): boolean { - debug.log(`Interview - quirks check for '${this.modelID}'-'${this.manufacturerName}'-'${this.type}'`); + logger.debug(`Interview - quirks check for '${this.modelID}'-'${this.manufacturerName}'-'${this.type}'`, NS); // TuYa devices are typically hard to interview. They also don't require a full interview to work correctly // e.g. no ias enrolling is required for the devices to work. @@ -516,7 +512,7 @@ class Device extends Entity { this._powerSource = this._powerSource || 'Battery'; this._interviewing = false; this._interviewCompleted = true; - debug.log(`Interview - quirks matched for TuYa end device`); + logger.debug(`Interview - quirks matched for TuYa end device`, NS); return true; } @@ -543,17 +539,17 @@ class Device extends Entity { const match = Object.keys(lookup).find((key) => this.modelID && this.modelID.match(key)); if (match) { const info = lookup[match]; - debug.log(`Interview procedure failed but got modelID matching '${match}', assuming interview succeeded`); + logger.debug(`Interview procedure failed but got modelID matching '${match}', assuming interview succeeded`, NS); this._type = this._type === 'Unknown' ? info.type : this._type; this._manufacturerID = this._manufacturerID || info.manufacturerID; this._manufacturerName = this._manufacturerName || info.manufacturerName; this._powerSource = this._powerSource || info.powerSource; this._interviewing = false; this._interviewCompleted = true; - debug.log(`Interview - quirks matched on '${match}'`); + logger.debug(`Interview - quirks matched on '${match}'`, NS); return true; } else { - debug.log('Interview - quirks did not match'); + logger.debug('Interview - quirks did not match', NS); return false; } } @@ -563,7 +559,7 @@ class Device extends Entity { const nodeDescriptor = await Entity.adapter.nodeDescriptor(this.networkAddress); this._manufacturerID = nodeDescriptor.manufacturerCode; this._type = nodeDescriptor.type; - debug.log(`Interview - got node descriptor for device '${this.ieeeAddr}'`); + logger.debug(`Interview - got node descriptor for device '${this.ieeeAddr}'`, NS); }; const hasNodeDescriptor = (): boolean => this._manufacturerID != null && this._type != null; @@ -575,18 +571,16 @@ class Device extends Entity { break; } catch (error) { if (this.interviewQuirks()) { - debug.log(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${error}')`); + logger.debug(`Interview - completed for device '${this.ieeeAddr}' because of quirks ('${error}')`, NS); return; } else { // Most of the times the first node descriptor query fails and the seconds one succeeds. - debug.log( - `Interview - node descriptor request failed for '${this.ieeeAddr}', attempt ${attempt + 1}` - ); + logger.debug(`Interview - node descriptor request failed for '${this.ieeeAddr}', attempt ${attempt + 1}`, NS); } } } } else { - debug.log(`Interview - skip node descriptor request for '${this.ieeeAddr}', already got it`); + logger.debug(`Interview - skip node descriptor request for '${this.ieeeAddr}', already got it`, NS); } if (!hasNodeDescriptor()) { @@ -596,14 +590,14 @@ class Device extends Entity { if (this.manufacturerID === 4619 && this._type === 'EndDevice') { // Give TuYa end device some time to pair. Otherwise they leave immediately. // https://github.com/Koenkk/zigbee2mqtt/issues/5814 - debug.log("Interview - Detected TuYa end device, waiting 10 seconds..."); + logger.debug("Interview - Detected TuYa end device, waiting 10 seconds...", NS); await Wait(10000); } else if ([0, 4098].includes(this.manufacturerID)) { // Potentially a TuYa device, some sleep fast so make sure to read the modelId and manufacturerName quickly. // In case the device responds, the endoint and modelID/manufacturerName are set // in controller.onZclOrRawData() // https://github.com/Koenkk/zigbee2mqtt/issues/7553 - debug.log("Interview - Detected potential TuYa end device, reading modelID and manufacturerName..."); + logger.debug("Interview - Detected potential TuYa end device, reading modelID and manufacturerName...", NS); try { const endpoint = Endpoint.create(1, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr); const result = await endpoint.read('genBasic', ['modelId', 'manufacturerName'], @@ -612,7 +606,7 @@ class Device extends Entity { .forEach((entry) => Device.ReportablePropertiesMapping[entry[0]].set(entry[1], this)); } catch (error) { /* istanbul ignore next */ - debug.log(`Interview - TuYa read modelID and manufacturerName failed (${error})`); + logger.debug(`Interview - TuYa read modelID and manufacturerName failed (${error})`, NS); } } @@ -624,7 +618,7 @@ class Device extends Entity { activeEndpoints = await Entity.adapter.activeEndpoints(this.networkAddress); break; } catch (error) { - debug.log(`Interview - active endpoints request failed for '${this.ieeeAddr}', attempt ${attempt + 1}`); + logger.debug(`Interview - active endpoints request failed for '${this.ieeeAddr}', attempt ${attempt + 1}`, NS); } } if (!activeEndpoints) { @@ -639,7 +633,7 @@ class Device extends Entity { // into an error. Therefore we filter it, more info: https://github.com/Koenkk/zigbee-herdsman/issues/82 activeEndpoints.endpoints.filter((e) => e !== 0 && !this.getEndpoint(e)).forEach((e) => this._endpoints.push(Endpoint.create(e, undefined, undefined, [], [], this.networkAddress, this.ieeeAddr))); - debug.log(`Interview - got active endpoints for device '${this.ieeeAddr}'`); + logger.debug(`Interview - got active endpoints for device '${this.ieeeAddr}'`, NS); for (const endpointID of activeEndpoints.endpoints.filter((e) => e !== 0)) { const endpoint = this.getEndpoint(endpointID); @@ -648,7 +642,7 @@ class Device extends Entity { endpoint.deviceID = simpleDescriptor.deviceID; endpoint.inputClusters = simpleDescriptor.inputClusters; endpoint.outputClusters = simpleDescriptor.outputClusters; - debug.log(`Interview - got simple descriptor for endpoint '${endpoint.ID}' device '${this.ieeeAddr}'`); + logger.debug(`Interview - got simple descriptor for endpoint '${endpoint.ID}' device '${this.ieeeAddr}'`, NS); // Read attributes, nice to have but not required for succesfull pairing as most of the attributes // are not mandatory in ZCL specification. @@ -665,8 +659,7 @@ class Device extends Entity { // https://github.com/Koenkk/zigbee-herdsman-converters/issues/2485. // The modelID and manufacturerName are crucial for device identification, so retry. if (item.key === 'modelID' || item.key === 'manufacturerName') { - debug.log(`Interview - first ${item.key} retrieval attempt failed, ` + - `retrying after 10 seconds...`); + logger.debug(`Interview - first ${item.key} retrieval attempt failed, retrying after 10 seconds...`, NS); await Wait(10000); result = await endpoint.read('genBasic', [key], {sendPolicy: 'immediate'}); } else { @@ -675,12 +668,9 @@ class Device extends Entity { } item.set(result[key], this); - debug.log(`Interview - got '${item.key}' for device '${this.ieeeAddr}'`); + logger.debug(`Interview - got '${item.key}' for device '${this.ieeeAddr}'`, NS); } catch (error) { - debug.log( - `Interview - failed to read attribute '${item.key}' from ` + - `endpoint '${endpoint.ID}' (${error})` - ); + logger.debug(`Interview - failed to read attribute '${item.key}' from endpoint '${endpoint.ID}' (${error})`, NS); } } } @@ -691,18 +681,18 @@ class Device extends Entity { // Enroll IAS device for (const endpoint of this.endpoints.filter((e): boolean => e.supportsInputCluster('ssIasZone'))) { - debug.log(`Interview - IAS - enrolling '${this.ieeeAddr}' endpoint '${endpoint.ID}'`); + logger.debug(`Interview - IAS - enrolling '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS); const stateBefore = await endpoint.read( 'ssIasZone', ['iasCieAddr', 'zoneState'], {sendPolicy: 'immediate'}); - debug.log(`Interview - IAS - before enrolling state: '${JSON.stringify(stateBefore)}'`); + logger.debug(`Interview - IAS - before enrolling state: '${JSON.stringify(stateBefore)}'`, NS); // Do not enroll when device has already been enrolled if (stateBefore.zoneState !== 1 || stateBefore.iasCieAddr !== coordinator.ieeeAddr) { - debug.log(`Interview - IAS - not enrolled, enrolling`); + logger.debug(`Interview - IAS - not enrolled, enrolling`, NS); await endpoint.write('ssIasZone', {'iasCieAddr': coordinator.ieeeAddr}, {sendPolicy: 'immediate'}); - debug.log(`Interview - IAS - wrote iasCieAddr`); + logger.debug(`Interview - IAS - wrote iasCieAddr`, NS); // There are 2 enrollment procedures: // - Auto enroll: coordinator has to send enrollResponse without receiving an enroll request @@ -711,7 +701,7 @@ class Device extends Entity { // this case in hanled in onZclData(). // https://github.com/Koenkk/zigbee2mqtt/issues/4569#issuecomment-706075676 await Wait(500); - debug.log(`IAS - '${this.ieeeAddr}' sending enroll response (auto enroll)`); + logger.debug(`IAS - '${this.ieeeAddr}' sending enroll response (auto enroll)`, NS); const payload = {enrollrspcode: 0, zoneid: 23}; await endpoint.command('ssIasZone', 'enrollRsp', payload, {disableDefaultResponse: true, sendPolicy: 'immediate'}); @@ -721,7 +711,7 @@ class Device extends Entity { await Wait(500); const stateAfter = await endpoint.read('ssIasZone', ['iasCieAddr', 'zoneState'], {sendPolicy: 'immediate'}); - debug.log(`Interview - IAS - after enrolling state (${attempt}): '${JSON.stringify(stateAfter)}'`); + logger.debug(`Interview - IAS - after enrolling state (${attempt}): '${JSON.stringify(stateAfter)}'`, NS); if (stateAfter.zoneState === 1) { enrolled = true; break; @@ -729,21 +719,19 @@ class Device extends Entity { } if (enrolled) { - debug.log(`Interview - IAS successfully enrolled '${this.ieeeAddr}' endpoint '${endpoint.ID}'`); + logger.debug(`Interview - IAS successfully enrolled '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS); } else { - throw new Error( - `Interview failed because of failed IAS enroll (zoneState didn't change ('${this.ieeeAddr}')` - ); + throw new Error(`Interview failed because of failed IAS enroll (zoneState didn't change ('${this.ieeeAddr}')`); } } else { - debug.log(`Interview - IAS - already enrolled, skipping enroll`); + logger.debug(`Interview - IAS - already enrolled, skipping enroll`, NS); } } // Bind poll control try { for (const endpoint of this.endpoints.filter((e): boolean => e.supportsInputCluster('genPollCtrl'))) { - debug.log(`Interview - Poll control - binding '${this.ieeeAddr}' endpoint '${endpoint.ID}'`); + logger.debug(`Interview - Poll control - binding '${this.ieeeAddr}' endpoint '${endpoint.ID}'`, NS); await endpoint.bind('genPollCtrl', coordinator.endpoints[0]); const pollPeriod = await endpoint.read('genPollCtrl', ['checkinInterval'], {sendPolicy: 'immediate'}); this._checkinInterval = pollPeriod.checkinInterval / 4; // convert to seconds @@ -751,7 +739,7 @@ class Device extends Entity { } } catch (error) { /* istanbul ignore next */ - debug.log(`Interview - failed to bind genPollCtrl (${error})`); + logger.debug(`Interview - failed to bind genPollCtrl (${error})`, NS); } } diff --git a/src/controller/model/endpoint.ts b/src/controller/model/endpoint.ts index f8c9bb4bb7..9b969e7ce6 100644 --- a/src/controller/model/endpoint.ts +++ b/src/controller/model/endpoint.ts @@ -8,13 +8,10 @@ import RequestQueue from '../helpers/requestQueue'; import {Events as AdapterEvents} from '../../adapter'; import Group from './group'; import Device from './device'; -import Debug from "debug"; import assert from 'assert'; +import {logger} from '../../utils/logger'; -const debug = { - info: Debug('zigbee-herdsman:controller:endpoint'), - error: Debug('zigbee-herdsman:controller:endpoint'), -}; +const NS = 'zh:controller:endpoint'; export interface ConfigureReportingItem { attribute: string | number | {ID: number; type: number}; @@ -288,24 +285,23 @@ class Endpoint extends Entity { || !this.getDevice().pendingRequestTimeout) { if (this.getDevice().pendingRequestTimeout > 0) { - debug.info(logPrefix + `send ${frame.getCommand().name} request immediately ` + - `(sendPolicy=${options.sendPolicy})`); + logger.debug(logPrefix + `send ${frame.getCommand().name} request immediately (sendPolicy=${options.sendPolicy})`, NS); } return request.send(); } // If this is a bulk message, we queue directly. if (request.sendPolicy === 'bulk') { - debug.info(logPrefix + `queue request (${this.pendingRequests.size})))`); + logger.debug(logPrefix + `queue request (${this.pendingRequests.size})`, NS); return this.pendingRequests.queue(request); } try { - debug.info(logPrefix + `send request`); + logger.debug(logPrefix + `send request`, NS); return await request.send(); } catch(error) { // If we got a failed transaction, the device is likely sleeping. // Queue for transmission later. - debug.info(logPrefix + `queue request (transaction failed)`); + logger.debug(logPrefix + `queue request (transaction failed)`, NS); return this.pendingRequests.queue(request); } } @@ -463,7 +459,7 @@ class Endpoint extends Entity { const log = `Bind ${this.deviceIeeeAddress}/${this.ID} ${cluster.name} from ` + `'${target instanceof Endpoint ? `${destinationAddress}/${target.ID}` : destinationAddress}'`; - debug.info(log); + logger.debug(log, NS); try { await Entity.adapter.bind( @@ -474,7 +470,7 @@ class Endpoint extends Entity { this.addBinding(clusterKey, target); } catch (error) { error.message = `${log} failed (${error.message})`; - debug.error(error.message); + logger.debug(error, NS); throw error; } } @@ -492,7 +488,7 @@ class Endpoint extends Entity { const log = `Unbind ${this.deviceIeeeAddress}/${this.ID} ${cluster.name} from ` + `'${target instanceof Endpoint ? `${destinationAddress}/${target.ID}` : destinationAddress}'`; - debug.info(log); + logger.debug(log, NS); try { await Entity.adapter.unbind( @@ -511,7 +507,7 @@ class Endpoint extends Entity { } } catch (error) { error.message = `${log} failed (${error.message})`; - debug.error(error.message); + logger.debug(error, NS); throw error; } } @@ -611,7 +607,7 @@ class Endpoint extends Entity { const log = `CommandResponse ${this.deviceIeeeAddress}/${this.ID} ` + `${cluster.name}.${command.name}(${JSON.stringify(payload)}, ${JSON.stringify(options)})`; - debug.info(log); + logger.debug(log, NS); try { await this.sendRequest(frame, options, async (f) => { @@ -627,7 +623,7 @@ class Endpoint extends Entity { }); } catch (error) { error.message = `${log} failed (${error.message})`; - debug.error(error.message); + logger.debug(error, NS); throw error; } } @@ -754,7 +750,7 @@ class Endpoint extends Entity { const log = `ZCL command ${this.deviceIeeeAddress}/${this.ID} ` + `${cluster.name}.${command.name}(${JSON.stringify((logPayload) ? logPayload : payload)}, ${JSON.stringify(options)})`; - debug.info(log); + logger.debug(log, NS); try { const result = await this.sendRequest(frame, options); @@ -764,7 +760,7 @@ class Endpoint extends Entity { return result; } catch (error) { error.message = `${log} failed (${error.message})`; - debug.error(error.message); + logger.debug(error, NS); throw error; } } diff --git a/src/controller/model/group.ts b/src/controller/model/group.ts index d4ff69ff4d..8ebf603346 100644 --- a/src/controller/model/group.ts +++ b/src/controller/model/group.ts @@ -5,12 +5,9 @@ import * as Zcl from '../../zcl'; import Endpoint from './endpoint'; import Device from './device'; import assert from 'assert'; -import Debug from "debug"; +import {logger} from '../../utils/logger'; -const debug = { - info: Debug('zigbee-herdsman:controller:group'), - error: Debug('zigbee-herdsman:controller:group'), -}; +const NS = 'zh:controller:group'; interface Options { manufacturerCode?: number; @@ -162,7 +159,7 @@ class Group extends Entity { } const log = `Write ${this.groupID} ${cluster.name}(${JSON.stringify(attributes)}, ${JSON.stringify(options)})`; - debug.info(log); + logger.debug(log, NS); try { const frame = Zcl.ZclFrame.create( @@ -173,7 +170,7 @@ class Group extends Entity { await Entity.adapter.sendZclFrameToGroup(this.groupID, frame, options.srcEndpoint); } catch (error) { error.message = `${log} failed (${error.message})`; - debug.error(error.message); + logger.debug(error, NS); throw error; } } @@ -195,13 +192,13 @@ class Group extends Entity { ); const log = `Read ${this.groupID} ${cluster.name}(${JSON.stringify(attributes)}, ${JSON.stringify(options)})`; - debug.info(log); + logger.debug(log, NS); try { await Entity.adapter.sendZclFrameToGroup(this.groupID, frame, options.srcEndpoint); } catch (error) { error.message = `${log} failed (${error.message})`; - debug.error(error.message); + logger.debug(error, NS); throw error; } } @@ -214,7 +211,7 @@ class Group extends Entity { const command = cluster.getCommand(commandKey); const log = `Command ${this.groupID} ${cluster.name}.${command.name}(${JSON.stringify(payload)})`; - debug.info(log); + logger.debug(log, NS); try { const frame = Zcl.ZclFrame.create( @@ -225,7 +222,7 @@ class Group extends Entity { await Entity.adapter.sendZclFrameToGroup(this.groupID, frame, options.srcEndpoint); } catch (error) { error.message = `${log} failed (${error.message})`; - debug.error(error.message); + logger.debug(error, NS); throw error; } } diff --git a/src/controller/touchlink.ts b/src/controller/touchlink.ts index b1dc122e51..dcf097ecd8 100644 --- a/src/controller/touchlink.ts +++ b/src/controller/touchlink.ts @@ -1,9 +1,9 @@ import {Adapter} from '../adapter'; import * as Zcl from '../zcl'; import {Wait, AssertString} from '../utils'; -import Debug from "debug"; +import {logger} from '../utils/logger'; -const debug = Debug('zigbee-herdsman:controller:touchlink'); +const NS = 'zh:controller:touchlink'; const scanChannels = [11, 15, 20, 25, 12, 13, 14, 16, 17, 18, 19, 21, 22, 23, 24, 26]; class Touchlink { @@ -33,7 +33,7 @@ class Touchlink { try { for (const channel of scanChannels) { - debug(`Set InterPAN channel to '${channel}'`); + logger.info(`Set InterPAN channel to '${channel}'`, NS); await this.adapter.setChannelInterPAN(channel); try { @@ -41,15 +41,15 @@ class Touchlink { const response = await this.adapter.sendZclFrameInterPANBroadcast( this.createScanRequestFrame(this.transactionNumber()), 500 ); - debug(`Got scan response on channel '${channel}' of '${response.address}'`); + logger.debug(`Got scan response on channel '${channel}' of '${response.address}'`, NS); AssertString(response.address); result.push({ieeeAddr: response.address, channel}); } catch (error) { - debug(`Scan request failed or was not answered: '${error}'`); + logger.warning(`Scan request failed or was not answered: '${error}'`, NS); } } } finally { - debug(`Restore InterPAN channel`); + logger.info(`Restore InterPAN channel`, NS); await this.adapter.restoreChannelInterPAN(); this.lock(false); } @@ -63,16 +63,16 @@ class Touchlink { try { const transaction = this.transactionNumber(); - debug(`Set InterPAN channel to '${channel}'`); + logger.info(`Set InterPAN channel to '${channel}'`, NS); await this.adapter.setChannelInterPAN(channel); await this.adapter.sendZclFrameInterPANBroadcast(this.createScanRequestFrame(transaction), 500); - debug(`Got scan response on channel '${channel}'`); + logger.debug(`Got scan response on channel '${channel}'`, NS); - debug(`Identifying '${ieeeAddr}'`); + logger.debug(`Identifying '${ieeeAddr}'`, NS); await this.adapter.sendZclFrameInterPANToIeeeAddr(this.createIdentifyRequestFrame(transaction), ieeeAddr); } finally { - debug(`Restore InterPAN channel`); + logger.info(`Restore InterPAN channel`, NS); await this.adapter.restoreChannelInterPAN(); this.lock(false); } @@ -83,22 +83,22 @@ class Touchlink { try { const transaction = this.transactionNumber(); - debug(`Set InterPAN channel to '${channel}'`); + logger.info(`Set InterPAN channel to '${channel}'`, NS); await this.adapter.setChannelInterPAN(channel); await this.adapter.sendZclFrameInterPANBroadcast(this.createScanRequestFrame(transaction), 500); - debug(`Got scan response on channel '${channel}'`); + logger.debug(`Got scan response on channel '${channel}'`, NS); - debug(`Identifying '${ieeeAddr}'`); + logger.debug(`Identifying '${ieeeAddr}'`, NS); await this.adapter.sendZclFrameInterPANToIeeeAddr(this.createIdentifyRequestFrame(transaction), ieeeAddr); await Wait(2000); - debug(`Reset to factory new '${ieeeAddr}'`); + logger.debug(`Reset to factory new '${ieeeAddr}'`, NS); await this.adapter.sendZclFrameInterPANToIeeeAddr( this.createResetFactoryNewRequestFrame(transaction), ieeeAddr ); } finally { - debug(`Restore InterPAN channel`); + logger.info(`Restore InterPAN channel`, NS); await this.adapter.restoreChannelInterPAN(); this.lock(false); } @@ -112,7 +112,7 @@ class Touchlink { try { for (const channel of scanChannels) { - debug(`Set InterPAN channel to '${channel}'`); + logger.info(`Set InterPAN channel to '${channel}'`, NS); await this.adapter.setChannelInterPAN(channel); try { @@ -121,30 +121,30 @@ class Touchlink { const response = await this.adapter.sendZclFrameInterPANBroadcast( this.createScanRequestFrame(transaction), 500 ); - debug(`Got scan response on channel '${channel}'`); + logger.debug(`Got scan response on channel '${channel}'`, NS); AssertString(response.address); // Device answered (if not it will fall in the catch below), // identify it (this will make e.g. the bulb flash) - debug(`Identifying`); + logger.debug(`Identifying`, NS); await this.adapter.sendZclFrameInterPANToIeeeAddr( this.createIdentifyRequestFrame(transaction), response.address ); await Wait(2000); - debug(`Reset to factory new`); + logger.debug(`Reset to factory new`, NS); await this.adapter.sendZclFrameInterPANToIeeeAddr( this.createResetFactoryNewRequestFrame(transaction), response.address ); done = true; } catch (error) { - debug(`Scan request failed or was not answered: '${error}'`); + logger.warning(`Scan request failed or was not answered: '${error}'`, NS); } if (done) break; } } finally { - debug(`Restore InterPAN channel`); + logger.info(`Restore InterPAN channel`, NS); await this.adapter.restoreChannelInterPAN(); this.lock(false); } diff --git a/src/index.ts b/src/index.ts index a2bd1f9a23..6497c8c093 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,8 @@ import Controller from './controller/controller'; import * as Zcl from './zcl'; +import * as logger from './utils/logger'; export {Zcl, Controller}; + +/* istanbul ignore next */ +export const setLogger = logger.setLogger; diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000000..2f96e08603 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,17 @@ +export interface Logger { + debug: (message: string, namespace: string) => void; + info: (message: string, namespace: string) => void; + warning: (message: string, namespace: string) => void; + error: (message: string | Error, namespace: string) => void; +} + +export let logger: Logger = { + debug: (message, namespace) => console.debug(`${namespace}: ${message}`), + info: (message, namespace) => console.info(`${namespace}: ${message}`), + warning: (message, namespace) => console.warn(`${namespace}: ${message}`), + error: (message, namespace) => console.error(`${namespace}: ${message}`), +}; + +export function setLogger(l: Logger): void { + logger = l; +} diff --git a/src/zcl/buffaloZcl.ts b/src/zcl/buffaloZcl.ts index 422bb14d50..babb5a9e86 100644 --- a/src/zcl/buffaloZcl.ts +++ b/src/zcl/buffaloZcl.ts @@ -1,13 +1,10 @@ import {Buffalo, TsType} from '../buffalo'; +import {logger} from '../utils/logger'; import {DataType} from './definition'; import {BuffaloZclOptions, StructuredIndicatorType, StructuredSelector, ZclArray} from './tstype'; import * as Utils from './utils'; -import Debug from "debug"; -const debug = { - info: Debug('zigbee-herdsman:controller:buffaloZcl'), - error: Debug('zigbee-herdsman:controller:buffaloZcl'), -}; +const NS = 'zh:controller:buffalozcl'; interface KeyValue {[s: string | number]: number | string} @@ -414,7 +411,7 @@ class BuffaloZcl extends Buffalo { try { attribute = cluster.getAttribute(attributeID).name; } catch { - debug.info("Unknown attribute " + attributeID + " in cluster " + cluster.name); + logger.info("Unknown attribute " + attributeID + " in cluster " + cluster.name, NS); } frame.attributes[attribute] = this.read(DataType[type], options); diff --git a/test/adapter/z-stack/adapter.test.ts b/test/adapter/z-stack/adapter.test.ts index cafd28c929..53b9f24737 100644 --- a/test/adapter/z-stack/adapter.test.ts +++ b/test/adapter/z-stack/adapter.test.ts @@ -8,12 +8,18 @@ import {ZnpVersion} from "../../../src/adapter/z-stack/adapter/tstype"; import * as Structs from "../../../src/adapter/z-stack/structs" import * as fs from "fs"; import * as path from "path"; -import {LoggerStub} from "../../../src/controller/logger-stub"; import * as Zcl from '../../../src/zcl'; import * as Constants from '../../../src/adapter/z-stack/constants'; import {ZclDataPayload} from "../../../src/adapter/events"; import {UnifiedBackupStorage} from "../../../src/models"; +import {setLogger} from "../../../src/utils/logger"; +const mockLogger = { + debug: jest.fn(), + info: jest.fn(), + warning: jest.fn(), + error: jest.fn(), +}; const deepClone = (obj) => JSON.parse(JSON.stringify(obj)); const mockSetTimeout = () => setTimeout = jest.fn().mockImplementation((r) => r()); @@ -1162,9 +1168,21 @@ jest.mock('../../../src/utils/queue', () => { Znp.isValidPath = jest.fn().mockReturnValue(true); Znp.autoDetectPath = jest.fn().mockReturnValue("/dev/autodetected"); + +const mocksClear = [ + mockLogger.debug, + mockLogger.info, + mockLogger.warning, + mockLogger.error, +]; + describe("zstack-adapter", () => { let adapter: ZStackAdapter; + beforeAll(async() => { + setLogger(mockLogger); + }); + afterAll(async () => { jest.useRealTimers(); }); @@ -1175,6 +1193,7 @@ describe("zstack-adapter", () => { adapter = new ZStackAdapter(networkOptions, serialPortOptions, "backup.json", {concurrent: 3}); mockZnpWaitForDefault(); mocks.forEach((m) => m.mockRestore()); + mocksClear.forEach((m) => m.mockClear()); mockQueueExecute.mockClear(); mockZnpWaitFor.mockClear(); dataConfirmCode = 0; @@ -1590,83 +1609,50 @@ describe("zstack-adapter", () => { fs.writeFileSync(backupFile, JSON.stringify(backup), "utf8"); adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3}); mockZnpRequestWith(empty3AlignedRequestMock); - await expect(adapter.start()).rejects.toThrowError("Backup corrupted - missing adapter IEEE address NV entry"); + await expect(adapter.start()).rejects.toThrow("Backup corrupted - missing adapter IEEE address NV entry"); }); it("should fail to start with 3.0.x adapter - commissioned, config-adapter mismatch", async () => { const backupFile = getTempFile(); fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8"); - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - - adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {concurrent: 3}, mockLogger); + adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {concurrent: 3}); mockZnpRequestWith(commissioned3AlignedRequestMock); - await expect(adapter.start()).rejects.toThrowError("startup failed - configuration-adapter mismatch - see logs above for more information"); - expect(mockLoggerError.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!"); - expect(mockLoggerError.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123"); - expect(mockLoggerError.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77"); - expect(mockLoggerError.mock.calls[3][0]).toBe("- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter=01030507090b0d0f00020406080a0c0d"); - expect(mockLoggerError.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21"); - expect(mockLoggerError.mock.calls[5][0]).toBe("Please update configuration to prevent further issues."); - expect(mockLoggerError.mock.calls[6][0]).toMatch(`If you wish to re\-commission your network, please remove coordinator backup at ${backupFile}`); - expect(mockLoggerError.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!"); + await expect(adapter.start()).rejects.toThrow("startup failed - configuration-adapter mismatch - see logs above for more information"); + expect(mockLogger.error.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!"); + expect(mockLogger.error.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123"); + expect(mockLogger.error.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77"); + expect(mockLogger.error.mock.calls[3][0]).toBe("- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter=01030507090b0d0f00020406080a0c0d"); + expect(mockLogger.error.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21"); + expect(mockLogger.error.mock.calls[5][0]).toBe("Please update configuration to prevent further issues."); + expect(mockLogger.error.mock.calls[6][0]).toMatch(`If you wish to re-commission your network, please remove coordinator backup at ${backupFile}`); + expect(mockLogger.error.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!"); }); it("should start with runInconsistent option with 3.0.x adapter - commissioned, config-adapter mismatch", async () => { const backupFile = getTempFile(); fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8"); - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - - adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {concurrent: 3, forceStartWithInconsistentAdapterConfiguration: true}, mockLogger); + adapter = new ZStackAdapter(networkOptionsMismatched, serialPortOptions, backupFile, {concurrent: 3, forceStartWithInconsistentAdapterConfiguration: true}); mockZnpRequestWith(commissioned3AlignedRequestMock); const result = await adapter.start(); expect(result).toBe("resumed"); - expect(mockLoggerError.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!"); - expect(mockLoggerError.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123"); - expect(mockLoggerError.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77"); - expect(mockLoggerError.mock.calls[3][0]).toBe("- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter=01030507090b0d0f00020406080a0c0d"); - expect(mockLoggerError.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21"); - expect(mockLoggerError.mock.calls[5][0]).toBe("Please update configuration to prevent further issues."); - expect(mockLoggerError.mock.calls[6][0]).toMatch(`If you wish to re\-commission your network, please remove coordinator backup at ${backupFile}`); - expect(mockLoggerError.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!"); - expect(mockLoggerError.mock.calls[8][0]).toBe("Running despite adapter configuration mismatch as configured. Please update the adapter to compatible firmware and recreate your network as soon as possible."); + expect(mockLogger.error.mock.calls[0][0]).toBe("Configuration is not consistent with adapter state/backup!"); + expect(mockLogger.error.mock.calls[1][0]).toBe("- PAN ID: configured=124, adapter=123"); + expect(mockLogger.error.mock.calls[2][0]).toBe("- Extended PAN ID: configured=00124b0009d69f77, adapter=00124b0009d69f77"); + expect(mockLogger.error.mock.calls[3][0]).toBe("- Network Key: configured=01030507090b0d0f00020406080a0c0d, adapter=01030507090b0d0f00020406080a0c0d"); + expect(mockLogger.error.mock.calls[4][0]).toBe("- Channel List: configured=21, adapter=21"); + expect(mockLogger.error.mock.calls[5][0]).toBe("Please update configuration to prevent further issues."); + expect(mockLogger.error.mock.calls[6][0]).toMatch(`If you wish to re-commission your network, please remove coordinator backup at ${backupFile}`); + expect(mockLogger.error.mock.calls[7][0]).toBe("Re-commissioning your network will require re-pairing of all devices!"); + expect(mockLogger.error.mock.calls[8][0]).toBe("Running despite adapter configuration mismatch as configured. Please update the adapter to compatible firmware and recreate your network as soon as possible."); }); it("should start with 3.0.x adapter - backward-compat - reversed extended pan id", async () => { const backupFile = getTempFile(); fs.writeFileSync(backupFile, JSON.stringify(backupMatchingConfig), "utf8"); - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - - adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3}, mockLogger); + adapter = new ZStackAdapter(networkOptions, serialPortOptions, backupFile, {concurrent: 3}); const nib = Structs.nib(Buffer.from(commissioned3AlignedRequestMock.nvItems.find(item => item.id === NvItemsIds.NIB).value)); nib.extendedPANID = nib.extendedPANID.reverse(); mockZnpRequestWith( @@ -1675,7 +1661,7 @@ describe("zstack-adapter", () => { ); const result = await adapter.start(); expect(result).toBe("resumed"); - expect(mockLoggerWarn.mock.calls[0][0]).toBe("Extended PAN ID is reversed (expected=00124b0009d69f77, actual=779fd609004b1200)"); + expect(mockLogger.warning.mock.calls[0][0]).toBe("Extended PAN ID is reversed (expected=00124b0009d69f77, actual=779fd609004b1200)"); }); it("should restore unified backup with 3.0.x adapter - commissioned, mismatched adapter-config, matching config-backup", async () => { diff --git a/test/controller.test.ts b/test/controller.test.ts index 2a8970b23e..aabe3d4f54 100755 --- a/test/controller.test.ts +++ b/test/controller.test.ts @@ -17,10 +17,17 @@ import * as Models from "../src/models"; import * as Utils from "../src/utils"; import { isTypedArray } from "util/types"; import Bonjour, {BrowserConfig, Service} from 'bonjour-service'; -import {LoggerStub} from "../src/controller/logger-stub"; +import {setLogger} from "../src/utils/logger"; const globalSetImmediate = setImmediate; const flushPromises = () => new Promise(globalSetImmediate); +const mockLogger = { + debug: jest.fn(), + info: jest.fn(), + warning: jest.fn(), + error: jest.fn(), +}; + let skipWait = true; Wait.mockImplementation((milliseconds) => { if (!skipWait) { @@ -155,6 +162,10 @@ const mocksClear = [ mockAddInstallCode, mockAdapterGetNetworkParameters, mockAdapterChangeChannel, + mockLogger.debug, + mockLogger.info, + mockLogger.warning, + mockLogger.error, ]; const deepClone = (obj) => JSON.parse(JSON.stringify(obj)); @@ -520,6 +531,7 @@ describe('Controller', () => { jest.useFakeTimers({doNotFake: ['setTimeout']}); Date.now = jest.fn() Date.now.mockReturnValue(150); + setLogger(mockLogger); dummyBackup = await Utils.BackupUtils.toUnifiedBackup(mockDummyBackup); }); @@ -557,7 +569,7 @@ describe('Controller', () => { it('Call controller constructor options mixed with default options', async () => { await controller.start(); - expect(ZStackAdapter).toBeCalledWith({"networkKeyDistribute":false,"networkKey":[1,3,5,7,9,11,13,15,0,2,4,6,8,10,12,13],"panID":6755,"extendedPanID":[221,221,221,221,221,221,221,221],"channelList":[15]}, {"baudRate": 115200, "path": "/dummy/conbee", "rtscts": true, "adapter": null}, backupPath, {"disableLED": false}, undefined); + expect(ZStackAdapter).toBeCalledWith({"networkKeyDistribute":false,"networkKey":[1,3,5,7,9,11,13,15,0,2,4,6,8,10,12,13],"panID":6755,"extendedPanID":[221,221,221,221,221,221,221,221],"channelList":[15]}, {"baudRate": 115200, "path": "/dummy/conbee", "rtscts": true, "adapter": null}, backupPath, {"disableLED": false}); }); it('Call controller constructor error on invalid channel', async () => { @@ -3531,106 +3543,68 @@ describe('Controller', () => { mockZStackAdapterIsValidPath.mockReturnValueOnce(true); await Adapter.create(null, {path: '/dev/bla', baudRate: 100, rtscts: false, adapter: null}, null, null); expect(mockZStackAdapterIsValidPath).toHaveBeenCalledWith('/dev/bla'); - expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/bla", "rtscts": false, adapter: null}, null, null, undefined); + expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/bla", "rtscts": false, adapter: null}, null, null); }); it('Adapter create continue when is valid path fails', async () => { mockZStackAdapterIsValidPath.mockImplementationOnce(() => {throw new Error('failed')}); await Adapter.create(null, {path: '/dev/bla', baudRate: 100, rtscts: false, adapter: null}, null, null); expect(mockZStackAdapterIsValidPath).toHaveBeenCalledWith('/dev/bla'); - expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/bla", "rtscts": false, adapter: null}, null, null, undefined); + expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/bla", "rtscts": false, adapter: null}, null, null); }); it('Adapter create auto detect', async () => { mockZStackAdapterIsValidPath.mockReturnValueOnce(true); mockZStackAdapterAutoDetectPath.mockReturnValueOnce('/dev/test'); await Adapter.create(null, {path: null, baudRate: 100, rtscts: false, adapter: null}, null, null); - expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: null}, null, null, undefined); + expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: null}, null, null); }); it('Adapter mdns timeout test', async () => { const fakeAdapterName = 'mdns_test_device'; - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - let error; + try { - await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null, mockLogger); + await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null); } catch(e) { - error = e; + expect(e).toStrictEqual(new Error(`Coordinator [${fakeAdapterName}] not found after timeout of 2000ms!`)); } - expect(error).toStrictEqual(new Error(`Coordinator [${fakeAdapterName}] not found after timeout of 2000ms!`)); }); it('Adapter mdns without type test', async () => { const fakeAdapterName = ''; - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - let error; + try { - await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null, mockLogger); + await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null,); } catch(e) { - error = e; + expect(e).toStrictEqual(new Error( + `No mdns device specified. You must specify the coordinator mdns service type after mdns://, e.g. mdns://my-adapter` + )); } - expect(error).toStrictEqual(new Error( - `No mdns device specified. You must specify the coordinator mdns service type after mdns://, e.g. mdns://my-adapter` - )); }); it('Adapter mdns wrong Zeroconf test', async () => { const fakeAdapterName = 'mdns_test_device'; const fakeIp = '111.111.111.111'; const fakePort = 6638; - const fakeRadio = 'znp'; - const fakeRadioDetected = fakeRadio == 'znp' ? 'zstack' : fakeRadio; const fakeBaud = '115200'; - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - Bonjour.prototype.findOne = function(opts?: BrowserConfig | undefined, timeout?: number, callback?: CallableFunction) { setTimeout(() => { callback({name: 'fakeAdapter', type: fakeAdapterName, port: fakePort, addresses: [fakeIp], txt: {baud_rate: fakeBaud}}); }, 200); } - let error; try { - await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null, mockLogger); + await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null); } catch(e) { - error = e; + expect(e).toStrictEqual(new Error( + `Coordinator returned wrong Zeroconf format! The following values are expected:\n` + + `txt.radio_type, got: undefined\n` + + `txt.baud_rate, got: 115200\n` + + `address, got: 111.111.111.111\n` + + `port, got: 6638` + )); } - expect(error).toStrictEqual(new Error( - `Coordinator returned wrong Zeroconf format! The following values are expected:\n` + - `txt.radio_type, got: undefined\n` + - `txt.baud_rate, got: 115200\n` + - `address, got: 111.111.111.111\n` + - `port, got: 6638` - )); - }); it('Adapter mdns detection ezsp test', async () => { @@ -3638,33 +3612,21 @@ describe('Controller', () => { const fakeIp = '111.111.111.111'; const fakePort = 6638; const fakeRadio = 'ezsp'; - const fakeRadioDetected = fakeRadio == 'znp' ? 'zstack' : fakeRadio; const fakeBaud = '115200'; - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - Bonjour.prototype.findOne = function(opts?: BrowserConfig | undefined, timeout?: number, callback?: CallableFunction) { setTimeout(() => { callback({name: 'fakeAdapter', type: fakeAdapterName, port: fakePort, addresses: [fakeIp], txt: {radio_type: fakeRadio, baud_rate: fakeBaud}}); }, 200); } - await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null, mockLogger); + await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null); - expect(mockLoggerInfo.mock.calls[0][0]).toBe(`Starting mdns discovery for coordinator: ${fakeAdapterName}`); - expect(mockLoggerInfo.mock.calls[1][0]).toBe(`Coordinator Ip: ${fakeIp}`); - expect(mockLoggerInfo.mock.calls[2][0]).toBe(`Coordinator Port: ${fakePort}`); - expect(mockLoggerInfo.mock.calls[3][0]).toBe(`Coordinator Radio: ${fakeRadioDetected}`); - expect(mockLoggerInfo.mock.calls[4][0]).toBe(`Coordinator Baud: ${fakeBaud}\n`); + expect(mockLogger.info.mock.calls[0][0]).toBe(`Starting mdns discovery for coordinator: ${fakeAdapterName}`); + expect(mockLogger.info.mock.calls[1][0]).toBe(`Coordinator Ip: ${fakeIp}`); + expect(mockLogger.info.mock.calls[2][0]).toBe(`Coordinator Port: ${fakePort}`); + expect(mockLogger.info.mock.calls[3][0]).toBe(`Coordinator Radio: ${fakeRadio}`); + expect(mockLogger.info.mock.calls[4][0]).toBe(`Coordinator Baud: ${fakeBaud}\n`); }); @@ -3675,34 +3637,17 @@ describe('Controller', () => { const fakeRadio = 'auto'; const fakeBaud = '115200'; - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - Bonjour.prototype.findOne = function(opts?: BrowserConfig | undefined, timeout?: number, callback?: CallableFunction) { setTimeout(() => { callback({name: 'fakeAdapter', type: fakeAdapterName, port: fakePort, addresses: [fakeIp], txt: {radio_type: fakeRadio, baud_rate: fakeBaud}}); }, 200); } - let error; try { - await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null, mockLogger); + await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null); } catch (e) { - error = e; + expect(e).toStrictEqual(new Error(`Adapter ${fakeRadio} is not supported.`)); } - - expect(error).toStrictEqual(new Error( - `Adapter ${fakeRadio} is not supported.` - )); - }); it('Adapter mdns detection zstack test', async () => { @@ -3710,54 +3655,39 @@ describe('Controller', () => { const fakeIp = '111.111.111.111'; const fakePort = 6638; const fakeRadio = 'znp'; - const fakeRadioDetected = fakeRadio == 'znp' ? 'zstack' : fakeRadio; const fakeBaud = '115200'; - const mockLoggerDebug = jest.fn(); - const mockLoggerInfo = jest.fn(); - const mockLoggerWarn = jest.fn(); - const mockLoggerError = jest.fn(); - const mockLogger: LoggerStub = { - debug: mockLoggerDebug, - info: mockLoggerInfo, - warn: mockLoggerWarn, - error: mockLoggerError - }; - Bonjour.prototype.findOne = function(opts?: BrowserConfig | undefined, timeout?: number, callback?: CallableFunction) { setTimeout(() => { callback({name: 'fakeAdapter', type: fakeAdapterName, port: fakePort, addresses: [fakeIp], txt: {radio_type: fakeRadio, baud_rate: fakeBaud}}); }, 200); } - await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null, mockLogger); + await Adapter.create(null, {path: `mdns://${fakeAdapterName}`, baudRate: 100, rtscts: false, adapter: null}, null, null); - expect(mockLoggerInfo.mock.calls[0][0]).toBe(`Starting mdns discovery for coordinator: ${fakeAdapterName}`); - expect(mockLoggerInfo.mock.calls[1][0]).toBe(`Coordinator Ip: ${fakeIp}`); - expect(mockLoggerInfo.mock.calls[2][0]).toBe(`Coordinator Port: ${fakePort}`); - expect(mockLoggerInfo.mock.calls[3][0]).toBe(`Coordinator Radio: ${fakeRadioDetected}`); - expect(mockLoggerInfo.mock.calls[4][0]).toBe(`Coordinator Baud: ${fakeBaud}\n`); - + expect(mockLogger.info.mock.calls[0][0]).toBe(`Starting mdns discovery for coordinator: ${fakeAdapterName}`); + expect(mockLogger.info.mock.calls[1][0]).toBe(`Coordinator Ip: ${fakeIp}`); + expect(mockLogger.info.mock.calls[2][0]).toBe(`Coordinator Port: ${fakePort}`); + expect(mockLogger.info.mock.calls[3][0]).toBe(`Coordinator Radio: zstack`); + expect(mockLogger.info.mock.calls[4][0]).toBe(`Coordinator Baud: ${fakeBaud}\n`); }); it('Adapter create auto detect nothing found', async () => { mockZStackAdapterIsValidPath.mockReturnValueOnce(false); mockZStackAdapterAutoDetectPath.mockReturnValueOnce(null); - let error; try { await Adapter.create(null, {path: null, baudRate: 100, rtscts: false, adapter: null}, null, null); } catch(e) { - error = e; + expect(e).toStrictEqual(new Error('No path provided and failed to auto detect path')); } - expect(error).toStrictEqual(new Error('No path provided and failed to auto detect path')); }); it('Adapter create with unknown path should take ZStackAdapter by default', async () => { mockZStackAdapterIsValidPath.mockReturnValueOnce(false); mockZStackAdapterAutoDetectPath.mockReturnValueOnce('/dev/test'); await Adapter.create(null, {path: null, baudRate: 100, rtscts: false, adapter: null}, null, null); - expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: null}, null, null, undefined); + expect(ZStackAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: null}, null, null); }); it('Adapter create should be able to specify adapter', async () => { @@ -3768,9 +3698,9 @@ describe('Controller', () => { mockZiGateAdapterIsValidPath.mockReturnValueOnce(false); mockZiGateAdapterAutoDetectPath.mockReturnValueOnce('/dev/test'); await Adapter.create(null, {path: null, baudRate: 100, rtscts: false, adapter: 'deconz'}, null, null); - expect(DeconzAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: 'deconz'}, null, null, undefined); + expect(DeconzAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: 'deconz'}, null, null); await Adapter.create(null, {path: null, baudRate: 100, rtscts: false, adapter: 'zigate'}, null, null); - expect(ZiGateAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: 'zigate'}, null, null, undefined); + expect(ZiGateAdapter).toHaveBeenCalledWith(null, {"baudRate": 100, "path": "/dev/test", "rtscts": false, adapter: 'zigate'}, null, null); }); it('Adapter create should throw on uknown adapter', async () => { @@ -3778,9 +3708,12 @@ describe('Controller', () => { mockZStackAdapterAutoDetectPath.mockReturnValueOnce('/dev/test'); mockDeconzAdapterIsValidPath.mockReturnValueOnce(false); mockDeconzAdapterAutoDetectPath.mockReturnValueOnce('/dev/test'); - let error; - try {await Adapter.create(null, {path: null, baudRate: 100, rtscts: false, adapter: 'efr'}, null, null)} catch (e) {error = e;} - expect(error).toStrictEqual(new Error(`Adapter 'efr' does not exists, possible options: zstack, deconz, zigate, ezsp, ember`)); + + try { + await Adapter.create(null, {path: null, baudRate: 100, rtscts: false, adapter: 'efr'}, null, null) + } catch (e) { + expect(e).toStrictEqual(new Error(`Adapter 'efr' does not exists, possible options: zstack, deconz, zigate, ezsp, ember`)); + } }); it('Emit read from device', async () => { diff --git a/test/utils.test.ts b/test/utils.test.ts index 49ec95bb05..188ea59773 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -1,5 +1,14 @@ import "regenerator-runtime/runtime"; import {IsNumberArray, Wait, Queue, Waitress, AssertString} from '../src/utils'; +import {logger, setLogger} from '../src/utils/logger'; + + +const mockLogger = { + debug: jest.fn(), + info: jest.fn(), + warning: jest.fn(), + error: jest.fn(), +}; describe('Utils', () => { it('IsNumberArray valid', () => { @@ -148,4 +157,30 @@ describe('Utils', () => { expect(finished).toEqual([4, 1, 2, 3]); expect(queue.count()).toBe(5); }); + + it('Logs', () => { + const debugSpy = jest.spyOn(console, "debug"); + const infoSpy = jest.spyOn(console, "info"); + const warningSpy = jest.spyOn(console, "warn"); + const errorSpy = jest.spyOn(console, "error"); + logger.debug('debug', 'zh'); + expect(debugSpy).toHaveBeenCalledWith('zh: debug'); + logger.info('info', 'zh'); + expect(infoSpy).toHaveBeenCalledWith('zh: info'); + logger.warning('warning', 'zh'); + expect(warningSpy).toHaveBeenCalledWith('zh: warning'); + logger.error('error', 'zh'); + expect(errorSpy).toHaveBeenCalledWith('zh: error'); + + setLogger(mockLogger); + expect(logger).toEqual(mockLogger); + logger.debug('debug', 'zh'); + expect(mockLogger.debug).toHaveBeenCalledWith('debug', 'zh'); + logger.info('info', 'zh'); + expect(mockLogger.info).toHaveBeenCalledWith('info', 'zh'); + logger.warning('warning', 'zh'); + expect(mockLogger.warning).toHaveBeenCalledWith('warning', 'zh'); + logger.error('error', 'zh'); + expect(mockLogger.error).toHaveBeenCalledWith('error', 'zh'); + }); }); \ No newline at end of file