iobroker.zigbee2mqtt 2.2.1 → 2.4.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 +13 -1
- package/admin/i18n/de/translations.json +2 -1
- package/admin/i18n/en/translations.json +2 -1
- package/admin/i18n/es/translations.json +2 -1
- package/admin/i18n/fr/translations.json +2 -1
- package/admin/i18n/it/translations.json +2 -1
- package/admin/i18n/nl/translations.json +2 -1
- package/admin/i18n/pl/translations.json +2 -1
- package/admin/i18n/pt/translations.json +2 -1
- package/admin/i18n/ru/translations.json +2 -1
- package/admin/i18n/uk/translations.json +25 -0
- package/admin/i18n/zh-cn/translations.json +2 -1
- package/admin/jsonConfig.json +5 -0
- package/io-package.json +33 -28
- package/lib/deviceController.js +90 -67
- package/lib/exposes.js +216 -224
- package/lib/states.js +108 -75
- package/lib/statesController.js +43 -19
- package/lib/z2mController.js +6 -1
- package/main.js +2 -2
- package/package.json +4 -4
package/lib/exposes.js
CHANGED
|
@@ -71,7 +71,7 @@ function genState(expose, role, name, desc) {
|
|
|
71
71
|
|
|
72
72
|
if (writable) {
|
|
73
73
|
state.setter = (payload) => (payload) ? (expose.value_on || 'ON') : ((expose.value_off != undefined) ? expose.value_off : 'OFF');
|
|
74
|
-
state.setattr = expose.
|
|
74
|
+
state.setattr = expose.property;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
if (expose.endpoint) {
|
|
@@ -109,7 +109,6 @@ function genState(expose, role, name, desc) {
|
|
|
109
109
|
role: role || 'state',
|
|
110
110
|
write: writable,
|
|
111
111
|
read: true,
|
|
112
|
-
type: 'string',
|
|
113
112
|
states: {}
|
|
114
113
|
};
|
|
115
114
|
|
|
@@ -118,6 +117,21 @@ function genState(expose, role, name, desc) {
|
|
|
118
117
|
state.type = typeof (val);
|
|
119
118
|
}
|
|
120
119
|
|
|
120
|
+
switch (state.type) {
|
|
121
|
+
case 'boolean':
|
|
122
|
+
state.def = false;
|
|
123
|
+
break;
|
|
124
|
+
case 'number':
|
|
125
|
+
state.def = 0;
|
|
126
|
+
break;
|
|
127
|
+
case 'object':
|
|
128
|
+
state.def = {};
|
|
129
|
+
break;
|
|
130
|
+
case 'string':
|
|
131
|
+
state.def = '';
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
|
|
121
135
|
if (expose.endpoint) {
|
|
122
136
|
state.epname = expose.endpoint;
|
|
123
137
|
state.setattr = expose.name;
|
|
@@ -149,15 +163,6 @@ function genState(expose, role, name, desc) {
|
|
|
149
163
|
|
|
150
164
|
function createFromExposes(deviceID, ieee_address, definitions, power_source, scenes, config) {
|
|
151
165
|
const states = [];
|
|
152
|
-
// make the different (set and get) part of state is updatable if different exposes is used for get and set
|
|
153
|
-
// as example:
|
|
154
|
-
// ...
|
|
155
|
-
// exposes.binary('some_option', ea.STATE, true, false).withDescription('Some Option'),
|
|
156
|
-
// exposes.composite('options', 'options')
|
|
157
|
-
// .withDescription('Some composite Options')
|
|
158
|
-
// .withFeature(exposes.binary('some_option', ea.SET, true, false).withDescription('Some Option'))
|
|
159
|
-
//in this case one state - `some_option` has two different exposes for set an get, we have to combine it ...
|
|
160
|
-
|
|
161
166
|
function pushToStates(state, access) {
|
|
162
167
|
if (state === undefined) {
|
|
163
168
|
return 0;
|
|
@@ -278,26 +283,42 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
278
283
|
for (const prop of expose.features) {
|
|
279
284
|
switch (prop.name) {
|
|
280
285
|
case 'state': {
|
|
281
|
-
const
|
|
286
|
+
const stateName = expose.endpoint ? `state_${expose.endpoint}` : 'state';
|
|
282
287
|
pushToStates({
|
|
283
|
-
id:
|
|
288
|
+
id: stateName,
|
|
284
289
|
name: `Switch state ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
285
290
|
icon: undefined,
|
|
286
291
|
role: 'switch',
|
|
287
292
|
write: true,
|
|
288
293
|
read: true,
|
|
289
294
|
type: 'boolean',
|
|
290
|
-
getter: (payload) => (payload[
|
|
295
|
+
getter: (payload) => (payload[stateName] === (prop.value_on || 'ON')),
|
|
291
296
|
setter: (value) => (value) ? prop.value_on || 'ON' : ((prop.value_off != undefined) ? prop.value_off : 'OFF'),
|
|
292
297
|
epname: expose.endpoint,
|
|
293
|
-
setattr:
|
|
298
|
+
//setattr: stateName,
|
|
294
299
|
}, prop.access);
|
|
300
|
+
// features contains TOGGLE?
|
|
301
|
+
if (prop.value_toggle) {
|
|
302
|
+
pushToStates({
|
|
303
|
+
id: `${stateName}_toggle`,
|
|
304
|
+
prop: `${stateName}_toggle`,
|
|
305
|
+
name: `Toggle state of the ${stateName}`,
|
|
306
|
+
icon: undefined,
|
|
307
|
+
role: 'button',
|
|
308
|
+
write: true,
|
|
309
|
+
read: true,
|
|
310
|
+
type: 'boolean',
|
|
311
|
+
def: true,
|
|
312
|
+
setattr: stateName,
|
|
313
|
+
setter: (value) => (value) ? prop.value_toggle : undefined
|
|
314
|
+
});
|
|
315
|
+
}
|
|
295
316
|
break;
|
|
296
317
|
}
|
|
297
318
|
case 'brightness': {
|
|
298
|
-
const
|
|
319
|
+
const stateName = expose.endpoint ? `brightness_${expose.endpoint}` : 'brightness';
|
|
299
320
|
pushToStates({
|
|
300
|
-
id:
|
|
321
|
+
id: stateName,
|
|
301
322
|
name: `Brightness ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
302
323
|
icon: undefined,
|
|
303
324
|
role: 'level.dimmer',
|
|
@@ -306,38 +327,40 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
306
327
|
type: 'number',
|
|
307
328
|
min: 0, // ignore expose.value_min
|
|
308
329
|
max: 100, // ignore expose.value_max
|
|
330
|
+
def: 100,
|
|
309
331
|
inOptions: true,
|
|
310
332
|
unit: '%',
|
|
311
333
|
getter: (value) => {
|
|
312
|
-
return utils.bulbLevelToAdapterLevel(value[
|
|
334
|
+
return utils.bulbLevelToAdapterLevel(value[stateName]);
|
|
313
335
|
},
|
|
314
336
|
setter: (value) => {
|
|
315
337
|
return utils.adapterLevelToBulbLevel(value);
|
|
316
338
|
},
|
|
317
|
-
setterOpt: (value, options) => {
|
|
318
|
-
const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
319
|
-
const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
320
|
-
const preparedOptions = { ...options, transition: transitionTime };
|
|
321
|
-
preparedOptions.brightness = utils.adapterLevelToBulbLevel(value);
|
|
322
|
-
return preparedOptions;
|
|
323
|
-
},
|
|
324
|
-
readResponse: (resp) => {
|
|
325
|
-
const respObj = resp[0];
|
|
326
|
-
if (respObj.status === 0 && respObj.attrData != undefined) {
|
|
327
|
-
return utils.bulbLevelToAdapterLevel(respObj.attrData);
|
|
328
|
-
}
|
|
329
|
-
},
|
|
330
|
-
epname: expose.endpoint,
|
|
331
|
-
setattr: 'brightness',
|
|
332
339
|
}, prop.access);
|
|
333
|
-
|
|
340
|
+
// brightnessMoveOnOff
|
|
341
|
+
const propName = config.brightnessMoveOnOff == true ? `${stateName}_move_onoff` : `${stateName}_move`;
|
|
342
|
+
pushToStates({
|
|
343
|
+
id: `${stateName}_move`,
|
|
344
|
+
prop: propName,
|
|
345
|
+
name: 'Dimming',
|
|
346
|
+
icon: undefined,
|
|
347
|
+
role: 'state',
|
|
348
|
+
write: true,
|
|
349
|
+
read: false,
|
|
350
|
+
type: 'number',
|
|
351
|
+
min: -50,
|
|
352
|
+
max: 50,
|
|
353
|
+
def: 0
|
|
354
|
+
}, prop.access);
|
|
334
355
|
break;
|
|
335
356
|
}
|
|
336
357
|
case 'color_temp': {
|
|
337
|
-
const
|
|
358
|
+
const stateName = expose.endpoint ? `colortemp_${expose.endpoint}` : 'colortemp';
|
|
359
|
+
const propName = expose.endpoint ? `color_temp_${expose.endpoint}` : 'color_temp';
|
|
360
|
+
const colorMode = expose.endpoint ? `color_mode_${expose.endpoint}` : 'color_mode';
|
|
338
361
|
pushToStates({
|
|
339
|
-
id:
|
|
340
|
-
prop:
|
|
362
|
+
id: stateName,
|
|
363
|
+
prop: propName,
|
|
341
364
|
name: `Color temperature ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
342
365
|
icon: undefined,
|
|
343
366
|
role: 'level.color.temperature',
|
|
@@ -346,42 +369,50 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
346
369
|
type: 'number',
|
|
347
370
|
min: config.useKelvin == true ? utils.miredKelvinConversion(prop.value_max) : prop.value_min,
|
|
348
371
|
max: config.useKelvin == true ? utils.miredKelvinConversion(prop.value_min) : prop.value_max,
|
|
372
|
+
def: config.useKelvin == true ? utils.miredKelvinConversion(prop.value_min) : prop.value_max,
|
|
349
373
|
unit: config.useKelvin == true ? 'K' : 'mired',
|
|
350
374
|
setter: (value) => {
|
|
351
375
|
return utils.toMired(value);
|
|
352
376
|
},
|
|
353
|
-
// setterOpt: (_value, options) => {
|
|
354
|
-
// const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
355
|
-
// const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
356
|
-
// return { ...options, transition: transitionTime };
|
|
357
|
-
// },
|
|
358
377
|
getter: (payload) => {
|
|
359
|
-
if (payload
|
|
378
|
+
if (payload[colorMode] != 'color_temp') {
|
|
360
379
|
return undefined;
|
|
361
380
|
}
|
|
362
381
|
if (config.useKelvin == true) {
|
|
363
|
-
return utils.miredKelvinConversion(payload
|
|
382
|
+
return utils.miredKelvinConversion(payload[propName]);
|
|
364
383
|
} else {
|
|
365
|
-
return payload
|
|
384
|
+
return payload[propName];
|
|
366
385
|
}
|
|
367
386
|
},
|
|
368
|
-
epname: expose.endpoint,
|
|
369
|
-
setattr: 'color_temp',
|
|
370
387
|
}, prop.access);
|
|
371
|
-
|
|
388
|
+
// Colortemp
|
|
389
|
+
pushToStates({
|
|
390
|
+
id: `${stateName}_move`,
|
|
391
|
+
prop: `${propName}_move`,
|
|
392
|
+
name: 'Colortemp change',
|
|
393
|
+
icon: undefined,
|
|
394
|
+
role: 'state',
|
|
395
|
+
write: true,
|
|
396
|
+
read: false,
|
|
397
|
+
type: 'number',
|
|
398
|
+
min: -50,
|
|
399
|
+
max: 50,
|
|
400
|
+
def: 0
|
|
401
|
+
}, prop.access);
|
|
372
402
|
break;
|
|
373
403
|
}
|
|
374
404
|
case 'color_xy': {
|
|
375
|
-
const
|
|
405
|
+
const stateName = expose.endpoint ? `color_${expose.endpoint}` : 'color';
|
|
406
|
+
const colorMode = expose.endpoint ? `color_mode_${expose.endpoint}` : 'color_mode';
|
|
376
407
|
pushToStates({
|
|
377
|
-
id:
|
|
378
|
-
prop: expose.endpoint ? `color_${expose.endpoint}` : 'color',
|
|
408
|
+
id: stateName,
|
|
379
409
|
name: `Color ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
380
410
|
icon: undefined,
|
|
381
411
|
role: 'level.color.rgb',
|
|
382
412
|
write: true,
|
|
383
413
|
read: true,
|
|
384
414
|
type: 'string',
|
|
415
|
+
def: '#ff00ff',
|
|
385
416
|
setter: (value) => {
|
|
386
417
|
|
|
387
418
|
let xy = [0, 0];
|
|
@@ -395,32 +426,32 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
395
426
|
|
|
396
427
|
},
|
|
397
428
|
getter: payload => {
|
|
398
|
-
if (payload
|
|
429
|
+
if (payload[colorMode] != 'xy' && config.colorTempSyncColor == false) {
|
|
399
430
|
return undefined;
|
|
400
431
|
}
|
|
401
|
-
if (payload
|
|
402
|
-
const colorval = rgb.cie_to_rgb(payload.
|
|
432
|
+
if (payload[stateName] && payload[stateName].hasOwnProperty('x') && payload[stateName].hasOwnProperty('y')) {
|
|
433
|
+
const colorval = rgb.cie_to_rgb(payload[stateName].x, payload[stateName].y);
|
|
403
434
|
return '#' + utils.decimalToHex(colorval[0]) + utils.decimalToHex(colorval[1]) + utils.decimalToHex(colorval[2]);
|
|
404
435
|
} else {
|
|
405
436
|
return undefined;
|
|
406
437
|
}
|
|
407
438
|
},
|
|
408
439
|
epname: expose.endpoint,
|
|
409
|
-
setattr: 'color',
|
|
410
440
|
}, prop.access);
|
|
411
441
|
break;
|
|
412
442
|
}
|
|
413
443
|
case 'color_hs': {
|
|
414
|
-
const
|
|
444
|
+
const stateName = expose.endpoint ? `color_${expose.endpoint}` : 'color';
|
|
445
|
+
const colorMode = expose.endpoint ? `color_mode_${expose.endpoint}` : 'color_mode';
|
|
415
446
|
pushToStates({
|
|
416
|
-
id:
|
|
417
|
-
prop: expose.endpoint ? `color_${expose.endpoint}` : 'color',
|
|
447
|
+
id: stateName,
|
|
418
448
|
name: `Color ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
419
449
|
icon: undefined,
|
|
420
450
|
role: 'level.color.rgb',
|
|
421
451
|
write: true,
|
|
422
452
|
read: true,
|
|
423
453
|
type: 'string',
|
|
454
|
+
def: '#ff00ff',
|
|
424
455
|
setter: (value) => {
|
|
425
456
|
const _rgb = colors.ParseColor(value);
|
|
426
457
|
const hsv = rgb.rgbToHSV(_rgb.r, _rgb.g, _rgb.b, true);
|
|
@@ -432,138 +463,22 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
432
463
|
};
|
|
433
464
|
},
|
|
434
465
|
getter: payload => {
|
|
435
|
-
if (payload.
|
|
466
|
+
if (!['hs', 'xy'].includes(payload[colorMode]) && config.colorTempSyncColor == false) {
|
|
436
467
|
return undefined;
|
|
437
468
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
469
|
+
|
|
470
|
+
if (payload[stateName] && payload[stateName].hasOwnProperty('h') && payload[stateName].hasOwnProperty('s') & payload[stateName].hasOwnProperty('b')) {
|
|
471
|
+
return rgb.hsvToRGBString(payload[stateName].h, payload[stateName].s, Math.round(payload[stateName].b / 2.55));
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (payload[stateName] && payload[stateName].hasOwnProperty('x') && payload[stateName].hasOwnProperty('y')) {
|
|
475
|
+
const colorval = rgb.cie_to_rgb(payload[stateName].x, payload[stateName].y);
|
|
476
|
+
return '#' + utils.decimalToHex(colorval[0]) + utils.decimalToHex(colorval[1]) + utils.decimalToHex(colorval[2]);
|
|
442
477
|
}
|
|
478
|
+
return undefined;
|
|
479
|
+
|
|
443
480
|
},
|
|
444
|
-
epname: expose.endpoint,
|
|
445
|
-
setattr: 'color',
|
|
446
481
|
}, prop.access);
|
|
447
|
-
// pushToStates({
|
|
448
|
-
// id: expose.endpoint ? `hue_${expose.endpoint}` : 'hue',
|
|
449
|
-
// prop: expose.endpoint ? `color_${expose.endpoint}` : 'color',
|
|
450
|
-
// name: `Hue ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
451
|
-
// icon: undefined,
|
|
452
|
-
// role: 'level.color.hue',
|
|
453
|
-
// write: true,
|
|
454
|
-
// read: false,
|
|
455
|
-
// type: 'number',
|
|
456
|
-
// min: 0,
|
|
457
|
-
// max: 360,
|
|
458
|
-
// inOptions: true,
|
|
459
|
-
// setter: (value, options) => {
|
|
460
|
-
// return {
|
|
461
|
-
// hue: value,
|
|
462
|
-
// saturation: options.saturation,
|
|
463
|
-
// };
|
|
464
|
-
// },
|
|
465
|
-
// setterOpt: (_value, options) => {
|
|
466
|
-
// const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
467
|
-
// const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
468
|
-
// const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
|
|
469
|
-
// if (hasHueCalibrationTable)
|
|
470
|
-
// try {
|
|
471
|
-
// return { ...options, transition: transitionTime, hue_correction: JSON.parse(options.hue_calibration) };
|
|
472
|
-
// }
|
|
473
|
-
// catch (err) {
|
|
474
|
-
// const hue_correction_table = [];
|
|
475
|
-
// options.hue_calibration.split(',').forEach(element => {
|
|
476
|
-
// const match = /([0-9]+):([0-9]+)/.exec(element);
|
|
477
|
-
// if (match && match.length == 3)
|
|
478
|
-
// hue_correction_table.push({ in: Number(match[1]), out: Number(match[2]) });
|
|
479
|
-
// });
|
|
480
|
-
// if (hue_correction_table.length > 0)
|
|
481
|
-
// return { ...options, transition: transitionTime, hue_correction: hue_correction_table };
|
|
482
|
-
// }
|
|
483
|
-
// return { ...options, transition: transitionTime };
|
|
484
|
-
// },
|
|
485
|
-
|
|
486
|
-
// }, prop.access);
|
|
487
|
-
// pushToStates({
|
|
488
|
-
// id: expose.endpoint ? `saturation_${expose.endpoint}` : 'saturation',
|
|
489
|
-
// prop: expose.endpoint ? `color_${expose.endpoint}` : 'color',
|
|
490
|
-
// name: `Saturation ${expose.endpoint ? expose.endpoint : ''}`.trim(),
|
|
491
|
-
// icon: undefined,
|
|
492
|
-
// role: 'level.color.saturation',
|
|
493
|
-
// write: true,
|
|
494
|
-
// read: false,
|
|
495
|
-
// type: 'number',
|
|
496
|
-
// min: 0,
|
|
497
|
-
// max: 100,
|
|
498
|
-
// inOptions: true,
|
|
499
|
-
// setter: (value, options) => {
|
|
500
|
-
// return {
|
|
501
|
-
// hue: options.hue,
|
|
502
|
-
// saturation: value,
|
|
503
|
-
// };
|
|
504
|
-
// },
|
|
505
|
-
// setterOpt: (_value, options) => {
|
|
506
|
-
// const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
507
|
-
// const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
508
|
-
// const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
|
|
509
|
-
// if (hasHueCalibrationTable)
|
|
510
|
-
// try {
|
|
511
|
-
// return { ...options, transition: transitionTime, hue_correction: JSON.parse(options.hue_calibration) };
|
|
512
|
-
// }
|
|
513
|
-
// catch (err) {
|
|
514
|
-
// const hue_correction_table = [];
|
|
515
|
-
// options.hue_calibration.split(',').forEach(element => {
|
|
516
|
-
// const match = /([0-9]+):([0-9]+)/.exec(element);
|
|
517
|
-
// if (match && match.length == 3)
|
|
518
|
-
// hue_correction_table.push({ in: Number(match[1]), out: Number(match[2]) });
|
|
519
|
-
// });
|
|
520
|
-
// if (hue_correction_table.length > 0)
|
|
521
|
-
// return { ...options, transition: transitionTime, hue_correction: hue_correction_table };
|
|
522
|
-
// }
|
|
523
|
-
// return { ...options, transition: transitionTime };
|
|
524
|
-
// },
|
|
525
|
-
|
|
526
|
-
// }, 2);
|
|
527
|
-
// pushToStates(statesDefs.hue_move, 2);
|
|
528
|
-
// pushToStates(statesDefs.saturation_move, 2);
|
|
529
|
-
// pushToStates({
|
|
530
|
-
// id: 'hue_calibration',
|
|
531
|
-
// prop: 'color',
|
|
532
|
-
// name: 'Hue color calibration table',
|
|
533
|
-
// icon: undefined,
|
|
534
|
-
// role: 'table',
|
|
535
|
-
// write: true,
|
|
536
|
-
// read: false,
|
|
537
|
-
// type: 'string',
|
|
538
|
-
// inOptions: true,
|
|
539
|
-
// setter: (_value, options) => {
|
|
540
|
-
// return {
|
|
541
|
-
// hue: options.hue,
|
|
542
|
-
// saturation: options.saturation,
|
|
543
|
-
// };
|
|
544
|
-
// },
|
|
545
|
-
// setterOpt: (_value, options) => {
|
|
546
|
-
// const hasTransitionTime = options && options.hasOwnProperty('transition_time');
|
|
547
|
-
// const transitionTime = hasTransitionTime ? options.transition_time : 0;
|
|
548
|
-
// const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
|
|
549
|
-
// if (hasHueCalibrationTable)
|
|
550
|
-
// try {
|
|
551
|
-
// return { ...options, transition: transitionTime, hue_correction: JSON.parse(options.hue_calibration) };
|
|
552
|
-
// }
|
|
553
|
-
// catch (err) {
|
|
554
|
-
// const hue_correction_table = [];
|
|
555
|
-
// options.hue_calibration.split(',').forEach(element => {
|
|
556
|
-
// const match = /([0-9]+):([0-9]+)/.exec(element);
|
|
557
|
-
// if (match && match.length == 3)
|
|
558
|
-
// hue_correction_table.push({ in: Number(match[1]), out: Number(match[2]) });
|
|
559
|
-
// });
|
|
560
|
-
// if (hue_correction_table.length > 0)
|
|
561
|
-
// return { ...options, transition: transitionTime, hue_correction: hue_correction_table };
|
|
562
|
-
// }
|
|
563
|
-
// return { ...options, transition: transitionTime };
|
|
564
|
-
// },
|
|
565
|
-
|
|
566
|
-
// }, prop.access);
|
|
567
482
|
break;
|
|
568
483
|
}
|
|
569
484
|
default:
|
|
@@ -580,6 +495,22 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
580
495
|
switch (prop.name) {
|
|
581
496
|
case 'state':
|
|
582
497
|
pushToStates(genState(prop, 'switch'), prop.access);
|
|
498
|
+
// features contains TOGGLE?
|
|
499
|
+
if (prop.value_toggle) {
|
|
500
|
+
pushToStates({
|
|
501
|
+
id: `${prop.property}_toggle`,
|
|
502
|
+
prop: `${prop.property}_toggle`,
|
|
503
|
+
name: `Toggle state of the ${prop.property}`,
|
|
504
|
+
icon: undefined,
|
|
505
|
+
role: 'button',
|
|
506
|
+
write: true,
|
|
507
|
+
read: true,
|
|
508
|
+
type: 'boolean',
|
|
509
|
+
def: true,
|
|
510
|
+
setattr: prop.property,
|
|
511
|
+
setter: (value) => (value) ? prop.value_toggle : undefined
|
|
512
|
+
});
|
|
513
|
+
}
|
|
583
514
|
break;
|
|
584
515
|
default:
|
|
585
516
|
pushToStates(genState(prop), prop.access);
|
|
@@ -659,21 +590,22 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
659
590
|
switch (expose.name) {
|
|
660
591
|
case 'action': {
|
|
661
592
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
// Action (bekommt text ausser hold und release, auto reset nach 250 ms)
|
|
666
|
-
// Hold: wird gesetzt bei hold, gelöscht bei passendem Release
|
|
593
|
+
if (!Array.isArray(expose.values)) {
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
667
596
|
|
|
668
|
-
if (!Array.isArray(expose.values)) break;
|
|
669
597
|
const hasHold = expose.values.find((actionName) => actionName.includes('hold'));
|
|
670
598
|
const hasRelease = expose.values.find((actionName) => actionName.includes('release'));
|
|
599
|
+
|
|
671
600
|
for (const actionName of expose.values) {
|
|
672
601
|
// is release state ? - skip
|
|
673
|
-
if (hasHold && hasRelease && actionName.includes('release'))
|
|
602
|
+
if (hasHold && hasRelease && actionName.includes('release')) {
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
|
|
674
606
|
// is hold state ?
|
|
675
607
|
if (hasHold && hasRelease && actionName.includes('hold')) {
|
|
676
|
-
|
|
608
|
+
pushToStates({
|
|
677
609
|
id: actionName.replace(/\*/g, ''),
|
|
678
610
|
prop: 'action',
|
|
679
611
|
name: actionName,
|
|
@@ -695,9 +627,69 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
695
627
|
}
|
|
696
628
|
return undefined;
|
|
697
629
|
},
|
|
698
|
-
};
|
|
699
|
-
}
|
|
700
|
-
|
|
630
|
+
}, expose.access);
|
|
631
|
+
}
|
|
632
|
+
else if (actionName.includes('color_temperature_move')) {
|
|
633
|
+
pushToStates({
|
|
634
|
+
id: 'color_temperature_move',
|
|
635
|
+
prop: 'action',
|
|
636
|
+
name: 'Color temperature move value',
|
|
637
|
+
icon: undefined,
|
|
638
|
+
role: 'level.color.temperature',
|
|
639
|
+
write: false,
|
|
640
|
+
read: true,
|
|
641
|
+
type: 'number',
|
|
642
|
+
def: config.useKelvin == true ? utils.miredKelvinConversion(150) : 500,
|
|
643
|
+
min: config.useKelvin == true ? utils.miredKelvinConversion(500) : 150,
|
|
644
|
+
max: config.useKelvin == true ? utils.miredKelvinConversion(150) : 500,
|
|
645
|
+
unit: config.useKelvin == true ? 'K' : 'mired',
|
|
646
|
+
isEvent: true,
|
|
647
|
+
getter: (payload) => {
|
|
648
|
+
if (payload.action != 'color_temperature_move') {
|
|
649
|
+
return undefined;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
if (payload.action_color_temperature) {
|
|
653
|
+
if (config.useKelvin == true) {
|
|
654
|
+
return utils.miredKelvinConversion(payload.action_color_temperature);
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
return payload.action_color_temperature;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
},
|
|
661
|
+
}, expose.access);
|
|
662
|
+
|
|
663
|
+
}
|
|
664
|
+
else if (actionName.includes('color_move')) {
|
|
665
|
+
pushToStates({
|
|
666
|
+
id: 'color_move',
|
|
667
|
+
prop: 'action',
|
|
668
|
+
name: 'Color move value',
|
|
669
|
+
icon: undefined,
|
|
670
|
+
role: 'level.color.rgb',
|
|
671
|
+
write: false,
|
|
672
|
+
read: true,
|
|
673
|
+
type: 'string',
|
|
674
|
+
def: '#ffffff',
|
|
675
|
+
isEvent: true,
|
|
676
|
+
getter: (payload) => {
|
|
677
|
+
if (payload.action != 'color_move') {
|
|
678
|
+
return undefined;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
if (payload.action_color && payload.action_color.hasOwnProperty('x') && payload.action_color.hasOwnProperty('y')) {
|
|
682
|
+
const colorval = rgb.cie_to_rgb(payload.action_color.x, payload.action_color.y);
|
|
683
|
+
return '#' + utils.decimalToHex(colorval[0]) + utils.decimalToHex(colorval[1]) + utils.decimalToHex(colorval[2]);
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
return undefined;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}, expose.access);
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
pushToStates({
|
|
701
693
|
id: actionName.replace(/\*/g, ''),
|
|
702
694
|
prop: 'action',
|
|
703
695
|
name: actionName,
|
|
@@ -709,27 +701,12 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
709
701
|
def: false,
|
|
710
702
|
isEvent: true,
|
|
711
703
|
getter: payload => (payload.action === actionName) ? true : undefined,
|
|
712
|
-
};
|
|
704
|
+
}, expose.access);
|
|
713
705
|
}
|
|
714
|
-
pushToStates(state, expose.access);
|
|
715
706
|
}
|
|
716
707
|
// Can the device simulated_brightness?
|
|
717
708
|
if (definitions.options && definitions.options.find(x => x.property == 'simulated_brightness')) {
|
|
718
|
-
pushToStates(
|
|
719
|
-
id: 'simulated_brightness',
|
|
720
|
-
prop: 'brightness',
|
|
721
|
-
name: 'Simulated brightness',
|
|
722
|
-
icon: undefined,
|
|
723
|
-
role: 'level.dimmer',
|
|
724
|
-
write: true,
|
|
725
|
-
read: true,
|
|
726
|
-
type: 'number',
|
|
727
|
-
unit: '%',
|
|
728
|
-
def: 0,
|
|
729
|
-
getter: payload => {
|
|
730
|
-
return utils.bulbLevelToAdapterLevel(payload.brightness);
|
|
731
|
-
},
|
|
732
|
-
}, expose.access);
|
|
709
|
+
pushToStates(statesDefs.simulated_brightness, z2mAccess.STATE);
|
|
733
710
|
}
|
|
734
711
|
state = null;
|
|
735
712
|
break;
|
|
@@ -791,6 +768,22 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
791
768
|
switch (prop.name) {
|
|
792
769
|
case 'state':
|
|
793
770
|
pushToStates(genState(prop, 'switch'), prop.access);
|
|
771
|
+
// features contains TOGGLE?
|
|
772
|
+
if (prop.value_toggle) {
|
|
773
|
+
pushToStates({
|
|
774
|
+
id: `${prop.property}_toggle`,
|
|
775
|
+
prop: `${prop.property}_toggle`,
|
|
776
|
+
name: `Toggle state of the ${prop.property}`,
|
|
777
|
+
icon: undefined,
|
|
778
|
+
role: 'button',
|
|
779
|
+
write: true,
|
|
780
|
+
read: true,
|
|
781
|
+
def: true,
|
|
782
|
+
type: 'boolean',
|
|
783
|
+
setattr: prop.property,
|
|
784
|
+
setter: (value) => (value) ? prop.value_toggle : undefined
|
|
785
|
+
});
|
|
786
|
+
}
|
|
794
787
|
break;
|
|
795
788
|
default:
|
|
796
789
|
pushToStates(genState(prop), prop.access);
|
|
@@ -881,16 +874,9 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
881
874
|
// Add default states
|
|
882
875
|
pushToStates(statesDefs.available, z2mAccess.STATE);
|
|
883
876
|
|
|
884
|
-
const newDevice = {
|
|
885
|
-
id: deviceID,
|
|
886
|
-
ieee_address: ieee_address,
|
|
887
|
-
power_source: power_source,
|
|
888
|
-
states: states,
|
|
889
|
-
};
|
|
890
|
-
|
|
891
877
|
// Create buttons for scenes
|
|
892
878
|
for (const scene of scenes) {
|
|
893
|
-
|
|
879
|
+
pushToStates({
|
|
894
880
|
id: `scene_${scene.id}`,
|
|
895
881
|
prop: `scene_recall`,
|
|
896
882
|
name: scene.name,
|
|
@@ -898,13 +884,19 @@ function createFromExposes(deviceID, ieee_address, definitions, power_source, sc
|
|
|
898
884
|
role: 'button',
|
|
899
885
|
write: true,
|
|
900
886
|
read: true,
|
|
887
|
+
def: true,
|
|
901
888
|
type: 'boolean',
|
|
902
889
|
setter: (value) => (value) ? scene.id : undefined
|
|
903
|
-
};
|
|
904
|
-
// @ts-ignore
|
|
905
|
-
newDevice.states.push(sceneSate);
|
|
890
|
+
});
|
|
906
891
|
}
|
|
907
892
|
|
|
893
|
+
const newDevice = {
|
|
894
|
+
id: deviceID,
|
|
895
|
+
ieee_address: ieee_address,
|
|
896
|
+
power_source: power_source,
|
|
897
|
+
states: states,
|
|
898
|
+
};
|
|
899
|
+
|
|
908
900
|
return newDevice;
|
|
909
901
|
}
|
|
910
902
|
|