iobroker.zigbee 3.1.4 → 3.1.6
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 +9 -0
- package/admin/admin.js +879 -680
- package/admin/img/philips_hue_lom001.png +0 -0
- package/admin/index_m.html +40 -150
- package/admin/tab_m.html +137 -238
- package/docs/tutorial/groups-1.png +0 -0
- package/docs/tutorial/groups-2.png +0 -0
- package/docs/tutorial/tab-dev-1.png +0 -0
- package/io-package.json +28 -28
- package/lib/DeviceDebug.js +0 -1
- package/lib/commands.js +117 -64
- package/lib/developer.js +0 -0
- package/lib/exposes.js +3 -2
- package/lib/localConfig.js +8 -0
- package/lib/ota.js +0 -0
- package/lib/statescontroller.js +1 -1
- package/lib/zbDeviceConfigure.js +0 -0
- package/lib/zbDeviceEvent.js +0 -1
- package/lib/zigbeecontroller.js +15 -7
- package/main.js +14 -21
- package/package.json +4 -4
package/lib/commands.js
CHANGED
|
@@ -176,6 +176,9 @@ class Commands {
|
|
|
176
176
|
case 'downloadIcons':
|
|
177
177
|
this.triggerIconDownload(obj);
|
|
178
178
|
break;
|
|
179
|
+
case 'aliveCheck':
|
|
180
|
+
this.adapter.sendTo(obj.from, obj.command, {msg:'success'}, obj.callback);
|
|
181
|
+
break;
|
|
179
182
|
default:
|
|
180
183
|
this.debug(`Commands: Command ${obj.command} is unknown`);
|
|
181
184
|
//this.adapter.sendTo(obj.from, obj.command, obj.message, obj.callback);
|
|
@@ -336,10 +339,6 @@ class Commands {
|
|
|
336
339
|
}
|
|
337
340
|
}
|
|
338
341
|
|
|
339
|
-
|
|
340
|
-
async handleDeviceforInfo(device, states) {
|
|
341
|
-
}
|
|
342
|
-
|
|
343
342
|
async handleGroupforInfo(group, groups) {
|
|
344
343
|
group.icon = 'img/group.png';
|
|
345
344
|
group.vendor = 'ioBroker';
|
|
@@ -355,7 +354,13 @@ class Commands {
|
|
|
355
354
|
if (member && typeof member.ieee === 'string') {
|
|
356
355
|
const memberId = member.ieee.substr(2);
|
|
357
356
|
const device = await this.adapter.getObjectAsync(`${this.adapter.namespace}.${member.ieee.substr(2)}`);
|
|
358
|
-
|
|
357
|
+
const item = groups[memberId] || { groups:[], gep: { }};
|
|
358
|
+
const gep = item.gep[member.epid] || [];
|
|
359
|
+
|
|
360
|
+
if (!item.groups.includes(groupID)) item.groups.push(groupID);
|
|
361
|
+
if (!gep.includes(`${groupID}`)) gep.push(`${groupID}`);
|
|
362
|
+
item.gep[member.epid] = gep;
|
|
363
|
+
groups[memberId] = item;
|
|
359
364
|
if (device) {
|
|
360
365
|
member.device = device.common.name;
|
|
361
366
|
} else {
|
|
@@ -370,7 +375,7 @@ class Commands {
|
|
|
370
375
|
}
|
|
371
376
|
}
|
|
372
377
|
|
|
373
|
-
async fillInfo(device, device_stateDefs, all_states) {
|
|
378
|
+
async fillInfo(device, device_stateDefs, all_states, models) {
|
|
374
379
|
device.statesDef = (device_stateDefs || []).filter(stateDef => {
|
|
375
380
|
const sid = stateDef._id.replace(this.adapter.namespace + '.', '');
|
|
376
381
|
const names = sid.split('.');
|
|
@@ -394,7 +399,23 @@ class Commands {
|
|
|
394
399
|
});
|
|
395
400
|
|
|
396
401
|
const id = getZbId(device._id);
|
|
397
|
-
|
|
402
|
+
const entity = await this.zbController.resolveEntity(id)
|
|
403
|
+
|
|
404
|
+
device.info = this.buildDeviceInfo(entity);
|
|
405
|
+
|
|
406
|
+
const UID = models.UIDbyModel[device.info?.mapped?.model || 'unknown'] || `m_${Object.keys(models.UIDbyModel).length}`;
|
|
407
|
+
if (models.byUID.hasOwnProperty(UID)) {
|
|
408
|
+
models.byUID[UID].devices.push(device);
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
models.byUID[UID] = {
|
|
412
|
+
model:device.info.mapped,
|
|
413
|
+
availableOptions : [...device.info?.mapped?.options || [], ...['use_legacy_model']],
|
|
414
|
+
setOptions: this.adapter.stController.localConfig.getByModel(device.info?.mapped?.model || 'unknown') || [],
|
|
415
|
+
devices: [device],
|
|
416
|
+
}
|
|
417
|
+
models.UIDbyModel[device.info?.mapped?.model || 'unknown'] = UID;
|
|
418
|
+
}
|
|
398
419
|
// check configuration
|
|
399
420
|
try {
|
|
400
421
|
if (device.info) {
|
|
@@ -403,13 +424,11 @@ class Commands {
|
|
|
403
424
|
[device.info.device, device.info.mapped],
|
|
404
425
|
);
|
|
405
426
|
if (result.length > 0) device.isConfigured = !result[0];
|
|
406
|
-
|
|
427
|
+
device.paired = true;
|
|
428
|
+
} else device.paired = false;
|
|
407
429
|
} catch (error) {
|
|
408
430
|
this.warn('error calling shouldConfigure: ' + error && error.message ? error.message : 'no error message');
|
|
409
431
|
}
|
|
410
|
-
device.paired = !!device.info;
|
|
411
|
-
|
|
412
|
-
|
|
413
432
|
}
|
|
414
433
|
|
|
415
434
|
buildDeviceInfo(device) {
|
|
@@ -418,11 +437,11 @@ class Commands {
|
|
|
418
437
|
rv.device = {
|
|
419
438
|
modelZigbee:device.device.modelID,
|
|
420
439
|
type:device.device.type,
|
|
421
|
-
ieee:device.device.ieeeAddr,
|
|
422
|
-
nwk:device.device.networkAddress,
|
|
440
|
+
ieee:device.device.ieeeAddr || device.device.groupID,
|
|
441
|
+
nwk:device.device.networkAddress || 0,
|
|
423
442
|
manuf_id:device.device.maufacturerID,
|
|
424
443
|
manuf_name:device.device.manufacturerName,
|
|
425
|
-
manufacturer:device.mapped
|
|
444
|
+
manufacturer:device.mapped?.vendor,
|
|
426
445
|
power:device.device.powerSource,
|
|
427
446
|
app_version:device.device.applicationVersion,
|
|
428
447
|
hard_version:device.device.hardwareVersion,
|
|
@@ -442,25 +461,40 @@ class Commands {
|
|
|
442
461
|
output_clusters:ep.outputClusters,
|
|
443
462
|
})
|
|
444
463
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
464
|
+
if (device.mapped) {
|
|
465
|
+
rv.mapped = {
|
|
466
|
+
model:device.mapped.model,
|
|
467
|
+
description:device.mapped.description,
|
|
468
|
+
//fingerprint:JSON.stringify(device.mapped.fingerprint),
|
|
469
|
+
vendor:device.mapped.vendor,
|
|
470
|
+
hasOnEvent:device.mapped.onEvent != undefined,
|
|
471
|
+
hasConfigure:device.mapped.configure != undefined,
|
|
472
|
+
options:[],
|
|
473
|
+
}
|
|
474
|
+
if (device.mapped.options && typeof (device.mapped.options == 'object')) {
|
|
475
|
+
for (const option of device.mapped.options) {
|
|
476
|
+
if (option.name) {
|
|
477
|
+
rv.mapped.options.push(option.name);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
rv.mapped = {
|
|
484
|
+
model:device.name,
|
|
485
|
+
description:device.name,
|
|
486
|
+
vendor:'not set',
|
|
487
|
+
hasOnEvent: false,
|
|
488
|
+
hasConfigure: false,
|
|
489
|
+
options:[],
|
|
459
490
|
}
|
|
460
491
|
}
|
|
461
492
|
}
|
|
462
493
|
catch (error) {
|
|
463
|
-
|
|
494
|
+
if (device && device.name === 'Coordinator') return rv;
|
|
495
|
+
const dev = device ? device.device || {} : {}
|
|
496
|
+
const msg = device ? `device ${device.name} (${dev.ieeeAddr}, NWK ${dev.networkAddres}, ID: ${dev.ID})` : 'undefined device';
|
|
497
|
+
this.warn(`Error ${error && error.message ? error.message + ' ' : ''}building device info for ${msg}`);
|
|
464
498
|
}
|
|
465
499
|
return rv;
|
|
466
500
|
}
|
|
@@ -472,19 +506,23 @@ class Commands {
|
|
|
472
506
|
}
|
|
473
507
|
const exists = devices.find((dev) => (dev._id && device.device.ieeeAddr === getZbId(dev._id)));
|
|
474
508
|
if (!exists) {
|
|
475
|
-
|
|
476
|
-
_id: device.device.ieeeAddr
|
|
477
|
-
icon: 'img/unknown.png',
|
|
509
|
+
const coordinatorData = {
|
|
510
|
+
_id : `${this.adapter.namespace}.${device.device.ieeeAddr.substring(2)}`,
|
|
478
511
|
paired: true,
|
|
479
512
|
info: this.buildDeviceInfo(device),
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
513
|
+
native: { id: device.device.ieeeAddr.substring(2) },
|
|
514
|
+
mapped : { model:'Coordinator' },
|
|
515
|
+
statesDev: [],
|
|
516
|
+
}
|
|
517
|
+
if (device.device.name === 'Coordinator') {
|
|
518
|
+
coordinatorData.icon = 'zigbee.png';
|
|
519
|
+
coordinatorData.common = { name: undefined, type: undefined };
|
|
520
|
+
} else {
|
|
521
|
+
coordinatorData.common = { name: 'Coordinator', type: 'Coordinator' };
|
|
522
|
+
coordinatorData.icon= 'img/unknown.png';
|
|
523
|
+
}
|
|
524
|
+
devices.push(coordinatorData);
|
|
486
525
|
}
|
|
487
|
-
|
|
488
526
|
}
|
|
489
527
|
|
|
490
528
|
async getDevices(from, command, id, callback) {
|
|
@@ -493,13 +531,14 @@ class Commands {
|
|
|
493
531
|
this.adapter.sendTo(from, command, {error: 'No active connection to Zigbee Hardware!'}, callback);
|
|
494
532
|
return;
|
|
495
533
|
}
|
|
496
|
-
const
|
|
534
|
+
const roomsEnum = await this.adapter.getEnumsAsync('enum.rooms') || {};
|
|
497
535
|
const deviceObjects = (id ? [await this.adapter.getObjectAsync(id)] : await this.adapter.getDevicesAsync());
|
|
498
536
|
const all_states = id ? await this.adapter.getStatesAsync(id + '.*') : await this.adapter.getStatesAsync('*');
|
|
499
537
|
const all_stateDefs = id ? await this.adapter.getStatesOfAsync(id) : await this.adapter.getStatesOfAsync();
|
|
500
538
|
const illegalDevices = [];
|
|
501
539
|
const groups = {};
|
|
502
540
|
const PromiseChain = [];
|
|
541
|
+
const models = { byUID : {}, UIDbyModel: {} };
|
|
503
542
|
for (const devInfo of deviceObjects) {
|
|
504
543
|
if (devInfo._id.indexOf('group') > -1) {
|
|
505
544
|
PromiseChain.push(this.handleGroupforInfo(devInfo, groups));
|
|
@@ -515,25 +554,26 @@ class Commands {
|
|
|
515
554
|
devInfo.link_quality_lc = lq_state ? lq_state.lc : undefined;
|
|
516
555
|
const battery_state = all_states[`${devInfo._id}.battery`];
|
|
517
556
|
devInfo.battery = battery_state ? battery_state.val : undefined;
|
|
518
|
-
devInfo.rooms = [];
|
|
519
|
-
for (const room in rooms) {
|
|
520
|
-
if (!rooms.hasOwnProperty(room) ||
|
|
521
|
-
!rooms[room] ||
|
|
522
|
-
!rooms[room].common ||
|
|
523
|
-
!rooms[room].common.members
|
|
524
|
-
) {
|
|
525
|
-
continue;
|
|
526
|
-
}
|
|
527
|
-
if (rooms[room].common.members.includes(devInfo._id)) {
|
|
528
|
-
devInfo.rooms.push(rooms[room].common.name);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
557
|
|
|
532
558
|
}
|
|
533
|
-
|
|
559
|
+
devInfo.rooms = [];
|
|
560
|
+
const rooms = roomsEnum['enum.rooms'] || {};
|
|
561
|
+
for (const room of Object.keys(rooms)) {
|
|
562
|
+
if (!rooms.hasOwnProperty(room) ||
|
|
563
|
+
!rooms[room] ||
|
|
564
|
+
!rooms[room].common ||
|
|
565
|
+
!rooms[room].common.members
|
|
566
|
+
) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
if (rooms[room].common.members.includes(devInfo._id)) {
|
|
570
|
+
devInfo.rooms.push(rooms[room].common.name);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
PromiseChain.push(this.fillInfo(devInfo, all_stateDefs.filter(item => item._id.startsWith(devInfo._id)),all_states, models));
|
|
534
574
|
}
|
|
535
575
|
if (!id) {
|
|
536
|
-
for (const client of this.zbController.getClientIterator(
|
|
576
|
+
for (const client of this.zbController.getClientIterator(true)) {
|
|
537
577
|
PromiseChain.push(this.appendDevicesWithoutObjects(deviceObjects,client))
|
|
538
578
|
}
|
|
539
579
|
}
|
|
@@ -543,14 +583,20 @@ class Commands {
|
|
|
543
583
|
for (const groupmember in groups) {
|
|
544
584
|
const device = deviceObjects.find(dev => (groupmember === dev.native.id));
|
|
545
585
|
if (device) {
|
|
546
|
-
device.groups = groups[groupmember];
|
|
586
|
+
device.groups = groups[groupmember].groups;
|
|
587
|
+
device.groups_by_ep = groups[groupmember].gep;
|
|
547
588
|
}
|
|
548
589
|
}
|
|
549
590
|
|
|
550
591
|
|
|
551
592
|
this.debug(`getDevices contains ${deviceObjects.length} Devices`);
|
|
552
593
|
const rv = { devices:deviceObjects, inLog:this.adapter.deviceDebug.logStatus, }
|
|
553
|
-
if (!id)
|
|
594
|
+
if (!id) {
|
|
595
|
+
rv.deviceDebugData = this.adapter.deviceDebug.collectDebugData();
|
|
596
|
+
rv.localOverrides = this.adapter.stController.localConfig.localData;
|
|
597
|
+
rv.models = models.byUID;
|
|
598
|
+
}
|
|
599
|
+
|
|
554
600
|
if (this.stController) {
|
|
555
601
|
rv.clean = this.stController.CleanupRequired();
|
|
556
602
|
rv.errors = this.stController.getStashedErrors();
|
|
@@ -777,7 +823,6 @@ class Commands {
|
|
|
777
823
|
this.debug(`updateLocalConfigItems : ${JSON.stringify(msg)}`);
|
|
778
824
|
const target = msg.target.replace(`${this.adapter.namespace}.`, '');
|
|
779
825
|
const entity = await this.zbController.resolveEntity(target);
|
|
780
|
-
//this.warn('entity for ' + target + ' is '+ JSON.stringify(entity))
|
|
781
826
|
if (entity && !entity.mapped) {
|
|
782
827
|
this.warn('unable to set local Override for device whithout mapped model');
|
|
783
828
|
return;
|
|
@@ -811,13 +856,18 @@ class Commands {
|
|
|
811
856
|
await this.stController.localConfig.updateLocalOverride(target, (entity ? entity.mapped.model : 'group'), prop, msg.data[prop], msg.global);
|
|
812
857
|
}
|
|
813
858
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
859
|
+
try {
|
|
860
|
+
if (entity) {
|
|
861
|
+
this.debug('updateLocalConfigItems with Entity');
|
|
862
|
+
this.stController.updateDev(target, entity.mapped.model, entity.mapped.model, () => {this.adapter.sendTo(from, command, {}, callback)});
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
this.debug('updateLocalConfigItems without Entity');
|
|
866
|
+
this.stController.updateDev(target, undefined, 'group',() => {this.adapter.sendTo(from, command, {}, callback)});
|
|
867
|
+
}
|
|
817
868
|
}
|
|
818
|
-
|
|
819
|
-
this.
|
|
820
|
-
this.stController.updateDev(target, undefined, 'group',() => {this.adapter.sendTo(from, command, {}, callback)});
|
|
869
|
+
catch (error) {
|
|
870
|
+
this.adapter.sendTo(from, command, {err: error.message}, callback);
|
|
821
871
|
}
|
|
822
872
|
}
|
|
823
873
|
}
|
|
@@ -841,6 +891,9 @@ class Commands {
|
|
|
841
891
|
//const targetModel = msg.model ? msg.model : '';
|
|
842
892
|
}
|
|
843
893
|
else {
|
|
894
|
+
if (msg.getAllData) {
|
|
895
|
+
this.adapter.sendTo(from, command, this.stController.localConfig.localData, callback);
|
|
896
|
+
}
|
|
844
897
|
rv.error = `missing data in message ${JSON.stringify(msg)}`;
|
|
845
898
|
}
|
|
846
899
|
}
|
package/lib/developer.js
CHANGED
|
File without changes
|
package/lib/exposes.js
CHANGED
|
@@ -801,7 +801,7 @@ function createFromExposes(model, def, device, log) {
|
|
|
801
801
|
|
|
802
802
|
case 'climate':
|
|
803
803
|
for (const prop of expose.features) {
|
|
804
|
-
switch (prop.name) {
|
|
804
|
+
/* switch (prop.name) {
|
|
805
805
|
case 'away_mode':
|
|
806
806
|
pushToStates(statesDefs.climate_away_mode, prop.access);
|
|
807
807
|
break;
|
|
@@ -814,7 +814,8 @@ function createFromExposes(model, def, device, log) {
|
|
|
814
814
|
default:
|
|
815
815
|
pushToStates(genState(prop), prop.access);
|
|
816
816
|
break;
|
|
817
|
-
}
|
|
817
|
+
}*/
|
|
818
|
+
pushToStates(genState(prop), prop.access);
|
|
818
819
|
}
|
|
819
820
|
break;
|
|
820
821
|
|
package/lib/localConfig.js
CHANGED
|
@@ -329,6 +329,14 @@ class localConfig extends EventEmitter {
|
|
|
329
329
|
return rv;
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
getByModel(id) {
|
|
333
|
+
return this.localData.by_model[id] || {};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
getByDevice(id) {
|
|
337
|
+
return this.localData.by_id[id] || {};
|
|
338
|
+
}
|
|
339
|
+
|
|
332
340
|
}
|
|
333
341
|
|
|
334
342
|
module.exports = localConfig;
|
package/lib/ota.js
CHANGED
|
File without changes
|
package/lib/statescontroller.js
CHANGED
|
@@ -458,7 +458,7 @@ class StatesController extends EventEmitter {
|
|
|
458
458
|
if (stateDesc.id === 'send_payload') {
|
|
459
459
|
try {
|
|
460
460
|
const json_value = JSON.parse(value);
|
|
461
|
-
const payload = {device: deviceId.replace('0x', ''), payload: json_value, model:model, stateModel:stateModel};
|
|
461
|
+
const payload = {device: deviceId.replace('0x', ''), payload: json_value, model:model, stateModel:stateModel, acknowledge:true};
|
|
462
462
|
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 }});
|
|
463
463
|
|
|
464
464
|
this.emit('send_payload', payload, debugID, has_elevated_debug);
|
package/lib/zbDeviceConfigure.js
CHANGED
|
File without changes
|
package/lib/zbDeviceEvent.js
CHANGED
package/lib/zigbeecontroller.js
CHANGED
|
@@ -618,6 +618,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
618
618
|
device: coordinator,
|
|
619
619
|
endpoint: coordinator.getEndpoint(1),
|
|
620
620
|
name: 'Coordinator',
|
|
621
|
+
mapped: { model: 'Coordinator'},
|
|
621
622
|
options:{}
|
|
622
623
|
};
|
|
623
624
|
}
|
|
@@ -657,6 +658,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
657
658
|
return {
|
|
658
659
|
type: 'device',
|
|
659
660
|
device: device,
|
|
661
|
+
mapped: { model: 'Coordinator'},
|
|
660
662
|
endpoint: device.getEndpoint(1),
|
|
661
663
|
name: 'Coordinator',
|
|
662
664
|
};
|
|
@@ -676,7 +678,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
676
678
|
endpoint = device.endpoints[0];
|
|
677
679
|
}
|
|
678
680
|
}
|
|
679
|
-
const options = this.adapter.stController.localConfig.getOptions(device.ieeeAddr, mapped.model);
|
|
681
|
+
const options = mapped ? this.adapter.stController.localConfig.getOptions(device.ieeeAddr, mapped.model) : {};
|
|
680
682
|
return {
|
|
681
683
|
type: 'device',
|
|
682
684
|
device,
|
|
@@ -731,13 +733,14 @@ class ZigbeeController extends EventEmitter {
|
|
|
731
733
|
}
|
|
732
734
|
|
|
733
735
|
try {
|
|
734
|
-
if (this.
|
|
736
|
+
if (this.herdsmanStarted) {
|
|
735
737
|
await this.permitJoin(0);
|
|
736
738
|
await this.herdsman.stop();
|
|
737
|
-
this.
|
|
739
|
+
this.herdsmanStarted = false;
|
|
738
740
|
this.info('zigbecontroller stopped successfully');
|
|
741
|
+
return;
|
|
739
742
|
}
|
|
740
|
-
this.info('zigbecontroller stopped successfully - ZH was not running');
|
|
743
|
+
else this.info('zigbecontroller stopped successfully - ZH was not running');
|
|
741
744
|
} catch (error) {
|
|
742
745
|
this.sendError(error);
|
|
743
746
|
if (this.herdsmanStarted) {
|
|
@@ -759,6 +762,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
759
762
|
|
|
760
763
|
// Permit join
|
|
761
764
|
async permitJoin(permitTime, devid) {
|
|
765
|
+
if (!this.herdsmanStarted) return false;
|
|
762
766
|
try {
|
|
763
767
|
this._permitJoinTime = permitTime;
|
|
764
768
|
await this.herdsman.permitJoin(permitTime);
|
|
@@ -876,10 +880,11 @@ class ZigbeeController extends EventEmitter {
|
|
|
876
880
|
async handleDeviceAnnounce(message) {
|
|
877
881
|
if (this.debugActive) this.debug('handleDeviceAnnounce', message);
|
|
878
882
|
const entity = await this.resolveEntity(message.device || message.ieeeAddr);
|
|
879
|
-
const friendlyName = entity.name;
|
|
880
|
-
|
|
883
|
+
const friendlyName = entity ? entity.name : message.ieeeAddr ? message.ieeeAddr : message.device && message.device.ieeeAddr ? message.device.ieeeAddr : 'without data';
|
|
881
884
|
|
|
882
885
|
this.emit('pairing', `Device '${friendlyName}' announced itself`);
|
|
886
|
+
if (!entity) return;
|
|
887
|
+
|
|
883
888
|
if (this.adapter.stController.checkDebugDevice(friendlyName)) {
|
|
884
889
|
this.emit('device_debug', {ID: Date.now(), data: {flag:'da', states:[{id: '--', value:'--', payload:message}] , IO:true} ,message:`Device '${friendlyName}' announced itself`});
|
|
885
890
|
}
|
|
@@ -1386,7 +1391,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
1386
1391
|
// device: name of the device. For a device zigbee.0.0011223344556677 this would be 0011223344556677
|
|
1387
1392
|
// payload: The data to send to the device as JSON object (key/Value pairs)
|
|
1388
1393
|
// endpoint: optional: the endpoint to send the data to, if supported.
|
|
1389
|
-
//
|
|
1394
|
+
// acknowledge: optional: if to update the devices 'send_payload' DP (if present) after successful publish
|
|
1390
1395
|
async publishPayload(payload, debugID, has_elevated_debug) {
|
|
1391
1396
|
let payloadObj = {};
|
|
1392
1397
|
if (typeof payload === 'string') {
|
|
@@ -1450,6 +1455,9 @@ class ZigbeeController extends EventEmitter {
|
|
|
1450
1455
|
}
|
|
1451
1456
|
try {
|
|
1452
1457
|
await this.publishFromState(`0x${payload.device}`, payload.model, payload.stateModel, stateList, payload.options, debugID, has_elevated_debug);
|
|
1458
|
+
if (payload.acknowledge) {
|
|
1459
|
+
this.emit('acknowledge_state', payload.device, payload.model, { id:'send_payload' }, undefined);
|
|
1460
|
+
}
|
|
1453
1461
|
return {success: true};
|
|
1454
1462
|
} catch (error) {
|
|
1455
1463
|
this.log.error(`Error ${error.code} on send command to ${payload.device}.` + ` Error: ${error.stack} ` + `Send command to ${payload.device} failed with ` + error);
|
package/main.js
CHANGED
|
@@ -274,7 +274,6 @@ class Zigbee extends utils.Adapter {
|
|
|
274
274
|
|
|
275
275
|
SandboxRequire(sandbox, items) {
|
|
276
276
|
if (!items) return true;
|
|
277
|
-
//let converterLoaded = true;
|
|
278
277
|
for (const item of items) {
|
|
279
278
|
const modulePath = item[2].replace(/['"]/gm, '');
|
|
280
279
|
|
|
@@ -350,9 +349,6 @@ class Zigbee extends utils.Adapter {
|
|
|
350
349
|
converterLoaded = false;
|
|
351
350
|
this.log.error(`converter does not export any converter array, please add 'module.exports' statement to ${mN}`);
|
|
352
351
|
}
|
|
353
|
-
|
|
354
|
-
//fs.writeFileSync(mN+'.tmp', modifiedCode)
|
|
355
|
-
|
|
356
352
|
if (converterLoaded) {
|
|
357
353
|
try {
|
|
358
354
|
this.log.warn('Trying to run sandbox for ' + mN);
|
|
@@ -422,7 +418,6 @@ class Zigbee extends utils.Adapter {
|
|
|
422
418
|
}
|
|
423
419
|
else try {
|
|
424
420
|
await this.zbController.stopHerdsman();
|
|
425
|
-
//this.logToPairing('herdsman stopped !');
|
|
426
421
|
this.sendTo(from, command, { status:true }, callback);
|
|
427
422
|
} catch (error) {
|
|
428
423
|
this.sendTo(from, command, { status:true, error }, callback);
|
|
@@ -458,12 +453,6 @@ class Zigbee extends utils.Adapter {
|
|
|
458
453
|
this.setState('info.connection', false, true);
|
|
459
454
|
this.logToPairing(`Failed to start Zigbee: ${error && error.message ? error.message : 'no message given'}`)
|
|
460
455
|
this.log.error(`Failed to start Zigbee: ${error && error.message ? error.message : 'no message given'}`);
|
|
461
|
-
/* if (error.stack) {
|
|
462
|
-
this.log.error(error.stack);
|
|
463
|
-
} else {
|
|
464
|
-
this.log.error(error);
|
|
465
|
-
}
|
|
466
|
-
*/
|
|
467
456
|
this.sendError(error, `Failed to start Zigbee`);
|
|
468
457
|
if (noReconnect) return false;
|
|
469
458
|
|
|
@@ -668,12 +657,18 @@ class Zigbee extends utils.Adapter {
|
|
|
668
657
|
}
|
|
669
658
|
|
|
670
659
|
acknowledgeState(deviceId, model, stateDesc, value) {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
this.
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
660
|
+
const stateId = (model === 'group' ?
|
|
661
|
+
`${this.namespace}.group_${deviceId}.${stateDesc.id}` :
|
|
662
|
+
`${this.namespace}.${deviceId.replace('0x', '')}.${stateDesc.id}`);
|
|
663
|
+
if (value === undefined) try {
|
|
664
|
+
this.getState(stateId, (err, state) => { if (!err && state.hasOwnProperty('val')) this.setState(stateId, state.val, true)});
|
|
665
|
+
}
|
|
666
|
+
catch (error) {
|
|
667
|
+
this.log.warn(`Error acknowledging ${stateId} without value: ${error && error.message ? error.message : 'no reason given'}`);
|
|
668
|
+
}
|
|
669
|
+
else try { this.setState(stateId, value, true); }
|
|
670
|
+
catch (error) {
|
|
671
|
+
this.log.warn(`Error acknowledging ${stateId} with value ${JSON.stringify(value)}: ${error && error.message ? error.message : 'no reason given'}`);
|
|
677
672
|
}
|
|
678
673
|
}
|
|
679
674
|
|
|
@@ -754,10 +749,8 @@ class Zigbee extends utils.Adapter {
|
|
|
754
749
|
this.log.info('cleaning everything up');
|
|
755
750
|
await this.callPluginMethod('stop');
|
|
756
751
|
if (this.stController) chain.push(this.stController.stop());
|
|
757
|
-
if (this.zbController)
|
|
758
|
-
|
|
759
|
-
}
|
|
760
|
-
Promise.all(chain);
|
|
752
|
+
if (this.zbController) chain.push(this.zbController.stop());
|
|
753
|
+
await Promise.all(chain);
|
|
761
754
|
this.log.info('cleanup successful');
|
|
762
755
|
callback();
|
|
763
756
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.6",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"uri-js": "^4.4.1",
|
|
30
30
|
"typescript": "^5.9.2",
|
|
31
31
|
"zigbee-herdsman": "^6.0.0",
|
|
32
|
-
"zigbee-herdsman-converters": "25.
|
|
32
|
+
"zigbee-herdsman-converters": "^25.37.0"
|
|
33
33
|
},
|
|
34
34
|
"description": "Zigbee devices",
|
|
35
35
|
"devDependencies": {
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"@alcalzone/release-script-plugin-iobroker": "^3.7.2",
|
|
38
38
|
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
39
39
|
"@alcalzone/release-script-plugin-manual-review": "^3.7.0",
|
|
40
|
-
"@iobroker/testing": "^5.1.
|
|
40
|
+
"@iobroker/testing": "^5.1.1",
|
|
41
41
|
"chai": "^5.2.1",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
|
-
"eslint": "^9.
|
|
43
|
+
"eslint": "^9.36.0",
|
|
44
44
|
"eslint-config-prettier": "^9.1.0",
|
|
45
45
|
"eslint-plugin-prettier": "^5.5.4",
|
|
46
46
|
"mixin-deep": "^2.0.1",
|