iobroker.zigbee 2.0.4 → 3.0.0

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 (48) hide show
  1. package/README.md +90 -57
  2. package/admin/admin.js +497 -120
  3. package/admin/img/philips_hue_lom001.png +0 -0
  4. package/admin/index_m.html +168 -124
  5. package/admin/tab_m.html +20 -11
  6. package/docs/de/img/Bild30.png +0 -0
  7. package/docs/de/img/Bild38.png +0 -0
  8. package/docs/de/img/Info.png +0 -0
  9. package/docs/de/img/Zigbee_config_de.jpg +0 -0
  10. package/docs/de/img/battery.png +0 -0
  11. package/docs/de/img/debug.png +0 -0
  12. package/docs/de/img/delete.png +0 -0
  13. package/docs/de/img/disconnected.png +0 -0
  14. package/docs/de/img/edit_grp.png +0 -0
  15. package/docs/de/img/edit_image.png +0 -0
  16. package/docs/de/img/grp_nok.png +0 -0
  17. package/docs/de/img/grp_ok.png +0 -0
  18. package/docs/de/img/on_off.png +0 -0
  19. package/docs/de/img/reconfigure.png +0 -0
  20. package/docs/de/readme.md +52 -43
  21. package/docs/en/img/Zigbee_config_en.png +0 -0
  22. package/docs/en/img/Zigbee_pairing_en.png +0 -0
  23. package/docs/en/readme.md +71 -66
  24. package/docs/tutorial/groups-1.png +0 -0
  25. package/docs/tutorial/groups-2.png +0 -0
  26. package/docs/tutorial/tab-dev-1.png +0 -0
  27. package/io-package.json +31 -65
  28. package/lib/DeviceDebug.js +5 -2
  29. package/lib/commands.js +182 -31
  30. package/lib/developer.js +0 -0
  31. package/lib/devices.js +2 -2
  32. package/lib/exposes.js +10 -27
  33. package/lib/groups.js +6 -8
  34. package/lib/localConfig.js +4 -5
  35. package/lib/ota.js +6 -6
  36. package/lib/seriallist.js +9 -2
  37. package/lib/statescontroller.js +397 -128
  38. package/lib/utils.js +41 -11
  39. package/lib/zbDeviceAvailability.js +2 -2
  40. package/lib/zbDeviceConfigure.js +99 -58
  41. package/lib/zigbeecontroller.js +152 -128
  42. package/main.js +251 -264
  43. package/package.json +10 -10
  44. package/docs/en/img/Bild23.png +0 -0
  45. package/docs/en/img/Bild25.png +0 -0
  46. package/docs/en/img/Bild26.png +0 -0
  47. package/docs/en/img/Bild4.png +0 -0
  48. package/docs/en/img/Bild9.png +0 -0
package/main.js CHANGED
@@ -36,6 +36,7 @@ const zigbeeHerdsmanPackage = require('zigbee-herdsman/package.json')
36
36
  const vm = require('vm');
37
37
  const util = require('util');
38
38
  const dmZigbee = require('./lib/devicemgmt.js');
39
+ const DeviceDebug = require('./lib/DeviceDebug');
39
40
 
