iobroker.zigbee2mqtt 2.5.0 → 2.6.0

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 CHANGED
@@ -32,6 +32,14 @@ This adapter allows to control the data points of the devices of a Zigbee2MQTT i
32
32
  Placeholder for the next version (at the beginning of the line):
33
33
  ### **WORK IN PROGRESS**
34
34
  -->
35
+ ### 2.6.0 (2023-01-10)
36
+
37
+ - (o0shojo0o) added state `transition` for transition overwrite (-1 disabled overwrite) ([#101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101))
38
+ - (o0shojo0o) consideration of the description when creating the friendly name ([#105](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/105))
39
+ - (o0shojo0o) added state `effect` for groups ([#101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101))
40
+ - (o0shojo0o) fix state contact
41
+ - (o0shojo0o) added handling for disabled devices
42
+
35
43
  ### 2.5.0 (2023-01-02)
36
44
 
37
45
  - (o0shojo0o) added option `Brightness step should also turn the light on or off`
@@ -40,7 +48,7 @@ This adapter allows to control the data points of the devices of a Zigbee2MQTT i
40
48
 
41
49
  ### 2.4.5 (2022-12-20)
42
50
 
43
- - (o0shojo0o) extend 'text' for 'action' ([#84](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/84))
51
+ - (o0shojo0o) extend `text` for `action` ([#84](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/84))
44
52
 
45
53
  ### 2.4.4 (2022-12-06)
46
54
 
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zigbee2mqtt",
4
- "version": "2.5.0",
4
+ "version": "2.6.0",
5
5
  "news": {
6
+ "2.6.0": {
7
+ "en": "added state `transition` for transition overwrite (-1 disabled overwrite) ([#101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101))\nconsideration of the description when creating the friendly name ([#105](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/105))\nadded state `effect` for groups ([#101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101))\nfix state contact\nadded handling for disabled devices",
8
+ "de": "hinzugefügter Zustandsübergang für Übergangsüberschreiben -(1 behinderte Überschreiben) #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nberücksichtigung der Beschreibung bei der Erstellung des freundlichen Namens #[105](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/105)\nzusätzliche staatliche Wirkung für Gruppen #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/101)\nkontakt mit dem status\nzusätzliches handling für behinderte",
9
+ "ru": "добавлен государственный переход для перехода переписать -(1 отключен перезапись) #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nрассмотрение описания при создании дружественного имени #[105](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/105)\nдобавлен государственный эффект для групп #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nисправить государственный контакт\nдобавлена обработка для инвалидов",
10
+ "pt": "adicionado transição de estado para a transição sobreescrita -(1 sobreescrita desativada) #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nconsideração da descrição ao criar o nome amigável #[105](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/105)\nadicionado efeito estatal para grupos #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\ncorrigir contato estado\nmanuseio adicionado para dispositivos com deficiência",
11
+ "nl": "voegde staatsoverschrijving toe voor overschrijving overschrijving - (1 gehandicapte overschrijving) (1) (1 gehandicapte overschrijving)\noverweeg de beschrijving als het creëren van de vriendelijke naam £10:\nvoegde toegevoegd staats effect voor groepen £101, httub.com/oshojoo/ioBroker\nvertaling:\nvoegde toegevoegd voor gehandicapte apparaten",
12
+ "fr": "transition de l ' État pour la surécriture de transition -(1 surécriture désactivée) #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/101)\nexamen de la description lors de la création du nom amical #[105](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/105)\neffet d ' État ajouté pour les groupes #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/101)\ncontact étatique\nmanipulation supplémentaire pour les dispositifs handicapés",
13
+ "it": "aggiunto passaggio di stato per overwrite di transizione -(1 overwrite disabilitato) #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/101)\nconsiderazione della descrizione quando si crea il nome amichevole #[105](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/105)\neffetto stato aggiunto per gruppi #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/101)\nfix contatto stato\nmanipolazione aggiuntiva per dispositivi disabili",
14
+ "es": "añadida transición estatal para la sobreescritura de transición -(1 invalidez sobreescritura) #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nexamen de la descripción al crear el nombre amistoso #[105](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/105)\nañadido efecto estatal para los grupos #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\narreglar contacto estado\nmanejo añadido para dispositivos discapacitados",
15
+ "pl": "dodano przejście stanowe na przepisanie -(1 disabled overwrite) #101(https:/github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nrezultatem tego opisu było stworzenie przyjaznej nazwy #105 (https:/github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/105)\ndodano efekt stanowy dla grup #101 (https:/github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nkontakt państwowy\nobsługa urządzeń dla osób niepełnosprawnych",
16
+ "uk": "додано державний перехід для переходу перезапису -(1 вимкнено перезапис) #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nрозгляд опису при створенні дружньої назви #[105](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/products/105)\nдодано державний ефект для груп #[101](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/101)\nфіксувати державний контакт\nдодана обробка для пристроїв відключення",
17
+ "zh-cn": "此外,国家向过渡过渡的过渡——《残疾》第[101]号(http://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/101)\n在建立友好名称编号(http://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/105)时,审议说明\n第[101]号(http://github.com/oshojo0o/ioBroker.zigbee2mqt/issues/101)\nfix 国家联络点\nd. 增加处理残疾装置"
18
+ },
6
19
  "2.5.0": {
7
20
  "en": "added option `Brightness step should also turn the light on or off`\nadded handling of `brightness_step` ([#96](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/96))\nstates processing more flexible designed ([#94](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/94))",
8
21
  "de": "zusätzliche Option `Brightness Schritt sollte auch das Licht ein- oder ausschalten `\nzusätzliches Handling der Helligkeit_step #[96](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/96)\nzustände, die flexibler gestaltet sind #[94](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/94)",
@@ -80,19 +93,6 @@
80
93
  "pl": "recenzent oparty na przeglądzie (https:/github.com/ioBroker/ioBroker.repositories/pull/1976#issuecomment-1316656363636378)",
81
94
  "uk": "javaScript licenses API Веб-сайт Go1.13.8",
82
95
  "zh-cn": "fix 基于[审查](http://github.com/ioBroker/ioBroker.reories/pull/1976#issuement-1316656378)"
83
- },
84
- "2.4.0": {
85
- "en": "fix for devices with multiple endpoints ([#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/57)).\nadded option `Brightness move should also turn the light on or off`\nadded state toggle for groups \nmore dynamic during data point creation ([#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/48)).",
86
- "de": "fix für Geräte mit mehreren Endpunkten [#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/57).\nzusätzliche Option `Brightness move sollte auch das Licht ein- oder ausschalten `\nzusatzzustandswinkel für gruppen\nmehr Dynamik bei der Erstellung von Datenpunkten [#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/48).",
87
- "ru": "исправить для устройств с несколькими точками [#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/57).\nдобавленная опция `Перемещение яркости должно также повернуть свет на или вне`\nдобавлена государственная очка для групп\nболее динамично во время создания данных [#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/48).",
88
- "pt": "correção para dispositivos com múltiplos endpoints [#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/57).\nopção adicionada `Brightness move também deve ligar ou desligar a luz`\nadicionado conjunto de estado para grupos\nmais dinâmico durante a criação do ponto de dados [#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/48).",
89
- "nl": "vertaling:.\nvoegde optie 'Brightness zet ook het licht aan of uit'\nvertaling:\ndynamischer tijdens datapunt 48: github.com/oshojoo/ioBroker.",
90
- "fr": "correction des dispositifs comportant plusieurs paramètres [#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/57).\noption ajoutée `Brightness move should also turn the light on or off`\nla lutte de l'état pour les groupes\nplus dynamique lors de la création de points de données [#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/48).",
91
- "it": "fix per dispositivi con più endpoint [#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/57).\nopzione aggiunta `Brightness movimento dovrebbe anche accendere o spegnere la luce `\ntoggle di stato aggiunto per gruppi\npiù dinamica durante la creazione di data point [#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/48).",
92
- "es": "fix for devices with multiple endpoints [#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/57).\nopción agregada `El movimiento de la rectitud también debe encender o apagar la luz &apos\nañadido a la lucha estatal para grupos\nmás dinámica durante la creación de puntos de datos [#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/48).",
93
- "pl": "urządzenia z wieloma punktami końcowymi (#57(https:/github.com/o0shojo0/ioBroker.zigbee2mqtt/issues/57).\ndodano również możliwość wykonania ruchu `Brightness'\ndodać stan dla grup\ndynamiczny w czasie tworzenia danych (#48)(https:/github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/48).",
94
- "uk": "виправлення для пристроїв з декількома кінцевими точками [#57](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/57).\nдоданий варіант `Брайтний рух також повинен перетворювати світло або вимкнути`\nдодано державний контроль за групами\nбільш динамічний при створенні точки даних [#48](https://github.com/o0shojo0o/ioBroker.zigbee2mqtt/issues/48).",
95
- "zh-cn": "fix 有多个最终用户的装置[第57号](http://github.com/o0shojo0o/ioBroker.zigbee2mqt/issues/57).\n增加“权利流动”的选择,也应该改变“或”以外的照明。\n加入集团的州\n在数据点创建期间,增加活力[第48](http://github.com/oshojo0o/ioBroker.zigbee2mqt/issues/48)."
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -1,5 +1,5 @@
1
1
  const states = require('./states').states;
2
- const defineDeviceFromExposes = require('./exposes').defineDeviceFromExposes;
2
+ const createDeviceFromExposes = require('./exposes').createDeviceFromExposes;
3
3
  const utils = require('./utils');
4
4
  const colors = require('./colors.js');
5
5
  const rgb = require('./rgb.js');
@@ -15,23 +15,21 @@ class DeviceController {
15
15
  this.createCache = createCache;
16
16
  }
17
17
 
18
- async createDeviceDefinitions(exposes) {
18
+ async createDeviceDefinitions(devicesMessage) {
19
19
  utils.clearArray(this.deviceCache);
20
- for (const expose of exposes) {
21
- if (expose.definition != null) {
22
- // search for scenes in the endpoints and build them into an array
23
- let scenes = [];
24
- for (const key in expose.endpoints) {
25
- if (expose.endpoints[key].scenes) {
26
- scenes = scenes.concat(expose.endpoints[key].scenes);
27
- }
28
- }
29
- if (this.logCustomizations.debugDevices.includes(expose.ieee_address)) {
30
- this.adapter.log.warn(`--->>> fromZ2M -> ${expose.ieee_address} exposes: ${JSON.stringify(expose)}`);
31
- }
20
+ for (const devicesMessag of devicesMessage) {
21
+ if (this.logCustomizations.debugDevices.includes(devicesMessag.ieee_address)) {
22
+ this.adapter.log.warn(`--->>> fromZ2M -> ${devicesMessag.ieee_address} exposes: ${JSON.stringify(devicesMessag)}`);
23
+ }
24
+
25
+ if (devicesMessag.definition != null) {
32
26
  // if the device is already present in the cache, remove it
33
- this.removeDeviceByIeee(this.deviceCache, expose.ieee_address);
34
- defineDeviceFromExposes(this.deviceCache, expose.friendly_name, expose.ieee_address, expose.definition, expose.power_source, scenes, this.config);
27
+ this.removeDeviceByIeee(this.deviceCache, devicesMessag.ieee_address);
28
+
29
+ if (devicesMessag.definition.exposes) {
30
+ const newDevice = createDeviceFromExposes(devicesMessag, this.config);
31
+ this.deviceCache.push(newDevice);
32
+ }
35
33
  }
36
34
  }
37
35
  }
@@ -44,10 +42,25 @@ class DeviceController {
44
42
  id: groupID,
45
43
  ieee_address: ieee_address,
46
44
  icon: undefined,
45
+ optionsValues: {},
47
46
  states: [
48
- states.state,
49
47
  states.brightness,
50
48
  states.colortemp_move,
49
+ states.transition,
50
+ {
51
+ id: 'state',
52
+ prob: 'state',
53
+ name: 'Switch state',
54
+ options: ['transition'],
55
+ icon: undefined,
56
+ role: 'switch',
57
+ write: true,
58
+ read: true,
59
+ type: 'boolean',
60
+ def: false,
61
+ getter: payload => (payload.state === 'ON'),
62
+ setter: (value) => (value) ? 'ON' : 'OFF',
63
+ },
51
64
  {
52
65
  id: 'brightness_move',
53
66
  prop: brmPropName,
@@ -61,7 +74,6 @@ class DeviceController {
61
74
  max: 50,
62
75
  def: 0
63
76
  },
64
-
65
77
  {
66
78
  id: 'brightness_step',
67
79
  prop: brsPropName,
@@ -79,6 +91,7 @@ class DeviceController {
79
91
  id: 'color',
80
92
  prop: 'color',
81
93
  name: 'Color',
94
+ options: ['transition'],
82
95
  icon: undefined,
83
96
  role: 'level.color.rgb',
84
97
  write: true,
@@ -110,6 +123,7 @@ class DeviceController {
110
123
  id: 'colortemp',
111
124
  prop: 'color_temp',
112
125
  name: 'Color temperature',
126
+ options: ['transition'],
113
127
  icon: undefined,
114
128
  role: 'level.color.temperature',
115
129
  write: true,
@@ -136,6 +150,7 @@ class DeviceController {
136
150
  {
137
151
  id: 'state_toggle',
138
152
  name: 'Toggle the state',
153
+ options: ['transition'],
139
154
  icon: undefined,
140
155
  role: 'button',
141
156
  write: true,
@@ -144,7 +159,19 @@ class DeviceController {
144
159
  setattr: 'state',
145
160
  def: true,
146
161
  setter: (value) => (value) ? 'TOGGLE' : undefined
147
- }
162
+ },
163
+ {
164
+ id: 'effect',
165
+ name: 'Triggers an effect on the light (e.g. make light blink for a few seconds)',
166
+ prop: 'effect',
167
+ icon: undefined,
168
+ role: 'state',
169
+ write: true,
170
+ read: true,
171
+ type: 'string',
172
+ def: '',
173
+ states: { blink: 'blink', breathe: 'breathe', okay: 'okay', channel_change: 'channel_change', finish_effect: 'finish_effect', stop_effect: 'stop_effect' }
174
+ },
148
175
  ],
149
176
  };
150
177
 
@@ -180,7 +207,17 @@ class DeviceController {
180
207
 
181
208
  async createOrUpdateDevices() {
182
209
  for (const device of this.groupCache.concat(this.deviceCache)) {
183
- const deviceName = device.id == device.ieee_address ? '' : device.id;
210
+ let deviceName = device.id == device.ieee_address ? '' : device.id;
211
+
212
+ if (deviceName == '' && device.description) {
213
+ deviceName = device.description;
214
+ }
215
+
216
+ // Manipulate deviceName if the device is disabled, so the update of the device is triggered as well
217
+ if (device.disabled && device.disabled == true) {
218
+ deviceName = `[Disabled] ${deviceName}`;
219
+ }
220
+
184
221
  if (!this.createCache[device.ieee_address] || this.createCache[device.ieee_address].name != deviceName) {
185
222
  const deviceObj = {
186
223
  type: 'device',
@@ -191,11 +228,17 @@ class DeviceController {
191
228
  native: {}
192
229
  };
193
230
 
194
- if (!device.ieee_address.includes('group_')) {
231
+ // Only the onlineId is set if the device is not disabled and is not a group
232
+ if (!device.ieee_address.includes('group_') && (!device.disabled || device.disabled == false)) {
195
233
  deviceObj.common.statusStates = {
196
234
  onlineId: `${this.adapter.name}.${this.adapter.instance}.${device.ieee_address}.available`
197
235
  };
198
236
  }
237
+ else {
238
+ deviceObj.common.statusStates = {
239
+ onlineId: ''
240
+ };
241
+ }
199
242
 
200
243
  //@ts-ignore
201
244
  await this.adapter.extendObjectAsync(device.ieee_address, deviceObj);
@@ -266,6 +309,7 @@ class DeviceController {
266
309
  async copyAndCleanStateObj(state) {
267
310
  const iobState = { ...state };
268
311
  const blacklistedKeys = [
312
+ 'prop',
269
313
  'setter',
270
314
  'setterOpt',
271
315
  'getter',
@@ -275,6 +319,7 @@ class DeviceController {
275
319
  'isOption',
276
320
  'inOptions',
277
321
  'isEvent',
322
+ 'options',
278
323
  ];
279
324
  for (const blacklistedKey of blacklistedKeys) {
280
325
  delete iobState[blacklistedKey];
package/lib/exposes.js CHANGED
@@ -164,8 +164,16 @@ function genState(expose, role, name, desc) {
164
164
  return state;
165
165
  }
166
166
 
167
- function createFromExposes(deviceID, ieee_address, definitions, power_source, scenes, config) {
167
+ function createDeviceFromExposes(devicesMessag, config) {
168
168
  const states = [];
169
+ let scenes = [];
170
+ const deviceID = devicesMessag.friendly_name;
171
+ const ieee_address = devicesMessag.ieee_address;
172
+ const definition = devicesMessag.definition;
173
+ const power_source = devicesMessag.power_source;
174
+ const disabled = devicesMessag.disabled && devicesMessag.disabled == true;
175
+ const description = devicesMessag.description ? devicesMessag.description : undefined;
176
+
169
177
  function pushToStates(state, access) {
170
178
  if (state === undefined) {
171
179
  return 0;
@@ -278,7 +286,14 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
278
286
  }
279
287
  }
280
288
 
281
- for (const expose of definitions.exposes) {
289
+ // search for scenes in the endpoints and build them into an array
290
+ for (const key in devicesMessag.endpoints) {
291
+ if (devicesMessag.endpoints[key].scenes) {
292
+ scenes = scenes.concat(devicesMessag.endpoints[key].scenes);
293
+ }
294
+ }
295
+
296
+ for (const expose of definition.exposes) {
282
297
  let state;
283
298
 
284
299
  switch (expose.type) {
@@ -290,6 +305,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
290
305
  pushToStates({
291
306
  id: stateName,
292
307
  name: `Switch state ${expose.endpoint ? expose.endpoint : ''}`.trim(),
308
+ options: ['transition'],
293
309
  icon: undefined,
294
310
  role: 'switch',
295
311
  write: true,
@@ -306,6 +322,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
306
322
  id: `${stateName}_toggle`,
307
323
  prop: `${stateName}_toggle`,
308
324
  name: `Toggle state of the ${stateName}`,
325
+ options: ['transition'],
309
326
  icon: undefined,
310
327
  role: 'button',
311
328
  write: true,
@@ -323,6 +340,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
323
340
  pushToStates({
324
341
  id: stateName,
325
342
  name: `Brightness ${expose.endpoint ? expose.endpoint : ''}`.trim(),
343
+ options: ['transition'],
326
344
  icon: undefined,
327
345
  role: 'level.dimmer',
328
346
  write: true,
@@ -331,7 +349,6 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
331
349
  min: 0, // ignore expose.value_min
332
350
  max: 100, // ignore expose.value_max
333
351
  def: 100,
334
- inOptions: true,
335
352
  unit: '%',
336
353
  getter: (value) => {
337
354
  return utils.bulbLevelToAdapterLevel(value[stateName]);
@@ -361,6 +378,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
361
378
  id: `${stateName}_step`,
362
379
  prop: brspropName,
363
380
  name: 'Increases or decreases brightness by X steps',
381
+ options: ['transition'],
364
382
  icon: undefined,
365
383
  role: 'state',
366
384
  write: true,
@@ -380,6 +398,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
380
398
  id: stateName,
381
399
  prop: propName,
382
400
  name: `Color temperature ${expose.endpoint ? expose.endpoint : ''}`.trim(),
401
+ options: ['transition'],
383
402
  icon: undefined,
384
403
  role: 'level.color.temperature',
385
404
  write: true,
@@ -425,6 +444,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
425
444
  pushToStates({
426
445
  id: stateName,
427
446
  name: `Color ${expose.endpoint ? expose.endpoint : ''}`.trim(),
447
+ options: ['transition'],
428
448
  icon: undefined,
429
449
  role: 'level.color.rgb',
430
450
  write: true,
@@ -464,6 +484,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
464
484
  pushToStates({
465
485
  id: stateName,
466
486
  name: `Color ${expose.endpoint ? expose.endpoint : ''}`.trim(),
487
+ options: ['transition'],
467
488
  icon: undefined,
468
489
  role: 'level.color.rgb',
469
490
  write: true,
@@ -504,8 +525,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
504
525
  break;
505
526
  }
506
527
  }
507
- // First don't create a transition_time datapoint, this will be set in the backend
508
- //pushToStates(statesDefs.transition_time, 2);
528
+ pushToStates(statesDefs.transition, z2mAccess.SET);
509
529
  break;
510
530
 
511
531
  case 'switch':
@@ -802,7 +822,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
802
822
  }
803
823
  }
804
824
  // Can the device simulated_brightness?
805
- if (definitions.options && definitions.options.find(x => x.property == 'simulated_brightness')) {
825
+ if (definition.options && definition.options.find(x => x.property == 'simulated_brightness')) {
806
826
  pushToStates(statesDefs.simulated_brightness, z2mAccess.STATE);
807
827
  }
808
828
  state = null;
@@ -964,7 +984,7 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
964
984
 
965
985
  // If necessary, add states defined for this device model.
966
986
  // Unfortunately this is necessary for some device models because they do not adhere to the standard
967
- for (const state of getNonGenDevStatesDefs(definitions.model)) {
987
+ for (const state of getNonGenDevStatesDefs(definition.model)) {
968
988
  pushToStates(state, state.write ? z2mAccess.SET : z2mAccess.STATE);
969
989
  }
970
990
 
@@ -991,19 +1011,16 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
991
1011
  id: deviceID,
992
1012
  ieee_address: ieee_address,
993
1013
  power_source: power_source,
1014
+ disabled: disabled,
1015
+ description: description,
1016
+ optionsValues: {},
994
1017
  states: states,
995
1018
  };
996
1019
 
997
1020
  return newDevice;
998
1021
  }
999
1022
 
1000
- function defineDeviceFromExposes(devices, deviceID, ieee_address, definitions, power_source, scenes, config) {
1001
- if (definitions.hasOwnProperty('exposes')) {
1002
- const newDevice = createFromExposes(deviceID, ieee_address, definitions, power_source, scenes, config);
1003
- devices.push(newDevice);
1004
- }
1005
- }
1006
1023
 
1007
1024
  module.exports = {
1008
- defineDeviceFromExposes: defineDeviceFromExposes,
1025
+ createDeviceFromExposes: createDeviceFromExposes,
1009
1026
  };
package/lib/states.js CHANGED
@@ -144,6 +144,7 @@ const states = {
144
144
  brightness: {
145
145
  id: 'brightness',
146
146
  name: 'Brightness',
147
+ options: ['transition'],
147
148
  icon: undefined,
148
149
  role: 'level.dimmer',
149
150
  write: true,
@@ -189,6 +190,22 @@ const states = {
189
190
  def: 0
190
191
  },
191
192
 
193
+ transition: {
194
+ id: 'transition',
195
+ prop: 'transition',
196
+ name: 'Transition time overwrite (-1 disabled)',
197
+ icon: undefined,
198
+ role: 'state',
199
+ write: true,
200
+ read: false,
201
+ type: 'number',
202
+ unit: 'sec',
203
+ min: -1,
204
+ max: 65535,
205
+ def: -1,
206
+ isOption: true
207
+ },
208
+
192
209
  //#################################################################
193
210
  device_query: { // button to trigger device read
194
211
  id: 'device_query',
@@ -781,6 +798,7 @@ const states = {
781
798
  },
782
799
  contact: {
783
800
  id: 'contact',
801
+ prop: 'contact',
784
802
  name: 'Contact event',
785
803
  icon: undefined,
786
804
  role: 'state',
@@ -1327,17 +1345,6 @@ const states = {
1327
1345
  }
1328
1346
  },
1329
1347
  },
1330
- transition_time: {
1331
- id: 'transition_time',
1332
- name: 'Transition time',
1333
- icon: undefined,
1334
- role: 'state',
1335
- write: true,
1336
- read: false,
1337
- type: 'number',
1338
- unit: 'sec',
1339
- isOption: true,
1340
- },
1341
1348
  operation_mode: {
1342
1349
  id: 'decoupled',
1343
1350
  prop: 'operation_mode',
@@ -40,23 +40,53 @@ class Z2mController {
40
40
  stateID = deviceState.setattr;
41
41
  }
42
42
 
43
-
44
43
  const controlObj = {
45
44
  payload: {
46
- [stateID]: stateVal
45
+ [stateID]: stateVal,
47
46
  },
48
47
  topic: `${device.id}/set`
49
48
  };
50
49
 
51
- // set stats with the mentioned role or ids always immediately to ack = true, because these are not reported back by Zigbee2MQTT
52
- if (['button'].includes(deviceState.role) || ['brightness_move', 'colortemp_move', 'brightness_move', 'brightness_step', 'effect'].includes(deviceState.id)) {
50
+ // if available read option and set payload
51
+ if (deviceState.options) {
52
+ for (const option of deviceState.options) {
53
+ // if optionsValues not set, set it!
54
+ if (!device.optionsValues[option]) {
55
+ const optionValue = (await this.adapter.getStateAsync(`${splitedID[0]}.${splitedID[1]}.${splitedID[2]}.${option}`)).val;
56
+ // optionsValues Cache
57
+ device.optionsValues[option] = optionValue;
58
+ }
59
+
60
+ // if transition value == -1 it will be ignored. -1 stands for no overwrite!
61
+ if (option == 'transition' && device.optionsValues[option] == -1) {
62
+ continue;
63
+ }
64
+
65
+ controlObj.payload[option] = device.optionsValues[option];
66
+ }
67
+ }
68
+
69
+ // If an option datapoint has been set, it does not have to be sent.
70
+ // This is confirmed directly by the adapter (ack = true)
71
+ if (deviceState.isOption && deviceState.isOption == true) {
72
+ // set optionsValues 'Cache'
73
+ device.optionsValues[stateName] = state.val;
74
+ this.adapter.setState(id, state, true);
75
+ return;
76
+ }
77
+
78
+ // set stats with the mentioned roles or always immediately to ack = true, because these are not reported back by Zigbee2MQTT
79
+ if (['button'].includes(deviceState.role)) {
80
+ this.adapter.setState(id, state, true);
81
+ }
82
+ // set stats with the mentioned ids always immediately to ack = true, because these are not reported back by Zigbee2MQTT
83
+ if (['brightness_move', 'colortemp_move', 'brightness_move', 'brightness_step', 'effect'].includes(deviceState.id)) {
53
84
  this.adapter.setState(id, state, true);
54
85
  }
55
86
 
56
87
  if (this.logCustomizations.debugDevices.includes(device.ieee_address)) {
57
88
  this.adapter.log.warn(`<<<--- toZ2M -> ${device.ieee_address} states: ${JSON.stringify(controlObj)}`);
58
89
  }
59
-
60
90
  return controlObj;
61
91
  }
62
92
 
@@ -80,6 +110,7 @@ class Z2mController {
80
110
  }
81
111
  }
82
112
 
113
+
83
114
  module.exports = {
84
115
  Z2mController: Z2mController
85
116
  };
package/main.js CHANGED
@@ -169,6 +169,8 @@ class Zigbee2mqtt extends core.Adapter {
169
169
  case 'bridge/response/device/remove':
170
170
  deviceController.processRemoveEvent(messageObj);
171
171
  break;
172
+ case 'bridge/response/device/options':
173
+ break;
172
174
  case 'bridge/extensions':
173
175
  break;
174
176
  case 'bridge/logging':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee2mqtt",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Zigbee2MQTT adapter for ioBroker",
5
5
  "author": {
6
6
  "name": "Dennis Rathjen",
@@ -24,7 +24,7 @@
24
24
  "aedes-persistence-nedb": "^2.0.3",
25
25
  "mqtt": "^4.3.7",
26
26
  "net": "^1.0.2",
27
- "ws": "^8.11.0"
27
+ "ws": "^8.12.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@alcalzone/release-script-plugin-iobroker": "^3.5.9",
@@ -43,10 +43,10 @@
43
43
  "chai": "^4.3.7",
44
44
  "chai-as-promised": "^7.1.1",
45
45
  "eslint": "^8.31.0",
46
- "eslint-config-prettier": "^8.5.0",
46
+ "eslint-config-prettier": "^8.6.0",
47
47
  "eslint-plugin-prettier": "^4.2.1",
48
48
  "mocha": "^10.2.0",
49
- "prettier": "^2.8.1",
49
+ "prettier": "^2.8.2",
50
50
  "proxyquire": "^2.1.3",
51
51
  "sinon": "^15.0.1",
52
52
  "sinon-chai": "^3.7.0",