iobroker.zigbee 1.8.3 → 1.8.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.
Files changed (87) hide show
  1. package/README.md +3 -0
  2. package/admin/admin.js +512 -493
  3. package/admin/index_m.html +1171 -1001
  4. package/admin/tab_m.html +44 -3
  5. package/docs/de/img/CC2531.png +0 -0
  6. package/docs/de/img/CC2538_CC2592_PA.PNG +0 -0
  7. package/docs/de/img/CC2591.png +0 -0
  8. package/docs/de/img/boards.jpg +0 -0
  9. package/docs/de/img/cc26x2r.PNG +0 -0
  10. package/docs/de/img/results.jpg +0 -0
  11. package/docs/de/img/sku_429478_2.png +0 -0
  12. package/docs/de/img/sku_429601_2.png +0 -0
  13. package/docs/de/readme.md +27 -0
  14. package/docs/en/img/CC2531.png +0 -0
  15. package/docs/en/img/CC2591.png +0 -0
  16. package/docs/en/img/deconz.png +0 -0
  17. package/docs/en/img/sku_429478_2.png +0 -0
  18. package/docs/en/img/sku_429601_2.png +0 -0
  19. package/docs/en/readme.md +30 -0
  20. package/docs/flashing_via_arduino_(en).md +110 -0
  21. package/docs/ru/img/CC2531.png +0 -0
  22. package/docs/ru/img/CC2591.png +0 -0
  23. package/docs/ru/img/sku_429478_2.png +0 -0
  24. package/docs/ru/img/sku_429601_2.png +0 -0
  25. package/docs/ru/readme.md +28 -0
  26. package/docs/tutorial/CC2530_20190425.zip +0 -0
  27. package/docs/tutorial/CC2530_CC2591_20190515.zip +0 -0
  28. package/docs/tutorial/CC2530_CC2592_20190515.zip +0 -0
  29. package/docs/tutorial/CC2531_20190425.zip +0 -0
  30. package/docs/tutorial/adm5_1.PNG +0 -0
  31. package/docs/tutorial/adm5_2.PNG +0 -0
  32. package/docs/tutorial/cat.PNG +0 -0
  33. package/docs/tutorial/groups-1.png +0 -0
  34. package/docs/tutorial/groups-2.png +0 -0
  35. package/docs/tutorial/inst.PNG +0 -0
  36. package/docs/tutorial/reflash-finish.PNG +0 -0
  37. package/docs/tutorial/reflash-step0.png +0 -0
  38. package/docs/tutorial/reflash-step1.PNG +0 -0
  39. package/docs/tutorial/reflash-step2.PNG +0 -0
  40. package/docs/tutorial/settings.png +0 -0
  41. package/docs/tutorial/tab-dev-1.png +0 -0
  42. package/docs/tutorial/zigbee.png +0 -0
  43. package/docs/tutorial/zigbee15.png +0 -0
  44. package/io-package.json +17 -25
  45. package/lib/backup.js +2 -2
  46. package/lib/binding.js +32 -37
  47. package/lib/colors.js +163 -158
  48. package/lib/commands.js +100 -91
  49. package/lib/developer.js +9 -12
  50. package/lib/devices.js +168 -178
  51. package/lib/exclude.js +30 -36
  52. package/lib/exposes.js +163 -139
  53. package/lib/groups.js +81 -83
  54. package/lib/json.js +5 -6
  55. package/lib/networkmap.js +2 -3
  56. package/lib/ota.js +34 -18
  57. package/lib/rgb.js +114 -72
  58. package/lib/seriallist.js +25 -20
  59. package/lib/states.js +511 -526
  60. package/lib/statescontroller.js +206 -183
  61. package/lib/utils.js +24 -23
  62. package/lib/zbBaseExtension.js +4 -4
  63. package/lib/zbDelayedAction.js +5 -13
  64. package/lib/zbDeviceAvailability.js +69 -65
  65. package/lib/zbDeviceConfigure.js +9 -21
  66. package/lib/zbDeviceEvent.js +3 -4
  67. package/lib/zigbeecontroller.js +133 -128
  68. package/main.js +169 -154
  69. package/package.json +27 -13
  70. package/.eslintignore +0 -2
  71. package/.eslintrc.json +0 -37
  72. package/.github/FUNDING.yml +0 -3
  73. package/.github/auto-merge.yml +0 -17
  74. package/.github/dependabot.yml +0 -24
  75. package/.github/stale.yml +0 -13
  76. package/.github/workflows/codeql.yml +0 -41
  77. package/.github/workflows/dependabot-automerge.yml +0 -22
  78. package/.github/workflows/test-and-release.yml +0 -149
  79. package/.releaseconfig.json +0 -3
  80. package/.travis/wiki.sh +0 -28
  81. package/.travis.yml +0 -41
  82. package/gulpfile.js +0 -464
  83. package/test/integration.js +0 -5
  84. package/test/mocha.custom.opts +0 -2
  85. package/test/mocha.setup.js +0 -14
  86. package/test/package.js +0 -5
  87. package/test/unit.js +0 -5
