iobroker.zigbee 3.0.3 → 3.1.2

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/lib/commands.js CHANGED
@@ -196,7 +196,7 @@ class Commands {
196
196
  }
197
197
  catch (error) {
198
198
  const msg = `Unable to read nvBackup ${error && error.message ? error.message : 'no message given'}`;
199
- this.error(msg);
199
+ //this.error(msg);
200
200
  this.adapter.sendTo(from, command, {error:msg}, callback)
201
201
  }
202
202
  }
@@ -240,12 +240,20 @@ class Commands {
240
240
  }
241
241
 
242
242
  async letsPairing(from, command, message, callback) {
243
- if (this.zbController) {
243
+ if (this.zbController && this.zbController.herdsmanStarted) {
244
244
  let devId = '';
245
245
  if (message) {
246
246
  if (message.id && message.id != undefined) {
247
247
  devId = getZbId(message.id);
248
248
  }
249
+ if (typeof devId == 'number') {
250
+ this.adapter.sendTo(
251
+ from, command,
252
+ {error: 'Pairing on a group is not supported'},
253
+ callback
254
+ );
255
+ return;
256
+ }
249
257
  if (message.code && message.code != undefined) {
250
258
  try {
251
259
  this.debug(`letsPairing called with code ${message.code}`);
@@ -273,23 +281,28 @@ class Commands {
273
281
  }
274
282
  // allow devices to join the network within 60 secs
275
283
  // this.adapter.logToPairing('Pairing started ' + devId, true);
276
-
277
284
  let cTimer = Number(this.adapter.config.countDown);
278
285
  if (!this.adapter.config.countDown || !cTimer) {
279
286
  cTimer = 60;
280
287
  }
288
+ if (message.stop) cTimer = 0;
281
289
 
282
- this.zbController.permitJoin(cTimer, devId, err => {
283
- if (!err) {
284
- // set pairing mode on
285
- this.adapter.setState('info.pairingMode', true);
286
- }
287
- });
288
- this.adapter.sendTo(from, command, 'Start pairing!', callback);
289
- } else {
290
+ if (await this.zbController.permitJoin(cTimer, devId)) {
291
+ this.adapter.setState('info.pairingMode', cTimer > 0, true);
292
+ this.adapter.sendTo(from, command, cTimer ? 'Start pairing!':'Stop pairing!', callback);
293
+ }
294
+ else {
295
+ this.adapter.sendTo(
296
+ from, command,
297
+ {error: 'Error opening the network'},
298
+ callback
299
+ );
300
+ }
301
+ }
302
+ else {
290
303
  this.adapter.sendTo(
291
304
  from, command,
292
- {error: 'You need to setup serial port and start the adapter before pairing!'},
305
+ {error: 'No connection to zigbee Hardware!'},
293
306
  callback
294
307
  );
295
308
  }
@@ -389,23 +402,25 @@ class Commands {
389
402
  if (groupmembers && groupmembers.length > 0) {
390
403
  const memberinfo = [];
391
404
  for (const member of groupmembers) {
392
- if (groups) {
393
- const grouparray = groups[member.ieee];
394
- if (grouparray) {
395
- if (!grouparray.includes(groupID)) {
396
- groups[member.ieee].push(groupID);
405
+ if (member && typeof member.ieee === 'string') {
406
+ if (groups) {
407
+ const grouparray = groups[member.ieee];
408
+ if (grouparray) {
409
+ if (!grouparray.includes(groupID)) {
410
+ groups[member.ieee].push(groupID);
411
+ }
412
+ } else {
413
+ groups[member.ieee] = [groupID];
397
414
  }
415
+ }
416
+ const device = await this.adapter.getObjectAsync(`${this.adapter.namespace}.${member.ieee.substr(2)}`);
417
+ if (device) {
418
+ member.device = device.common.name;
398
419
  } else {
399
- groups[member.ieee] = [groupID];
420
+ member.device = 'unknown';
400
421
  }
422
+ memberinfo.push(member);
401
423
  }
402
- const device = await this.adapter.getObjectAsync(`${this.adapter.namespace}.${member.ieee.substr(2)}`);
403
- if (device) {
404
- member.device = device.common.name;
405
- } else {
406
- member.device = 'unknown';
407
- }
408
- memberinfo.push(member);
409
424
  }
410
425
  devInfo.memberinfo = memberinfo;
411
426
  this.debug(`memberinfo for ${match[1]}: ${JSON.stringify(devInfo.memberinfo)}`);
@@ -464,7 +479,7 @@ class Commands {
464
479
  if (!id) {
465
480
  for (const d of pairedDevices) {
466
481
  const device = await this.zbController.resolveEntity(d.ieeeAddr);
467
- if (!device) {
482
+ if (!device || !device.device) {
468
483
  continue;
469
484
  }
470
485
  const exists = devices.find((dev) => (dev._id && device.device.ieeeAddr === getZbId(dev._id)));
@@ -506,76 +521,84 @@ class Commands {
506
521
 
507
522
 
508
523
  async getCoordinatorInfo(from, command, callback) {
509
- if (this.zbController && this.zbController.herdsmanStarted) {
510
- const coordinatorinfo = {
511
- installSource: 'IADefault_1',
512
- channel: '-1',
513
- port: 'Default_1',
514
- installedVersion: 'Default_1',
515
- type: 'Default_1',
516
- revision: 'Default_1',
517
- version: '9-9.9.9.9'
518
- };
519
-
520
- const coordinatorVersion = await this.adapter.zbController.herdsman.getCoordinatorVersion();
521
-
522
- await this.adapter.getForeignObject(`system.adapter.${this.adapter.namespace}`, (err, obj) => {
523
- if (!err && obj) {
524
- if (obj.common.installedFrom && obj.common.installedFrom.includes('://')) {
525
- const instFrom = obj.common.installedFrom;
526
- coordinatorinfo.installSource = instFrom.replace('tarball', 'commit');
527
- } else {
528
- coordinatorinfo.installSource = obj.common.installedFrom;
529
- }
524
+ const coordinatorinfo = {
525
+ installSource: 'IADefault_1',
526
+ channel: '-1',
527
+ port: 'Default_1',
528
+ installedVersion: 'Default_1',
529
+ type: 'Default_1',
530
+ revision: 'unknown',
531
+ version: 'unknown',
532
+ herdsman: this.adapter.zhversion,
533
+ converters: this.adapter.zhcversion,
534
+ };
535
+
536
+ const coordinatorVersion = this.zbController && this.zbController.herdsmanStarted ? await this.adapter.zbController.herdsman.getCoordinatorVersion() : {};
537
+
538
+ await this.adapter.getForeignObject(`system.adapter.${this.adapter.namespace}`, (err, obj) => {
539
+ if (!err && obj) {
540
+ if (obj.common.installedFrom && obj.common.installedFrom.includes('://')) {
541
+ const instFrom = obj.common.installedFrom;
542
+ coordinatorinfo.installSource = instFrom.replace('tarball', 'commit');
543
+ } else {
544
+ coordinatorinfo.installSource = obj.common.installedFrom;
530
545
  }
531
- try {
532
- coordinatorinfo.port = obj.native.port;
533
- coordinatorinfo.channel = obj.native.channel;
534
- coordinatorinfo.installedVersion = obj.native.version;
535
- if (coordinatorVersion && coordinatorVersion.type && coordinatorVersion.meta) {
536
- coordinatorinfo.type = coordinatorVersion.type;
537
- const meta = coordinatorVersion.meta;
538
- if (meta) {
539
- if (meta.hasOwnProperty('revision')) {
540
- coordinatorinfo.revision = meta.revision;
541
- }
542
- let vt = 'x-';
543
- if (meta.hasOwnProperty('transportrev')) {
544
- vt = meta.transportrev + '-';
545
- }
546
- if (meta.hasOwnProperty('product')) {
547
- vt = vt + meta.product + '.';
548
- } else {
549
- vt = vt + 'x.';
550
- }
551
- if (meta.hasOwnProperty('majorrel')) {
552
- vt = vt + meta.majorrel + '.';
553
- } else {
554
- vt = vt + 'x.';
555
- }
556
- if (meta.hasOwnProperty('minorrel')) {
557
- vt = vt + meta.minorrel + '.';
558
- } else {
559
- vt = vt + 'x.';
560
- }
561
- if (meta.hasOwnProperty('maintrel')) {
562
- vt = vt + meta.maintrel + '.';
563
- } else {
564
- vt = vt + 'x.';
565
- }
566
- coordinatorinfo.version = vt;
546
+ }
547
+ try {
548
+ coordinatorinfo.port = obj.native.port;
549
+ coordinatorinfo.type = obj.native.adapterType;
550
+ coordinatorinfo.channel = obj.native.channel;
551
+ coordinatorinfo.installedVersion = obj.common.version;
552
+ if (coordinatorVersion && coordinatorVersion.type && coordinatorVersion.meta) {
553
+ coordinatorinfo.type = coordinatorVersion.type;
554
+ const meta = coordinatorVersion.meta;
555
+ if (typeof meta == 'object') {
556
+ if (meta.hasOwnProperty('revision')) {
557
+ coordinatorinfo.revision = meta.revision;
558
+ }
559
+ let vt = 'x-';
560
+ if (meta.hasOwnProperty('transportrev')) {
561
+ vt = meta.transportrev + '-';
562
+ }
563
+ if (meta.hasOwnProperty('product')) {
564
+ vt = vt + meta.product + '.';
565
+ } else {
566
+ vt = vt + 'x.';
567
+ }
568
+ if (meta.hasOwnProperty('majorrel')) {
569
+ vt = vt + meta.majorrel + '.';
570
+ } else {
571
+ vt = vt + 'x.';
572
+ }
573
+ if (meta.hasOwnProperty('minorrel')) {
574
+ vt = vt + meta.minorrel + '.';
575
+ } else {
576
+ vt = vt + 'x.';
567
577
  }
578
+ if (meta.hasOwnProperty('maintrel')) {
579
+ vt = vt + meta.maintrel + '.';
580
+ } else {
581
+ vt = vt + 'x.';
582
+ }
583
+ coordinatorinfo.version = vt;
584
+ }
585
+ else {
586
+ coordinatorinfo.version = 'illegal data';
587
+ coordinatorinfo.revision = 'illegal data';
568
588
  }
569
- } catch {
570
- this.warn('exception raised in getCoordinatorInfo');
571
589
  }
590
+ else {
591
+ coordinatorinfo.version = 'not connected';
592
+ coordinatorinfo.revision = 'not connected';
572
593
 
573
- this.debug(`getCoordinatorInfo result: ${JSON.stringify(coordinatorinfo)}`);
574
- this.adapter.sendTo(from, command, coordinatorinfo, callback);
575
- });
576
- } else {
577
- this.adapter.sendTo(from, command, {error: 'No active connection to Zigbee Hardware!'}, callback);
578
- }
594
+ }
595
+ } catch {
596
+ this.warn('exception raised in getCoordinatorInfo');
597
+ }
598
+
599
+ this.debug(`getCoordinatorInfo result: ${JSON.stringify(coordinatorinfo)}`);
600
+ this.adapter.sendTo(from, command, coordinatorinfo, callback);
601
+ });
579
602
  }
580
603
 
581
604
 
@@ -598,18 +621,19 @@ class Commands {
598
621
  this.debug(`deleteDevice sysid: ${sysid}`);
599
622
  const dev = this.zbController.getDevice(sysid);
600
623
  if (!dev) {
601
- this.debug('Not found!');
602
- this.debug(`Try delete dev ${devId} from iobroker.`);
624
+ this.info(`Attempted to delete device ${devId} - the device is not known to the zigbee controller.`);
603
625
  this.stController.deleteObj(devId, () =>
604
626
  this.adapter.sendTo(from, command, {}, callback));
605
627
  return;
606
628
  }
629
+ this.info(`${force ? 'Force removing' : 'Gracefully removing '} device ${devId} from the network.`);
607
630
  this.zbController.remove(sysid, force, err => {
608
631
  if (!err) {
609
- this.stController.deleteObj(devId, () =>
610
- this.adapter.sendTo(from, command, {}, callback));
632
+ this.info('Device removed from the network, deleting objects.')
633
+ this.stController.deleteObj(devId, () => {
634
+ this.adapter.sendTo(from, command, {}, callback);
635
+ });
611
636
  } else {
612
- this.debug(`Error on remove! ${err}`);
613
637
  this.adapter.sendTo(from, command, {error: err}, callback);
614
638
  }
615
639
  });
@@ -710,7 +734,7 @@ class Commands {
710
734
  async updateLocalConfigItems(from, command, msg, callback) {
711
735
  if (this.stController) {
712
736
  this.debug(`updateLocalConfigItems : ${JSON.stringify(msg)}`);
713
- const target = msg.global ? msg.target : msg.target.replace(`${this.adapter.namespace}.`, '');
737
+ const target = msg.target.replace(`${this.adapter.namespace}.`, '');
714
738
  const entity = await this.zbController.resolveEntity(target);
715
739
  //this.warn('entity for ' + target + ' is '+ JSON.stringify(entity))
716
740
  if (entity && !entity.mapped) {
@@ -794,6 +818,13 @@ class Commands {
794
818
  }
795
819
 
796
820
  async testConnection(from, command, msg, callback) {
821
+ const result = await this.adapter.testConnection(msg.address, true);
822
+ if (result.error) {
823
+ this.error(result.error);
824
+ this.adapter.logToPairing(`Error: ${result.error}`)
825
+ }
826
+ this.adapter.sendTo(from, command, result, callback);
827
+ /*
797
828
  this.debug(`TestConnection with ${JSON.stringify(msg)}`);
798
829
  if (msg && msg.address) {
799
830
  const netAddress = getNetAddress(msg.address);
@@ -851,6 +882,7 @@ class Commands {
851
882
  }
852
883
  }
853
884
  }
885
+ */
854
886
  }
855
887
  }
856
888
 
package/lib/developer.js CHANGED
@@ -112,7 +112,7 @@ class Developer {
112
112
  return;
113
113
  }
114
114
  } catch (error) {
115
- this.error(`SendToZigbee failed from publishTarget ${devId} (${error})`);
115
+ this.error(`SendToZigbee failed from publishTarget ${devId} (${error && error.message ? error.message : 'no details given'})`);
116
116
  }
117
117
 
118
118
  if (!cid || !cmd) {
package/lib/devices.js CHANGED
@@ -119,11 +119,12 @@ const sync = {
119
119
  },
120
120
  };
121
121
 
122
- const lightStatesWithColortemp = [states.state, states.brightness, states.colortemp, states.brightness_move, states.colortemp_move, states.transition_time];
123
- const lightStatesWithColor = [states.state, states.brightness, states.colortemp, states.color, states.brightness_move, states.colortemp_move, states.transition_time];
124
- const lightStatesWithColor_hue = [states.state, states.brightness, states.colortemp, states.color, states.brightness_move, states.colortemp_move, states.hue_move, states.transition_time, states.effect_type_hue];
125
- const lightStatesWithColorNoTemp = [states.state, states.brightness, states.color, states.brightness_move, states.transition_time];
126
- const lightStates = [states.state, states.brightness, states.brightness_move, states.transition_time];
122
+ const lightStates = [states.state, states.brightness, states.brightness_move, states.transition_time, states.brightness_step];
123
+ const lightStatesWithColortemp = [...lightStates, states.colortemp, states.colortemp_move];
124
+ const lightStatesWithColor = [...lightStatesWithColortemp, states.color];
125
+ const lightStatesWithColor_hue = [...lightStatesWithColor, states.hue_move, states.transition_time, states.effect_type_hue];
126
+ const lightStatesWithColorNoTemp = [...lightStates, states.color];
127
+ const onOffStates = [states.state];
127
128
 
128
129
  const gl_lightStatesWithColor = [states.gl_state, states.gl_brightness, states.gl_colortemp, states.gl_color, states.transition_time];
129
130
  const gl_white_channel = [states.white_brightness, states.white_state, states.white_colortemp];
@@ -3072,7 +3073,7 @@ const commonStates = [
3072
3073
  const DevicesByModel = new Map();
3073
3074
  const LegacyDevicesByModel = new Map();
3074
3075
 
3075
- const groupStates = [states.brightness_step].concat(lightStatesWithColor);
3076
+ const groupStates = [states.groupstateupdate, states.groupmemberupdate, states.brightness_step].concat(lightStatesWithColor);
3076
3077
 
3077
3078
  function getByModel() {
3078
3079
  DevicesByModel.clear();
@@ -3171,8 +3172,11 @@ module.exports = {
3171
3172
  devices,
3172
3173
  legacy_devices,
3173
3174
  commonStates,
3175
+ commonGroupStates: [...commonStates, states.groupmemberupdate, states.groupstateupdate],
3174
3176
  groupStates,
3175
- groupsState: states.groups,
3177
+ lightStatesWithColor,
3178
+ onOffStates,
3179
+ lightStates,
3176
3180
  fillStatesWithExposes,
3177
3181
  addExposeToDevices,
3178
3182
  getByModel,
package/lib/exposes.js CHANGED
@@ -412,14 +412,25 @@ function createFromExposes(model, def, device, log) {
412
412
  return {...options, transition: transitionTime};
413
413
  },
414
414
  getter: payload => {
415
- if (typeof payload.color == 'object') {
416
- // Requires testing!
415
+ // Requires testing!
416
+
417
+ try {
418
+ // JSON
419
+ const colorJSON = JSON.parse(payload.replaceAll("'",'"'));
420
+ const numProp = Object.keys(colorJSON).length;
417
421
  if (hasMultipleProperties(colorJSON, ['r', 'g', 'b'], numProp)) {
418
422
  const hexstring = (colorJSON.r*65536 + colorJSON.g * 256 + colorJSON.b).toString(16).padStart(6);
419
423
  return `#${hexstring.substring(2)}`;
420
424
  }
425
+ return undefined;
426
+ }
427
+ catch {
428
+ // intentionally empty;
421
429
  }
422
- if (typeof payload.color === 'string' && payload.color.startsWith('#')) return payload.color;
430
+ if (payload.color.startsWith('#')) return payload.color;
431
+ const p = payload.replace('0x', '');
432
+ const m = p.match(/[0123456789abcdefABCDEF]+/);
433
+ if (p.length < 7 && m && m[0].length == p.length) return '#000000'.substring(0, 7-p.length) + p;
423
434
  return undefined;
424
435
  },
425
436
  epname: expose.endpoint,