iobroker.zigbee 2.0.2 → 2.0.3

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