iobroker.zigbee2mqtt 2.13.6 → 2.13.11
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 +21 -10
- package/admin/jsonConfig.json +11 -0
- package/io-package.json +73 -70
- package/lib/check.js +12 -6
- package/lib/colors.js +4 -6
- package/lib/deviceController.js +64 -39
- package/lib/exposes.js +623 -466
- package/lib/imageController.js +24 -12
- package/lib/messages.js +10 -4
- package/lib/mqttServerController.js +12 -5
- package/lib/nonGenericDevicesExtension.js +30 -31
- package/lib/rgb.js +50 -52
- package/lib/states.js +650 -494
- package/lib/statesController.js +22 -13
- package/lib/utils.js +5 -5
- package/lib/websocketController.js +6 -4
- package/lib/z2mController.js +18 -12
- package/main.js +38 -17
- package/package.json +23 -21
package/lib/exposes.js
CHANGED
|
@@ -11,28 +11,28 @@ const getNonGenDevStatesDefs = require('./nonGenericDevicesExtension').getStateD
|
|
|
11
11
|
// https://www.zigbee2mqtt.io/guide/usage/exposes.html#access
|
|
12
12
|
const z2mAccess = {
|
|
13
13
|
/**
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
* Bit 0: The property can be found in the published state of this device
|
|
15
|
+
*/
|
|
16
16
|
STATE: 1,
|
|
17
17
|
/**
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
* Bit 1: The property can be set with a /set command
|
|
19
|
+
*/
|
|
20
20
|
SET: 2,
|
|
21
21
|
/**
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
* Bit 2: The property can be retrieved with a /get command
|
|
23
|
+
*/
|
|
24
24
|
GET: 4,
|
|
25
25
|
/**
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
* Bitwise inclusive OR of STATE and SET : 0b001 | 0b010
|
|
27
|
+
*/
|
|
28
28
|
STATE_SET: 3,
|
|
29
29
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
* Bitwise inclusive OR of STATE and GET : 0b001 | 0b100
|
|
31
|
+
*/
|
|
32
32
|
STATE_GET: 5,
|
|
33
33
|
/**
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
* Bitwise inclusive OR of STATE and GET and SET : 0b001 | 0b100 | 0b010
|
|
35
|
+
*/
|
|
36
36
|
ALL: 7,
|
|
37
37
|
};
|
|
38
38
|
|
|
@@ -40,14 +40,14 @@ function genState(expose, role, name, desc) {
|
|
|
40
40
|
let state;
|
|
41
41
|
const readable = (expose.access & z2mAccess.STATE) > 0;
|
|
42
42
|
const writable = (expose.access & z2mAccess.SET) > 0;
|
|
43
|
-
const stname =
|
|
43
|
+
const stname = name || expose.property;
|
|
44
44
|
|
|
45
45
|
if (typeof stname !== 'string') {
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const stateId = stname.replace(/\*/g, '');
|
|
50
|
-
const stateName =
|
|
50
|
+
const stateName = desc || expose.description || expose.name;
|
|
51
51
|
const propName = expose.property;
|
|
52
52
|
|
|
53
53
|
switch (expose.type) {
|
|
@@ -64,13 +64,14 @@ function genState(expose, role, name, desc) {
|
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
if (readable) {
|
|
67
|
-
state.getter = (payload) =>
|
|
67
|
+
state.getter = (payload) => payload[propName] === (expose.value_on || 'ON');
|
|
68
68
|
} else {
|
|
69
|
-
state.getter = (_payload) =>
|
|
69
|
+
state.getter = (_payload) => undefined;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
if (writable) {
|
|
73
|
-
state.setter = (payload) =>
|
|
73
|
+
state.setter = (payload) =>
|
|
74
|
+
payload ? expose.value_on || 'ON' : expose.value_off != undefined ? expose.value_off : 'OFF';
|
|
74
75
|
state.setattr = expose.property;
|
|
75
76
|
}
|
|
76
77
|
|
|
@@ -108,7 +109,7 @@ function genState(expose, role, name, desc) {
|
|
|
108
109
|
role: role || 'state',
|
|
109
110
|
write: writable,
|
|
110
111
|
read: true,
|
|
111
|
-
states: {}
|
|
112
|
+
states: {},
|
|
112
113
|
};
|
|
113
114
|
|
|
114
115
|
for (const val of expose.values) {
|
|
@@ -118,7 +119,7 @@ function genState(expose, role, name, desc) {
|
|
|
118
119
|
} else {
|
|
119
120
|
state.states[val] = val;
|
|
120
121
|
}
|
|
121
|
-
state.type = typeof
|
|
122
|
+
state.type = typeof val;
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
if (expose.endpoint) {
|
|
@@ -139,7 +140,9 @@ function genState(expose, role, name, desc) {
|
|
|
139
140
|
};
|
|
140
141
|
if (propName == 'action') {
|
|
141
142
|
state.isEvent = true;
|
|
142
|
-
state.getter = (payload) => {
|
|
143
|
+
state.getter = (payload) => {
|
|
144
|
+
return payload[propName];
|
|
145
|
+
};
|
|
143
146
|
}
|
|
144
147
|
if (expose.endpoint) {
|
|
145
148
|
state.epname = expose.endpoint;
|
|
@@ -182,7 +185,6 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
182
185
|
const disabled = devicesMessag.disabled && devicesMessag.disabled == true;
|
|
183
186
|
const description = devicesMessag.description ? devicesMessag.description : undefined;
|
|
184
187
|
|
|
185
|
-
|
|
186
188
|
function pushToStates(state, access) {
|
|
187
189
|
if (state === undefined) {
|
|
188
190
|
return 0;
|
|
@@ -190,7 +192,7 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
190
192
|
if (access === undefined) access = z2mAccess.ALL;
|
|
191
193
|
state.readable = (access & z2mAccess.STATE) > 0;
|
|
192
194
|
state.writable = (access & z2mAccess.SET) > 0;
|
|
193
|
-
const stateExists = states.findIndex((x, _index, _array) =>
|
|
195
|
+
const stateExists = states.findIndex((x, _index, _array) => x.id === state.id);
|
|
194
196
|
|
|
195
197
|
if (stateExists < 0) {
|
|
196
198
|
state.write = state.writable;
|
|
@@ -207,14 +209,13 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
207
209
|
if (!state.readable) {
|
|
208
210
|
if (state.hasOwnProperty('getter')) {
|
|
209
211
|
//to awid some worning on unprocessed data
|
|
210
|
-
state.getter = _payload =>
|
|
212
|
+
state.getter = (_payload) => undefined;
|
|
211
213
|
}
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
return states.push(state);
|
|
215
217
|
} else {
|
|
216
|
-
|
|
217
|
-
if ((state.readable) && (!states[stateExists].readable)) {
|
|
218
|
+
if (state.readable && !states[stateExists].readable) {
|
|
218
219
|
states[stateExists].read = state.read;
|
|
219
220
|
// as state is readable, it can't be button or event
|
|
220
221
|
if (states[stateExists].role === 'button') {
|
|
@@ -233,7 +234,7 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
233
234
|
// trying to remove the `prop` property, as main key for get and set,
|
|
234
235
|
// as it can be different in new and old states, and leave only:
|
|
235
236
|
// setattr for old and id for new
|
|
236
|
-
if (
|
|
237
|
+
if (state.hasOwnProperty('prop') && state.prop === state.id) {
|
|
237
238
|
if (states[stateExists].hasOwnProperty('prop')) {
|
|
238
239
|
if (states[stateExists].prop !== states[stateExists].id) {
|
|
239
240
|
if (!states[stateExists].hasOwnProperty('setattr')) {
|
|
@@ -248,7 +249,7 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
248
249
|
states[stateExists].readable = true;
|
|
249
250
|
}
|
|
250
251
|
|
|
251
|
-
if (
|
|
252
|
+
if (state.writable && !states[stateExists].writable) {
|
|
252
253
|
states[stateExists].write = state.writable;
|
|
253
254
|
// use new state `setter`
|
|
254
255
|
if (state.hasOwnProperty('setter')) {
|
|
@@ -267,7 +268,10 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
267
268
|
|
|
268
269
|
// as we have new state, responsible for set, we have to use new `isOption`
|
|
269
270
|
// or remove it
|
|
270
|
-
if (
|
|
271
|
+
if (
|
|
272
|
+
(!state.hasOwnProperty('isOption') || state.isOptions === false) &&
|
|
273
|
+
states[stateExists].hasOwnProperty('isOption')
|
|
274
|
+
) {
|
|
271
275
|
delete states[stateExists].isOption;
|
|
272
276
|
} else {
|
|
273
277
|
states[stateExists].isOption = state.isOption;
|
|
@@ -311,20 +315,28 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
311
315
|
switch (prop.name) {
|
|
312
316
|
case 'state': {
|
|
313
317
|
const stateName = expose.endpoint ? `state_${expose.endpoint}` : 'state';
|
|
314
|
-
pushToStates(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
318
|
+
pushToStates(
|
|
319
|
+
{
|
|
320
|
+
id: stateName,
|
|
321
|
+
name: `Switch state ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
322
|
+
options: ['transition'],
|
|
323
|
+
icon: undefined,
|
|
324
|
+
role: 'switch',
|
|
325
|
+
write: true,
|
|
326
|
+
read: true,
|
|
327
|
+
type: 'boolean',
|
|
328
|
+
getter: (payload) => payload[stateName] === (prop.value_on || 'ON'),
|
|
329
|
+
setter: (value) =>
|
|
330
|
+
value
|
|
331
|
+
? prop.value_on || 'ON'
|
|
332
|
+
: prop.value_off != undefined
|
|
333
|
+
? prop.value_off
|
|
334
|
+
: 'OFF',
|
|
335
|
+
epname: expose.endpoint,
|
|
336
|
+
//setattr: stateName,
|
|
337
|
+
},
|
|
338
|
+
prop.access
|
|
339
|
+
);
|
|
328
340
|
// features contains TOGGLE?
|
|
329
341
|
if (prop.value_toggle) {
|
|
330
342
|
pushToStates({
|
|
@@ -339,228 +351,303 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
339
351
|
type: 'boolean',
|
|
340
352
|
def: true,
|
|
341
353
|
setattr: stateName,
|
|
342
|
-
setter: (value) => (value
|
|
354
|
+
setter: (value) => (value ? prop.value_toggle : undefined),
|
|
343
355
|
});
|
|
344
356
|
}
|
|
345
357
|
break;
|
|
346
358
|
}
|
|
347
359
|
case 'brightness': {
|
|
348
360
|
const stateName = expose.endpoint ? `brightness_${expose.endpoint}` : 'brightness';
|
|
349
|
-
pushToStates(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
361
|
+
pushToStates(
|
|
362
|
+
{
|
|
363
|
+
id: stateName,
|
|
364
|
+
name: `Brightness ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
365
|
+
options: ['transition'],
|
|
366
|
+
icon: undefined,
|
|
367
|
+
role: 'level.dimmer',
|
|
368
|
+
write: true,
|
|
369
|
+
read: true,
|
|
370
|
+
type: 'number',
|
|
371
|
+
min: 0, // ignore expose.value_min
|
|
372
|
+
max: 100, // ignore expose.value_max
|
|
373
|
+
def: 100,
|
|
374
|
+
unit: '%',
|
|
375
|
+
getter: (value) => {
|
|
376
|
+
return utils.bulbLevelToAdapterLevel(value[stateName]);
|
|
377
|
+
},
|
|
378
|
+
setter: (value) => {
|
|
379
|
+
return utils.adapterLevelToBulbLevel(value);
|
|
380
|
+
},
|
|
367
381
|
},
|
|
368
|
-
|
|
382
|
+
prop.access
|
|
383
|
+
);
|
|
369
384
|
// brightnessMoveOnOff
|
|
370
|
-
const brmPropName =
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
385
|
+
const brmPropName =
|
|
386
|
+
config.brightnessMoveOnOff == true
|
|
387
|
+
? `${stateName}_move_onoff`
|
|
388
|
+
: `${stateName}_move`;
|
|
389
|
+
pushToStates(
|
|
390
|
+
{
|
|
391
|
+
id: `${stateName}_move`,
|
|
392
|
+
prop: brmPropName,
|
|
393
|
+
name: 'Increases or decreases the brightness by X units per second',
|
|
394
|
+
icon: undefined,
|
|
395
|
+
role: 'state',
|
|
396
|
+
write: true,
|
|
397
|
+
read: false,
|
|
398
|
+
type: 'number',
|
|
399
|
+
min: -50,
|
|
400
|
+
max: 50,
|
|
401
|
+
def: 0,
|
|
402
|
+
},
|
|
403
|
+
z2mAccess.SET
|
|
404
|
+
);
|
|
384
405
|
// brightnessStepOnOff
|
|
385
|
-
const brspropName =
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
406
|
+
const brspropName =
|
|
407
|
+
config.brightnessStepOnOff == true
|
|
408
|
+
? `${stateName}_step_onoff`
|
|
409
|
+
: `${stateName}_step`;
|
|
410
|
+
pushToStates(
|
|
411
|
+
{
|
|
412
|
+
id: `${stateName}_step`,
|
|
413
|
+
prop: brspropName,
|
|
414
|
+
name: 'Increases or decreases brightness by X steps',
|
|
415
|
+
options: ['transition'],
|
|
416
|
+
icon: undefined,
|
|
417
|
+
role: 'state',
|
|
418
|
+
write: true,
|
|
419
|
+
read: false,
|
|
420
|
+
type: 'number',
|
|
421
|
+
min: -255,
|
|
422
|
+
max: 255,
|
|
423
|
+
def: 0,
|
|
424
|
+
},
|
|
425
|
+
z2mAccess.SET
|
|
426
|
+
);
|
|
400
427
|
break;
|
|
401
428
|
}
|
|
402
429
|
case 'color_temp': {
|
|
403
430
|
const stateName = expose.endpoint ? `colortemp_${expose.endpoint}` : 'colortemp';
|
|
404
431
|
const propName = expose.endpoint ? `color_temp_${expose.endpoint}` : 'color_temp';
|
|
405
432
|
const colorMode = expose.endpoint ? `color_mode_${expose.endpoint}` : 'color_mode';
|
|
406
|
-
pushToStates(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
433
|
+
pushToStates(
|
|
434
|
+
{
|
|
435
|
+
id: stateName,
|
|
436
|
+
prop: propName,
|
|
437
|
+
name: `Color temperature ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
438
|
+
options: ['transition'],
|
|
439
|
+
icon: undefined,
|
|
440
|
+
role: 'level.color.temperature',
|
|
441
|
+
write: true,
|
|
442
|
+
read: true,
|
|
443
|
+
type: 'number',
|
|
444
|
+
min:
|
|
445
|
+
config.useKelvin == true
|
|
446
|
+
? utils.miredKelvinConversion(prop.value_max)
|
|
447
|
+
: prop.value_min,
|
|
448
|
+
max:
|
|
449
|
+
config.useKelvin == true
|
|
450
|
+
? utils.miredKelvinConversion(prop.value_min)
|
|
451
|
+
: prop.value_max,
|
|
452
|
+
def:
|
|
453
|
+
config.useKelvin == true
|
|
454
|
+
? utils.miredKelvinConversion(prop.value_min)
|
|
455
|
+
: prop.value_max,
|
|
456
|
+
unit: config.useKelvin == true ? 'K' : 'mired',
|
|
457
|
+
setter: (value) => {
|
|
458
|
+
return utils.toMired(value);
|
|
459
|
+
},
|
|
460
|
+
getter: (payload) => {
|
|
461
|
+
if (payload[colorMode] != 'color_temp') {
|
|
462
|
+
return undefined;
|
|
463
|
+
}
|
|
464
|
+
if (config.useKelvin == true) {
|
|
465
|
+
return utils.miredKelvinConversion(payload[propName]);
|
|
466
|
+
} else {
|
|
467
|
+
return payload[propName];
|
|
468
|
+
}
|
|
469
|
+
},
|
|
432
470
|
},
|
|
433
|
-
|
|
471
|
+
prop.access
|
|
472
|
+
);
|
|
434
473
|
// Colortemp
|
|
435
|
-
pushToStates(
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
474
|
+
pushToStates(
|
|
475
|
+
{
|
|
476
|
+
id: `${stateName}_move`,
|
|
477
|
+
prop: `${propName}_move`,
|
|
478
|
+
name: 'Colortemp change',
|
|
479
|
+
icon: undefined,
|
|
480
|
+
role: 'state',
|
|
481
|
+
write: true,
|
|
482
|
+
read: false,
|
|
483
|
+
type: 'number',
|
|
484
|
+
min: -50,
|
|
485
|
+
max: 50,
|
|
486
|
+
def: 0,
|
|
487
|
+
},
|
|
488
|
+
prop.access
|
|
489
|
+
);
|
|
448
490
|
break;
|
|
449
491
|
}
|
|
450
492
|
case 'color_temp_startup': {
|
|
451
|
-
const stateName = expose.endpoint
|
|
452
|
-
|
|
493
|
+
const stateName = expose.endpoint
|
|
494
|
+
? `colortempstartup_${expose.endpoint}`
|
|
495
|
+
: 'colortempstartup';
|
|
496
|
+
const propName = expose.endpoint
|
|
497
|
+
? `color_temp_startup_${expose.endpoint}`
|
|
498
|
+
: 'color_temp_startup';
|
|
453
499
|
//const colorMode = expose.endpoint ? `color_mode_${expose.endpoint}` : 'color_mode';
|
|
454
|
-
pushToStates(
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
500
|
+
pushToStates(
|
|
501
|
+
{
|
|
502
|
+
id: stateName,
|
|
503
|
+
prop: propName,
|
|
504
|
+
name: `${prop.description} ${expose.endpoint ? `(${expose.endpoint})` : ''}`.trim(),
|
|
505
|
+
//options: ['transition'],
|
|
506
|
+
icon: undefined,
|
|
507
|
+
role: 'level.color.temperature',
|
|
508
|
+
write: true,
|
|
509
|
+
read: true,
|
|
510
|
+
type: 'number',
|
|
511
|
+
min: 0,
|
|
512
|
+
max: 65535,
|
|
513
|
+
def: undefined,
|
|
514
|
+
unit: config.useKelvin == true ? 'K' : 'mired',
|
|
515
|
+
setter: (value) => {
|
|
516
|
+
return utils.toMired(value);
|
|
517
|
+
},
|
|
518
|
+
getter: (payload) => {
|
|
519
|
+
//if (payload[colorMode] != 'color_temp') {
|
|
520
|
+
// return undefined;
|
|
521
|
+
//}
|
|
522
|
+
if (config.useKelvin == true) {
|
|
523
|
+
return utils.miredKelvinConversion(payload[propName]);
|
|
524
|
+
} else {
|
|
525
|
+
return payload[propName];
|
|
526
|
+
}
|
|
527
|
+
},
|
|
480
528
|
},
|
|
481
|
-
|
|
529
|
+
prop.access
|
|
530
|
+
);
|
|
482
531
|
break;
|
|
483
532
|
}
|
|
484
533
|
case 'color_xy': {
|
|
485
534
|
const stateName = expose.endpoint ? `color_${expose.endpoint}` : 'color';
|
|
486
535
|
const colorMode = expose.endpoint ? `color_mode_${expose.endpoint}` : 'color_mode';
|
|
487
|
-
pushToStates(
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
536
|
+
pushToStates(
|
|
537
|
+
{
|
|
538
|
+
id: stateName,
|
|
539
|
+
name: `Color ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
540
|
+
options: ['transition'],
|
|
541
|
+
icon: undefined,
|
|
542
|
+
role: 'level.color.rgb',
|
|
543
|
+
write: true,
|
|
544
|
+
read: true,
|
|
545
|
+
type: 'string',
|
|
546
|
+
def: '#ff00ff',
|
|
547
|
+
setter: (value) => {
|
|
548
|
+
let xy = [0, 0];
|
|
549
|
+
const rgbcolor = colors.ParseColor(value);
|
|
550
|
+
|
|
551
|
+
xy = rgb.rgb_to_cie(rgbcolor.r, rgbcolor.g, rgbcolor.b);
|
|
552
|
+
return {
|
|
553
|
+
x: xy[0],
|
|
554
|
+
y: xy[1],
|
|
555
|
+
};
|
|
556
|
+
},
|
|
557
|
+
getter: (payload) => {
|
|
558
|
+
if (payload[colorMode] != 'xy' && config.colorTempSyncColor == false) {
|
|
559
|
+
return undefined;
|
|
560
|
+
}
|
|
561
|
+
if (
|
|
562
|
+
payload[stateName] &&
|
|
563
|
+
payload[stateName].hasOwnProperty('x') &&
|
|
564
|
+
payload[stateName].hasOwnProperty('y')
|
|
565
|
+
) {
|
|
566
|
+
const colorval = rgb.cie_to_rgb(
|
|
567
|
+
payload[stateName].x,
|
|
568
|
+
payload[stateName].y
|
|
569
|
+
);
|
|
570
|
+
return (
|
|
571
|
+
'#' +
|
|
572
|
+
utils.decimalToHex(colorval[0]) +
|
|
573
|
+
utils.decimalToHex(colorval[1]) +
|
|
574
|
+
utils.decimalToHex(colorval[2])
|
|
575
|
+
);
|
|
576
|
+
} else {
|
|
577
|
+
return undefined;
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
epname: expose.endpoint,
|
|
519
581
|
},
|
|
520
|
-
|
|
521
|
-
|
|
582
|
+
prop.access
|
|
583
|
+
);
|
|
522
584
|
break;
|
|
523
585
|
}
|
|
524
586
|
case 'color_hs': {
|
|
525
587
|
const stateName = expose.endpoint ? `color_${expose.endpoint}` : 'color';
|
|
526
588
|
const colorMode = expose.endpoint ? `color_mode_${expose.endpoint}` : 'color_mode';
|
|
527
|
-
pushToStates(
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
589
|
+
pushToStates(
|
|
590
|
+
{
|
|
591
|
+
id: stateName,
|
|
592
|
+
name: `Color ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
593
|
+
options: ['transition'],
|
|
594
|
+
icon: undefined,
|
|
595
|
+
role: 'level.color.rgb',
|
|
596
|
+
write: true,
|
|
597
|
+
read: true,
|
|
598
|
+
type: 'string',
|
|
599
|
+
def: '#ff00ff',
|
|
600
|
+
setter: (value) => {
|
|
601
|
+
const _rgb = colors.ParseColor(value);
|
|
602
|
+
const hsv = rgb.rgbToHSV(_rgb.r, _rgb.g, _rgb.b, true);
|
|
603
|
+
return {
|
|
604
|
+
h: Math.min(Math.max(hsv.h, 1), 359),
|
|
605
|
+
s: hsv.s,
|
|
606
|
+
//b: Math.round(hsv.v * 2.55),
|
|
607
|
+
};
|
|
608
|
+
},
|
|
609
|
+
getter: (payload) => {
|
|
610
|
+
if (
|
|
611
|
+
!['hs', 'xy'].includes(payload[colorMode]) &&
|
|
612
|
+
config.colorTempSyncColor == false
|
|
613
|
+
) {
|
|
614
|
+
return undefined;
|
|
615
|
+
}
|
|
555
616
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
617
|
+
if (
|
|
618
|
+
payload[stateName] &&
|
|
619
|
+
payload[stateName].hasOwnProperty('h') &&
|
|
620
|
+
payload[stateName].hasOwnProperty('s') &
|
|
621
|
+
payload[stateName].hasOwnProperty('b')
|
|
622
|
+
) {
|
|
623
|
+
return rgb.hsvToRGBString(
|
|
624
|
+
payload[stateName].h,
|
|
625
|
+
payload[stateName].s,
|
|
626
|
+
Math.round(payload[stateName].b / 2.55)
|
|
627
|
+
);
|
|
628
|
+
}
|
|
561
629
|
|
|
630
|
+
if (
|
|
631
|
+
payload[stateName] &&
|
|
632
|
+
payload[stateName].hasOwnProperty('x') &&
|
|
633
|
+
payload[stateName].hasOwnProperty('y')
|
|
634
|
+
) {
|
|
635
|
+
const colorval = rgb.cie_to_rgb(
|
|
636
|
+
payload[stateName].x,
|
|
637
|
+
payload[stateName].y
|
|
638
|
+
);
|
|
639
|
+
return (
|
|
640
|
+
'#' +
|
|
641
|
+
utils.decimalToHex(colorval[0]) +
|
|
642
|
+
utils.decimalToHex(colorval[1]) +
|
|
643
|
+
utils.decimalToHex(colorval[2])
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
return undefined;
|
|
647
|
+
},
|
|
562
648
|
},
|
|
563
|
-
|
|
649
|
+
prop.access
|
|
650
|
+
);
|
|
564
651
|
break;
|
|
565
652
|
}
|
|
566
653
|
default:
|
|
@@ -589,7 +676,7 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
589
676
|
type: 'boolean',
|
|
590
677
|
def: true,
|
|
591
678
|
setattr: prop.property,
|
|
592
|
-
setter: (value) => (value
|
|
679
|
+
setter: (value) => (value ? prop.value_toggle : undefined),
|
|
593
680
|
});
|
|
594
681
|
}
|
|
595
682
|
break;
|
|
@@ -651,7 +738,7 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
651
738
|
state = statesDefs.battery_voltage;
|
|
652
739
|
}
|
|
653
740
|
if (expose.unit == 'mV') {
|
|
654
|
-
state.getter = payload => payload.voltage / 1000;
|
|
741
|
+
state.getter = (payload) => payload.voltage / 1000;
|
|
655
742
|
}
|
|
656
743
|
break;
|
|
657
744
|
|
|
@@ -670,262 +757,319 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
670
757
|
case 'enum':
|
|
671
758
|
switch (expose.name) {
|
|
672
759
|
case 'action': {
|
|
673
|
-
|
|
674
760
|
if (!Array.isArray(expose.values)) {
|
|
675
761
|
break;
|
|
676
762
|
}
|
|
677
763
|
|
|
678
764
|
// Support for DIYRuZ Device
|
|
679
|
-
const wildcardValues = expose.values.filter(x => x.startsWith('*'));
|
|
765
|
+
const wildcardValues = expose.values.filter((x) => x.startsWith('*'));
|
|
680
766
|
if (wildcardValues && wildcardValues.length > 0) {
|
|
681
|
-
for (const endpointName of [
|
|
767
|
+
for (const endpointName of [
|
|
768
|
+
...new Set(definition.exposes.filter((x) => x.endpoint).map((x) => x.endpoint)),
|
|
769
|
+
]) {
|
|
682
770
|
for (const value of wildcardValues) {
|
|
683
771
|
const actionName = value.replace('*', endpointName);
|
|
684
|
-
pushToStates(
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
772
|
+
pushToStates(
|
|
773
|
+
{
|
|
774
|
+
id: actionName,
|
|
775
|
+
prop: 'action',
|
|
776
|
+
name: `Triggered action ${value.replace('*_', endpointName)}`,
|
|
777
|
+
icon: undefined,
|
|
778
|
+
role: 'button',
|
|
779
|
+
write: false,
|
|
780
|
+
read: true,
|
|
781
|
+
type: 'boolean',
|
|
782
|
+
def: false,
|
|
783
|
+
isEvent: true,
|
|
784
|
+
getter: (payload) => (payload.action === actionName ? true : undefined),
|
|
785
|
+
},
|
|
786
|
+
expose.access
|
|
787
|
+
);
|
|
697
788
|
}
|
|
698
789
|
}
|
|
699
790
|
break;
|
|
700
791
|
}
|
|
701
792
|
|
|
702
793
|
for (const actionName of expose.values) {
|
|
703
|
-
|
|
704
794
|
// is release -> hold state? - skip
|
|
705
|
-
if (
|
|
795
|
+
if (
|
|
796
|
+
config.simpleHoldReleaseState == true &&
|
|
797
|
+
actionName.endsWith('release') &&
|
|
798
|
+
expose.values.find((x) => x == actionName.replace('release', 'hold'))
|
|
799
|
+
) {
|
|
706
800
|
continue;
|
|
707
801
|
}
|
|
708
802
|
|
|
709
803
|
// is stop - move state? - skip
|
|
710
|
-
if (
|
|
804
|
+
if (
|
|
805
|
+
config.simpleMoveStopState == true &&
|
|
806
|
+
actionName.endsWith('stop') &&
|
|
807
|
+
expose.values.find((x) => x.includes(actionName.replace('stop', 'move')))
|
|
808
|
+
) {
|
|
711
809
|
continue;
|
|
712
810
|
}
|
|
713
811
|
|
|
714
812
|
// is release -> press state? - skip
|
|
715
|
-
if (
|
|
813
|
+
if (
|
|
814
|
+
config.simplePressReleaseState == true &&
|
|
815
|
+
actionName.endsWith('release') &&
|
|
816
|
+
expose.values.find((x) => x == actionName.replace('release', 'press'))
|
|
817
|
+
) {
|
|
716
818
|
continue;
|
|
717
819
|
}
|
|
718
820
|
|
|
719
821
|
// is hold -> release state ?
|
|
720
|
-
if (
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
822
|
+
if (
|
|
823
|
+
config.simpleHoldReleaseState == true &&
|
|
824
|
+
actionName.endsWith('hold') &&
|
|
825
|
+
expose.values.find((x) => x == actionName.replace('hold', 'release'))
|
|
826
|
+
) {
|
|
827
|
+
pushToStates(
|
|
828
|
+
{
|
|
829
|
+
id: actionName.replace(/\*/g, ''),
|
|
830
|
+
prop: 'action',
|
|
831
|
+
name: actionName,
|
|
832
|
+
icon: undefined,
|
|
833
|
+
role: 'button',
|
|
834
|
+
write: false,
|
|
835
|
+
read: true,
|
|
836
|
+
def: false,
|
|
837
|
+
type: 'boolean',
|
|
838
|
+
getter: (payload) => {
|
|
839
|
+
if (payload.action === actionName) {
|
|
840
|
+
return true;
|
|
841
|
+
}
|
|
842
|
+
if (payload.action === actionName.replace('hold', 'release')) {
|
|
843
|
+
return false;
|
|
844
|
+
}
|
|
845
|
+
if (payload.action === `${actionName}_release`) {
|
|
846
|
+
return false;
|
|
847
|
+
}
|
|
848
|
+
return undefined;
|
|
849
|
+
},
|
|
742
850
|
},
|
|
743
|
-
|
|
851
|
+
expose.access
|
|
852
|
+
);
|
|
744
853
|
}
|
|
745
854
|
// is move -> stop state ?
|
|
746
|
-
else if (
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
855
|
+
else if (
|
|
856
|
+
config.simpleMoveStopState == true &&
|
|
857
|
+
actionName.includes('move') &&
|
|
858
|
+
expose.values.find((x) => x == `${actionName.split('_')[0]}_stop`)
|
|
859
|
+
) {
|
|
860
|
+
pushToStates(
|
|
861
|
+
{
|
|
862
|
+
id: actionName.replace(/\*/g, ''),
|
|
863
|
+
prop: 'action',
|
|
864
|
+
name: actionName,
|
|
865
|
+
icon: undefined,
|
|
866
|
+
role: 'button',
|
|
867
|
+
write: false,
|
|
868
|
+
read: true,
|
|
869
|
+
def: false,
|
|
870
|
+
type: 'boolean',
|
|
871
|
+
getter: (payload) => {
|
|
872
|
+
if (payload.action === actionName) {
|
|
873
|
+
return true;
|
|
874
|
+
}
|
|
875
|
+
if (payload.action === `${actionName.split('_')[0]}_stop`) {
|
|
876
|
+
return false;
|
|
877
|
+
}
|
|
878
|
+
return undefined;
|
|
879
|
+
},
|
|
765
880
|
},
|
|
766
|
-
|
|
881
|
+
expose.access
|
|
882
|
+
);
|
|
767
883
|
}
|
|
768
884
|
// is press -> release state ?
|
|
769
|
-
else if (
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
},
|
|
789
|
-
}, expose.access);
|
|
790
|
-
}
|
|
791
|
-
else if (actionName == 'color_temperature_move') {
|
|
792
|
-
pushToStates({
|
|
793
|
-
id: 'color_temperature_move',
|
|
794
|
-
prop: 'action',
|
|
795
|
-
name: 'Color temperature move value',
|
|
796
|
-
icon: undefined,
|
|
797
|
-
role: 'level.color.temperature',
|
|
798
|
-
write: false,
|
|
799
|
-
read: true,
|
|
800
|
-
type: 'number',
|
|
801
|
-
def: config.useKelvin == true ? utils.miredKelvinConversion(150) : 500,
|
|
802
|
-
min: config.useKelvin == true ? utils.miredKelvinConversion(500) : 150,
|
|
803
|
-
max: config.useKelvin == true ? utils.miredKelvinConversion(150) : 500,
|
|
804
|
-
unit: config.useKelvin == true ? 'K' : 'mired',
|
|
805
|
-
isEvent: true,
|
|
806
|
-
getter: (payload) => {
|
|
807
|
-
if (payload.action != 'color_temperature_move') {
|
|
808
|
-
return undefined;
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
if (payload.action_color_temperature) {
|
|
812
|
-
if (config.useKelvin == true) {
|
|
813
|
-
return utils.miredKelvinConversion(payload.action_color_temperature);
|
|
885
|
+
else if (
|
|
886
|
+
config.simplePressReleaseState == true &&
|
|
887
|
+
actionName.endsWith('press') &&
|
|
888
|
+
expose.values.find((x) => x == actionName.replace('press', 'release'))
|
|
889
|
+
) {
|
|
890
|
+
pushToStates(
|
|
891
|
+
{
|
|
892
|
+
id: actionName.replace(/\*/g, ''),
|
|
893
|
+
prop: 'action',
|
|
894
|
+
name: actionName,
|
|
895
|
+
icon: undefined,
|
|
896
|
+
role: 'button',
|
|
897
|
+
write: false,
|
|
898
|
+
read: true,
|
|
899
|
+
def: false,
|
|
900
|
+
type: 'boolean',
|
|
901
|
+
getter: (payload) => {
|
|
902
|
+
if (payload.action === actionName) {
|
|
903
|
+
return true;
|
|
814
904
|
}
|
|
815
|
-
|
|
816
|
-
return
|
|
905
|
+
if (payload.action === actionName.replace('press', 'release')) {
|
|
906
|
+
return false;
|
|
817
907
|
}
|
|
818
|
-
|
|
908
|
+
return undefined;
|
|
909
|
+
},
|
|
819
910
|
},
|
|
820
|
-
|
|
911
|
+
expose.access
|
|
912
|
+
);
|
|
913
|
+
} else if (actionName == 'color_temperature_move') {
|
|
914
|
+
pushToStates(
|
|
915
|
+
{
|
|
916
|
+
id: 'color_temperature_move',
|
|
917
|
+
prop: 'action',
|
|
918
|
+
name: 'Color temperature move value',
|
|
919
|
+
icon: undefined,
|
|
920
|
+
role: 'level.color.temperature',
|
|
921
|
+
write: false,
|
|
922
|
+
read: true,
|
|
923
|
+
type: 'number',
|
|
924
|
+
def: config.useKelvin == true ? utils.miredKelvinConversion(150) : 500,
|
|
925
|
+
min: config.useKelvin == true ? utils.miredKelvinConversion(500) : 150,
|
|
926
|
+
max: config.useKelvin == true ? utils.miredKelvinConversion(150) : 500,
|
|
927
|
+
unit: config.useKelvin == true ? 'K' : 'mired',
|
|
928
|
+
isEvent: true,
|
|
929
|
+
getter: (payload) => {
|
|
930
|
+
if (payload.action != 'color_temperature_move') {
|
|
931
|
+
return undefined;
|
|
932
|
+
}
|
|
821
933
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
934
|
+
if (payload.action_color_temperature) {
|
|
935
|
+
if (config.useKelvin == true) {
|
|
936
|
+
return utils.miredKelvinConversion(
|
|
937
|
+
payload.action_color_temperature
|
|
938
|
+
);
|
|
939
|
+
} else {
|
|
940
|
+
return payload.action_color_temperature;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
},
|
|
944
|
+
},
|
|
945
|
+
expose.access
|
|
946
|
+
);
|
|
947
|
+
} else if (actionName == 'color_move') {
|
|
948
|
+
pushToStates(
|
|
949
|
+
{
|
|
950
|
+
id: 'color_move',
|
|
951
|
+
prop: 'action',
|
|
952
|
+
name: 'Color move value',
|
|
953
|
+
icon: undefined,
|
|
954
|
+
role: 'level.color.rgb',
|
|
955
|
+
write: false,
|
|
956
|
+
read: true,
|
|
957
|
+
type: 'string',
|
|
958
|
+
def: '#ffffff',
|
|
959
|
+
isEvent: true,
|
|
960
|
+
getter: (payload) => {
|
|
961
|
+
if (payload.action != 'color_move') {
|
|
962
|
+
return undefined;
|
|
963
|
+
}
|
|
839
964
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
965
|
+
if (
|
|
966
|
+
payload.action_color &&
|
|
967
|
+
payload.action_color.hasOwnProperty('x') &&
|
|
968
|
+
payload.action_color.hasOwnProperty('y')
|
|
969
|
+
) {
|
|
970
|
+
const colorval = rgb.cie_to_rgb(
|
|
971
|
+
payload.action_color.x,
|
|
972
|
+
payload.action_color.y
|
|
973
|
+
);
|
|
974
|
+
return (
|
|
975
|
+
'#' +
|
|
976
|
+
utils.decimalToHex(colorval[0]) +
|
|
977
|
+
utils.decimalToHex(colorval[1]) +
|
|
978
|
+
utils.decimalToHex(colorval[2])
|
|
979
|
+
);
|
|
980
|
+
} else {
|
|
981
|
+
return undefined;
|
|
982
|
+
}
|
|
983
|
+
},
|
|
984
|
+
},
|
|
985
|
+
expose.access
|
|
986
|
+
);
|
|
987
|
+
} else if (actionName == 'brightness_move_to_level') {
|
|
988
|
+
pushToStates(
|
|
989
|
+
{
|
|
990
|
+
id: 'brightness_move_to_level',
|
|
991
|
+
name: 'Brightness move to level',
|
|
992
|
+
icon: undefined,
|
|
993
|
+
role: 'level.dimmer',
|
|
994
|
+
write: false,
|
|
995
|
+
read: true,
|
|
996
|
+
type: 'number',
|
|
997
|
+
min: 0,
|
|
998
|
+
max: 100,
|
|
999
|
+
def: 100,
|
|
1000
|
+
unit: '%',
|
|
1001
|
+
isEvent: true,
|
|
1002
|
+
getter: (payload) => {
|
|
1003
|
+
if (payload.action != 'brightness_move_to_level') {
|
|
1004
|
+
return undefined;
|
|
1005
|
+
}
|
|
868
1006
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1007
|
+
if (payload.action_level) {
|
|
1008
|
+
return utils.bulbLevelToAdapterLevel(payload.action_level);
|
|
1009
|
+
} else {
|
|
1010
|
+
return undefined;
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
},
|
|
1014
|
+
expose.access
|
|
1015
|
+
);
|
|
1016
|
+
} else if (actionName == 'move_to_saturation') {
|
|
1017
|
+
pushToStates(
|
|
1018
|
+
{
|
|
1019
|
+
id: 'move_to_saturation',
|
|
1020
|
+
name: 'Move to level saturation',
|
|
1021
|
+
icon: undefined,
|
|
1022
|
+
role: 'level.color.saturation',
|
|
1023
|
+
write: false,
|
|
1024
|
+
read: true,
|
|
1025
|
+
type: 'number',
|
|
1026
|
+
// min: 0,
|
|
1027
|
+
// max: 100,
|
|
1028
|
+
def: 0,
|
|
1029
|
+
isEvent: true,
|
|
1030
|
+
getter: (payload) => {
|
|
1031
|
+
if (payload.action != 'move_to_saturation') {
|
|
1032
|
+
return undefined;
|
|
1033
|
+
}
|
|
894
1034
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1035
|
+
if (payload.action_level) {
|
|
1036
|
+
return payload.action_saturation;
|
|
1037
|
+
} else {
|
|
1038
|
+
return undefined;
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
},
|
|
1042
|
+
expose.access
|
|
1043
|
+
);
|
|
1044
|
+
} else if (actionName == 'enhanced_move_to_hue_and_saturation') {
|
|
1045
|
+
pushToStates(
|
|
1046
|
+
{
|
|
1047
|
+
id: 'enhanced_move_to_hue_and_saturation',
|
|
1048
|
+
prop: 'action',
|
|
1049
|
+
name: 'Enhanced move to hue and saturation value',
|
|
1050
|
+
icon: undefined,
|
|
1051
|
+
role: 'level.color.hue',
|
|
1052
|
+
write: false,
|
|
1053
|
+
read: true,
|
|
1054
|
+
type: 'number',
|
|
1055
|
+
min: 0,
|
|
1056
|
+
max: 65536,
|
|
1057
|
+
def: 0,
|
|
1058
|
+
isEvent: true,
|
|
1059
|
+
getter: (payload) => {
|
|
1060
|
+
if (payload.action != 'enhanced_move_to_hue_and_saturation') {
|
|
1061
|
+
return undefined;
|
|
1062
|
+
}
|
|
921
1063
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1064
|
+
if (payload.action_enhanced_hue) {
|
|
1065
|
+
return payload.action_enhanced_hue;
|
|
1066
|
+
} else {
|
|
1067
|
+
return undefined;
|
|
1068
|
+
}
|
|
1069
|
+
},
|
|
1070
|
+
},
|
|
1071
|
+
expose.access
|
|
1072
|
+
);
|
|
929
1073
|
}
|
|
930
1074
|
// else if (actionName == 'hue_move') {
|
|
931
1075
|
// pushToStates({
|
|
@@ -954,23 +1098,29 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
954
1098
|
// }, expose.access);
|
|
955
1099
|
// }
|
|
956
1100
|
else {
|
|
957
|
-
pushToStates(
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1101
|
+
pushToStates(
|
|
1102
|
+
{
|
|
1103
|
+
id: actionName.replace(/\*/g, ''),
|
|
1104
|
+
prop: 'action',
|
|
1105
|
+
name: actionName,
|
|
1106
|
+
icon: undefined,
|
|
1107
|
+
role: 'button',
|
|
1108
|
+
write: false,
|
|
1109
|
+
read: true,
|
|
1110
|
+
type: 'boolean',
|
|
1111
|
+
def: false,
|
|
1112
|
+
isEvent: true,
|
|
1113
|
+
getter: (payload) => (payload.action === actionName ? true : undefined),
|
|
1114
|
+
},
|
|
1115
|
+
expose.access
|
|
1116
|
+
);
|
|
970
1117
|
}
|
|
971
1118
|
}
|
|
972
1119
|
// Can the device simulated_brightness?
|
|
973
|
-
if (
|
|
1120
|
+
if (
|
|
1121
|
+
definition.options &&
|
|
1122
|
+
definition.options.find((x) => x.property == 'simulated_brightness')
|
|
1123
|
+
) {
|
|
974
1124
|
pushToStates(statesDefs.simulated_brightness, z2mAccess.STATE);
|
|
975
1125
|
}
|
|
976
1126
|
state = null;
|
|
@@ -1046,7 +1196,7 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
1046
1196
|
def: true,
|
|
1047
1197
|
type: 'boolean',
|
|
1048
1198
|
setattr: prop.property,
|
|
1049
|
-
setter: (value) => (value
|
|
1199
|
+
setter: (value) => (value ? prop.value_toggle : undefined),
|
|
1050
1200
|
});
|
|
1051
1201
|
}
|
|
1052
1202
|
break;
|
|
@@ -1125,15 +1275,23 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
1125
1275
|
}
|
|
1126
1276
|
// if we have a composite expose, the payload will be an object {expose.property : {prop.property: value}}
|
|
1127
1277
|
if (prop.access & z2mAccess.STATE) {
|
|
1128
|
-
state.getter = payload => {
|
|
1129
|
-
if (
|
|
1130
|
-
|
|
1278
|
+
state.getter = (payload) => {
|
|
1279
|
+
if (
|
|
1280
|
+
payload.hasOwnProperty(expose.property) &&
|
|
1281
|
+
payload[expose.property] !== null &&
|
|
1282
|
+
payload[expose.property].hasOwnProperty(prop.property)
|
|
1283
|
+
) {
|
|
1284
|
+
return !isNaN(payload[expose.property][prop.property])
|
|
1285
|
+
? payload[expose.property][prop.property]
|
|
1286
|
+
: undefined;
|
|
1131
1287
|
} else {
|
|
1132
1288
|
return undefined;
|
|
1133
1289
|
}
|
|
1134
1290
|
};
|
|
1135
1291
|
} else {
|
|
1136
|
-
state.getter = _payload => {
|
|
1292
|
+
state.getter = (_payload) => {
|
|
1293
|
+
return undefined;
|
|
1294
|
+
};
|
|
1137
1295
|
}
|
|
1138
1296
|
pushToStates(state, prop.access);
|
|
1139
1297
|
}
|
|
@@ -1169,7 +1327,7 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
1169
1327
|
read: true,
|
|
1170
1328
|
def: true,
|
|
1171
1329
|
type: 'boolean',
|
|
1172
|
-
setter: (value) => (value
|
|
1330
|
+
setter: (value) => (value ? scene.id : undefined),
|
|
1173
1331
|
});
|
|
1174
1332
|
}
|
|
1175
1333
|
|
|
@@ -1186,7 +1344,6 @@ async function createDeviceFromExposes(devicesMessag, adapter) {
|
|
|
1186
1344
|
return newDevice;
|
|
1187
1345
|
}
|
|
1188
1346
|
|
|
1189
|
-
|
|
1190
1347
|
module.exports = {
|
|
1191
1348
|
createDeviceFromExposes: createDeviceFromExposes,
|
|
1192
1349
|
};
|