package/main.js CHANGED
@@ -40,21 +40,20 @@ const createByteArray = function (hexString) {
40
40
  return bytes;
41
41
  };
42
42
 
43
- const E_INFO=1;
44
- const E_DEBUG=2;
45
- const E_WARN=3;
46
- const E_ERROR=4;
43
+ const E_INFO = 1;
44
+ const E_DEBUG = 2;
45
+ const E_WARN = 3;
46
+ const E_ERROR = 4;
47
47
 
48
48
  let _pairingMode = false;
49
49
 
50
50
  const errorCodes = {
51
- 9999: { severity:E_INFO, message:'No response'},
52
- 233: { severity:E_DEBUG, message:'MAC NO ACK'},
53
- 205: { severity:E_WARN, message:'No network route'},
54
- 134: { severity:E_WARN, message:'Unnsupported Attribute'},
51
+ 9999: {severity: E_INFO, message: 'No response'},
52
+ 233: {severity: E_DEBUG, message: 'MAC NO ACK'},
53
+ 205: {severity: E_WARN, message: 'No network route'},
54
+ 134: {severity: E_WARN, message: 'Unsupported Attribute'},
55
55
  };
56
56
 
57
-
58
57
  class Zigbee extends utils.Adapter {
59
58
  /**
60
59
  * @param {Partial<ioBroker.AdapterOptions>} [options={}]
@@ -65,9 +64,9 @@ class Zigbee extends utils.Adapter {
65
64
  name: 'zigbee',
66
65
  systemConfig: true,
67
66
  }));
68
- this.on('ready', this.onReady.bind(this));
69
- this.on('unload', this.onUnload.bind(this));
70
- this.on('message', this.onMessage.bind(this));
67
+ this.on('ready', () => this.onReady());
68
+ this.on('unload', callback => this.onUnload(callback));
69
+ this.on('message', obj => this.onMessage(obj));
71
70
 
72
71
  this.query_device_block = [];
73
72
 
@@ -93,14 +92,15 @@ class Zigbee extends utils.Adapter {
93
92
  case 'SendToDevice': {
94
93
  let rv = {
95
94
  success: false,
96
- loc:-1,
95
+ loc: -1,
97
96
  };
97
+
98
98
  try {
99
- rv = await this.SendPayload(obj.message);
100
- }
101
- catch (e) {
99
+ rv = await this.sendPayload(obj.message);
100
+ } catch (e) {
102
101
  rv.error = e;
103
102
  }
103
+
104
104
  this.sendTo(obj.from, obj.command, rv, obj.callback);
105
105
  break;
106
106
  }
@@ -115,15 +115,15 @@ class Zigbee extends utils.Adapter {
115
115
  const Sentry = sentryInstance.getSentryObject();
116
116
  if (Sentry) {
117
117
  if (message) {
118
- Sentry.configureScope(scope => {
118
+ Sentry.configureScope(scope =>
119
119
  scope.addBreadcrumb({
120
- type: "error", // predefined types
121
- category: "error message",
120
+ type: 'error', // predefined types
121
+ category: 'error message',
122
122
  level: Sentry.Severity.Error,
123
- message: message
124
- });
125
- });
123
+ message
124
+ }));
126
125
  }
126
+
127
127
  if (typeof error == 'string') {
128
128
  Sentry.captureException(new Error(error));
129
129
  } else {
@@ -135,27 +135,31 @@ class Zigbee extends utils.Adapter {
135
135
  }
136
136
 
137
137
  filterError(errormessage, message, error) {
138
- if (error.code === undefined)
139
- {
140
- let em = error.stack.match(/failed \((.+?)\) at/);
141
- if (!em) em = error.stack.match(/failed \((.+?)\)/);
142
- this.log.error(`${message} no error code (${(em ? em[1]:'undefined')})`);
138
+ if (error.code === undefined) {
139
+ let em = error.stack.match(/failed \((.+?)\) at/);
140
+ em = em || error.stack.match(/failed \((.+?)\)/);
141
+ this.log.error(`${message} no error code (${(em ? em[1] : 'undefined')})`);
143
142
  this.sendError(error, `${message} no error code`);
144
143
  this.log.debug(`Stack trace for ${em}: ${error.stack}`);
145
144
  return;
146
145
  }
146
+
147
147
  const ecode = errorCodes[error.code];
148
148
  if (ecode === undefined) {
149
149
  this.log.error(errormessage);
150
150
  this.sendError(error, errormessage);
151
151
  return;
152
152
  }
153
+
153
154
  switch (ecode.severity) {
154
- case E_INFO: this.log.info(`${message}: Code ${error.code} (${ecode.message})`);
155
+ case E_INFO:
156
+ this.log.info(`${message}: Code ${error.code} (${ecode.message})`);
155
157
  break;
156
- case E_DEBUG: this.log.debug(`${message}: Code ${error.code} (${ecode.message})`);
158
+ case E_DEBUG:
159
+ this.log.debug(`${message}: Code ${error.code} (${ecode.message})`);
157
160
  break;
158
- case E_WARN: this.log.warn(`${message}: Code ${error.code} (${ecode.message})`);
161
+ case E_WARN:
162
+ this.log.warn(`${message}: Code ${error.code} (${ecode.message})`);
159
163
  break;
160
164
  case E_ERROR:
161
165
  this.log.error(`${message}: Code ${error.code} (${ecode.message})`);
@@ -164,10 +168,11 @@ class Zigbee extends utils.Adapter {
164
168
  default:
165
169
  this.log.error(`${message}: Code ${error.code} (malformed error)`);
166
170
  this.sendError(error, `${message}: Code ${error.code} (malformed error)`);
171
+ break;
167
172
  }
168
173
  }
169
174
 
170
- debugLog (data, ...args) {
175
+ debugLog(data, ...args) {
171
176
  const message = (args) ? util.format(data, ...args) : data;
172
177
  this.log.debug(message.slice(message.indexOf('zigbee-herdsman')));
173
178
  }
@@ -181,9 +186,8 @@ class Zigbee extends utils.Adapter {
181
186
  // external converters
182
187
  this.applyExternalConverters();
183
188
  // get exclude list from object
184
- this.getState('exclude.all', (err, state) => {
185
- this.stController.getExcludeExposes(state);
186
- });
189
+ this.getState('exclude.all', (err, state) =>
190
+ this.stController.getExcludeExposes(state));
187
191
 
188
192
  this.subscribeStates('*');
189
193
  // set connection false before connect to zigbee
@@ -212,7 +216,9 @@ class Zigbee extends utils.Adapter {
212
216
  }
213
217
  const extfiles = this.config.external.split(';');
214
218
  for (const moduleName of extfiles) {
215
- if (!moduleName) continue;
219
+ if (!moduleName) {
220
+ continue;
221
+ }
216
222
  this.log.info(`Apply converter from module: ${moduleName}`);
217
223
  const sandbox = {
218
224
  require,
@@ -231,7 +237,7 @@ class Zigbee extends utils.Adapter {
231
237
  }
232
238
  }
233
239
 
234
- applyExternalConverters(){
240
+ applyExternalConverters() {
235
241
  for (const definition of this.getExternalDefinition()) {
236
242
  const toAdd = {...definition};
237
243
  delete toAdd['homeassistant'];
@@ -244,24 +250,23 @@ class Zigbee extends utils.Adapter {
244
250
  try {
245
251
  const DebugIdentify = require('./debugidentify');
246
252
  debugversion = DebugIdentify.ReportIdentifier();
247
- }
248
- catch {
253
+ } catch {
249
254
  debugversion = ' npm ...';
250
255
  }
251
256
 
252
257
  // installed version
253
258
  let gitVers = '';
254
259
  try {
255
- this.log.info('Starting Zigbee ' + debugversion);
260
+ this.log.info(`Starting Zigbee ${debugversion}`);
256
261
 
257
- await this.getForeignObject('system.adapter.' + this.namespace, (err, obj) => {
262
+ await this.getForeignObject(`system.adapter.${this.namespace}`, (err, obj) => {
258
263
  if (!err && obj && obj.common.installedFrom && obj.common.installedFrom.includes('://')) {
259
264
  const instFrom = obj.common.installedFrom;
260
- gitVers = gitVers + instFrom.replace('tarball','commit');
265
+ gitVers = gitVers + instFrom.replace('tarball', 'commit');
261
266
  } else {
262
267
  gitVers = obj.common.installedFrom;
263
268
  }
264
- this.log.info('Installed Version: ' + gitVers );
269
+ this.log.info(`Installed Version: ${gitVers}`);
265
270
  });
266
271
 
267
272
  await this.zbController.start();
@@ -274,6 +279,7 @@ class Zigbee extends utils.Adapter {
274
279
  this.log.error(error);
275
280
  }
276
281
  this.sendError(error, `Failed to start Zigbee`);
282
+
277
283
  if (this.reconnectCounter > 0) {
278
284
  this.tryToReconnect();
279
285
  }
@@ -290,11 +296,11 @@ class Zigbee extends utils.Adapter {
290
296
  }
291
297
 
292
298
  tryToReconnect() {
293
- this.reconnectTimer = setTimeout(()=>{
294
- if (this.config.port.indexOf('tcp://') !== -1) {
295
- // Controller connect though WiFi.
296
- // Unlikely USB dongle, connection broken may only caused user unpluged the dongle,
297
- // WiFi connected gateway is possible that device connection is broken caused by
299
+ this.reconnectTimer = setTimeout(() => {
300
+ if (this.config.port.includes('tcp://')) {
301
+ // Controller connect though Wi-Fi.
302
+ // Unlikely USB dongle, connection broken may only cause user unplugged the dongle,
303
+ // Wi-Fi connected gateway is possible that device connection is broken caused by
298
304
  // AP issue or Zigbee gateway power is turned off unexpectedly.
299
305
  // So try to reconnect gateway every 10 seconds all the time.
300
306
  this.log.info(`Try to reconnect.`);
@@ -303,22 +309,22 @@ class Zigbee extends utils.Adapter {
303
309
  this.reconnectCounter -= 1;
304
310
  }
305
311
  this.doConnect();
306
- }, 10*1000); // every 10 seconds
312
+ }, 10 * 1000); // every 10 seconds
307
313
  }
308
314
 
309
315
  async onZigbeeAdapterReady() {
310
- if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
316
+ this.reconnectTimer && clearTimeout(this.reconnectTimer);
311
317
  this.log.info(`Zigbee started`);
312
318
  // https://github.com/ioBroker/ioBroker.zigbee/issues/668
313
319
  const extPanIdFix = this.config.extPanIdFix ? this.config.extPanIdFix : false;
314
320
  if (!extPanIdFix) {
315
- const configExtPanId = this.config.extPanID ? '0x'+this.config.extPanID.toLowerCase() : '0xdddddddddddddddd';
321
+ const configExtPanId = this.config.extPanID ? `0x${this.config.extPanID.toLowerCase()}` : '0xdddddddddddddddd';
316
322
  let networkExtPanId = (await this.zbController.herdsman.getNetworkParameters()).extendedPanID;
317
323
  let needChange = false;
318
324
  this.log.debug(`Config value ${configExtPanId} : Network value ${networkExtPanId}`);
319
325
  const adapterType = this.config.adapterType || 'zstack';
320
326
  if (adapterType === 'zstack') {
321
- if (configExtPanId != networkExtPanId) {
327
+ if (configExtPanId !== networkExtPanId) {
322
328
  try {
323
329
  // try to read from nvram
324
330
  const result = await this.zbController.herdsman.adapter.znp.request(
@@ -334,9 +340,9 @@ class Zigbee extends utils.Adapter {
334
340
  2, // ZnpCommandStatus.INVALID_PARAM
335
341
  ]
336
342
  );
337
- const nwExtPanId = '0x'+result.payload.value.reverse().toString('hex');
343
+ const nwExtPanId = `0x${result.payload.value.reverse().toString('hex')}`;
338
344
  this.log.debug(`Config value ${configExtPanId} : nw value ${nwExtPanId}`);
339
- if (configExtPanId != nwExtPanId) {
345
+ if (configExtPanId !== nwExtPanId) {
340
346
  networkExtPanId = nwExtPanId;
341
347
  needChange = true;
342
348
  }
@@ -366,37 +372,36 @@ class Zigbee extends utils.Adapter {
366
372
  for (const device of devicesFromDB) {
367
373
  const entity = await this.zbController.resolveEntity(device);
368
374
  if (entity) {
369
- const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID;
370
- this.stController.updateDev(device.ieeeAddr.substr(2), model, model, () => {
371
- this.stController.syncDevStates(device, model);
372
- });
375
+ const model = entity.mapped ? entity.mapped.model : entity.device.modelID;
376
+ this.stController.updateDev(device.ieeeAddr.substr(2), model, model, () =>
377
+ this.stController.syncDevStates(device, model));
373
378
  }
374
379
  }
375
380
  await this.callPluginMethod('start', [this.zbController, this.stController]);
376
381
  }
377
382
 
378
383
  async checkIfModelUpdate(entity) {
379
- const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID,
384
+ const model = entity.mapped ? entity.mapped.model : entity.device.modelID,
380
385
  device = entity.device,
381
386
  devId = device.ieeeAddr.substr(2);
387
+
382
388
  return new Promise((resolve) => {
383
389
  this.getObject(devId, (err, obj) => {
384
- if (obj && obj.common.type != model) {
390
+ if (obj && obj.common.type !== model) {
385
391
  // let's change model
386
392
  this.getStatesOf(devId, (err, states) => {
387
393
  if (!err && states) {
388
394
  const chain = [];
389
- states.forEach((state) => {
390
- chain.push(this.deleteStateAsync(devId, null, state._id));
391
- });
392
- Promise.all(chain).then(()=>{
393
- this.stController.deleteDeviceStates(devId, () => {
394
- this.stController.updateDev(devId, model, model, async () => {
395
- await this.stController.syncDevStates(device, model);
396
- resolve();
397
- });
398
- });
399
- });
395
+ states.forEach((state) =>
396
+ chain.push(this.deleteStateAsync(devId, null, state._id)));
397
+
398
+ Promise.all(chain)
399
+ .then(() =>
400
+ this.stController.deleteDeviceStates(devId, () =>
401
+ this.stController.updateDev(devId, model, model, async () => {
402
+ await this.stController.syncDevStates(device, model);
403
+ resolve();
404
+ })));
400
405
  } else {
401
406
  resolve();
402
407
  }
@@ -408,17 +413,16 @@ class Zigbee extends utils.Adapter {
408
413
  });
409
414
  }
410
415
 
411
-
412
-
413
- async onZigbeeEvent(type, entity, message){
416
+ async onZigbeeEvent(type, entity, message) {
414
417
  this.log.debug(`Type ${type} device ${safeJsonStringify(entity)} incoming event: ${safeJsonStringify(message)}`);
415
- const device = entity.device,
416
- mappedModel = entity.mapped,
417
- model = (entity.mapped) ? entity.mapped.model : entity.device.modelID,
418
- cluster = message.cluster,
419
- devId = device.ieeeAddr.substr(2),
420
- meta = {device: device};
421
- //this assigment give possibility to use iobroker logger in code of the converters, via meta.logger
418
+ const device = entity.device;
419
+ const mappedModel = entity.mapped;
420
+ const model = entity.mapped ? entity.mapped.model : entity.device.modelID;
421
+ const cluster = message.cluster;
422
+ const devId = device.ieeeAddr.substr(2);
423
+ const meta = {device};
424
+
425
+ // this assigment give possibility to use iobroker logger in code of the converters, via meta.logger
422
426
  meta.logger = this.log;
423
427
 
424
428
  await this.checkIfModelUpdate(entity);
@@ -439,12 +443,14 @@ class Zigbee extends utils.Adapter {
439
443
  }
440
444
  let converters = mappedModel.fromZigbee.filter(c => c && c.cluster === cluster && (
441
445
  (c.type instanceof Array) ? c.type.includes(type) : c.type === type));
446
+
442
447
  if (!converters.length && type === 'readResponse') {
443
448
  converters = mappedModel.fromZigbee.filter(c => c.cluster === cluster && (
444
449
  (c.type instanceof Array) ? c.type.includes('attributeReport') : c.type === 'attributeReport'));
445
450
  }
451
+
446
452
  if (!converters.length) {
447
- if (type != 'readResponse') {
453
+ if (type !== 'readResponse') {
448
454
  this.log.debug(
449
455
  `No converter available for '${mappedModel.model}' with cluster '${cluster}' and type '${type}'`
450
456
  );
@@ -476,10 +482,10 @@ class Zigbee extends utils.Adapter {
476
482
 
477
483
  acknowledgeState(deviceId, model, stateDesc, value) {
478
484
  if (model === 'group') {
479
- const stateId = this.namespace + '.group_' + deviceId + '.' + stateDesc.id;
485
+ const stateId = `${this.namespace}.group_${deviceId}.${stateDesc.id}`;
480
486
  this.setState(stateId, value, true);
481
487
  } else {
482
- const stateId = this.namespace + '.' + deviceId.replace('0x', '') + '.' + stateDesc.id;
488
+ const stateId = `${this.namespace}.${deviceId.replace('0x', '')}.${stateDesc.id}`;
483
489
  this.setState(stateId, value, true);
484
490
  }
485
491
  }
@@ -490,9 +496,9 @@ class Zigbee extends utils.Adapter {
490
496
  });
491
497
  }
492
498
 
493
- async publishFromState(deviceId, model, stateModel, stateList, options){
499
+ async publishFromState(deviceId, model, stateModel, stateList, options) {
494
500
  let isGroup = false;
495
- if (model == 'group') {
501
+ if (model === 'group') {
496
502
  isGroup = true;
497
503
  deviceId = parseInt(deviceId);
498
504
  }
@@ -503,17 +509,17 @@ class Zigbee extends utils.Adapter {
503
509
  this.log.debug(`No mapped model for ${model}`);
504
510
  return;
505
511
  }
506
- this.log.debug('Mapped Model: ' + JSON.stringify(mappedModel));
512
+ this.log.debug(`Mapped Model: ${JSON.stringify(mappedModel)}`);
507
513
 
508
- stateList.forEach(async(changedState) => {
514
+ stateList.forEach(async changedState => {
509
515
  const stateDesc = changedState.stateDesc;
510
516
  const value = changedState.value;
511
517
 
512
- if (stateDesc.id == 'send_payload') {
518
+ if (stateDesc.id === 'send_payload') {
513
519
  try {
514
520
  const json_value = JSON.parse(value);
515
- const payload = { device:deviceId.replace('0x', ''), payload:json_value };
516
- const result = await(this.SendPayload(payload));
521
+ const payload = {device: deviceId.replace('0x', ''), payload: json_value};
522
+ const result = await this.sendPayload(payload);
517
523
  if (result.hasOwnProperty('success') && result.success) {
518
524
  this.acknowledgeState(deviceId, model, stateDesc, value);
519
525
  }
@@ -532,7 +538,7 @@ class Zigbee extends utils.Adapter {
532
538
  // if this is the device query state => trigger the device query
533
539
 
534
540
  // on activation of the 'device_query' state trigger hardware query where possible
535
- if (stateDesc.id == 'device_query') {
541
+ if (stateDesc.id === 'device_query') {
536
542
  if (this.query_device_block.indexOf(deviceId) > -1) {
537
543
  this.log.warn(`Device query for '${entity.device.ieeeAddr}' blocked`);
538
544
  return;
@@ -554,16 +560,18 @@ class Zigbee extends utils.Adapter {
554
560
  }
555
561
  this.log.debug(`Device query for '${entity.device.ieeeAddr}' done`);
556
562
  const idToRemove = deviceId;
557
- setTimeout(()=>{
563
+ setTimeout(() => {
558
564
  const idx = this.query_device_block.indexOf(idToRemove);
559
- if (idx > -1) this.query_device_block.splice(idx);
565
+ if (idx > -1) {
566
+ this.query_device_block.splice(idx);
567
+ }
560
568
  }, 10000);
561
569
  }
562
570
  return;
563
571
  }
564
572
  return;
565
573
  }
566
- const converter = mappedModel.toZigbee.find((c) => c && (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id)));
574
+ const converter = mappedModel.toZigbee.find(c => c && (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id)));
567
575
  if (!converter) {
568
576
  this.log.error(`No converter available for '${model}' with key '${stateDesc.id}' `);
569
577
  this.sendError(`No converter available for '${model}' with key '${stateDesc.id}' `);
@@ -574,7 +582,7 @@ class Zigbee extends utils.Adapter {
574
582
  const preparedOptions = (stateDesc.setterOpt) ? stateDesc.setterOpt(value, options) : {};
575
583
  let syncStateList = [];
576
584
  if (stateModel && stateModel.syncStates) {
577
- stateModel.syncStates.forEach((syncFunct) => {
585
+ stateModel.syncStates.forEach(syncFunct => {
578
586
  const res = syncFunct(stateDesc, value, options);
579
587
  if (res) {
580
588
  syncStateList = syncStateList.concat(res);
@@ -593,12 +601,14 @@ class Zigbee extends utils.Adapter {
593
601
  target = await this.zbController.resolveEntity(deviceId, epName);
594
602
  target = target.endpoint;
595
603
  }
604
+
596
605
  this.log.debug(`target: ${safeJsonStringify(target)}`);
606
+
597
607
  const meta = {
598
608
  endpoint_name: epName,
599
609
  options: preparedOptions,
600
610
  device: entity.device,
601
- mapped: (model == 'group') ? [] : mappedModel,
611
+ mapped: model === 'group' ? [] : mappedModel,
602
612
  message: {[key]: preparedValue},
603
613
  logger: this.log,
604
614
  state: {},
@@ -610,23 +620,24 @@ class Zigbee extends utils.Adapter {
610
620
  const result = await converter.convertSet(target, key, preparedValue, meta);
611
621
  this.log.debug(`convert result ${safeJsonStringify(result)}`);
612
622
  if (result !== undefined) {
613
- if (stateModel && !isGroup)
623
+ if (stateModel && !isGroup) {
614
624
  this.acknowledgeState(deviceId, model, stateDesc, value);
625
+ }
615
626
  // process sync state list
616
627
  this.processSyncStatesList(deviceId, model, syncStateList);
628
+
617
629
  if (isGroup) {
618
630
  await this.callPluginMethod('queryGroupMemberState', [deviceId, stateDesc]);
619
631
  this.acknowledgeState(deviceId, model, stateDesc, value);
620
632
  }
621
633
  }
622
- } catch(error) {
623
- this.filterError(`Error ${error.code} on send command to ${deviceId}.`+
624
- ` Error: ${error.stack}`, `Send command to ${deviceId} failed with`, error);
634
+ } catch (error) {
635
+ this.filterError(`Error ${error.code} on send command to ${deviceId}.` +
636
+ ` Error: ${error.stack}`, `Send command to ${deviceId} failed with`, error);
625
637
  }
626
638
  });
627
639
  }
628
- //
629
- //
640
+
630
641
  // This function is introduced to explicitly allow user level scripts to send Commands
631
642
  // directly to the zigbee device. It utilizes the zigbee-herdsman-converters to generate
632
643
  // the exact zigbee message to be sent and can be used to set device options which are
@@ -639,74 +650,79 @@ class Zigbee extends utils.Adapter {
639
650
  // payload: The data to send to the device as JSON object (key/Value pairs)
640
651
  // endpoint: optional: the endpoint to send the data to, if supported.
641
652
  //
642
- async SendPayload(payload) {
653
+ async sendPayload(payload) {
643
654
  this.log.debug(`publishToDevice called with ${safeJsonStringify(payload)}`);
644
- let payload_obj = {};
655
+ let payloadObj = {};
645
656
  if (typeof payload === 'string') {
646
657
  try {
647
- payload_obj = JSON.parse();
658
+ payloadObj = JSON.parse(payload);
648
659
  } catch (e) {
649
660
  this.log.error(`Unable to parse ${safeJsonStringify(payload)}: ${safeJsonStringify(e)}`);
650
661
  this.sendError(e, `Unable to parse ${safeJsonStringify(payload)}: ${safeJsonStringify(e)}`);
651
- return {success:false, error: `Unable to parse ${safeJsonStringify(payload)}: ${safeJsonStringify(e)}`};
662
+ return {
663
+ success: false,
664
+ error: `Unable to parse ${safeJsonStringify(payload)}: ${safeJsonStringify(e)}`
665
+ };
652
666
  }
653
667
  } else if (typeof payload === 'object') {
654
- payload_obj = payload;
668
+ payloadObj = payload;
655
669
  }
656
- if (payload_obj.hasOwnProperty('device') && payload_obj.hasOwnProperty('payload'))
657
- {
670
+
671
+ if (payloadObj.hasOwnProperty('device') && payloadObj.hasOwnProperty('payload')) {
658
672
  try {
659
- const isDevice = payload.device.indexOf('group_') == -1;
673
+ const isDevice = !payload.device.includes('group_');
660
674
  const stateList = [];
661
- const devID = (isDevice ? `0x${payload.device}`:parseInt(payload.device.replace('group_', '')));
675
+ const devID = isDevice ? `0x${payload.device}` : parseInt(payload.device.replace('group_', ''));
662
676
 
663
677
  const entity = await this.zbController.resolveEntity(devID);
664
678
  if (!entity) {
665
- this.log.error(`Device ${safeJsonStringify(payload_obj.device)} not found`);
666
- this.sendError(`Device ${safeJsonStringify(payload_obj.device)} not found`);
667
- return {success: false, error: `Device ${safeJsonStringify(payload_obj.device)} not found`};
679
+ this.log.error(`Device ${safeJsonStringify(payloadObj.device)} not found`);
680
+ this.sendError(`Device ${safeJsonStringify(payloadObj.device)} not found`);
681
+ return {success: false, error: `Device ${safeJsonStringify(payloadObj.device)} not found`};
668
682
  }
669
683
  const mappedModel = entity.mapped;
670
684
  if (!mappedModel) {
671
- this.log.error(`No Model for Device ${safeJsonStringify(payload_obj.device)}`);
672
- this.sendError(`No Model for Device ${safeJsonStringify(payload_obj.device)}`);
673
- return {success: false, error: `No Model for Device ${safeJsonStringify(payload_obj.device)}`};
685
+ this.log.error(`No Model for Device ${safeJsonStringify(payloadObj.device)}`);
686
+ this.sendError(`No Model for Device ${safeJsonStringify(payloadObj.device)}`);
687
+ return {success: false, error: `No Model for Device ${safeJsonStringify(payloadObj.device)}`};
674
688
  }
675
- if (typeof payload_obj.payload !== 'object') {
676
- this.log.error(`Illegal payload type for ${safeJsonStringify(payload_obj.device)}`);
677
- this.sendError(`Illegal payload type for ${safeJsonStringify(payload_obj.device)}`);
678
- return {success: false, error: `Illegal payload type for ${safeJsonStringify(payload_obj.device)}`};
689
+ if (typeof payloadObj.payload !== 'object') {
690
+ this.log.error(`Illegal payload type for ${safeJsonStringify(payloadObj.device)}`);
691
+ this.sendError(`Illegal payload type for ${safeJsonStringify(payloadObj.device)}`);
692
+ return {success: false, error: `Illegal payload type for ${safeJsonStringify(payloadObj.device)}`};
679
693
  }
680
- for (const key in payload_obj.payload) {
681
- if (payload_obj.payload[key] != undefined) {
682
- const datatype = typeof payload_obj.payload[key];
683
- stateList.push({stateDesc: {
684
- id:key,
685
- prop:key,
686
- role:'state',
687
- type:datatype,
688
- epname:payload_obj.endpoint,
689
- }, value: payload_obj.payload[key], index:0, timeout:0});
694
+ for (const key in payloadObj.payload) {
695
+ if (payloadObj.payload[key] != undefined) {
696
+ const datatype = typeof payloadObj.payload[key];
697
+ stateList.push({
698
+ stateDesc: {
699
+ id: key,
700
+ prop: key,
701
+ role: 'state',
702
+ type: datatype,
703
+ epname: payloadObj.endpoint,
704
+ },
705
+ value: payloadObj.payload[key],
706
+ index: 0,
707
+ timeout: 0,
708
+ });
690
709
  }
691
710
  }
692
711
  try {
693
- this.log.debug(`Calling publish to state for ${safeJsonStringify(payload_obj.device)} with ${safeJsonStringify(stateList)}`);
712
+ this.log.debug(`Calling publish to state for ${safeJsonStringify(payloadObj.device)} with ${safeJsonStringify(stateList)}`);
694
713
  await this.publishFromState(`0x${payload.device}`, '', undefined, stateList, payload.options);
695
714
  return {success: true};
715
+ } catch (error) {
716
+ this.filterError(`Error ${error.code} on send command to ${payload.device}.` +
717
+ ` Error: ${error.stack}`, `Send command to ${payload.device} failed with`, error);
718
+ return {success: false, error};
696
719
  }
697
- catch (error)
698
- {
699
- this.filterError(`Error ${error.code} on send command to ${payload.device}.`+
700
- ` Error: ${error.stack}`, `Send command to ${payload.device} failed with`, error);
701
- return {success:false, error: error};
702
- }
703
- }
704
- catch (e) {
705
- return {success:false, error: e};
720
+ } catch (e) {
721
+ return {success: false, error: e};
706
722
  }
707
-
708
723
  }
709
- return {success:false, error: 'missing parameter device or payload in message ' + JSON.stringify(payload)};
724
+
725
+ return {success: false, error: `missing parameter device or payload in message ${JSON.stringify(payload)}`};
710
726
  }
711
727
 
712
728
 
@@ -719,9 +735,8 @@ class Zigbee extends utils.Adapter {
719
735
  const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID;
720
736
  this.log.debug(`new device ${dev.ieeeAddr} ${dev.networkAddress} ${model} `);
721
737
  this.logToPairing(`New device joined '${dev.ieeeAddr}' model ${model}`, true);
722
- this.stController.updateDev(dev.ieeeAddr.substr(2), model, model, () => {
723
- this.stController.syncDevStates(dev, model);
724
- });
738
+ this.stController.updateDev(dev.ieeeAddr.substr(2), model, model, () =>
739
+ this.stController.syncDevStates(dev, model));
725
740
  }
726
741
  // else this.log.warn(`Device ${safeJsonStringify(entity)} rejoined, no new device`);
727
742
  });
@@ -732,7 +747,7 @@ class Zigbee extends utils.Adapter {
732
747
  this.log.debug(`Leave device event: ${ieeeAddr}`);
733
748
  if (ieeeAddr) {
734
749
  const devId = ieeeAddr.substr(2);
735
- this.log.debug('Delete device ' + devId + ' from iobroker.');
750
+ this.log.debug(`Delete device ${devId} from iobroker.`);
736
751
  this.stController.deleteDeviceStates(devId);
737
752
  }
738
753
  }
@@ -756,7 +771,7 @@ class Zigbee extends utils.Adapter {
756
771
  }
757
772
  }
758
773
  }
759
-
774
+
760
775
  /**
761
776
  * @param {() => void} callback
762
777
  */
@@ -841,7 +856,7 @@ class Zigbee extends utils.Adapter {
841
856
  }
842
857
  if (data === 0) {
843
858
  // set pairing mode off
844
- this.setState('info.pairingMode', false,true);
859
+ this.setState('info.pairingMode', false, true);
845
860
  _pairingMode = false;
846
861
  }
847
862
  if (data) {
@@ -856,7 +871,7 @@ class Zigbee extends utils.Adapter {
856
871
  }
857
872
 
858
873
  expandFileName(fn) {
859
- return path.join(utils.getAbsoluteInstanceDataDir(this), fn);
874
+ return path.join(utils.getAbsoluteInstanceDataDir(this), fn);
860
875
  }
861
876
 
862
877
  onLog(level, msg, data) {
@@ -867,8 +882,8 @@ class Zigbee extends utils.Adapter {
867
882
  logger = this.log.error;
868
883
  if (data)
869
884
  data = data.toString();
870
- this.logToPairing('Error: ' + msg + '. ' + data, true);
871
- this.sendError('Error: ' + msg + '. ' + data);
885
+ this.logToPairing(`Error: ${msg}. ${data}`, true);
886
+ this.sendError(`Error: ${msg}. ${data}`);
872
887
  break;
873
888
  case 'debug':
874
889
  logger = this.log.debug;
@@ -882,9 +897,9 @@ class Zigbee extends utils.Adapter {
882
897
  }
883
898
  if (data) {
884
899
  if (typeof data === 'string') {
885
- logger(msg + '. ' + data);
900
+ logger(`${msg}. ${data}`);
886
901
  } else {
887
- logger(msg + '. ' + safeJsonStringify(data));
902
+ logger(`${msg}. ${safeJsonStringify(data)}`);
888
903
  }
889
904
  } else {
890
905
  logger(msg);