40
41
  const createByteArray = function (hexString) {
41
42
  const bytes = [];
@@ -79,6 +80,10 @@ class Zigbee extends utils.Adapter {
79
80
  this.stController.on('changed', this.publishFromState.bind(this));
80
81
 
81
82
  this.deviceManagement = new dmZigbee(this);
83
+ this.deviceDebug = new DeviceDebug(this),
84
+ this.deviceDebug.on('log', this.onLog.bind(this));
85
+ this.debugActive = true;
86
+
82
87
 
83
88
  this.plugins = [
84
89
  new SerialListPlugin(this),
@@ -151,7 +156,7 @@ class Zigbee extends utils.Adapter {
151
156
  em = em || error.stack.match(/failed \((.+?)\)/);
152
157
  this.log.error(`${message} no error code (${(em ? em[1] : 'undefined')})`);
153
158
  this.sendError(error, `${message} no error code`);
154
- this.log.debug(`Stack trace for ${em}: ${error.stack}`);
159
+ if (this.debugActive) this.log.debug(`Stack trace for ${em}: ${error.stack}`);
155
160
  return;
156
161
  }
157
162
 
@@ -167,7 +172,7 @@ class Zigbee extends utils.Adapter {
167
172
  this.log.info(`${message}: Code ${error.code} (${ecode.message})`);
168
173
  break;
169
174
  case E_DEBUG:
170
- this.log.debug(`${message}: Code ${error.code} (${ecode.message})`);
175
+ if (this.debugActive) this.log.debug(`${message}: Code ${error.code} (${ecode.message})`);
171
176
  break;
172
177
  case E_WARN:
173
178
  this.log.warn(`${message}: Code ${error.code} (${ecode.message})`);
@@ -185,10 +190,14 @@ class Zigbee extends utils.Adapter {
185
190
 
186
191
  debugLog(data, ...args) {
187
192
  const message = (args) ? util.format(data, ...args) : data;
188
- this.log.debug(message.slice(message.indexOf('zigbee-herdsman')));
193
+ if (this.debugActive) this.log.debug(message.slice(message.indexOf('zigbee-herdsman')));
189
194
  }
190
195
 
191
196
  async onReady() {
197
+
198
+ const dbActive = await this.getForeignState(`system.adapter.${this.namespace}.logLevel`);
199
+ this.debugActive = (dbActive && dbActive.val === 'debug');
200
+ this.log.info('Adapter ready - starting subsystems. Adapter is running in '+dbActive.val+ ' mode.');
192
201
  if (this.config.debugHerdsman) {
193
202
  debug.log = this.debugLog.bind(this);
194
203
  debug.enable('zigbee-herdsman*');
@@ -200,6 +209,7 @@ class Zigbee extends utils.Adapter {
200
209
  this.stController.getExposes();
201
210
 
202
211
  this.subscribeStates('*');
212
+ this.subscribeForeignStates(`system.adapter.${this.namespace}.logLevel`)
203
213
  // set connection false before connect to zigbee
204
214
  this.setState('info.connection', false, true);
205
215
  const zigbeeOptions = this.getZigbeeOptions();
@@ -210,14 +220,26 @@ class Zigbee extends utils.Adapter {
210
220
  this.zbController.on('new', this.newDevice.bind(this));
211
221
  this.zbController.on('leave', this.leaveDevice.bind(this));
212
222
  this.zbController.on('pairing', this.onPairing.bind(this));
213
- this.zbController.on('event', this.onZigbeeEvent.bind(this));
214
- this.zbController.on('msg', this.onZigbeeEvent.bind(this));
223
+ this.zbController.on('event', this.stController.onZigbeeEvent.bind(this.stController));
224
+ this.zbController.on('msg', this.stController.onZigbeeEvent.bind(this.stController));
215
225
  this.zbController.on('publish', this.publishToState.bind(this));
216
226
  this.zbController.configure(zigbeeOptions);
227
+ this.zbController.debugActive = this.debugActive;
228
+ this.stController.debugActive = this.debugActive;
217
229
  await this.callPluginMethod('configure', [zigbeeOptions]);
218
230
 
231
+ // elevated debug handling
232
+ this.deviceDebug.start(this.stController, this.zbController);
233
+
219
234
  this.reconnectCounter = 1;
220
- this.doConnect();
235
+ if (this.config.autostart) this.doConnect();
236
+ }
237
+ updateDebugLevel(state) {
238
+ const dbActive = state === 'debug';
239
+ this.debugActive = dbActive;
240
+ this.stController.debugActive = dbActive;
241
+ this.zbController.debugActive = dbActive;
242
+ this.log.info('Change of log level while running to ' + state);
221
243
  }
222
244
 
223
245
  sandboxAdd(sandbox, item, module) {
@@ -242,18 +264,18 @@ class Zigbee extends utils.Adapter {
242
264
 
243
265
  let zhcm1 = modulePath.match(/^zigbee-herdsman-converters\//);
244
266
  if (zhcm1) {
245
- const i2 = modulePath.replace(/^zigbee-herdsman-converters\//, `../zigbee-herdsman-converters/`);
246
267
  try {
268
+ const i2 = modulePath.replace(/^zigbee-herdsman-converters\//, `../${sandbox.zhclibBase}/`);
247
269
  this.sandboxAdd(sandbox, item[1], i2);
248
270
  }
249
271
  catch (error) {
250
- this.log.error(`Sandbox error: ${(error && error.message ? error.message : 'no error message given')}`);
272
+ this.log.error(`Sandbox error: ${(error && error.message ? error.message : 'no error message given')}`)
251
273
  }
252
274
  continue;
253
275
  }
254
276
  zhcm1 = modulePath.match(/^..\//);
255
277
  if (zhcm1) {
256
- const i2 = modulePath.replace(/^..\//, `../zigbee-herdsman-converters/`);
278
+ const i2 = modulePath.replace(/^..\//, `../${sandbox.zhclibBase}/`);
257
279
  try {
258
280
  this.sandboxAdd(sandbox, item[1], i2);
259
281
  }
@@ -283,11 +305,14 @@ class Zigbee extends utils.Adapter {
283
305
  const extfiles = this.config.external.split(';');
284
306
  for (const moduleName of extfiles) {
285
307
  if (!moduleName) continue;
308
+ const ZHCP = zigbeeHerdsmanConvertersPackage;
286
309
  const sandbox = {
287
310
  require,
288
311
  module: {},
312
+ zhclibBase : path.join('zigbee-herdsman-converters',(ZHCP && ZHCP.exports && ZHCP.exports['.'] ? path.dirname(ZHCP.exports['.']) : ''))
289
313
  };
290
- const mN = (fs.existsSync(moduleName) ? moduleName : this.expandFileName(moduleName).replace('.', '_'));
314
+
315
+ const mN = (fs.existsSync(moduleName) ? moduleName : this.expandFileName(moduleName));
291
316
  if (!fs.existsSync(mN)) {
292
317
  this.log.warn(`External converter not loaded - neither ${moduleName} nor ${mN} exist.`);
293
318
  }
@@ -313,13 +338,18 @@ class Zigbee extends utils.Adapter {
313
338
  //fs.writeFileSync(mN+'.tmp5', modifiedCode)
314
339
  converterLoaded &= this.SandboxRequire(sandbox,[...modifiedCode.matchAll(/const\s+(\S+)\s+=\s+require\((.+)\)/gm)]);
315
340
  modifiedCode = modifiedCode.replace(/const\s+\S+\s+=\s+require\(.+\)/gm, '');
316
- //fs.writeFileSync(mN+'.tmp6', modifiedCode)
341
+ //mfs.writeFileSync(mN+'.tmp', modifiedCode)
317
342
 
318
343
  for(const component of modifiedCode.matchAll(/const (.+):(.+)=/gm)) {
319
344
  modifiedCode = modifiedCode.replace(component[0], `const ${component[1]} = `);
320
345
  }
321
346
  modifiedCode = modifiedCode.replace(/export .+;/gm, '');
322
347
 
348
+ if (modifiedCode.indexOf('module.exports') < 0) {
349
+ converterLoaded = false;
350
+ this.log.error(`converter does not export any converter array, please add 'module.exports' statement to ${mN}`);
351
+ }
352
+
323
353
  fs.writeFileSync(mN+'.tmp', modifiedCode)
324
354
 
325
355
  if (converterLoaded) {
@@ -353,32 +383,47 @@ class Zigbee extends utils.Adapter {
353
383
  const toAdd = {...definition};
354
384
  delete toAdd['homeassistant'];
355
385
  try {
386
+ const t = Date.now();
356
387
  if (zigbeeHerdsmanConverters.hasOwnProperty('addExternalDefinition')) {
357
388
  zigbeeHerdsmanConverters.addExternalDefinition(toAdd);
358
- this.log.info('added external converter using addExternalDefinition')
389
+ this.log.info(`added external converter using addExternalDefinition (${Date.now()-t} ms)`)
359
390
  }
360
391
  else if (zigbeeHerdsmanConverters.hasOwnProperty('addDefinition')) {
361
392
  zigbeeHerdsmanConverters.addDefinition(toAdd);
362
- this.log.info('added external converter using addDefinition')
393
+ this.log.info(`added external converter using addDefinition (${Date.now()-t} ms)`);
363
394
  }
364
-
365
- /*
366
- for (const zigbeeModel of toAdd.zigbeeModel)
367
- {
368
- try {
369
- zigbeeHerdsmanConverters.addToExternalDefinitionsLookup(zigbeeModel, toAdd.toAdd);
370
- } catch (e) {
371
- this.log.error(`unable to apply external converter ${JSON.stringify(toAdd)} for device ${zigbeeModel}: ${e && e.message ? e.message : 'no error message available'}`);
372
- }
373
- }
374
- */
375
395
  } catch (e) {
376
396
  this.log.error(`unable to apply external converter for ${JSON.stringify(toAdd.model)}: ${e && e.message ? e.message : 'no error message available'}`);
377
397
  }
378
398
  }
379
399
  }
380
400
 
381
- async doConnect() {
401
+ async testConnect(from, command, message, callback) {
402
+ const response = {};
403
+ if (message.start) {
404
+ try {
405
+ this.logToPairing(`overriding zigbee options with:`);
406
+ for (const k of Object.keys(message.zigbeeOptions)) {
407
+ this.logToPairing(`${k} : ${message.zigbeeOptions[k]}`)
408
+ }
409
+ this.zbController.configure(this.getZigbeeOptions(message.zigbeeOptions));
410
+ response.status = await this.doConnect(true);
411
+ this.sendTo(from, command, response, callback);
412
+ }
413
+ catch (error) {
414
+ this.sendTo(from, command, { status:false }, callback);
415
+ }
416
+ }
417
+ else try {
418
+ await this.zbController.stopHerdsman();
419
+ //this.logToPairing('herdsman stopped !');
420
+ this.sendTo(from, command, { status:true }, callback);
421
+ } catch (error) {
422
+ this.sendTo(from, command, { status:false }, callback);
423
+ }
424
+ }
425
+
426
+ async doConnect(noReconnect) {
382
427
  let debugversion = '';
383
428
  try {
384
429
  const DebugIdentify = require('./debugidentify');
@@ -390,33 +435,44 @@ class Zigbee extends utils.Adapter {
390
435
  // installed version
391
436
  let gitVers = '';
392
437
  try {
438
+ if (noReconnect) this.logToPairing(`Starting Adapter ${debugversion}`);
393
439
  this.log.info(`Starting Adapter ${debugversion}`);
394
440
 
395
441
  this.getForeignObject(`system.adapter.${this.namespace}`,async (err, obj) => {
396
- if (!err && obj && obj.common.installedFrom && obj.common.installedFrom.includes('://')) {
397
- const instFrom = obj.common.installedFrom;
398
- gitVers = gitVers + instFrom.replace('tarball', 'commit');
399
- } else {
400
- gitVers = obj.common.installedFrom;
442
+ try {
443
+ if (!err && obj && obj.common.installedFrom && obj.common.installedFrom.includes('://')) {
444
+ const instFrom = obj.common.installedFrom;
445
+ gitVers = gitVers + instFrom.replace('tarball', 'commit');
446
+ } else {
447
+ gitVers = obj.common.installedFrom;
448
+ }
449
+ if (noReconnect) this.logToPairing(`Installed Version: ${gitVers} (Converters ${zigbeeHerdsmanConvertersPackage.version} Herdsman ${zigbeeHerdsmanPackage.version})`);
450
+ this.log.info(`Installed Version: ${gitVers} (Converters ${zigbeeHerdsmanConvertersPackage.version} Herdsman ${zigbeeHerdsmanPackage.version})`);
451
+ await this.zbController.start(noReconnect);
452
+ } catch (error) {
453
+ this.logToPairing(error && error.message ? error.message : error);
454
+ this.log.error(error && error.message ? error.message : error);
401
455
  }
402
- this.log.info(`Installed Version: ${gitVers} (Converters ${zigbeeHerdsmanConvertersPackage.version} Herdsman ${zigbeeHerdsmanPackage.version})`);
403
- await this.zbController.start();
456
+ return false;
404
457
  });
405
-
406
458
  } catch (error) {
407
459
  this.setState('info.connection', false, true);
408
- this.log.error(`Failed to start Zigbee`);
409
- if (error.stack) {
460
+ this.logToPairing(`Failed to start Zigbee: ${error && error.message ? error.message : 'no message given'}`)
461
+ this.log.error(`Failed to start Zigbee: ${error && error.message ? error.message : 'no message given'}`);
462
+ /* if (error.stack) {
410
463
  this.log.error(error.stack);
411
464
  } else {
412
465
  this.log.error(error);
413
466
  }
467
+ */
414
468
  this.sendError(error, `Failed to start Zigbee`);
469
+ if (noReconnect) return false;
415
470
 
416
471
  if (this.reconnectCounter > 0) {
417
472
  this.tryToReconnect();
418
473
  }
419
474
  }
475
+ return true;
420
476
  }
421
477
 
422
478
  UploadRequired(status) {
@@ -479,14 +535,16 @@ class Zigbee extends utils.Adapter {
479
535
  ]
480
536
  );
481
537
  const nwExtPanId = `0x${result.payload.value.reverse().toString('hex')}`;
482
- this.log.debug(`Config value ${configExtPanId} : nw value ${nwExtPanId}`);
538
+ if (this.debugActive) this.log.debug(`Config value ${configExtPanId} : nw value ${nwExtPanId}`);
539
+ this.logToPairing(`Config value ${configExtPanId} : nw value ${nwExtPanId}`)
483
540
  if (configExtPanId !== nwExtPanId) {
484
541
  networkExtPanId = nwExtPanId;
485
542
  needChange = true;
486
543
  }
487
544
  } catch (e) {
488
- this.log.error(`Unable to apply ExtPanID changes: ${e}`);
489
- this.sendError(e, `Unable to apply ExtPanID changes`);
545
+ const msg = `Unable to apply ExtPanID changes: ${e}`;
546
+ this.log.error(msg);
547
+ this.logToPairing(msg)
490
548
  needChange = false;
491
549
  }
492
550
  } else {
@@ -495,11 +553,11 @@ class Zigbee extends utils.Adapter {
495
553
  }
496
554
  if (needChange) {
497
555
  // need change config value and mark that fix is applied
498
- this.log.debug(`Fix extPanId value to ${networkExtPanId}. And restart adapter.`);
556
+ if (this.debugActive) this.log.debug(`Fix extPanId value to ${networkExtPanId}. And restart adapter.`);
499
557
  this.updateConfig({extPanID: networkExtPanId.substr(2), extPanIdFix: true});
500
558
  } else {
501
559
  // only mark that fix is applied
502
- this.log.debug(`Fix without changes. And restart adapter.`);
560
+ if (this.debugActive) this.log.debug(`Fix without changes. And restart adapter.`);
503
561
  this.updateConfig({extPanIdFix: true});
504
562
  }
505
563
  }
@@ -510,7 +568,6 @@ class Zigbee extends utils.Adapter {
510
568
  for (const device of devicesFromDB) {
511
569
  const entity = await this.zbController.resolveEntity(device);
512
570
  if (entity) {
513
- // this.log.warn('sync dev states for ' + (entity.mapped ? entity.mapped.model : entity.device.modelID));
514
571
  const model = entity.mapped ? entity.mapped.model : entity.device.modelID;
515
572
  this.stController.updateDev(device.ieeeAddr.substr(2), model, model, () =>
516
573
  this.stController.syncDevStates(device, model));
@@ -553,154 +610,6 @@ class Zigbee extends utils.Adapter {
553
610
  });
554
611
  }
555
612
 
556
- async onZigbeeEvent(type, entity, message) {
557
- this.log.debug(`Type ${type} device ${safeJsonStringify(entity)} incoming event: ${safeJsonStringify(message)}`);
558
-
559
- const device = entity.device;
560
- const mappedModel = entity.mapped;
561
- const model = entity.mapped ? entity.mapped.model : entity.device.modelID;
562
- const cluster = message.cluster;
563
- const devId = device.ieeeAddr.substr(2);
564
- const meta = {device};
565
-
566
- const has_elevated_debug = this.stController.checkDebugDevice(devId);
567
-
568
- if (has_elevated_debug) {
569
- const shortMessage = {};
570
- for(const propertyName in message) {
571
- shortMessage[propertyName] = message[propertyName];
572
- }
573
- shortMessage.device = device.ieeeAddr;
574
- shortMessage.meta = undefined;
575
- shortMessage.endpoint = (message.endpoint.ID ? message.endpoint.ID: -1);
576
- this.log.warn(`ELEVATED I00: Zigbee Event of Type ${type} from device ${safeJsonStringify(device.ieeeAddr)}, incoming event: ${safeJsonStringify(shortMessage)}`);
577
- }
578
- // this assigment give possibility to use iobroker logger in code of the converters, via meta.logger
579
- meta.logger = this.log;
580
-
581
- await this.checkIfModelUpdate(entity);
582
-
583
- let _voltage = 0;
584
- let _temperature = 0;
585
- let _humidity = 0;
586
-
587
- let isMessure = false;
588
- let isBattKey = false;
589
-
590
- if (mappedModel && mappedModel.meta && mappedModel.meta.battery) {
591
- const isVoltage = mappedModel.meta.battery.hasOwnProperty('voltageToPercentage');
592
-
593
- if (isVoltage) {
594
- const keys = Object.keys(message.data);
595
-
596
- for (const key of keys) {
597
- const value = message.data[key];
598
-
599
- if (value && value[1]) {
600
- if (key == 65282 && value[1][1]) {
601
- _voltage = value[1][1].elmVal;
602
- isBattKey = true;
603
- break;
604
- }
605
- if (key == 65281) {
606
- _voltage = value[1];
607
- isBattKey = true;
608
- _temperature = value[100];
609
- _temperature = _temperature /100;
610
- _humidity = value[101];
611
- _humidity = _humidity / 100;
612
- isMessure = true;
613
- break;
614
- }
615
- }
616
- }
617
- }
618
- }
619
-
620
- // always publish link_quality and battery
621
- if (message.linkquality) { // send battery with
622
- this.publishToState(devId, model, {linkquality: message.linkquality});
623
- if (isBattKey) {
624
- this.publishToState(devId, model, {voltage: _voltage});
625
- const battProz = zigbeeHerdsmanConvertersUtils.batteryVoltageToPercentage(_voltage,entity.mapped.meta.battery.voltageToPercentage);
626
- this.publishToState(devId, model, {battery: battProz});
627
- }
628
- if (isMessure) {
629
- this.publishToState(devId, model, {temperature: _temperature});
630
- this.publishToState(devId, model, {humidity: _humidity});
631
- }
632
- }
633
-
634
- // publish raw event to "from_zigbee"
635
- // some cleanup
636
- const msgForState = Object.assign({}, message);
637
- delete msgForState['device'];
638
- delete msgForState['endpoint'];
639
-
640
- msgForState['endpoint_id'] = message.endpoint.ID;
641
- this.publishToState(devId, model, {msg_from_zigbee: safeJsonStringify(msgForState)});
642
-
643
- if (!entity.mapped) {
644
- return;
645
- }
646
-
647
- let converters = mappedModel.fromZigbee.filter(c => c && c.cluster === cluster && (
648
- Array.isArray(c.type) ? c.type.includes(type) : c.type === type));
649
-
650
-
651
- if (!converters.length && type === 'readResponse') {
652
- converters = mappedModel.fromZigbee.filter(c => c.cluster === cluster && (
653
- Array.isArray(c.type) ? c.type.includes('attributeReport') : c.type === 'attributeReport'));
654
- }
655
-
656
- if (!converters.length) {
657
- if (type !== 'readResponse') {
658
- this.log.debug(`No converter available for '${mappedModel.model}' '${devId}' with cluster '${cluster}' and type '${type}'`);
659
- if (has_elevated_debug)
660
- this.log.warn(`ELEVATED IE00: No converter available for '${mappedModel.model}' '${devId}' with cluster '${cluster}' and type '${type}'`);
661
- }
662
- return;
663
- }
664
-
665
- meta.state = { state: '' }; // for tuya
666
-
667
- this.processConverters(converters, devId, model, mappedModel, message, meta)
668
- .catch((error) => {
669
- // 'Error: Expected one of: 0, 1, got: 'undefined''
670
- if (cluster !== '64529') {
671
- this.log.error(`Error while processing converters DEVICE_ID: '${devId}' cluster '${cluster}' type '${type}'`);
672
- }
673
- });
674
- }
675
-
676
- async processConverters(converters, devId, model, mappedModel, message, meta) {
677
- for (const converter of converters) {
678
- const publish = (payload) => {
679
- this.log.debug(`Publish ${safeJsonStringify(payload)} to ${safeJsonStringify(devId)}`);
680
- if (typeof payload === 'object') {
681
- this.publishToState(devId, model, payload);
682
- }
683
- };
684
-
685
- const options = await new Promise((resolve, reject) => {
686
- this.stController.collectOptions(devId, model, (options) => {
687
- resolve(options);
688
- });
689
- });
690
-
691
- const payload = await new Promise((resolve, reject) => {
692
- const payloadConv = converter.convert(mappedModel, message, publish, options, meta);
693
- if (typeof payloadConv === 'object') {
694
- resolve(payloadConv);
695
- }
696
- });
697
-
698
- publish(payload);
699
- }
700
- }
701
-
702
-
703
-
704
613
  publishToState(devId, model, payload) {
705
614
  this.stController.publishToState(devId, model, payload);
706
615
  }
@@ -721,30 +630,36 @@ class Zigbee extends utils.Adapter {
721
630
  });
722
631
  }
723
632
 
724
- async publishFromState(deviceId, model, stateModel, stateList, options) {
633
+ async publishFromState(deviceId, model, stateModel, stateList, options, debugID) {
725
634
  let isGroup = false;
726
635
  const has_elevated_debug = this.stController.checkDebugDevice(deviceId)
727
636
 
728
637
  if (has_elevated_debug)
729
638
  {
730
639
  const stateNames = [];
731
- stateList.forEach( state => stateNames.push(state.id));
732
- this.log.warn(`ELEVATED O03: Publishing to ${deviceId} of model ${model} ${stateNames.join(', ')}`);
640
+ for (const state of stateList) {
641
+ stateNames.push(state.stateDesc.id);
642
+ }
643
+ const message = `Publishing to ${deviceId} of model ${model} with ${stateNames.join(', ')}`;
644
+ this.emit('device_debug', { ID:debugID, data: { ID: deviceId, flag: '03', IO:false }, message: message});
733
645
  }
734
646
  else
735
- this.log.debug(`publishFromState : ${deviceId} ${model} ${safeJsonStringify(stateList)}`);
647
+ if (this.debugActive) this.log.debug(`publishFromState : ${deviceId} ${model} ${safeJsonStringify(stateList)}`);
736
648
  if (model === 'group') {
737
649
  isGroup = true;
738
650
  deviceId = parseInt(deviceId);
739
651
  }
740
652
  try {
741
653
  const entity = await this.zbController.resolveEntity(deviceId);
742
- this.log.debug(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`);
654
+ if (this.debugActive) this.log.debug(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`);
743
655
  const mappedModel = entity ? entity.mapped : undefined;
744
656
 
745
657
  if (!mappedModel) {
746
- this.log.debug(`No mapped model for ${model}`);
747
- if (has_elevated_debug) this.log.error(`ELEVATED OE01: No mapped model ${deviceId} (model ${model})`)
658
+ if (this.debugActive) this.log.debug(`No mapped model for ${model}`);
659
+ if (has_elevated_debug) {
660
+ const message=`No mapped model ${deviceId} (model ${model})`;
661
+ this.emit('device_debug', { ID:debugID, data: { error: 'NOMODEL' , IO:false }, message: message});
662
+ }
748
663
  return;
749
664
  }
750
665
 
@@ -761,13 +676,20 @@ class Zigbee extends utils.Adapter {
761
676
  if (stateDesc.id === 'send_payload') {
762
677
  try {
763
678
  const json_value = JSON.parse(value);
764
- const payload = {device: deviceId.replace('0x', ''), payload: json_value};
679
+ const payload = {device: deviceId.replace('0x', ''), payload: json_value, model:model, stateModel:stateModel};
680
+ if (has_elevated_debug) this.emit('device_debug', { ID:debugID, data: { flag: '04' ,payload:value ,states:[{id:stateDesc.id, value:json_value, payload:'none'}], IO:false }});
681
+
765
682
  const result = await this.sendPayload(payload);
766
683
  if (result.hasOwnProperty('success') && result.success) {
767
684
  this.acknowledgeState(deviceId, model, stateDesc, value);
768
685
  }
686
+ else {
687
+ this.log.error('Error in SendPayload: '+result.error.message);
688
+ }
769
689
  } catch (error) {
770
- this.log.warn(`send_payload: ${value} does not parse as JSON Object : ${error.message}`);
690
+ const message = `send_payload: ${value} does not parse as JSON Object : ${error.message}`;
691
+ if (has_elevated_debug) this.emit('device_debug', { ID:debugID, data: { error: 'EXSEND' ,states:[{id:stateDesc.id, value:value, payload:error.message}], IO:false }, message:message});
692
+ else this.log.error(message);
771
693
  return;
772
694
  }
773
695
  return;
@@ -775,31 +697,31 @@ class Zigbee extends utils.Adapter {
775
697
 
776
698
  if (stateDesc.isOption || stateDesc.compositeState) {
777
699
  // acknowledge state with given value
778
- if (has_elevated_debug)
779
- this.log.warn('ELEVATED OC: changed state: ' + JSON.stringify(changedState));
700
+ if (has_elevated_debug) {
701
+ const message = 'changed state: ' + JSON.stringify(changedState);
702
+ this.emit('device_debug', { ID:debugID, data: { flag: 'cc', states:[{id:stateDesc.id, value:value, payload:'none (OC State)'}] , IO:false }, message:message});
703
+ }
780
704
  else
781
- this.log.debug('changed composite state: ' + JSON.stringify(changedState));
705
+ if (this.debugActive) this.log.debug('changed composite state: ' + JSON.stringify(changedState));
782
706
 
783
707
  this.acknowledgeState(deviceId, model, stateDesc, value);
784
708
  if (stateDesc.compositeState && stateDesc.compositeTimeout) {
785
709
  this.stController.triggerComposite(deviceId, model, stateDesc, changedState.source.includes('.admin.'));
786
710
  }
787
- // process sync state list
788
- //this.processSyncStatesList(deviceId, modelId, syncStateList);
789
- // if this is the device query state => trigger the device query
790
-
791
711
  // on activation of the 'device_query' state trigger hardware query where possible
792
712
  if (stateDesc.id === 'device_query') {
793
713
  if (this.query_device_block.indexOf(deviceId) > -1) {
794
- this.log.warn(`Device query for '${entity.device.ieeeAddr}' blocked`);
714
+ this.log.info(`Device query for '${entity.device.ieeeAddr}' blocked`);
795
715
  return;
796
716
  }
797
717
  if (mappedModel) {
798
718
  this.query_device_block.push(deviceId);
799
- if (has_elevated_debug)
800
- this.log.warn(`ELEVATED O06: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' triggered`);
719
+ if (has_elevated_debug) {
720
+ const message = `Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' triggered`;
721
+ this.emit('device_debug', { ID:debugID, data: { flag: 'qs' ,states:[{id:stateDesc.id, value:value, payload:'none for device query'}], IO:false }, message:message});
722
+ }
801
723
  else
802
- this.log.debug(`Device query for '${entity.device.ieeeAddr}' started`);
724
+ if (this.debugActive) this.log.debug(`Device query for '${entity.device.ieeeAddr}' started`);
803
725
  for (const converter of mappedModel.toZigbee) {
804
726
  if (converter.hasOwnProperty('convertGet')) {
805
727
  for (const ckey of converter.key) {
@@ -807,7 +729,9 @@ class Zigbee extends utils.Adapter {
807
729
  await converter.convertGet(entity.device.endpoints[0], ckey, {});
808
730
  } catch (error) {
809
731
  if (has_elevated_debug) {
810
- this.log.warn(`ELEVATED OE02.1 Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' from query with '${error && error.message ? error.message : 'no error message'}`);
732
+ const message = `Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' from query with '${error && error.message ? error.message : 'no error message'}`;
733
+ this.log.warn(`ELEVATED OE02.1 ${message}`);
734
+ this.emit('device_debug', { ID:debugID, data: { error: 'NOTREAD' , IO:false }, message:message });
811
735
  }
812
736
  else
813
737
  this.log.info(`failed to read state ${JSON.stringify(ckey)} of ${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} after device query`);
@@ -815,8 +739,10 @@ class Zigbee extends utils.Adapter {
815
739
  }
816
740
  }
817
741
  }
818
- if (has_elevated_debug)
819
- this.log.warn(`ELEVATED O07: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`);
742
+ if (has_elevated_debug) {
743
+ const message = `ELEVATED O07: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`;
744
+ this.emit('device_debug', { ID:debugID, data: { flag: 'qe' , IO:false }, message:message});
745
+ }
820
746
  else
821
747
  this.log.info(`Device query for '${entity.device.ieeeAddr}' done`);
822
748
  const idToRemove = deviceId;
@@ -837,41 +763,54 @@ class Zigbee extends utils.Adapter {
837
763
  for (const c of mappedModel.toZigbee) {
838
764
 
839
765
  if (!c.hasOwnProperty('convertSet')) continue;
840
- this.log.debug(`Type of toZigbee is '${typeof c}', Contains key ${(c.hasOwnProperty('key')?JSON.stringify(c.key):'false ')}`)
766
+ if (this.debugActive) this.log.debug(`Type of toZigbee is '${typeof c}', Contains key ${(c.hasOwnProperty('key')?JSON.stringify(c.key):'false ')}`)
841
767
  if (!c.hasOwnProperty('key'))
842
768
  {
843
- if (c.hasOwnProperty('convertSet') && converter === undefined)
769
+ if (converter === undefined)
844
770
  {
845
771
  converter = c;
846
- if (has_elevated_debug)
847
- this.log.warn(`ELEVATED O04.${msg_counter}: Setting converter to keyless converter for ${deviceId} of type ${model}`)
772
+ if (has_elevated_debug) {
773
+ const message = `Setting converter to keyless converter for ${deviceId} of type ${model}`;
774
+ this.emit('device_debug', { ID:debugID, data: { flag: `s4.${msg_counter}` , IO:false }, message:message});
775
+ }
848
776
  else
849
- this.log.debug(`Setting converter to keyless converter for ${deviceId} of type ${model}`)
777
+ if (this.debugActive) this.log.debug(`Setting converter to keyless converter for ${deviceId} of type ${model}`);
850
778
  msg_counter++;
851
779
  }
852
780
  else
853
781
  {
854
782
  if (has_elevated_debug)
855
- this.log.warn(`ELEVATED O04.${msg_counter}: ignoring keyless converter for ${deviceId} of type ${model}`)
783
+ {
784
+ const message = `ignoring keyless converter for ${deviceId} of type ${model}`;
785
+ this.emit('device_debug', { ID:debugID, data: { flag: `i4.${msg_counter}` , IO:false} , message:message});
786
+ }
856
787
  else
857
- this.log.debug(`ignoring keyless converter for ${deviceId} of type ${model}`)
788
+ if (this.debugActive) this.log.debug(`ignoring keyless converter for ${deviceId} of type ${model}`);
858
789
  msg_counter++;
859
790
  }
860
791
  continue;
861
792
  }
862
793
  if (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id))
863
794
  {
864
- if (has_elevated_debug)
865
- this.log.warn(`ELEVATED O04.${msg_counter}: ${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`)
795
+ const message = `${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`;
796
+ if (has_elevated_debug) {
797
+ this.emit('device_debugug', { ID:debugID, data: { flag: `${converter===undefined ? 's' : 'o'}4.${msg_counter}` , IO:false }, message:message});
798
+
799
+ }
866
800
  else
867
- this.log.debug(`${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`)
801
+ if (this.debugActive) this.log.debug(message);
868
802
  converter = c;
869
803
  msg_counter++;
870
804
  }
871
805
  }
872
806
  if (converter === undefined) {
873
- this.log.error(`No converter available for '${model}' with key '${stateDesc.id}' `);
874
- this.sendError(`No converter available for '${model}' with key '${stateDesc.id}' `);
807
+ const message = `No converter available for '${model}' with key '${stateDesc.id}' `;
808
+ if (has_elevated_debug) {
809
+ this.emit('device_debug', { ID:debugID, data: { error: 'NOCONV',states:[{id:stateDesc.id, value:value, payload:'no converter'}] , IO:false }, message:message});
810
+ }
811
+ else {
812
+ this.log.warn(message);
813
+ }
875
814
  return;
876
815
  }
877
816
 
@@ -890,10 +829,12 @@ class Zigbee extends utils.Adapter {
890
829
 
891
830
  const epName = stateDesc.epname !== undefined ? stateDesc.epname : (stateDesc.prop || stateDesc.id);
892
831
  const key = stateDesc.setattr || stateDesc.prop || stateDesc.id;
893
- if (has_elevated_debug)
894
- this.log.warn(`ELEVATED O04: convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)} for device ${deviceId} with Endpoint ${epName}`);
832
+ const message = `convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)} for device ${deviceId} with Endpoint ${epName}`;
833
+ if (has_elevated_debug) {
834
+ this.emit('device_debug', { ID:debugID, data: { flag: '04', payload: {key:key, ep: stateDesc.epname, value:preparedValue, options:preparedOptions}, IO:false }, message:message});
835
+ }
895
836
  else
896
- this.log.debug(`convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)}`);
837
+ if (this.debugActive) this.log.debug(message);
897
838
 
898
839
  let target;
899
840
  if (model === 'group') {
@@ -903,7 +844,7 @@ class Zigbee extends utils.Adapter {
903
844
  target = target.endpoint;
904
845
  }
905
846
 
906
- this.log.debug(`target: ${safeJsonStringify(target)}`);
847
+ if (this.debugActive) this.log.debug(`target: ${safeJsonStringify(target)}`);
907
848
 
908
849
  const meta = {
909
850
  endpoint_name: epName,
@@ -923,6 +864,9 @@ class Zigbee extends utils.Adapter {
923
864
  meta.message.state = preparedValue;
924
865
  }
925
866
  }
867
+ if (has_elevated_debug) {
868
+ this.emit('device_debug', { ID:debugID, data: { states:[{id:stateDesc.id, value:value, payload:preparedValue, ep:stateDesc.epname}] , IO:false }});
869
+ }
926
870
 
927
871
  if (preparedOptions !== undefined) {
928
872
  if (preparedOptions.hasOwnProperty('state')) {
@@ -932,33 +876,52 @@ class Zigbee extends utils.Adapter {
932
876
 
933
877
  try {
934
878
  const result = await converter.convertSet(target, key, preparedValue, meta);
935
- if (has_elevated_debug)
936
- this.log.warn(`ELEVATED O05: convert result ${safeJsonStringify(result)} for device ${deviceId}`);
879
+ const message = `convert result ${safeJsonStringify(result)} for device ${deviceId}`;
880
+ if (has_elevated_debug) {
881
+ this.emit('device_debug', { ID:debugID, data: { flag: 'SUCCESS' , IO:false }, message:message});
882
+ }
937
883
  else
938
- this.log.debug(`convert result ${safeJsonStringify(result)}`);
884
+ if (this.debugActive) this.log.debug(message);
939
885
  if (result !== undefined) {
940
- if (stateModel && !isGroup) {
886
+ if (stateModel && !isGroup && !stateDesc.noack) {
941
887
  this.acknowledgeState(deviceId, model, stateDesc, value);
942
888
  }
943
889
  // process sync state list
944
890
  this.processSyncStatesList(deviceId, model, syncStateList);
945
891
  }
946
- else
947
- if (has_elevated_debug)
948
- this.log.error(`ELEVATED OE2: Error convert result for ${key} with ${safeJsonStringify(preparedValue)} is undefined on device ${deviceId}.`);
949
-
892
+ else {
893
+ if (has_elevated_debug) {
894
+ const message = `Convert does not return a result result for ${key} with ${safeJsonStringify(preparedValue)} on device ${deviceId}.`;
895
+ this.emit('device_debug', { ID:debugID, data: { flag: '06' , IO:false }, message:message});
896
+ }
897
+ }
950
898
  } catch (error) {
951
- if (has_elevated_debug)
952
- this.log.error(`ELEVATED OE3: caught error ${safeJsonStringify(error)} when setting value for device ${deviceId}.`);
899
+ if (has_elevated_debug) {
900
+ const message = `caught error ${safeJsonStringify(error)} when setting value for device ${deviceId}.`;
901
+ this.emit('device_debug', { ID:debugID, data: { error: 'EXSET' , IO:false },message:message});
902
+ }
953
903
  this.filterError(`Error ${error.code} on send command to ${deviceId}.` +
954
904
  ` Error: ${error.stack}`, `Send command to ${deviceId} failed with`, error);
955
905
  }
956
906
  });
957
907
  } catch (err) {
958
- this.log.error(`No entity for ${deviceId} : ${err && err.message ? err.message : 'no error message'}`);
908
+ const message = `No entity for ${deviceId} : ${err && err.message ? err.message : 'no error message'}`;
909
+ this.emit('device_debug', { ID:debugID, data: { error: 'EXPUB' , IO:false }, message:message});
959
910
  }
960
911
  }
961
912
 
913
+
914
+ extractEP(key, endpoints) {
915
+ try {
916
+ if (endpoints) for (const ep of Object.keys(endpoints)) {
917
+ if (key.endsWith('_'+ep)) return { setattr: key.replace('_'+ep, ''), epname:ep }
918
+ }
919
+ }
920
+ catch {
921
+ return {};
922
+ }
923
+ return {};
924
+ }
962
925
  // This function is introduced to explicitly allow user level scripts to send Commands
963
926
  // directly to the zigbee device. It utilizes the zigbee-herdsman-converters to generate
964
927
  // the exact zigbee message to be sent and can be used to set device options which are
@@ -972,7 +935,6 @@ class Zigbee extends utils.Adapter {
972
935
  // endpoint: optional: the endpoint to send the data to, if supported.
973
936
  //
974
937
  async sendPayload(payload) {
975
- this.log.debug(`publishToDevice called with ${safeJsonStringify(payload)}`);
976
938
  let payloadObj = {};
977
939
  if (typeof payload === 'string') {
978
940
  try {
@@ -987,7 +949,7 @@ class Zigbee extends utils.Adapter {
987
949
  }
988
950
  } else if (typeof payload === 'object') {
989
951
  payloadObj = payload;
990
- }
952
+ } else return { success: false, error: 'illegal type of payload: ' + typeof payload};
991
953
 
992
954
  if (payloadObj.hasOwnProperty('device') && payloadObj.hasOwnProperty('payload')) {
993
955
  try {
@@ -1012,16 +974,24 @@ class Zigbee extends utils.Adapter {
1012
974
  this.sendError(`Illegal payload type for ${safeJsonStringify(payloadObj.device)}`);
1013
975
  return {success: false, error: `Illegal payload type for ${safeJsonStringify(payloadObj.device)}`};
1014
976
  }
977
+ const endpoints = mappedModel && mappedModel.endpoint ? mappedModel.endpoint(entity.device) : null;
1015
978
  for (const key in payloadObj.payload) {
1016
979
  if (payloadObj.payload[key] != undefined) {
1017
980
  const datatype = typeof payloadObj.payload[key];
981
+ const epobj = this.extractEP(key, endpoints);
982
+ if (payloadObj.endpoint) {
983
+ epobj.epname = payloadObj.endpoint;
984
+ delete epobj.setattr;
985
+ }
1018
986
  stateList.push({
1019
987
  stateDesc: {
1020
988
  id: key,
1021
989
  prop: key,
1022
990
  role: 'state',
1023
991
  type: datatype,
1024
- epname: payloadObj.endpoint,
992
+ noack:true,
993
+ epname: epobj.epname,
994
+ setattr: epobj.setattr,
1025
995
  },
1026
996
  value: payloadObj.payload[key],
1027
997
  index: 0,
@@ -1030,8 +1000,7 @@ class Zigbee extends utils.Adapter {
1030
1000
  }
1031
1001
  }
1032
1002
  try {
1033
- this.log.debug(`Calling publish to state for ${safeJsonStringify(payloadObj.device)} with ${safeJsonStringify(stateList)}`);
1034
- await this.publishFromState(`0x${payload.device}`, '', undefined, stateList, payload.options);
1003
+ await this.publishFromState(`0x${payload.device}`, payload.model, payload.stateModel, stateList, payload.options, Date.now());
1035
1004
  return {success: true};
1036
1005
  } catch (error) {
1037
1006
  this.log.error(`Error ${error.code} on send command to ${payload.device}.` + ` Error: ${error.stack} ` + `Send command to ${payload.device} failed with ` + error);
@@ -1048,28 +1017,39 @@ class Zigbee extends utils.Adapter {
1048
1017
 
1049
1018
 
1050
1019
  newDevice(entity) {
1051
- this.log.debug(`New device event: ${safeJsonStringify(entity)}`);
1052
- this.stController.AddModelFromHerdsman(entity.device, entity.mapped.model)
1020
+
1021
+ if (this.debugActive) this.log.debug(`New device event: ${safeJsonStringify(entity)}`);
1022
+ this.stController.AddModelFromHerdsman(entity.device, entity.mapped ? entity.mapped.model : entity.device.modelID)
1023
+
1053
1024
  const dev = entity.device;
1025
+ const model = (entity.mapped) ? entity.mapped.model : dev.modelID;
1026
+ this.log.debug(`New device event: ${safeJsonStringify(entity)}`);
1027
+ if (!entity.mapped && !entity.device.interviewing) {
1028
+ const msg = `New device: '${dev.ieeeAddr}' does not have a known model. please provide an external converter for '${dev.modelID}'.`;
1029
+ this.log.warn(msg);
1030
+ this.logToPairing(msg, true);
1031
+ }
1032
+ this.stController.AddModelFromHerdsman(entity.device, model)
1054
1033
  if (dev) {
1055
1034
  this.getObject(dev.ieeeAddr.substr(2), (err, obj) => {
1056
1035
  if (!obj) {
1057
1036
  const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID;
1058
- this.log.debug(`new device ${dev.ieeeAddr} ${dev.networkAddress} ${model} `);
1037
+ if (this.debugActive) this.log.debug(`new device ${dev.ieeeAddr} ${dev.networkAddress} ${model} `);
1038
+
1059
1039
  this.logToPairing(`New device joined '${dev.ieeeAddr}' model ${model}`, true);
1060
1040
  this.stController.updateDev(dev.ieeeAddr.substr(2), model, model, () =>
1061
1041
  this.stController.syncDevStates(dev, model));
1062
1042
  }
1063
- else this.log.debug(`Device ${safeJsonStringify(entity)} rejoined, no new device`);
1043
+ else if (this.debugActive) this.log.debug(`Device ${safeJsonStringify(entity)} rejoined, no new device`);
1064
1044
  });
1065
1045
  }
1066
1046
  }
1067
1047
 
1068
1048
  leaveDevice(ieeeAddr) {
1069
- this.log.debug(`Leave device event: ${ieeeAddr}`);
1049
+ if (this.debugActive) this.log.debug(`Leave device event: ${ieeeAddr}`);
1070
1050
  if (ieeeAddr) {
1071
1051
  const devId = ieeeAddr.substr(2);
1072
- this.log.debug(`Delete device ${devId} from iobroker.`);
1052
+ if (this.debugActive) this.log.debug(`Delete device ${devId} from iobroker.`);
1073
1053
  this.stController.deleteObj(devId);
1074
1054
  }
1075
1055
  }
@@ -1120,10 +1100,10 @@ class Zigbee extends utils.Adapter {
1120
1100
  }
1121
1101
  }
1122
1102
 
1123
- getZigbeeOptions() {
1103
+ getZigbeeOptions(_overrideOptions) {
1104
+ const override = (_overrideOptions ? _overrideOptions:{});
1124
1105
  // file path for db
1125
- let dbDir = path.join(utils.getAbsoluteInstanceDataDir(this), '');
1126
- dbDir = dbDir.replace('.', '_');
1106
+ const dbDir = this.expandFileName('');
1127
1107
 
1128
1108
  if (this.systemConfig && !fs.existsSync(dbDir)) {
1129
1109
  try {
@@ -1133,21 +1113,21 @@ class Zigbee extends utils.Adapter {
1133
1113
  this.sendError(`Cannot create directory ${dbDir}: ${e}`);
1134
1114
  }
1135
1115
  }
1136
- const port = this.config.port;
1116
+ const port = override.port ? override.port : this.config.port;
1137
1117
  if (!port) {
1138
1118
  this.log.error('Serial port not selected! Go to settings page.');
1139
1119
  this.sendError('Serial port not selected! Go to settings page.');
1140
1120
  }
1141
- const panID = parseInt(this.config.panID ? this.config.panID : 0x1a62);
1142
- const channel = parseInt(this.config.channel ? this.config.channel : 11);
1143
- const precfgkey = createByteArray(this.config.precfgkey ? this.config.precfgkey : '01030507090B0D0F00020406080A0C0D');
1144
- const extPanId = createByteArray(this.config.extPanID ? this.config.extPanID : 'DDDDDDDDDDDDDDDD').reverse();
1145
- const adapterType = this.config.adapterType || 'zstack';
1121
+ const panID = parseInt(override.panID ? override.panID : this.config.panID ? this.config.panID : 0x1a62);
1122
+ const channel = parseInt(override.channel ? override.channel : this.config.channel ? this.config.channel : 11);
1123
+ const precfgkey = createByteArray(override.precfgkey ? override.precfgkey : this.config.precfgkey ? this.config.precfgkey : '01030507090B0D0F00020406080A0C0D');
1124
+ const extPanId = createByteArray(override.extPanID ? override.extPanID : this.config.extPanID ? this.config.extPanID : 'DDDDDDDDDDDDDDDD').reverse();
1125
+ const adapterType = override.adapterType ? override.adapterType : this.config.adapterType || 'zstack';
1146
1126
  // https://github.com/ioBroker/ioBroker.zigbee/issues/668
1147
1127
  const extPanIdFix = this.config.extPanIdFix ? this.config.extPanIdFix : false;
1148
- const baudRate = parseInt(this.config.baudRate ? this.config.baudRate : 115200);
1128
+ const baudRate = parseInt(override.baudRate ? override.baudRate : this.config.baudRate ? this.config.baudRate : 115200);
1149
1129
 
1150
- const setRtscts = this.config.flowCTRL ? this.config.flowCTRL : false;
1130
+ const setRtscts = override.flowCTRL ? override.flowCTRL : this.config.flowCTRL ? this.config.flowCTRL : false;
1151
1131
 
1152
1132
  return {
1153
1133
  net: {
@@ -1162,6 +1142,7 @@ class Zigbee extends utils.Adapter {
1162
1142
  rtscts: setRtscts,
1163
1143
  adapter: adapterType,
1164
1144
  },
1145
+ transmitpower: this.transmitPower,
1165
1146
  dbDir: dbDir,
1166
1147
  dbPath: 'shepherd.db',
1167
1148
  backupPath: 'nvbackup.json',
@@ -1170,7 +1151,7 @@ class Zigbee extends utils.Adapter {
1170
1151
  transmitPower: this.config.transmitPower,
1171
1152
  disableBackup: this.config.disableBackup,
1172
1153
  extPanIdFix: extPanIdFix,
1173
- startWithInconsistent: this.config.startWithInconsistent || false,
1154
+ startWithInconsistent: override.startWithInconsistent ? override.startWithInconsistent: this.config.startWithInconsistent || false,
1174
1155
  };
1175
1156
  }
1176
1157
 
@@ -1194,7 +1175,12 @@ class Zigbee extends utils.Adapter {
1194
1175
  }
1195
1176
 
1196
1177
  expandFileName(fn) {
1197
- return path.join(utils.getAbsoluteInstanceDataDir(this), fn);
1178
+ return path.join(this.getDataFolder(), fn);
1179
+ }
1180
+
1181
+ getDataFolder() {
1182
+ const datapath=this.namespace.replace('.','_');
1183
+ return path.join(utils.getAbsoluteInstanceDataDir(this).replace(this.namespace, datapath));
1198
1184
  }
1199
1185
 
1200
1186
  onLog(level, msg, data) {
@@ -1205,7 +1191,8 @@ class Zigbee extends utils.Adapter {
1205
1191
  logger = this.log.error;
1206
1192
  if (data)
1207
1193
  data = data.toString();
1208
- this.logToPairing(`Error: ${msg}. ${data}`, true);
1194
+ if (this.ErrorMessagesToPairing)
1195
+ this.logToPairing(`Error: ${msg}. ${data}`, true);
1209
1196
  this.sendError(`Error: ${msg}. ${data}`);
1210
1197
  break;
1211
1198
  case 'debug':