iobroker.zigbee 2.0.3 → 2.0.4
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 +38 -51
- package/admin/admin.js +19 -211
- package/admin/img/philips_hue_lom001.png +0 -0
- package/admin/tab_m.html +8 -13
- 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 +62 -28
- package/lib/commands.js +1 -16
- package/lib/developer.js +0 -0
- package/lib/exposes.js +1 -1
- package/lib/groups.js +8 -6
- package/lib/localConfig.js +2 -1
- package/lib/ota.js +6 -6
- package/lib/statescontroller.js +97 -270
- package/lib/zbDeviceAvailability.js +2 -2
- package/lib/zbDeviceConfigure.js +15 -22
- package/lib/zigbeecontroller.js +6 -13
- package/main.js +193 -131
- package/package.json +2 -2
package/lib/zigbeecontroller.js
CHANGED
|
@@ -179,7 +179,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
179
179
|
this.warn(`Network parameters on Coordinator: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`);
|
|
180
180
|
}
|
|
181
181
|
catch (error) {
|
|
182
|
-
this.
|
|
182
|
+
this.warn(`Unable to obtain herdsman settings`)
|
|
183
183
|
}
|
|
184
184
|
try {
|
|
185
185
|
await this.herdsman.stop();
|
|
@@ -747,11 +747,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
747
747
|
this.debug('handleDeviceLeave', message);
|
|
748
748
|
const entity = await this.resolveEntity(message.device || message.ieeeAddr);
|
|
749
749
|
const friendlyName = entity ? entity.name : message.ieeeAddr;
|
|
750
|
-
|
|
751
|
-
this.emit('device_debug', {ID: Date.now(), data: {flag:'dl', states:[{id: '--', value:'--', payload:message}], IO:true},message:`Device '${friendlyName}' has left the network`});
|
|
752
|
-
}
|
|
753
|
-
else
|
|
754
|
-
this.info(`Device '${friendlyName}' left the network`);
|
|
750
|
+
this.debug(`Device '${friendlyName}' left the network`);
|
|
755
751
|
this.emit('leave', message.ieeeAddr);
|
|
756
752
|
// Call extensions
|
|
757
753
|
this.callExtensionMethod(
|
|
@@ -768,10 +764,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
768
764
|
this.debug('handleDeviceAnnounce', message);
|
|
769
765
|
const entity = await this.resolveEntity(message.device || message.ieeeAddr);
|
|
770
766
|
const friendlyName = entity.name;
|
|
771
|
-
if (this.
|
|
772
|
-
this.emit('device_debug', {ID: Date.now(), data: {flag:'da', states:[{id: '--', value:'--', payload:message}] , IO:true} ,message:`Device '${friendlyName}' announced itself`});
|
|
773
|
-
}
|
|
774
|
-
else if (this.warnOnDeviceAnnouncement) {
|
|
767
|
+
if (this.warnOnDeviceAnnouncement) {
|
|
775
768
|
this.warn(`Device '${friendlyName}' announced itself`);
|
|
776
769
|
} else {
|
|
777
770
|
this.info(`Device '${friendlyName}' announced itself`);
|
|
@@ -890,7 +883,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
890
883
|
let resolved = await this.resolveEntity(device, 0);
|
|
891
884
|
if (!resolved) {
|
|
892
885
|
resolved = { name:'unresolved device', device:device }
|
|
893
|
-
this.
|
|
886
|
+
this.warn('resolve Entity failed for ' + device.ieeeAddr)
|
|
894
887
|
}
|
|
895
888
|
let result;
|
|
896
889
|
|
|
@@ -950,9 +943,9 @@ class ZigbeeController extends EventEmitter {
|
|
|
950
943
|
|
|
951
944
|
callback && callback({lqis, routing, errors});
|
|
952
945
|
if (errors.length) {
|
|
953
|
-
this.
|
|
946
|
+
this.warn(`Map Data collection complete with ${errors.length} issues:`);
|
|
954
947
|
for (const msg of errors)
|
|
955
|
-
this.
|
|
948
|
+
this.warn(msg);
|
|
956
949
|
}
|
|
957
950
|
else
|
|
958
951
|
this.info('Map data collection complete');
|
package/main.js
CHANGED
|
@@ -36,7 +36,6 @@ 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');
|
|
40
39
|
|
|
41
40
|
const createByteArray = function (hexString) {
|
|
42
41
|
const bytes = [];
|
|
@@ -80,9 +79,6 @@ class Zigbee extends utils.Adapter {
|
|
|
80
79
|
this.stController.on('changed', this.publishFromState.bind(this));
|
|
81
80
|
|
|
82
81
|
this.deviceManagement = new dmZigbee(this);
|
|
83
|
-
this.deviceDebug = new DeviceDebug(this),
|
|
84
|
-
this.deviceDebug.on('log', this.onLog.bind(this));
|
|
85
|
-
|
|
86
82
|
|
|
87
83
|
this.plugins = [
|
|
88
84
|
new SerialListPlugin(this),
|
|
@@ -119,19 +115,6 @@ class Zigbee extends utils.Adapter {
|
|
|
119
115
|
}
|
|
120
116
|
}
|
|
121
117
|
|
|
122
|
-
warn(message) {
|
|
123
|
-
this.log.warn(message);
|
|
124
|
-
}
|
|
125
|
-
debug(message) {
|
|
126
|
-
this.log.debug(message);
|
|
127
|
-
}
|
|
128
|
-
error(message) {
|
|
129
|
-
this.log.error(message);
|
|
130
|
-
}
|
|
131
|
-
info(message) {
|
|
132
|
-
this.log.info(message);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
118
|
sendError(error, message) {
|
|
136
119
|
try {
|
|
137
120
|
if (this.supportsFeature && this.supportsFeature('PLUGINS')) {
|
|
@@ -227,15 +210,12 @@ class Zigbee extends utils.Adapter {
|
|
|
227
210
|
this.zbController.on('new', this.newDevice.bind(this));
|
|
228
211
|
this.zbController.on('leave', this.leaveDevice.bind(this));
|
|
229
212
|
this.zbController.on('pairing', this.onPairing.bind(this));
|
|
230
|
-
this.zbController.on('event', this.
|
|
231
|
-
this.zbController.on('msg', this.
|
|
213
|
+
this.zbController.on('event', this.onZigbeeEvent.bind(this));
|
|
214
|
+
this.zbController.on('msg', this.onZigbeeEvent.bind(this));
|
|
232
215
|
this.zbController.on('publish', this.publishToState.bind(this));
|
|
233
216
|
this.zbController.configure(zigbeeOptions);
|
|
234
217
|
await this.callPluginMethod('configure', [zigbeeOptions]);
|
|
235
218
|
|
|
236
|
-
// elevated debug handling
|
|
237
|
-
this.deviceDebug.start(this.stController, this.zbController);
|
|
238
|
-
|
|
239
219
|
this.reconnectCounter = 1;
|
|
240
220
|
this.doConnect();
|
|
241
221
|
}
|
|
@@ -530,6 +510,7 @@ class Zigbee extends utils.Adapter {
|
|
|
530
510
|
for (const device of devicesFromDB) {
|
|
531
511
|
const entity = await this.zbController.resolveEntity(device);
|
|
532
512
|
if (entity) {
|
|
513
|
+
// this.log.warn('sync dev states for ' + (entity.mapped ? entity.mapped.model : entity.device.modelID));
|
|
533
514
|
const model = entity.mapped ? entity.mapped.model : entity.device.modelID;
|
|
534
515
|
this.stController.updateDev(device.ieeeAddr.substr(2), model, model, () =>
|
|
535
516
|
this.stController.syncDevStates(device, model));
|
|
@@ -572,6 +553,154 @@ class Zigbee extends utils.Adapter {
|
|
|
572
553
|
});
|
|
573
554
|
}
|
|
574
555
|
|
|
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
|
+
|
|
575
704
|
publishToState(devId, model, payload) {
|
|
576
705
|
this.stController.publishToState(devId, model, payload);
|
|
577
706
|
}
|
|
@@ -592,18 +721,15 @@ class Zigbee extends utils.Adapter {
|
|
|
592
721
|
});
|
|
593
722
|
}
|
|
594
723
|
|
|
595
|
-
async publishFromState(deviceId, model, stateModel, stateList, options
|
|
724
|
+
async publishFromState(deviceId, model, stateModel, stateList, options) {
|
|
596
725
|
let isGroup = false;
|
|
597
726
|
const has_elevated_debug = this.stController.checkDebugDevice(deviceId)
|
|
598
727
|
|
|
599
728
|
if (has_elevated_debug)
|
|
600
729
|
{
|
|
601
730
|
const stateNames = [];
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
const message = `Publishing to ${deviceId} of model ${model} with ${stateNames.join(', ')}`;
|
|
606
|
-
this.emit('device_debug', { ID:debugID, data: { ID: deviceId, flag: '03', IO:false }, message: message});
|
|
731
|
+
stateList.forEach( state => stateNames.push(state.id));
|
|
732
|
+
this.log.warn(`ELEVATED O03: Publishing to ${deviceId} of model ${model} ${stateNames.join(', ')}`);
|
|
607
733
|
}
|
|
608
734
|
else
|
|
609
735
|
this.log.debug(`publishFromState : ${deviceId} ${model} ${safeJsonStringify(stateList)}`);
|
|
@@ -618,10 +744,7 @@ class Zigbee extends utils.Adapter {
|
|
|
618
744
|
|
|
619
745
|
if (!mappedModel) {
|
|
620
746
|
this.log.debug(`No mapped model for ${model}`);
|
|
621
|
-
if (has_elevated_debug) {
|
|
622
|
-
const message=`No mapped model ${deviceId} (model ${model})`;
|
|
623
|
-
this.emit('device_debug', { ID:debugID, data: { error: 'NOMODEL' , IO:false }, message: message});
|
|
624
|
-
}
|
|
747
|
+
if (has_elevated_debug) this.log.error(`ELEVATED OE01: No mapped model ${deviceId} (model ${model})`)
|
|
625
748
|
return;
|
|
626
749
|
}
|
|
627
750
|
|
|
@@ -638,20 +761,13 @@ class Zigbee extends utils.Adapter {
|
|
|
638
761
|
if (stateDesc.id === 'send_payload') {
|
|
639
762
|
try {
|
|
640
763
|
const json_value = JSON.parse(value);
|
|
641
|
-
const payload = {device: deviceId.replace('0x', ''), payload: json_value
|
|
642
|
-
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 }});
|
|
643
|
-
|
|
764
|
+
const payload = {device: deviceId.replace('0x', ''), payload: json_value};
|
|
644
765
|
const result = await this.sendPayload(payload);
|
|
645
766
|
if (result.hasOwnProperty('success') && result.success) {
|
|
646
767
|
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
647
768
|
}
|
|
648
|
-
else {
|
|
649
|
-
this.error('Error in SendPayload: '+result.error.message);
|
|
650
|
-
}
|
|
651
769
|
} catch (error) {
|
|
652
|
-
|
|
653
|
-
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});
|
|
654
|
-
else this.error(message);
|
|
770
|
+
this.log.warn(`send_payload: ${value} does not parse as JSON Object : ${error.message}`);
|
|
655
771
|
return;
|
|
656
772
|
}
|
|
657
773
|
return;
|
|
@@ -659,10 +775,8 @@ class Zigbee extends utils.Adapter {
|
|
|
659
775
|
|
|
660
776
|
if (stateDesc.isOption || stateDesc.compositeState) {
|
|
661
777
|
// acknowledge state with given value
|
|
662
|
-
if (has_elevated_debug)
|
|
778
|
+
if (has_elevated_debug)
|
|
663
779
|
this.log.warn('ELEVATED OC: changed state: ' + JSON.stringify(changedState));
|
|
664
|
-
this.emit('device_debug', { ID:debugID, data: { flag: 'cc', states:[{id:stateDesc.id, value:value, payload:'none (OC State)'}] , IO:false }});
|
|
665
|
-
}
|
|
666
780
|
else
|
|
667
781
|
this.log.debug('changed composite state: ' + JSON.stringify(changedState));
|
|
668
782
|
|
|
@@ -682,11 +796,8 @@ class Zigbee extends utils.Adapter {
|
|
|
682
796
|
}
|
|
683
797
|
if (mappedModel) {
|
|
684
798
|
this.query_device_block.push(deviceId);
|
|
685
|
-
if (has_elevated_debug)
|
|
686
|
-
|
|
687
|
-
//this.log.warn(`ELEVATED O06: ${message}`);
|
|
688
|
-
this.emit('device_debug', { ID:debugID, data: { flag: 'qs' ,states:[{id:stateDesc.id, value:value, payload:'none for device query'}], IO:false }, message:message});
|
|
689
|
-
}
|
|
799
|
+
if (has_elevated_debug)
|
|
800
|
+
this.log.warn(`ELEVATED O06: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' triggered`);
|
|
690
801
|
else
|
|
691
802
|
this.log.debug(`Device query for '${entity.device.ieeeAddr}' started`);
|
|
692
803
|
for (const converter of mappedModel.toZigbee) {
|
|
@@ -696,9 +807,7 @@ class Zigbee extends utils.Adapter {
|
|
|
696
807
|
await converter.convertGet(entity.device.endpoints[0], ckey, {});
|
|
697
808
|
} catch (error) {
|
|
698
809
|
if (has_elevated_debug) {
|
|
699
|
-
|
|
700
|
-
this.log.warn(`ELEVATED OE02.1 ${message}`);
|
|
701
|
-
this.emit('device_debug', { ID:debugID, data: { error: 'NOTREAD' , IO:false }, message:message });
|
|
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'}`);
|
|
702
811
|
}
|
|
703
812
|
else
|
|
704
813
|
this.log.info(`failed to read state ${JSON.stringify(ckey)} of ${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} after device query`);
|
|
@@ -706,11 +815,8 @@ class Zigbee extends utils.Adapter {
|
|
|
706
815
|
}
|
|
707
816
|
}
|
|
708
817
|
}
|
|
709
|
-
if (has_elevated_debug)
|
|
710
|
-
|
|
711
|
-
//this.log.warn(`ELEVATED O07: ${message}`);
|
|
712
|
-
this.emit('device_debug', { ID:debugID, data: { flag: 'qe' , IO:false }, message:message});
|
|
713
|
-
}
|
|
818
|
+
if (has_elevated_debug)
|
|
819
|
+
this.log.warn(`ELEVATED O07: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`);
|
|
714
820
|
else
|
|
715
821
|
this.log.info(`Device query for '${entity.device.ieeeAddr}' done`);
|
|
716
822
|
const idToRemove = deviceId;
|
|
@@ -734,51 +840,38 @@ class Zigbee extends utils.Adapter {
|
|
|
734
840
|
this.log.debug(`Type of toZigbee is '${typeof c}', Contains key ${(c.hasOwnProperty('key')?JSON.stringify(c.key):'false ')}`)
|
|
735
841
|
if (!c.hasOwnProperty('key'))
|
|
736
842
|
{
|
|
737
|
-
if (converter === undefined)
|
|
843
|
+
if (c.hasOwnProperty('convertSet') && converter === undefined)
|
|
738
844
|
{
|
|
739
845
|
converter = c;
|
|
740
|
-
if (has_elevated_debug)
|
|
741
|
-
|
|
742
|
-
this.emit('device_debug', { ID:debugID, data: { flag: `s4.${msg_counter}` , IO:false }, message:message});
|
|
743
|
-
}
|
|
846
|
+
if (has_elevated_debug)
|
|
847
|
+
this.log.warn(`ELEVATED O04.${msg_counter}: Setting converter to keyless converter for ${deviceId} of type ${model}`)
|
|
744
848
|
else
|
|
745
|
-
this.log.debug(`Setting converter to keyless converter for ${deviceId} of type ${model}`)
|
|
849
|
+
this.log.debug(`Setting converter to keyless converter for ${deviceId} of type ${model}`)
|
|
746
850
|
msg_counter++;
|
|
747
851
|
}
|
|
748
852
|
else
|
|
749
853
|
{
|
|
750
854
|
if (has_elevated_debug)
|
|
751
|
-
|
|
752
|
-
const message = `ignoring keyless converter for ${deviceId} of type ${model}`;
|
|
753
|
-
this.emit('device_debug', { ID:debugID, data: { flag: `i4.${msg_counter}` , IO:false} , message:message});
|
|
754
|
-
}
|
|
855
|
+
this.log.warn(`ELEVATED O04.${msg_counter}: ignoring keyless converter for ${deviceId} of type ${model}`)
|
|
755
856
|
else
|
|
756
|
-
this.log.debug(`ignoring keyless converter for ${deviceId} of type ${model}`)
|
|
857
|
+
this.log.debug(`ignoring keyless converter for ${deviceId} of type ${model}`)
|
|
757
858
|
msg_counter++;
|
|
758
859
|
}
|
|
759
860
|
continue;
|
|
760
861
|
}
|
|
761
862
|
if (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id))
|
|
762
863
|
{
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
this.emit('device_debugug', { ID:debugID, data: { flag: `${converter===undefined ? 's' : 'o'}4.${msg_counter}` , IO:false }, message:message});
|
|
766
|
-
|
|
767
|
-
}
|
|
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)}}`)
|
|
768
866
|
else
|
|
769
|
-
this.log.debug(
|
|
867
|
+
this.log.debug(`${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`)
|
|
770
868
|
converter = c;
|
|
771
869
|
msg_counter++;
|
|
772
870
|
}
|
|
773
871
|
}
|
|
774
872
|
if (converter === undefined) {
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
this.emit('device_debug', { ID:debugID, data: { error: 'NOCONV',states:[{id:stateDesc.id, value:value, payload:'no converter'}] , IO:false }, message:message});
|
|
778
|
-
}
|
|
779
|
-
else {
|
|
780
|
-
this.log.warn(message);
|
|
781
|
-
}
|
|
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}' `);
|
|
782
875
|
return;
|
|
783
876
|
}
|
|
784
877
|
|
|
@@ -797,12 +890,10 @@ class Zigbee extends utils.Adapter {
|
|
|
797
890
|
|
|
798
891
|
const epName = stateDesc.epname !== undefined ? stateDesc.epname : (stateDesc.prop || stateDesc.id);
|
|
799
892
|
const key = stateDesc.setattr || stateDesc.prop || stateDesc.id;
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
this.emit('device_debug', { ID:debugID, data: { flag: '04', payload: {key:key, ep: stateDesc.epname, value:preparedValue, options:preparedOptions}, IO:false }, message:message});
|
|
803
|
-
}
|
|
893
|
+
if (has_elevated_debug)
|
|
894
|
+
this.log.warn(`ELEVATED O04: convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)} for device ${deviceId} with Endpoint ${epName}`);
|
|
804
895
|
else
|
|
805
|
-
this.log.debug(
|
|
896
|
+
this.log.debug(`convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)}`);
|
|
806
897
|
|
|
807
898
|
let target;
|
|
808
899
|
if (model === 'group') {
|
|
@@ -832,10 +923,6 @@ class Zigbee extends utils.Adapter {
|
|
|
832
923
|
meta.message.state = preparedValue;
|
|
833
924
|
}
|
|
834
925
|
}
|
|
835
|
-
if (has_elevated_debug) {
|
|
836
|
-
//this.log.warn('epname is ' + epName + ' or ' + stateDesc.epname);
|
|
837
|
-
this.emit('device_debug', { ID:debugID, data: { states:[{id:stateDesc.id, value:value, payload:preparedValue, ep:stateDesc.epname}] , IO:false }});
|
|
838
|
-
}
|
|
839
926
|
|
|
840
927
|
if (preparedOptions !== undefined) {
|
|
841
928
|
if (preparedOptions.hasOwnProperty('state')) {
|
|
@@ -845,52 +932,33 @@ class Zigbee extends utils.Adapter {
|
|
|
845
932
|
|
|
846
933
|
try {
|
|
847
934
|
const result = await converter.convertSet(target, key, preparedValue, meta);
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
this.emit('device_debug', { ID:debugID, data: { flag: 'SUCCESS' , IO:false }, message:message});
|
|
851
|
-
}
|
|
935
|
+
if (has_elevated_debug)
|
|
936
|
+
this.log.warn(`ELEVATED O05: convert result ${safeJsonStringify(result)} for device ${deviceId}`);
|
|
852
937
|
else
|
|
853
|
-
this.log.debug(
|
|
938
|
+
this.log.debug(`convert result ${safeJsonStringify(result)}`);
|
|
854
939
|
if (result !== undefined) {
|
|
855
|
-
if (stateModel && !isGroup
|
|
940
|
+
if (stateModel && !isGroup) {
|
|
856
941
|
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
857
942
|
}
|
|
858
943
|
// process sync state list
|
|
859
944
|
this.processSyncStatesList(deviceId, model, syncStateList);
|
|
860
945
|
}
|
|
861
|
-
else
|
|
862
|
-
if (has_elevated_debug)
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
}
|
|
866
|
-
}
|
|
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
|
+
|
|
867
950
|
} catch (error) {
|
|
868
|
-
if (has_elevated_debug)
|
|
869
|
-
|
|
870
|
-
this.emit('device_debug', { ID:debugID, data: { error: 'EXSET' , IO:false },message:message});
|
|
871
|
-
}
|
|
951
|
+
if (has_elevated_debug)
|
|
952
|
+
this.log.error(`ELEVATED OE3: caught error ${safeJsonStringify(error)} when setting value for device ${deviceId}.`);
|
|
872
953
|
this.filterError(`Error ${error.code} on send command to ${deviceId}.` +
|
|
873
954
|
` Error: ${error.stack}`, `Send command to ${deviceId} failed with`, error);
|
|
874
955
|
}
|
|
875
956
|
});
|
|
876
957
|
} catch (err) {
|
|
877
|
-
|
|
878
|
-
this.emit('device_debug', { ID:debugID, data: { error: 'EXPUB' , IO:false }, message:message});
|
|
958
|
+
this.log.error(`No entity for ${deviceId} : ${err && err.message ? err.message : 'no error message'}`);
|
|
879
959
|
}
|
|
880
960
|
}
|
|
881
961
|
|
|
882
|
-
|
|
883
|
-
extractEP(key, endpoints) {
|
|
884
|
-
try {
|
|
885
|
-
if (endpoints) for (const ep of Object.keys(endpoints)) {
|
|
886
|
-
if (key.endsWith('_'+ep)) return { setattr: key.replace('_'+ep, ''), epname:ep }
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
catch {
|
|
890
|
-
return {};
|
|
891
|
-
}
|
|
892
|
-
return {};
|
|
893
|
-
}
|
|
894
962
|
// This function is introduced to explicitly allow user level scripts to send Commands
|
|
895
963
|
// directly to the zigbee device. It utilizes the zigbee-herdsman-converters to generate
|
|
896
964
|
// the exact zigbee message to be sent and can be used to set device options which are
|
|
@@ -904,6 +972,7 @@ class Zigbee extends utils.Adapter {
|
|
|
904
972
|
// endpoint: optional: the endpoint to send the data to, if supported.
|
|
905
973
|
//
|
|
906
974
|
async sendPayload(payload) {
|
|
975
|
+
this.log.debug(`publishToDevice called with ${safeJsonStringify(payload)}`);
|
|
907
976
|
let payloadObj = {};
|
|
908
977
|
if (typeof payload === 'string') {
|
|
909
978
|
try {
|
|
@@ -918,7 +987,7 @@ class Zigbee extends utils.Adapter {
|
|
|
918
987
|
}
|
|
919
988
|
} else if (typeof payload === 'object') {
|
|
920
989
|
payloadObj = payload;
|
|
921
|
-
}
|
|
990
|
+
}
|
|
922
991
|
|
|
923
992
|
if (payloadObj.hasOwnProperty('device') && payloadObj.hasOwnProperty('payload')) {
|
|
924
993
|
try {
|
|
@@ -943,24 +1012,16 @@ class Zigbee extends utils.Adapter {
|
|
|
943
1012
|
this.sendError(`Illegal payload type for ${safeJsonStringify(payloadObj.device)}`);
|
|
944
1013
|
return {success: false, error: `Illegal payload type for ${safeJsonStringify(payloadObj.device)}`};
|
|
945
1014
|
}
|
|
946
|
-
const endpoints = mappedModel && mappedModel.endpoint ? mappedModel.endpoint(entity.device) : null;
|
|
947
1015
|
for (const key in payloadObj.payload) {
|
|
948
1016
|
if (payloadObj.payload[key] != undefined) {
|
|
949
1017
|
const datatype = typeof payloadObj.payload[key];
|
|
950
|
-
const epobj = this.extractEP(key, endpoints);
|
|
951
|
-
if (payloadObj.endpoint) {
|
|
952
|
-
epobj.epname = payloadObj.endpoint;
|
|
953
|
-
delete epobj.setattr;
|
|
954
|
-
}
|
|
955
1018
|
stateList.push({
|
|
956
1019
|
stateDesc: {
|
|
957
1020
|
id: key,
|
|
958
1021
|
prop: key,
|
|
959
1022
|
role: 'state',
|
|
960
1023
|
type: datatype,
|
|
961
|
-
|
|
962
|
-
epname: epobj.epname,
|
|
963
|
-
setattr: epobj.setattr,
|
|
1024
|
+
epname: payloadObj.endpoint,
|
|
964
1025
|
},
|
|
965
1026
|
value: payloadObj.payload[key],
|
|
966
1027
|
index: 0,
|
|
@@ -969,7 +1030,8 @@ class Zigbee extends utils.Adapter {
|
|
|
969
1030
|
}
|
|
970
1031
|
}
|
|
971
1032
|
try {
|
|
972
|
-
|
|
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);
|
|
973
1035
|
return {success: true};
|
|
974
1036
|
} catch (error) {
|
|
975
1037
|
this.log.error(`Error ${error.code} on send command to ${payload.device}.` + ` Error: ${error.stack} ` + `Send command to ${payload.device} failed with ` + error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
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.6.3",
|
|
31
31
|
"zigbee-herdsman": "3.2.7",
|
|
32
|
-
"zigbee-herdsman-converters": "
|
|
32
|
+
"zigbee-herdsman-converters": "21.38.0"
|
|
33
33
|
},
|
|
34
34
|
"description": "Zigbee devices",
|
|
35
35
|
"devDependencies": {
|