iobroker.zigbee 1.6.0 → 1.6.12

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/exposes.js CHANGED
@@ -76,6 +76,7 @@ function genState(expose, role, name, desc) {
76
76
  };
77
77
  if (expose.endpoint) {
78
78
  state.epname = expose.endpoint;
79
+ state.setattr = expose.name;
79
80
  }
80
81
  break;
81
82
 
@@ -115,16 +116,18 @@ function createFromExposes(model, def) {
115
116
  // .withFeature(exposes.binary('some_option', ea.SET, true, false).withDescription('Some Option'))
116
117
  //in this case one state - `some_option` has two different exposes for set an get, we have to combine it ...
117
118
  //
119
+
118
120
  function pushToStates(state, access) {
119
121
  if (state === undefined) {
120
122
  return 0;
121
123
  }
124
+ if (access === undefined) access = ea.ALL;
122
125
  state.readable = (access & ea.STATE) > 0;
123
126
  state.writable = (access & ea.SET) > 0;
124
127
  const stateExists = states.findIndex( (element, index, array) => (element.id === state.id ));
125
128
  if (stateExists < 0 ) {
129
+ state.write = state.writable;
126
130
  if (! state.writable) {
127
- state.write = false;
128
131
  if ( state.hasOwnProperty('setter') ) {
129
132
  delete state.setter;
130
133
  }
@@ -173,7 +176,7 @@ function createFromExposes(model, def) {
173
176
  states[stateExists].readable = true;
174
177
  }
175
178
  if ( (state.writable) && (! states[stateExists].writable ) ) {
176
- states[stateExists].write = state.write;
179
+ states[stateExists].write = state.writable;
177
180
  // use new state `setter`
178
181
  if ( state.hasOwnProperty('setter') ) {
179
182
  states[stateExists].setter = state.setter;
@@ -214,7 +217,7 @@ function createFromExposes(model, def) {
214
217
  return states.length;
215
218
  }
216
219
  }
217
- const icon = `https://www.zigbee2mqtt.io/images/devices/${model.replace(/\//g, '-')}.jpg`;
220
+ const icon = utils.getDeviceIcon(def);
218
221
  for (const expose of def.exposes) {
219
222
  let state;
220
223
 
@@ -757,7 +760,7 @@ function createFromExposes(model, def) {
757
760
  };
758
761
  // make the function code printable in log
759
762
  //console.log(`Created mapping for device ${model}: ${JSON.stringify(newDev, function(key, value) {
760
- // if (typeof value === 'function') {return value.toString() } else { return value } }, ' ')}`);
763
+ // if (typeof value === 'function') {return value.toString() } else { return value } }, ' ')}`);
761
764
  return newDev;
762
765
  }
763
766
 
package/lib/groups.js CHANGED
@@ -115,34 +115,44 @@ class Groups {
115
115
  this.adapter.sendTo(obj.from, obj.command, response, obj.callback);
116
116
 
117
117
  }
118
+ return response.groups;
118
119
  }
119
120
 
120
121
  async updateGroupMembership(from, command, message, callback) {
121
122
  try {
122
- const groups = (message && message.groups ? message.groups : []);
123
+ const groups = (message && message.groups ? message.groups : {});
123
124
  const devId = (message && message.id ? message.id : undefined);
124
125
  if (devId === undefined) {
125
126
  this.adapter.sendTo(from, command, {error: 'No device specified'}, callback);
126
127
  }
127
128
  const sysid = devId.replace(this.adapter.namespace + '.', '0x');
128
- const id = `${devId}.groups`;
129
+ // Keeping this for reference. State update or state removal needs to be decided upon
130
+ //const id = `${devId}.groups`;
131
+ // this.adapter.setState(id, JSON.stringify(groups), true);
129
132
 
130
- this.adapter.setState(id, JSON.stringify(groups), true);
131
- let response = await this.zbController.removeDevFromAllGroups(sysid);
132
- if (response && response.error)
133
- {
134
- this.adapter.sendTo(from, command, response, callback);
135
- return;
136
- }
137
- for (const groupId of groups) {
138
- response = await this.zbController.addDevToGroup(sysid, parseInt(groupId));
139
- if (response && response.error)
140
- {
141
- this.adapter.sendTo(from, command, response, callback);
142
- return;
133
+ //const current = await this.zbController.getGroupMembersFromController(sysid);
134
+ const errors = []
135
+ for (const epid in groups) {
136
+ for (const gpid of groups[epid]) {
137
+ const gpidn = parseInt(gpid);
138
+ if (gpidn < 0) {
139
+ let response = await this.zbController.removeDevFromGroup(sysid,(-gpidn), epid);
140
+ if (response && response.error) {
141
+ errors.push(response.error);
142
+ this.error("remove dev from group Error: "+ JSON.stringify(response.error));
143
+ }
144
+ }
145
+ else if (gpidn > 0){
146
+ let response = await this.zbController.addDevToGroup(sysid,(gpidn), epid);
147
+ if (response && response.error) {
148
+ errors.push(response.error);
149
+ this.error("add dev to group Error: "+ JSON.stringify(response.error));
150
+ }
151
+
152
+ }
153
+ else this.warn('illegal group id 0');
143
154
  }
144
155
  }
145
-
146
156
  } catch (e) {
147
157
  this.adapter.sendTo(from, command, {error: e}, callback);
148
158
  return;
@@ -177,7 +187,6 @@ class Groups {
177
187
  }
178
188
  }
179
189
  if (result.unsupported.length>0) {
180
- // this.warn('unsupported ' + stateDesc.id + ' change for group members ' + JSON.stringify(result.unsupported));
181
190
  const error = {
182
191
  code: 134,
183
192
  message: `unsupported ${stateDesc.id} change for group members ${result.unsupported.join()}`
@@ -255,7 +264,8 @@ class Groups {
255
264
  }
256
265
 
257
266
 
258
- syncGroups(groups) {
267
+ async syncGroups(adapterGroups) {
268
+ const groups = await this.getGroups();
259
269
  const chain = [];
260
270
  const usedGroupsIds = [];
261
271
  for (const j in groups) {
package/lib/rgb.js CHANGED
@@ -212,14 +212,44 @@ function colorArrayFromString(value) {
212
212
  return [{r:0,g:128,b:255}];
213
213
  }
214
214
 
215
+ function colorStringFromRGBArray(payload)
216
+ {
217
+ let rv = []
218
+ payload.forEach(element => {
219
+ rv.push(rgb_to_rgbstring(element));
220
+ });
221
+ return rv.toString();
222
+ }
223
+
215
224
  function hsv_to_cie(h,s,v){
216
225
  const rgb = hsvToRGB(h,s,v);
217
226
  return rgb_to_cie(rgb.r, rgb.g, rgb.b);
218
227
  }
219
228
 
229
+ function rgb_to_rgbstring(element) {
230
+ let col = '#';
231
+ if (element && element.hasOwnProperty("r"))
232
+ col = col + element.r.toString(16).padStart(2, '0');
233
+ else col = col + '00';
234
+ if (element && element.hasOwnProperty("g"))
235
+ col = col + element.g.toString(16).padStart(2, '0');
236
+ else col = col + '00';
237
+ if (element && element.hasOwnProperty("b"))
238
+ col = col + element.b.toString(16).padStart(2, '0');
239
+ else col = col + '00';
240
+ return col;
241
+ }
242
+
243
+
244
+ function hsvToRGBString(h,s,v) {
245
+ return rgb_to_rgbstring(hsvToRGB(h,s,v))
246
+ }
247
+
220
248
  exports.hsv_to_cie = hsv_to_cie;
221
249
  exports.rgb_to_cie = rgb_to_cie;
222
250
  exports.cie_to_rgb = cie_to_rgb;
223
251
  exports.hsvToRGB = hsvToRGB;
224
252
  exports.rgbToHSV = rgbToHSV;
225
253
  exports.colorArrayFromString = colorArrayFromString;
254
+ exports.colorStringFromRGBArray = colorStringFromRGBArray;
255
+ exports.hsvToRGBString = hsvToRGBString;
package/lib/states.js CHANGED
@@ -296,7 +296,7 @@ const states = {
296
296
  prop: 'battery',
297
297
  name: 'Battery percent',
298
298
  icon: 'img/battery_p.png',
299
- role: 'battery.percent',
299
+ role: 'value.battery',
300
300
  write: false,
301
301
  read: true,
302
302
  type: 'number',
@@ -747,7 +747,7 @@ const states = {
747
747
  prop: 'battery_low',
748
748
  name: 'Battery Status Low',
749
749
  icon: undefined,
750
- role: 'state',
750
+ role: 'indicator.lowbat',
751
751
  write: false,
752
752
  read: true,
753
753
  type: 'boolean'
@@ -2139,7 +2139,7 @@ const states = {
2139
2139
  prop: 'local_temperature_calibration',
2140
2140
  name: 'Temperature Calibration',
2141
2141
  icon: undefined,
2142
- role: 'value.temperature',
2142
+ role: 'level',
2143
2143
  write: true,
2144
2144
  read: true,
2145
2145
  type: 'number',
@@ -2352,7 +2352,7 @@ const states = {
2352
2352
  prop: 'pi_heating_demand',
2353
2353
  name: 'Auto Valve position',
2354
2354
  icon: undefined,
2355
- role: 'state',
2355
+ role: 'value.valve',
2356
2356
  write: false,
2357
2357
  read: true,
2358
2358
  type: 'number',
@@ -2364,7 +2364,7 @@ const states = {
2364
2364
  prop: 'eurotronic_valve_position',
2365
2365
  name: 'Manual Valve position',
2366
2366
  icon: undefined,
2367
- role: 'state',
2367
+ role: 'level.valve',
2368
2368
  write: true,
2369
2369
  read: true,
2370
2370
  type: 'number',
@@ -2379,7 +2379,7 @@ const states = {
2379
2379
  prop: 'current_heating_setpoint',
2380
2380
  name: 'Current Target Temperature',
2381
2381
  icon: undefined,
2382
- role: 'value.temperature',
2382
+ role: 'level.temperature',
2383
2383
  write: true,
2384
2384
  read: true,
2385
2385
  type: 'number',
@@ -2391,10 +2391,10 @@ const states = {
2391
2391
  // 1 = manual valve control
2392
2392
  // 2 = auto (default)
2393
2393
  id: 'spz_trv_mode',
2394
- name: 'TRV Mode',
2394
+ name: 'TRV Mode (1 = manual | 2 = auto)',
2395
2395
  prop: 'eurotronic_trv_mode',
2396
2396
  icon: undefined,
2397
- role: 'state',
2397
+ role: 'level',
2398
2398
  write: true,
2399
2399
  read: true,
2400
2400
  type: 'number',
@@ -2411,7 +2411,7 @@ const states = {
2411
2411
  name: 'Thermostat Mode',
2412
2412
  prop: 'eurotronic_system_mode',
2413
2413
  icon: undefined,
2414
- role: 'state',
2414
+ role: 'level',
2415
2415
  write: true,
2416
2416
  read: true,
2417
2417
  type: 'number',
@@ -2421,7 +2421,7 @@ const states = {
2421
2421
  name: 'Thermostat Error',
2422
2422
  prop: 'eurotronic_error_status',
2423
2423
  icon: undefined,
2424
- role: 'state',
2424
+ role: 'value',
2425
2425
  write: false,
2426
2426
  read: true,
2427
2427
  type: 'number',
@@ -2431,7 +2431,7 @@ const states = {
2431
2431
  name: 'Window Open / Off',
2432
2432
  prop: 'eurotronic_host_flags',
2433
2433
  icon: undefined,
2434
- role: 'state',
2434
+ role: 'switch',
2435
2435
  write: true,
2436
2436
  read: true,
2437
2437
  type: 'boolean',
@@ -2450,7 +2450,7 @@ const states = {
2450
2450
  name: 'Boost Mode',
2451
2451
  prop: 'eurotronic_host_flags',
2452
2452
  icon: undefined,
2453
- role: 'state',
2453
+ role: 'switch.mode.boost',
2454
2454
  write: true,
2455
2455
  read: true,
2456
2456
  type: 'boolean',
@@ -2469,7 +2469,7 @@ const states = {
2469
2469
  name: 'Child Protection',
2470
2470
  prop: 'eurotronic_host_flags',
2471
2471
  icon: undefined,
2472
- role: 'state',
2472
+ role: 'switch.lock',
2473
2473
  write: true,
2474
2474
  read: true,
2475
2475
  type: 'boolean',
@@ -2488,7 +2488,7 @@ const states = {
2488
2488
  name: 'Mirror Display',
2489
2489
  prop: 'eurotronic_host_flags',
2490
2490
  icon: undefined,
2491
- role: 'state',
2491
+ role: 'switch',
2492
2492
  write: true,
2493
2493
  read: true,
2494
2494
  type: 'boolean',
@@ -4070,7 +4070,7 @@ const states = {
4070
4070
  prop: 'current_heating_setpoint',
4071
4071
  name: 'Current Target Temperature',
4072
4072
  icon: undefined,
4073
- role: 'value.temperature',
4073
+ role: 'level.temperature',
4074
4074
  write: true,
4075
4075
  read: true,
4076
4076
  type: 'number',
@@ -4083,7 +4083,7 @@ const states = {
4083
4083
  name: 'Locked',
4084
4084
  prop: 'child_lock',
4085
4085
  icon: undefined,
4086
- role: 'state',
4086
+ role: 'switch.lock',
4087
4087
  write: true,
4088
4088
  read: true,
4089
4089
  type: 'boolean',
@@ -4095,7 +4095,7 @@ const states = {
4095
4095
  name: 'Window detected',
4096
4096
  prop: 'window_detection',
4097
4097
  icon: undefined,
4098
- role: 'state',
4098
+ role: 'value',
4099
4099
  write: false,
4100
4100
  read: true,
4101
4101
  type: 'boolean',
@@ -4106,7 +4106,7 @@ const states = {
4106
4106
  name: 'Valve detected',
4107
4107
  prop: 'valve_detection',
4108
4108
  icon: undefined,
4109
- role: 'state',
4109
+ role: 'value',
4110
4110
  write: false,
4111
4111
  read: true,
4112
4112
  type: 'boolean',
@@ -4117,7 +4117,7 @@ const states = {
4117
4117
  name: 'Auto lock',
4118
4118
  prop: 'auto_lock',
4119
4119
  icon: undefined,
4120
- role: 'state',
4120
+ role: 'value',
4121
4121
  write: false,
4122
4122
  read: true,
4123
4123
  type: 'boolean',
@@ -4128,7 +4128,7 @@ const states = {
4128
4128
  prop: 'min_temperature',
4129
4129
  name: 'Minimal Temperature',
4130
4130
  icon: undefined,
4131
- role: 'value.temperature',
4131
+ role: 'level',
4132
4132
  write: true,
4133
4133
  read: true,
4134
4134
  type: 'number',
@@ -4141,7 +4141,7 @@ const states = {
4141
4141
  prop: 'max_temperature',
4142
4142
  name: 'Maximal Temperature',
4143
4143
  icon: undefined,
4144
- role: 'value.temperature',
4144
+ role: 'level',
4145
4145
  write: true,
4146
4146
  read: true,
4147
4147
  type: 'number',
@@ -4154,7 +4154,7 @@ const states = {
4154
4154
  prop: 'boost_time',
4155
4155
  name: 'Boost time',
4156
4156
  icon: undefined,
4157
- role: 'state',
4157
+ role: 'level',
4158
4158
  write: true,
4159
4159
  read: true,
4160
4160
  type: 'number',
@@ -4167,7 +4167,7 @@ const states = {
4167
4167
  prop: 'comfort_temperature',
4168
4168
  name: 'Comfort Temperature',
4169
4169
  icon: undefined,
4170
- role: 'value.temperature',
4170
+ role: 'level',
4171
4171
  write: true,
4172
4172
  read: true,
4173
4173
  type: 'number',
@@ -4180,7 +4180,7 @@ const states = {
4180
4180
  prop: 'eco_temperature',
4181
4181
  name: 'ECO Temperature',
4182
4182
  icon: undefined,
4183
- role: 'value.temperature',
4183
+ role: 'level',
4184
4184
  write: true,
4185
4185
  read: true,
4186
4186
  type: 'number',
@@ -4193,7 +4193,7 @@ const states = {
4193
4193
  name: 'Mode',
4194
4194
  prop: 'system_mode',
4195
4195
  icon: undefined,
4196
- role: 'state',
4196
+ role: 'level.mode.thermostat',
4197
4197
  write: true,
4198
4198
  read: true,
4199
4199
  type: 'string', // valid: low, medium, high
@@ -4260,7 +4260,7 @@ const states = {
4260
4260
  prop: 'position',
4261
4261
  name: 'Valve position',
4262
4262
  icon: undefined,
4263
- role: 'state',
4263
+ role: 'value.valve',
4264
4264
  write: false,
4265
4265
  read: true,
4266
4266
  type: 'number',
@@ -4547,10 +4547,11 @@ const states = {
4547
4547
  name: 'Button ROW 2',
4548
4548
  icon: undefined,
4549
4549
  role: 'button',
4550
- write: false,
4550
+ write: true,
4551
4551
  read: true,
4552
4552
  type: 'boolean',
4553
4553
  getter: payload => (payload.action === 'row_2_on') ? true : (payload.action === 'row_2_off') ? false : undefined,
4554
+ setter: (value) => (value) ? 'row_2_on' : 'row_2_off',
4554
4555
  },
4555
4556
  rm01_row_3: {
4556
4557
  id: 'rm01_row_3',
@@ -4558,10 +4559,11 @@ const states = {
4558
4559
  name: 'Button ROW 3',
4559
4560
  icon: undefined,
4560
4561
  role: 'button',
4561
- write: false,
4562
+ write: true,
4562
4563
  read: true,
4563
4564
  type: 'boolean',
4564
4565
  getter: payload => (payload.action === 'row_3_on') ? true : (payload.action === 'row_3_off') ? false : undefined,
4566
+ setter: (value) => (value) ? 'row_3_on' : 'row_3_off',
4565
4567
  },
4566
4568
  rm01_row_4: {
4567
4569
  id: 'rm01_row_4',
@@ -4569,10 +4571,11 @@ const states = {
4569
4571
  name: 'Button ROW 4',
4570
4572
  icon: undefined,
4571
4573
  role: 'button',
4572
- write: false,
4574
+ write: true,
4573
4575
  read: true,
4574
4576
  type: 'boolean',
4575
4577
  getter: payload => (payload.action === 'row_4_on') ? true : (payload.action === 'row_4_off') ? false : undefined,
4578
+ setter: (value) => (value) ? 'row_4_on' : 'row_4_off',
4576
4579
  },
4577
4580
  left_top_click: {
4578
4581
  id: 'left_top_click',
@@ -5800,16 +5803,21 @@ const states = {
5800
5803
  speed:10,
5801
5804
  effect:'glow',
5802
5805
  };
5803
- if (options.hasOwnProperty('effect_speed'))
5806
+ if (options && options.hasOwnProperty('effect_speed'))
5804
5807
  effectjson.speed = options.effect_speed;
5805
- if (options.hasOwnProperty('effect_colors'))
5808
+ if (options && options.hasOwnProperty('effect_colors'))
5806
5809
  {
5807
5810
  effectjson.colors = rgb.colorArrayFromString(options.effect_colors);
5808
5811
  }
5809
5812
  effectjson.effect = value;
5810
5813
  return effectjson;
5814
+ },
5815
+ getter: (payload) => {
5816
+ if (payload && payload.effect && payload.effect.hasOwnProperty('effect')) return payload.effect.effect;
5817
+ return "steady";
5811
5818
  }
5812
- },
5819
+
5820
+ },
5813
5821
  effect_json: {
5814
5822
  id: 'effect_json',
5815
5823
  name: 'Effect',
@@ -5829,11 +5837,11 @@ const states = {
5829
5837
  speed:10,
5830
5838
  effect:'glow',
5831
5839
  };
5832
- if (options.hasOwnProperty('effect_speed'))
5840
+ if (options && options.hasOwnProperty('effect_speed'))
5833
5841
  effectjson.speed = options.effect_speed;
5834
- if (options.hasOwnProperty('effect_colors'))
5842
+ if (options && options.hasOwnProperty('effect_colors'))
5835
5843
  effectjson.colors = rgb.colorArrayFromString(options.effect_colors);
5836
- if (options.hasOwnProperty('effect_type'))
5844
+ if (options && options.hasOwnProperty('effect_type'))
5837
5845
  effectjson.effect = options.effect_type;
5838
5846
  value = JSON.stringify(effectjson);
5839
5847
  return effectjson;
@@ -5859,12 +5867,16 @@ const states = {
5859
5867
  speed:10,
5860
5868
  effect:'snake',
5861
5869
  };
5862
- if (options.hasOwnProperty('effect_type'))
5870
+ if (options && options.hasOwnProperty('effect_type'))
5863
5871
  effectjson.effect = options.effect_type;
5864
- if (options.hasOwnProperty('effect_colors'))
5872
+ if (options && options.hasOwnProperty('effect_colors'))
5865
5873
  effectjson.colors = rgb.colorArrayFromString(options.effect_colors);
5866
5874
  effectjson.speed = value;
5867
5875
  return effectjson;
5876
+ },
5877
+ getter: (payload) => {
5878
+ if (payload && payload.effect && payload.effect.hasOwnProperty('speed')) return payload.effect.speed;
5879
+ return 1;
5868
5880
  }
5869
5881
  },
5870
5882
 
@@ -5885,12 +5897,16 @@ const states = {
5885
5897
  effect:'sparkle',
5886
5898
  };
5887
5899
 
5888
- if (options.hasOwnProperty('effect_speed'))
5900
+ if (options && options.hasOwnProperty('effect_speed'))
5889
5901
  effectjson.speed = options.effect_speed;
5890
- if (options.hasOwnProperty('effect_type'))
5902
+ if (options && options.hasOwnProperty('effect_type'))
5891
5903
  effectjson.effect = options.effect_type;
5892
5904
  effectjson.colors = rgb.colorArrayFromString(value);
5893
5905
  return effectjson;
5906
+ },
5907
+ getter: (payload) => {
5908
+ if (payload && payload.effect && payload.effect.hasOwnProperty('colors')) return rgb.colorStringFromRGBArray(payload.effect.colors);
5909
+ return '#ffff00,#ff00ff,#00ffff,#0000ff,#00ff00,#ff0000';
5894
5910
  }
5895
5911
  },
5896
5912
 
@@ -5925,6 +5941,15 @@ const states = {
5925
5941
 
5926
5942
  };
5927
5943
  },
5944
+ getter: (payload) => {
5945
+ if (payload.color) {
5946
+ const c = payload.color;
5947
+ if (c.hasOwnProperty("h") && c.hasOwnProperty("s") && c.hasOwnProperty("b"))
5948
+ return rgb.hsvToRGBString(c.h, c.s, c.b * 100 / 255);
5949
+ if (c.hasOwnProperty("h") && c.hasOwnProperty("s") && c.hasOwnProperty("v"))
5950
+ return rgb.hsvToRGBString(c.h, c.s, c.v * 100);
5951
+ }
5952
+ },
5928
5953
  setterOpt: (value, options) => {
5929
5954
  const hasTransitionTime = options && options.hasOwnProperty('transition_time');
5930
5955
  const transitionTime = hasTransitionTime ? options.transition_time : 0;