iobroker.zigbee 3.0.5 → 3.1.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/lib/developer.js CHANGED
@@ -106,13 +106,13 @@ class Developer {
106
106
  const cfg = obj.message.hasOwnProperty('cfg') ? obj.message.cfg : null;
107
107
  let publishTarget;
108
108
  try {
109
- publishTarget = this.zbController.getDevice(devId) ? devId : this.zbController.getGroup(parseInt(devId));
109
+ publishTarget = await this.zbController.getDevice(devId) ? devId : await this.zbController.getGroup(parseInt(devId));
110
110
  if (!publishTarget) {
111
111
  this.adapter.sendTo(obj.from, obj.command, {localErr: `Device or group ${devId} not found!`}, obj.callback);
112
112
  return;
113
113
  }
114
114
  } catch (error) {
115
- this.error(`SendToZigbee failed from publishTarget ${devId} (${error})`);
115
+ this.error(`SendToZigbee failed from publishTarget ${devId} (${error && error.message ? error.message : 'no details given'})`);
116
116
  }
117
117
 
118
118
  if (!cid || !cmd) {
package/lib/devices.js CHANGED
@@ -3,7 +3,7 @@
3
3
  const states = require('./states.js').states;
4
4
  const utils = require('./utils.js');
5
5
  const rgb = require('./rgb.js');
6
- const {applyExposes, applyExposeForDevice} = require('./exposes.js');
6
+ const { applyExposeForDevice} = require('./exposes.js');
7
7
 
8
8
 
9
9
  // return list of changing states when incoming state is changed
@@ -119,11 +119,12 @@ const sync = {
119
119
  },
120
120
  };
121
121
 
122
- const lightStatesWithColortemp = [states.state, states.brightness, states.colortemp, states.brightness_move, states.colortemp_move, states.transition_time];
123
- const lightStatesWithColor = [states.state, states.brightness, states.colortemp, states.color, states.brightness_move, states.colortemp_move, states.transition_time];
124
- const lightStatesWithColor_hue = [states.state, states.brightness, states.colortemp, states.color, states.brightness_move, states.colortemp_move, states.hue_move, states.transition_time, states.effect_type_hue];
125
- const lightStatesWithColorNoTemp = [states.state, states.brightness, states.color, states.brightness_move, states.transition_time];
126
- const lightStates = [states.state, states.brightness, states.brightness_move, states.transition_time];
122
+ const lightStates = [states.state, states.brightness, states.brightness_move, states.transition_time, states.brightness_step];
123
+ const lightStatesWithColortemp = [...lightStates, states.colortemp, states.colortemp_move];
124
+ const lightStatesWithColor = [...lightStatesWithColortemp, states.color];
125
+ const lightStatesWithColor_hue = [...lightStatesWithColor, states.hue_move, states.transition_time, states.effect_type_hue];
126
+ const lightStatesWithColorNoTemp = [...lightStates, states.color];
127
+ const onOffStates = [states.state];
127
128
 
128
129
  const gl_lightStatesWithColor = [states.gl_state, states.gl_brightness, states.gl_colortemp, states.gl_color, states.transition_time];
129
130
  const gl_white_channel = [states.white_brightness, states.white_state, states.white_colortemp];
@@ -3072,7 +3073,7 @@ const commonStates = [
3072
3073
  const DevicesByModel = new Map();
3073
3074
  const LegacyDevicesByModel = new Map();
3074
3075
 
3075
- const groupStates = [states.brightness_step].concat(lightStatesWithColor);
3076
+ const groupStates = [states.groupstateupdate, states.groupmemberupdate, states.brightness_step].concat(lightStatesWithColor);
3076
3077
 
3077
3078
  function getByModel() {
3078
3079
  DevicesByModel.clear();
@@ -3104,7 +3105,7 @@ function fillStatesWithExposes(logger) {
3104
3105
  async function addExposeToDevices(device, logger, model) {
3105
3106
  const s = DevicesByModel.size;
3106
3107
  if (s < 1) getByModel();
3107
- const rv = await applyExposeForDevice(devices, DevicesByModel, device, logger, model);
3108
+ const rv = await applyExposeForDevice(devices, DevicesByModel, device, { logger, model, newCompositeMethod:true });
3108
3109
  removeEmptyStates(devices);
3109
3110
  return rv;
3110
3111
  }
@@ -3171,8 +3172,11 @@ module.exports = {
3171
3172
  devices,
3172
3173
  legacy_devices,
3173
3174
  commonStates,
3175
+ commonGroupStates: [...commonStates, states.groupmemberupdate, states.groupstateupdate],
3174
3176
  groupStates,
3175
- groupsState: states.groups,
3177
+ lightStatesWithColor,
3178
+ onOffStates,
3179
+ lightStates,
3176
3180
  fillStatesWithExposes,
3177
3181
  addExposeToDevices,
3178
3182
  getByModel,
package/lib/exclude.js CHANGED
@@ -91,7 +91,7 @@ class Exclude {
91
91
 
92
92
  async addExclude(from, command, params, callback) {
93
93
  try {
94
- //this.warn('addExclude message: ' + JSON.stringify(params));
94
+ this.debug('addExclude message: ' + JSON.stringify(params));
95
95
  const exclude_mod = params.exclude_model.common.type;
96
96
  this.localConfig.updateLocalOverride(exclude_mod, exclude_mod, 'legacy', exclude_mod, true);
97
97
  callback({});
package/lib/exposes.js CHANGED
@@ -7,7 +7,7 @@ const utils = require('./utils');
7
7
  const colors = require('./colors');
8
8
  const ea = require('zigbee-herdsman-converters/lib/exposes').access;
9
9
 
10
-
10
+ const LocalData = { options:{} };
11
11
  const __logger = undefined;
12
12
 
13
13
  function genState(expose, role, name, desc) {
@@ -412,6 +412,8 @@ function createFromExposes(model, def, device, log) {
412
412
  return {...options, transition: transitionTime};
413
413
  },
414
414
  getter: payload => {
415
+ // Requires testing!
416
+
415
417
  try {
416
418
  // JSON
417
419
  const colorJSON = JSON.parse(payload.replaceAll("'",'"'));
@@ -817,9 +819,28 @@ function createFromExposes(model, def, device, log) {
817
819
  break;
818
820
 
819
821
  case 'composite':
822
+ {
823
+ const stname = (expose.property);
824
+ const stateId = stname.replace(/\*/g, '');
825
+ const stateName = (expose.description || expose.name);
826
+ const channelID = LocalData.options.newCompositeMethod ? `${stateId}.` : '';
827
+ if (LocalData.options.newCompositeMethod) {
828
+
829
+ if (typeof stname !== 'string') break;
830
+ pushToStates({
831
+ id: stateId,
832
+ name: stateName,
833
+ icon: undefined,
834
+ role: 'state',
835
+ write: expose.access & ea.SET,
836
+ read: expose.access & ea.GET,
837
+ type: 'string',
838
+ }, expose.access)
839
+
840
+ }
820
841
  for (const prop of expose.features) {
821
842
  if (prop.type == 'numeric') {
822
- const st = genState(prop);
843
+ const st = genState(prop, 'state', `${channelID}${prop.name}`);
823
844
  st.prop = expose.property;
824
845
  st.inOptions = true;
825
846
  // I'm not fully sure, as it really needed, but
@@ -829,27 +850,34 @@ function createFromExposes(model, def, device, log) {
829
850
  result[expose.property] = options;
830
851
  return result;
831
852
  };
832
- // if we have a composite expose, the value have to be an object {expose.property : {prop.property: value}}
833
- if (prop.access & ea.SET) {
834
- st.setter = (value, options) => {
835
- const result = {};
836
- options[prop.property] = value;
837
- result[expose.property] = options;
838
- return result;
839
- };
840
- st.setattr = expose.property;
841
- }
842
- // if we have a composite expose, the payload will be an object {expose.property : {prop.property: value}}
843
- if (prop.access & ea.STATE) {
844
- st.getter = payload => {
845
- if ((payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(prop.property)) {
846
- return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined;
847
- } else {
848
- return undefined;
849
- }
850
- };
851
- } else {
852
- st.getter = payload => undefined;
853
+ if (LocalData.options.newCompositeMethod) {
854
+ st.compositeKey = stateId;
855
+ st.compositeTimeout = 250;
856
+ st.compositeState = stateId;
857
+ } else
858
+ {
859
+ // if we have a composite expose, the value have to be an object {expose.property : {prop.property: value}}
860
+ if (prop.access & ea.SET) {
861
+ st.setter = (value, options) => {
862
+ const result = {};
863
+ options[prop.property] = value;
864
+ result[expose.property] = options;
865
+ return result;
866
+ };
867
+ st.setattr = expose.property;
868
+ }
869
+ // if we have a composite expose, the payload will be an object {expose.property : {prop.property: value}}
870
+ if (prop.access & ea.STATE) {
871
+ st.getter = payload => {
872
+ if ((payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(prop.property)) {
873
+ return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined;
874
+ } else {
875
+ return undefined;
876
+ }
877
+ };
878
+ } else {
879
+ st.getter = payload => undefined;
880
+ }
853
881
  }
854
882
  pushToStates(st, prop.access);
855
883
  }
@@ -892,6 +920,7 @@ function createFromExposes(model, def, device, log) {
892
920
  }
893
921
  }
894
922
  break;
923
+ }
895
924
  case 'list':
896
925
  // is not mapped
897
926
  // for (const prop of expose) {
@@ -907,7 +936,10 @@ function createFromExposes(model, def, device, log) {
907
936
 
908
937
  }
909
938
 
910
- async function applyExposeForDevice(mappedDevices, byModel, device) {
939
+ async function applyExposeForDevice(mappedDevices, byModel, device, options) {
940
+ if (options && typeof options == 'object') {
941
+ LocalData.options = options;
942
+ }
911
943
  const deviceDef = await zigbeeHerdsmanConverters.findByDevice(device);
912
944
  if (!deviceDef) {
913
945
  return undefined;