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 +9 -1
- package/io-package.json +14 -14
- package/lib/deviceController.js +66 -21
- package/lib/exposes.js +31 -14
- package/lib/states.js +18 -11
- package/lib/z2mController.js +36 -5
- package/main.js +2 -0
- package/package.json +4 -4
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
|
|
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.
|
|
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": {
|
package/lib/deviceController.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const states = require('./states').states;
|
|
2
|
-
const
|
|
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(
|
|
18
|
+
async createDeviceDefinitions(devicesMessage) {
|
|
19
19
|
utils.clearArray(this.deviceCache);
|
|
20
|
-
for (const
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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,
|
|
34
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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 (
|
|
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(
|
|
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
|
-
|
|
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',
|
package/lib/z2mController.js
CHANGED
|
@@ -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
|
-
//
|
|
52
|
-
if (
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
49
|
+
"prettier": "^2.8.2",
|
|
50
50
|
"proxyquire": "^2.1.3",
|
|
51
51
|
"sinon": "^15.0.1",
|
|
52
52
|
"sinon-chai": "^3.7.0",
|