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.
- package/README.md +68 -14
- package/admin/adapter-settings.js +39 -3
- package/admin/admin.js +273 -47
- package/admin/img/14153905L.png +0 -0
- package/admin/img/81855.png +0 -0
- package/admin/img/HG06338.png +0 -0
- package/admin/img/R7060.png +0 -0
- package/admin/img/TI0001-cover.png +0 -0
- package/admin/img/WHD02.png +0 -0
- package/admin/img/ikea_E1812.png +0 -0
- package/admin/img/tuya_rb280.png +0 -0
- package/admin/index_m.html +170 -24
- package/admin/tab_m.html +181 -216
- package/admin/words.js +30 -29
- package/docs/tutorial/zigbee.png +0 -0
- package/io-package.json +28 -1
- package/lib/commands.js +75 -9
- package/lib/developer.js +6 -2
- package/lib/devices.js +46 -1
- package/lib/exposes.js +3 -1
- package/lib/groups.js +54 -28
- package/lib/ota.js +26 -0
- package/lib/rgb.js +30 -0
- package/lib/states.js +40 -14
- package/lib/statescontroller.js +207 -92
- package/lib/utils.js +1 -1
- package/lib/zbBaseExtension.js +4 -3
- package/lib/zbDelayedAction.js +1 -0
- package/lib/zbDeviceAvailability.js +14 -2
- package/lib/zbDeviceConfigure.js +11 -7
- package/lib/zbDeviceEvent.js +6 -0
- package/lib/zigbeecontroller.js +119 -17
- package/main.js +12 -4
- package/package.json +3 -3
package/lib/zigbeecontroller.js
CHANGED
|
@@ -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
|
-
|
|
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( {
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
"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.
|
|
22
|
-
"zigbee-herdsman-converters": "14.0.
|
|
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"
|