iobroker.zigbee 1.6.3 → 1.6.14

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.
@@ -105,11 +105,11 @@ class ZigbeeController extends EventEmitter {
105
105
  this.debug('zigbee-herdsman started');
106
106
  this.herdsman_started = true;
107
107
  this.info(`Coordinator firmware version: ${JSON.stringify(await this.herdsman.getCoordinatorVersion())}`);
108
-
108
+
109
109
  // debug info from herdsman getNetworkParameters
110
110
  const debNetworkParam = JSON.parse(JSON.stringify(await this.herdsman.getNetworkParameters()));
111
111
  const extendedPanIDDebug = (typeof debNetworkParam.extendedPanID == 'string') ? debNetworkParam.extendedPanID.replace('0x','') : debNetworkParam.extendedPanID;
112
-
112
+
113
113
  let extPanIDDebug = '';
114
114
  for (let i = extendedPanIDDebug.length - 1; i >= 0; i--) {
115
115
  extPanIDDebug += extendedPanIDDebug[i-1];
@@ -117,8 +117,8 @@ class ZigbeeController extends EventEmitter {
117
117
  i--;
118
118
  }
119
119
 
120
- this.debug(`Zigbee network parameters: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`);
121
-
120
+ this.debug(`Zigbee network parameters: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`);
121
+
122
122
  } catch (e) {
123
123
  this.sendError(e);
124
124
  this.error('Starting zigbee-herdsman problem : ' + JSON.stringify(e.message));
@@ -148,6 +148,9 @@ class ZigbeeController extends EventEmitter {
148
148
  case '19':
149
149
  powerText = 'high';
150
150
  break;
151
+ case '20':
152
+ powerText = 'high+';
153
+ break;
151
154
  default:
152
155
  powerText = 'normal';
153
156
  }
@@ -175,8 +178,16 @@ class ZigbeeController extends EventEmitter {
175
178
  }
176
179
  for (const device of devices) {
177
180
  const entity = await this.resolveEntity(device);
181
+ this.adapter.getObject(device.ieeeAddr.substr(2),(err, obj) => {
182
+ if (obj && obj.common && obj.common.deactivated)
183
+ {
184
+ this.callExtensionMethod('deregisterDevicePing', [device, entity]);
185
+ }
186
+ else {
187
+ this.callExtensionMethod('registerDevicePing', [device, entity]);
188
+ }
189
+ });
178
190
  // ensure that objects for all found clients are present
179
- this.callExtensionMethod('registerDevicePing', [device, entity]);
180
191
 
181
192
  if (entity.mapped) this.emit('new', entity);
182
193
  this.info(
@@ -217,13 +228,14 @@ class ZigbeeController extends EventEmitter {
217
228
  }
218
229
 
219
230
  callExtensionMethod(method, parameters) {
231
+ const result = [];
220
232
  for (const extension of this.extensions) {
221
233
  if (extension[method]) {
222
234
  try {
223
235
  if (parameters !== undefined) {
224
- extension[method](...parameters);
236
+ result.push(extension[method](...parameters));
225
237
  } else {
226
- extension[method]();
238
+ result.push(extension[method]());
227
239
  }
228
240
  } catch (error) {
229
241
  this.sendError(error);
@@ -231,6 +243,7 @@ class ZigbeeController extends EventEmitter {
231
243
  }
232
244
  }
233
245
  }
246
+ return Promise.all(result);
234
247
  }
235
248
 
236
249
  async getClients(all) {
@@ -248,9 +261,11 @@ class ZigbeeController extends EventEmitter {
248
261
 
249
262
  async getGroups() {
250
263
  try {
251
- return this.herdsman.getGroups();
264
+ const rv = await this.herdsman.getGroups();
265
+ return rv;
252
266
  } catch (error) {
253
267
  this.sendError(error);
268
+ this.error(JSON.stringify(error));
254
269
  return undefined;
255
270
  }
256
271
  }
@@ -274,17 +289,32 @@ class ZigbeeController extends EventEmitter {
274
289
  }
275
290
  }
276
291
 
292
+ async verifyGroupExists(id) {
293
+ const nid = (typeof(id) === 'number' ? id:parseInt(id));
294
+ let group = await this.herdsman.getGroupByID(nid);
295
+ if (!group) {
296
+ group = await this.herdsman.createGroup(nid);
297
+ group.toZigbee = groupConverters;
298
+ group.model = 'group';
299
+ this.debug('verifyGroupExists: created group ' + nid);
300
+ }
301
+ else {
302
+ this.debug('verifyGroupExists: group ' + nid + ' exists');
303
+ }
304
+
305
+ }
306
+
277
307
  async getGroupMembersFromController(id) {
278
308
  const members = [];
279
309
  try {
280
310
  const group = await this.getGroupByID(id);
281
311
  if (group) {
282
312
  const groupmembers = group.members;
283
-
284
313
  for (const member of groupmembers) {
314
+ const epid = (member.ID ? member.ID:-1);
285
315
  const nwk = member.deviceNetworkAddress;
286
316
  const device = this.getDeviceByNetworkAddress(nwk);
287
- if (device && device.ieeeAddr) members.push( { device:device.ieeeAddr, model:device.modelID } );
317
+ if (device && device.ieeeAddr) members.push( { ieee:device.ieeeAddr, model:device.modelID, epid:epid, ep:member } );
288
318
  }
289
319
  }
290
320
  else {
@@ -525,6 +555,13 @@ class ZigbeeController extends EventEmitter {
525
555
  const entity = await this.resolveEntity(message.device || message.ieeeAddr);
526
556
  const friendlyName = entity.name;
527
557
  this.warn(`Device '${friendlyName}' announced itself`);
558
+
559
+ if (entity && entity.mapped) {
560
+ this.callExtensionMethod(
561
+ 'onZigbeeEvent',
562
+ [ {'device': message.device, 'type': 'deviceAnnounce'}, (entity ? entity.mapped : null)]);
563
+ }
564
+
528
565
  this.emit('pairing', `Device '${friendlyName}' announced itself`);
529
566
  if (!this.herdsman.getPermitJoin()) this.callExtensionMethod('registerDevicePing', [message.device, entity]);
530
567
  // if has modelID so can create device
@@ -534,6 +571,7 @@ class ZigbeeController extends EventEmitter {
534
571
  }
535
572
  }
536
573
 
574
+
537
575
  async handleDeviceJoined(message) {
538
576
  this.debug('handleDeviceJoined', message);
539
577
  //const entity = await this.resolveEntity(message.device || message.ieeeAddr);
@@ -686,7 +724,7 @@ class ZigbeeController extends EventEmitter {
686
724
  }
687
725
  }
688
726
 
689
- async publish(deviceID, cid, cmd, zclData, cfg, ep, type, callback) {
727
+ async publish(deviceID, cid, cmd, zclData, cfg, ep, type, callback, zclSeqNum) {
690
728
  const entity = await this.resolveEntity(deviceID, ep);
691
729
  const device = entity.device;
692
730
  const endpoint = entity.endpoint;
@@ -727,20 +765,57 @@ class ZigbeeController extends EventEmitter {
727
765
  result = await endpoint[cmd](cid, zclData, cfg);
728
766
  }
729
767
  if (callback) callback(undefined, result);
730
- } else {
768
+ }
769
+ else if(type === 'functionalResp'){
770
+ cfg.disableDefaultResponse = false;
771
+ const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum);
772
+ if (callback) callback(undefined, result);
773
+ }
774
+ else {
731
775
  cfg.disableDefaultResponse = false;
732
776
  const result = await endpoint.command(cid, cmd, zclData, cfg);
733
777
  if (callback) callback(undefined, result);
734
778
  }
735
779
  }
736
780
 
737
- async addDevToGroup(devId, groupId) {
781
+ async addDevToGroup(devId, groupId, epid) {
738
782
  try {
739
783
  const entity = await this.resolveEntity(devId);
740
784
  const group = await this.resolveEntity(groupId);
741
- this.debug(`entity: ${safeJsonStringify(entity)}`);
742
- this.debug(`group: ${safeJsonStringify(group)}`);
743
- await entity.endpoint.addToGroup(group.mapped);
785
+ this.debug(`addDevFromGroup - entity: ${safeJsonStringify(entity)}`);
786
+ this.debug(`addDevFromGroup - group: ${safeJsonStringify(group)}`);
787
+ if (epid != undefined) {
788
+ for (const ep of entity.endpoints) {
789
+ if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)))
790
+ {
791
+ this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`)
792
+ await(ep.addToGroup(group.mapped));
793
+ }
794
+ }
795
+
796
+ }
797
+ else
798
+ {
799
+ if (entity.endpoint.inputClusters.includes(4))
800
+ {
801
+ this.debug(`adding endpoint ${entity.endpoint.ID} to group`)
802
+ await entity.endpoint.addToGroup(group.mapped);
803
+ }
804
+ else {
805
+ let added = false;
806
+ for (const ep of entity.endpoints)
807
+ {
808
+ if (ep.inputClusters.includes(4))
809
+ {
810
+ this.debug(`adding endpoint ${ep.ID} to group`)
811
+ await ep.addToGroup(group.mapped);
812
+ added = true;
813
+ break;
814
+ }
815
+ }
816
+ if (!added) throw ('cluster genGroups not supported');
817
+ }
818
+ }
744
819
  } catch (error) {
745
820
  this.sendError(error);
746
821
  this.error(`Exception when trying to Add ${devId} to group ${groupId}`, error);
@@ -749,11 +824,38 @@ class ZigbeeController extends EventEmitter {
749
824
  return {};
750
825
  }
751
826
 
827
+ async removeDevFromGroup(devId, groupId, epid) {
828
+ try {
829
+ const entity = await this.resolveEntity(devId);
830
+ const group = await this.resolveEntity(groupId);
831
+ this.debug(`removeDevFromGroup - entity: ${safeJsonStringify(entity)}`);
832
+ this.debug(`removeDevFromGroup - group: ${safeJsonStringify(group)}`);
833
+ if (epid != undefined) {
834
+ for (const ep of entity.endpoints) {
835
+ if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)))
836
+ {
837
+ this.debug(`removing endpoint ${ep.ID} (${epid}) group ${groupId}`)
838
+ await(ep.removeFromGroup(group.mapped))
839
+ }
840
+ }
841
+ } else await entity.endpoint.removeFromGroup(group.mapped);
842
+ } catch (error) {
843
+ this.sendError(error);
844
+ this.error(`Exception when trying remove ${devId} (ep ${epid?epid:entity.endpoint.ID}) from group ${devId}`, error);
845
+ return { error: `Failed to remove dev ${devId} (ep ${epid?epid:entity.endpoint.ID}) from group ${devId}`};
846
+ }
847
+ return {};
848
+ }
849
+
752
850
  async removeDevFromAllGroups(devId) {
753
851
  try {
754
852
  const entity = await this.resolveEntity(devId);
755
853
  this.debug(`entity: ${safeJsonStringify(entity)}`);
756
- await entity.endpoint.removeFromAllGroups();
854
+ for (const ep of entity.endpoints) {
855
+ if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))
856
+ await ep.removefromAllGroups();
857
+ }
858
+ //await entity.endpoint.removeFromAllGroups();
757
859
  } catch (error) {
758
860
  this.sendError(error);
759
861
  this.error(`Exception when trying remove ${devId} from all groups`, error);
package/main.js CHANGED
@@ -159,7 +159,7 @@ class Zigbee extends utils.Adapter {
159
159
  this.log.error(`${message}: Code ${error.code} (${ecode.message})`);
160
160
  this.sendError(error, `${message}: Code ${error.code} (${ecode.message})`);
161
161
  break;
162
- default:
162
+ default:
163
163
  this.log.error(`${message}: Code ${error.code} (malformed error)`);
164
164
  this.sendError(error, `${message}: Code ${error.code} (malformed error)`);
165
165
  }
@@ -431,7 +431,7 @@ class Zigbee extends utils.Adapter {
431
431
  delete msgForState['endpoint'];
432
432
  msgForState['endpoint_id'] = message.endpoint.ID;
433
433
  this.publishToState(devId, model, {msg_from_zigbee: safeJsonStringify(msgForState)});
434
-
434
+
435
435
  if (!entity.mapped) {
436
436
  return;
437
437
  }
@@ -497,6 +497,10 @@ class Zigbee extends utils.Adapter {
497
497
  const entity = await this.zbController.resolveEntity(deviceId);
498
498
  this.log.debug(`entity: ${safeJsonStringify(entity)}`);
499
499
  const mappedModel = entity.mapped;
500
+ if (!mappedModel) {
501
+ this.log.debug(`No mapped model for ${model}`);
502
+ return;
503
+ }
500
504
  this.log.debug('Mapped Model: ' + JSON.stringify(mappedModel));
501
505
 
502
506
  stateList.forEach(async(changedState) => {
@@ -767,8 +771,8 @@ class Zigbee extends utils.Adapter {
767
771
  getZigbeeOptions() {
768
772
  // file path for db
769
773
  let dbDir = path.join(utils.getAbsoluteInstanceDataDir(this), '');
770
- dbDir = dbDir.replace('.', '_');
771
-
774
+ dbDir = dbDir.replace('.', '_');
775
+
772
776
  if (this.systemConfig && !fs.existsSync(dbDir)) {
773
777
  try {
774
778
  fs.mkdirSync(dbDir);
@@ -833,6 +837,10 @@ class Zigbee extends utils.Adapter {
833
837
  this.setState('info.pairingMessage', message, true);
834
838
  }
835
839
 
840
+ expandFileName(fn) {
841
+ return path.join(utils.getAbsoluteInstanceDataDir(this), fn);
842
+ }
843
+
836
844
  onLog(level, msg, data) {
837
845
  if (msg) {
838
846
  let logger = this.log.info;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee",
3
- "version": "1.6.3",
3
+ "version": "1.6.14",
4
4
  "author": {
5
5
  "name": "Kirov Ilya",
6
6
  "email": "kirovilya@gmail.com"
@@ -18,8 +18,8 @@
18
18
  "node": ">=10"
19
19
  },
20
20
  "dependencies": {
21
- "zigbee-herdsman": "0.13.149",
22
- "zigbee-herdsman-converters": "14.0.256",
21
+ "zigbee-herdsman": "0.14.6",
22
+ "zigbee-herdsman-converters": "14.0.397",
23
23
  "@iobroker/adapter-core": "^2.4.0",
24
24
  "tar": "^6.0.5",
25
25
  "typescript": "^4.0.5"