iobroker.zigbee 2.0.4 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -56
- package/admin/admin.js +217 -19
- package/admin/img/philips_hue_lom001.png +0 -0
- package/admin/tab_m.html +13 -8
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/io-package.json +15 -49
- package/lib/DeviceDebug.js +4 -2
- package/lib/commands.js +21 -2
- package/lib/developer.js +0 -0
- package/lib/exposes.js +8 -3
- package/lib/groups.js +6 -8
- package/lib/localConfig.js +4 -5
- package/lib/ota.js +6 -6
- package/lib/statescontroller.js +276 -101
- package/lib/zbDeviceAvailability.js +2 -2
- package/lib/zbDeviceConfigure.js +92 -58
- package/lib/zigbeecontroller.js +44 -46
- package/main.js +143 -217
- package/package.json +5 -5
package/lib/zbDeviceConfigure.js
CHANGED
|
@@ -12,72 +12,75 @@ class DeviceConfigure extends BaseExtension {
|
|
|
12
12
|
this.delayedConfigure = {};
|
|
13
13
|
|
|
14
14
|
this.configuring = new Set();
|
|
15
|
-
this.
|
|
15
|
+
this.configureOnMessage = new Set();
|
|
16
|
+
this.configureOnMessageAttempts = {};
|
|
16
17
|
this.name = 'DeviceConfigure';
|
|
18
|
+
|
|
19
|
+
this.MessageStash = [];
|
|
20
|
+
this.deviceConfigureQueue = [];
|
|
21
|
+
this.configureIntervall = null;
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
setOptions(options) {
|
|
20
25
|
return typeof options === 'object';
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return
|
|
28
|
+
async handleConfigureQueue() {
|
|
29
|
+
if (this.deviceConfigureQueue.length < 1) {
|
|
30
|
+
this.info('Handled all devices Queued for configuration.')
|
|
31
|
+
clearInterval(this.configureIntervall);
|
|
32
|
+
this.configureIntervall == null;
|
|
33
|
+
return;
|
|
29
34
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return (device.interviewing !== true && this.checkDelayedConfigure(device.ieeeAddr)>0);
|
|
35
|
+
const configureItem = this.deviceConfigureQueue.shift();
|
|
36
|
+
this.info(`DeviceConfigureQueue configuring ${configureItem.dev.ieeeAddr} ${configureItem.dev.modelID}`)
|
|
37
|
+
this.doConfigure(configureItem.dev, configureItem.mapped);
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
PushDeviceToQueue(device, mappedDevice) {
|
|
41
|
+
const id = device.ieeeAddr;
|
|
42
|
+
for (const candidate of this.deviceConfigureQueue) {
|
|
43
|
+
if (candidate.id == id) {
|
|
44
|
+
this.debug('no duplicate entry in queue');
|
|
45
|
+
return;
|
|
43
46
|
}
|
|
44
|
-
return 0;
|
|
45
|
-
}
|
|
46
|
-
const dc = this.delayedConfigure[device.ieeeAddr];
|
|
47
|
-
dc.maxAttempts--;
|
|
48
|
-
if (dc.maxAttempts > 0) return dc.maxAttempts;
|
|
49
|
-
if (num && num > 0) {
|
|
50
|
-
dc.maxAttempts = num;
|
|
51
|
-
return num;
|
|
52
47
|
}
|
|
53
|
-
|
|
48
|
+
this.deviceConfigureQueue.push({ id: device.ieeeAddr, dev:device, mapped:mappedDevice });
|
|
49
|
+
if (this.configureIntervall) return;
|
|
50
|
+
this.configureIntervall = setInterval(async () => await this.handleConfigureQueue(), 5000);
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
return 0;
|
|
53
|
+
shouldConfigure(device, mappedDevice) {
|
|
54
|
+
if (!device || !mappedDevice) {
|
|
55
|
+
return false;
|
|
60
56
|
}
|
|
61
|
-
|
|
57
|
+
if (!mappedDevice || !mappedDevice.configure) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// no configuration if we are interviewing or configuring
|
|
61
|
+
if (this.configuring.has(device.ieeeAddr) || device.interviewing) return false;
|
|
62
|
+
const t = Date.now();
|
|
63
|
+
const cfgkey = zigbeeHerdsmanConverters.getConfigureKey(mappedDevice);
|
|
64
|
+
const result = device.meta.hasOwnProperty('configured') && device.meta.configured !== cfgkey;
|
|
65
|
+
this.debug(`should configure for device ${device.ieeeAddr} (${mappedDevice.model}: ${device.meta.hasOwnProperty('configured') ? device.meta.configured: 'none'} - ${cfgkey} (query took ${Date.now()- t} ms)`);
|
|
66
|
+
return result;
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
|
|
65
69
|
async onZigbeeStarted() {
|
|
66
70
|
try {
|
|
67
71
|
this.coordinatorEndpoint = await this.zigbee.getDevicesByType('Coordinator')[0].endpoints[0];
|
|
68
72
|
|
|
69
73
|
for (const device of await this.zigbee.getClients()) {
|
|
70
74
|
const mappedDevice = await zigbeeHerdsmanConverters.findByDevice(device);
|
|
71
|
-
|
|
72
75
|
if (forcedConfigureOnEachStart.find((d) => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
|
|
73
|
-
this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} forced by adapter config`);
|
|
76
|
+
this.debug(`DeviceConfigure ${device.ieeeAddr} ${mappedDevice ? mappedDevice.model : device.modelID} forced by adapter config`);
|
|
74
77
|
device.meta.configured = -1; // Force a reconfiguration for this device
|
|
75
78
|
}
|
|
76
79
|
if (this.shouldConfigure(device, mappedDevice)) {
|
|
77
|
-
this.
|
|
78
|
-
await this.
|
|
80
|
+
this.info(`DeviceConfigure ${device.ieeeAddr} ${mappedDevice ? mappedDevice.model : device.modelID} needed - Device added to Configuration Queue`);
|
|
81
|
+
await this.PushDeviceToQueue(device, mappedDevice);
|
|
79
82
|
} else {
|
|
80
|
-
this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} not needed`);
|
|
83
|
+
this.debug(`DeviceConfigure ${device.ieeeAddr} ${mappedDevice ? mappedDevice.model : device.modelID} not needed`);
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
} catch (error) {
|
|
@@ -89,8 +92,14 @@ class DeviceConfigure extends BaseExtension {
|
|
|
89
92
|
onZigbeeEvent(data, mappedDevice) {
|
|
90
93
|
try {
|
|
91
94
|
const device = data.device;
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
const com = this.configureOnMessageAttempts[device.ieeeAddr];
|
|
96
|
+
if (com) {
|
|
97
|
+
this.info(`checking configure on message : next attempt in ${30000 - (Date.now() - com.timestamp)} seconds`);
|
|
98
|
+
if (Date.now() - com.timestamp > 30000 && !this.configuring.has(device.ieeeAddr)) {
|
|
99
|
+
com.timestamp = Date.now();
|
|
100
|
+
this.info('Configure on Message for ' + device.ieeeAddr);
|
|
101
|
+
this.doConfigure(device, mappedDevice);
|
|
102
|
+
}
|
|
94
103
|
}
|
|
95
104
|
} catch (error) {
|
|
96
105
|
this.sendError(error);
|
|
@@ -98,14 +107,15 @@ class DeviceConfigure extends BaseExtension {
|
|
|
98
107
|
}
|
|
99
108
|
}
|
|
100
109
|
|
|
110
|
+
|
|
101
111
|
onDeviceRemove(device) {
|
|
102
112
|
try {
|
|
103
113
|
if (this.configuring.has(device.ieeeAddr)) {
|
|
104
114
|
this.configuring.delete(device.ieeeAddr);
|
|
105
115
|
}
|
|
106
116
|
|
|
107
|
-
if (this.
|
|
108
|
-
delete this.
|
|
117
|
+
if (this.configureOnMessageAttempts && this.configureOnMessageAttempts.hasOwnProperty(device.ieeeAddr)) {
|
|
118
|
+
delete this.configureOnMessageAttempts[device.ieeeAddr];
|
|
109
119
|
}
|
|
110
120
|
} catch (error) {
|
|
111
121
|
this.sendError(error);
|
|
@@ -124,16 +134,17 @@ class DeviceConfigure extends BaseExtension {
|
|
|
124
134
|
async configure(device, mappedDevice) {
|
|
125
135
|
try {
|
|
126
136
|
if (mappedDevice !== undefined && device !== undefined) {
|
|
137
|
+
|
|
127
138
|
try {
|
|
128
139
|
await this.doConfigure(device, mappedDevice)
|
|
129
140
|
} catch (error) {
|
|
130
141
|
this.sendError(error);
|
|
131
|
-
this.warn(`DeviceConfigure failed ${device.ieeeAddr} ${
|
|
142
|
+
this.warn(`DeviceConfigure failed ${device.ieeeAddr} ${mappedDevice.model}`);
|
|
132
143
|
}
|
|
133
144
|
}
|
|
134
145
|
} catch (error) {
|
|
135
146
|
this.sendError(error);
|
|
136
|
-
this.error(`Failed to DeviceConfigure.configure ${device.ieeeAddr} ${
|
|
147
|
+
this.error(`Failed to DeviceConfigure.configure ${device.ieeeAddr} ${mappedDevice.model}: ${error && error.message ? error.message : 'no error message'})`);
|
|
137
148
|
}
|
|
138
149
|
}
|
|
139
150
|
|
|
@@ -141,33 +152,51 @@ class DeviceConfigure extends BaseExtension {
|
|
|
141
152
|
const coordinatorEndpoint = await this.zigbee.getDevicesByType('Coordinator')[0].endpoints[0];
|
|
142
153
|
try {
|
|
143
154
|
if (mappedDevice) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
155
|
+
if (mappedDevice.configure === undefined) return `No configure available for ${device.ieeeAddr} ${mappedDevice.model}.`;
|
|
156
|
+
this.info(`Configuring ${device.ieeeAddr} ${mappedDevice.model}`);
|
|
157
|
+
this.configuring.add(device.ieeeAddr);
|
|
158
|
+
if (typeof mappedDevice.configure === 'function') await mappedDevice.configure(device, coordinatorEndpoint, this);
|
|
159
|
+
else {
|
|
160
|
+
const promises = [];
|
|
161
|
+
promises.push(...mappedDevice.configure);
|
|
162
|
+
await Promise.all(promises.map(callback => callback(device, coordinatorEndpoint, mappedDevice)))
|
|
163
|
+
}
|
|
151
164
|
device.meta.configured = zigbeeHerdsmanConverters.getConfigureKey(mappedDevice);
|
|
165
|
+
this.configuring.delete(device.ieeeAddr);
|
|
166
|
+
delete this.configureOnMessageAttempts[device.ieeeAddr];
|
|
152
167
|
device.save();
|
|
153
|
-
this.info(`DeviceConfigure successful ${device.ieeeAddr} ${
|
|
154
|
-
this.delayedConfigureAttempt(device, true);
|
|
168
|
+
this.info(`DeviceConfigure successful ${device.ieeeAddr} ${mappedDevice.model}`);
|
|
155
169
|
return '';
|
|
156
170
|
}
|
|
157
171
|
} catch (error) {
|
|
172
|
+
this.configuring.delete(device.ieeeAddr);
|
|
158
173
|
// https://github.com/Koenkk/zigbee2mqtt/issues/14857
|
|
159
174
|
if (error.stack.includes('UNSUPPORTED_ATTRIBUTE')) {
|
|
175
|
+
this.debug(`Configuration attempt on ${device.ieeeAddr} ${mappedDevice.model} with unsupported Attribute(s) : ${error.message}`)
|
|
160
176
|
// do nothing
|
|
161
177
|
} else {
|
|
162
178
|
if (error && error.message && error.message.match(/(\d+)ms/gm)) {
|
|
163
179
|
// timeout message - we do want to start the configure chain
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
180
|
+
if (this.configureOnMessageAttempts.hasOwnProperty(device.ieeeAddr)) {
|
|
181
|
+
const com = this.configureOnMessageAttempts[device.ieeeAddr];
|
|
182
|
+
com.count--;
|
|
183
|
+
com.timestamp = Date.now();
|
|
184
|
+
this.info(`Timeout trying to configure ${device.ieeeAddr} ${mappedDevice.model} (${com.count}).`)
|
|
185
|
+
if ( com.count < 0) delete this.configureOnMessage[device.ieeeAddr];
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
this.info(`Timeout trying to configure ${device.ieeeAddr} ${mappedDevice.model} (starting CoM).`)
|
|
189
|
+
this.configureOnMessageAttempts[device.ieeeAddr] = {
|
|
190
|
+
count: 5,
|
|
191
|
+
timestamp: 0,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return `Configuration timed out ${device.ieeeAddr} ${device.modelID}. The device did not repond in time to the configuration request. Another attempt will be made when the device is awake.`;
|
|
167
195
|
} else {
|
|
168
196
|
this.sendError(error);
|
|
169
|
-
|
|
170
|
-
|
|
197
|
+
const msg = `${device.ieeeAddr} ${device.modelID} Failed to configure. --> ${error && error.message ? error.message : ' no error message given'}`
|
|
198
|
+
this.warn(msg);
|
|
199
|
+
return msg;
|
|
171
200
|
}
|
|
172
201
|
|
|
173
202
|
|
|
@@ -175,6 +204,11 @@ class DeviceConfigure extends BaseExtension {
|
|
|
175
204
|
}
|
|
176
205
|
return 'no return value specified';
|
|
177
206
|
}
|
|
207
|
+
|
|
208
|
+
async stop() {
|
|
209
|
+
clearInterval(this.configureIntervall);
|
|
210
|
+
this.configureOnMessageAttempts = {};
|
|
211
|
+
}
|
|
178
212
|
}
|
|
179
213
|
|
|
180
214
|
module.exports = DeviceConfigure;
|
package/lib/zigbeecontroller.js
CHANGED
|
@@ -65,6 +65,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
65
65
|
super();
|
|
66
66
|
this.adapter = adapter;
|
|
67
67
|
this._permitJoinTime = 0;
|
|
68
|
+
this.transmitPower = 0;
|
|
68
69
|
this.herdsmanStarted = false;
|
|
69
70
|
this.extensions = [
|
|
70
71
|
new DeviceAvailabilityExt(this, {}),
|
|
@@ -74,19 +75,41 @@ class ZigbeeController extends EventEmitter {
|
|
|
74
75
|
];
|
|
75
76
|
this.herdsmanTimeoutRegexp = new RegExp(/(\d+)ms/);
|
|
76
77
|
this.herdsmanLogSettings = {}
|
|
78
|
+
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
|
|
80
82
|
ByteArrayToString(data) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
if (data) {
|
|
84
|
+
return data.map(function (x) {
|
|
85
|
+
x = x + 0x100 + 1; // twos complement
|
|
86
|
+
x = x.toString(16); // to hex
|
|
87
|
+
x = ('00'+x).substr(-2); // zero-pad to 8-digits
|
|
88
|
+
return x
|
|
89
|
+
}).join('');
|
|
90
|
+
}
|
|
91
|
+
else return '';
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
configure(options) {
|
|
95
|
+
|
|
96
|
+
if (options.transmitPower != undefined) {
|
|
97
|
+
this.transmitPower = options.transmitPower;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.powerText = '';
|
|
101
|
+
if (this.transmitPower !== '0') {
|
|
102
|
+
const powerLevels = {
|
|
103
|
+
'-22': 'low',
|
|
104
|
+
'19': 'high',
|
|
105
|
+
'20': 'high+'
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
this.powerText = powerLevels[this.transmitPower] || 'normal';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.info(` --> transmitPower : ${this.powerText}`);
|
|
112
|
+
|
|
90
113
|
const herdsmanSettings = {
|
|
91
114
|
network: {
|
|
92
115
|
panID: options.net.panId,
|
|
@@ -102,6 +125,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
102
125
|
path: options.sp.port,
|
|
103
126
|
adapter: options.sp.adapter,
|
|
104
127
|
},
|
|
128
|
+
transmitpower: this.transmitPower,
|
|
105
129
|
adapter: {
|
|
106
130
|
forceStartWithInconsistentAdapterConfiguration: options.startWithInconsistent
|
|
107
131
|
},
|
|
@@ -114,11 +138,6 @@ class ZigbeeController extends EventEmitter {
|
|
|
114
138
|
herdsmanSettings.network.extenedPanID = options.net.extPanId;
|
|
115
139
|
}
|
|
116
140
|
|
|
117
|
-
if (options.transmitPower == undefined) {
|
|
118
|
-
this.transmitPower = 0;
|
|
119
|
-
} else {
|
|
120
|
-
this.transmitPower = options.transmitPower;
|
|
121
|
-
}
|
|
122
141
|
this.disableLed = options.disableLed;
|
|
123
142
|
this.warnOnDeviceAnnouncement = options.warnOnDeviceAnnouncement;
|
|
124
143
|
this.herdsmanLogSettings.panID = herdsmanSettings.network.panID;
|
|
@@ -179,7 +198,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
179
198
|
this.warn(`Network parameters on Coordinator: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`);
|
|
180
199
|
}
|
|
181
200
|
catch (error) {
|
|
182
|
-
this.
|
|
201
|
+
this.info(`Unable to obtain herdsman settings`)
|
|
183
202
|
}
|
|
184
203
|
try {
|
|
185
204
|
await this.herdsman.stop();
|
|
@@ -204,35 +223,6 @@ class ZigbeeController extends EventEmitter {
|
|
|
204
223
|
this.sendError(e);
|
|
205
224
|
}
|
|
206
225
|
|
|
207
|
-
// only for CC1352P and CC26X2R1 transmit power
|
|
208
|
-
let powerText = 'normal';
|
|
209
|
-
|
|
210
|
-
if (this.transmitPower != '0') {
|
|
211
|
-
switch (this.transmitPower) {
|
|
212
|
-
case '-22':
|
|
213
|
-
powerText = 'low';
|
|
214
|
-
break;
|
|
215
|
-
case '19':
|
|
216
|
-
powerText = 'high';
|
|
217
|
-
break;
|
|
218
|
-
case '20':
|
|
219
|
-
powerText = 'high+';
|
|
220
|
-
break;
|
|
221
|
-
default:
|
|
222
|
-
powerText = 'normal';
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.info(` --> transmitPower : ${powerText}`);
|
|
228
|
-
try {
|
|
229
|
-
await this.herdsman.setTransmitPower(this.transmitPower);
|
|
230
|
-
} catch (e) {
|
|
231
|
-
this.sendError(e);
|
|
232
|
-
this.info('Unable to set transmit power, unsupported function.');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Call extensions
|
|
236
226
|
|
|
237
227
|
const deviceIterator = this.getClientIterator();
|
|
238
228
|
let deviceCount = 0;
|
|
@@ -575,6 +565,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
575
565
|
if (_key.kind === 'ieee') _key.key = await this.herdsman.getDeviceByIeeeAddr(_key.key);
|
|
576
566
|
const device = _key.key;
|
|
577
567
|
if (device) {
|
|
568
|
+
const t = Date.now();
|
|
578
569
|
const mapped = await zigbeeHerdsmanConverters.findByDevice(device);
|
|
579
570
|
const endpoints = mapped && mapped.endpoint ? mapped.endpoint(device) : null;
|
|
580
571
|
let endpoint;
|
|
@@ -747,7 +738,11 @@ class ZigbeeController extends EventEmitter {
|
|
|
747
738
|
this.debug('handleDeviceLeave', message);
|
|
748
739
|
const entity = await this.resolveEntity(message.device || message.ieeeAddr);
|
|
749
740
|
const friendlyName = entity ? entity.name : message.ieeeAddr;
|
|
750
|
-
this.
|
|
741
|
+
if (this.adapter.stController.checkDebugDevice(friendlyName)) {
|
|
742
|
+
this.emit('device_debug', {ID: Date.now(), data: {flag:'dl', states:[{id: '--', value:'--', payload:message}], IO:true},message:`Device '${friendlyName}' has left the network`});
|
|
743
|
+
}
|
|
744
|
+
else
|
|
745
|
+
this.info(`Device '${friendlyName}' left the network`);
|
|
751
746
|
this.emit('leave', message.ieeeAddr);
|
|
752
747
|
// Call extensions
|
|
753
748
|
this.callExtensionMethod(
|
|
@@ -764,7 +759,10 @@ class ZigbeeController extends EventEmitter {
|
|
|
764
759
|
this.debug('handleDeviceAnnounce', message);
|
|
765
760
|
const entity = await this.resolveEntity(message.device || message.ieeeAddr);
|
|
766
761
|
const friendlyName = entity.name;
|
|
767
|
-
if (this.
|
|
762
|
+
if (this.adapter.stController.checkDebugDevice(friendlyName)) {
|
|
763
|
+
this.emit('device_debug', {ID: Date.now(), data: {flag:'da', states:[{id: '--', value:'--', payload:message}] , IO:true} ,message:`Device '${friendlyName}' announced itself`});
|
|
764
|
+
}
|
|
765
|
+
else if (this.warnOnDeviceAnnouncement) {
|
|
768
766
|
this.warn(`Device '${friendlyName}' announced itself`);
|
|
769
767
|
} else {
|
|
770
768
|
this.info(`Device '${friendlyName}' announced itself`);
|
|
@@ -883,7 +881,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
883
881
|
let resolved = await this.resolveEntity(device, 0);
|
|
884
882
|
if (!resolved) {
|
|
885
883
|
resolved = { name:'unresolved device', device:device }
|
|
886
|
-
this.
|
|
884
|
+
this.debug('resolve Entity failed for ' + device.ieeeAddr)
|
|
887
885
|
}
|
|
888
886
|
let result;
|
|
889
887
|
|
|
@@ -943,9 +941,9 @@ class ZigbeeController extends EventEmitter {
|
|
|
943
941
|
|
|
944
942
|
callback && callback({lqis, routing, errors});
|
|
945
943
|
if (errors.length) {
|
|
946
|
-
this.
|
|
944
|
+
this.debug(`Map Data collection complete with ${errors.length} issues:`);
|
|
947
945
|
for (const msg of errors)
|
|
948
|
-
this.
|
|
946
|
+
this.debug(msg);
|
|
949
947
|
}
|
|
950
948
|
else
|
|
951
949
|
this.info('Map data collection complete');
|