iobroker.zigbee 1.8.1 → 1.8.3

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.
Files changed (89) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.json +37 -0
  3. package/.github/FUNDING.yml +3 -0
  4. package/.github/auto-merge.yml +17 -0
  5. package/.github/dependabot.yml +24 -0
  6. package/.github/stale.yml +13 -0
  7. package/.github/workflows/codeql.yml +41 -0
  8. package/.github/workflows/dependabot-automerge.yml +22 -0
  9. package/.github/workflows/test-and-release.yml +149 -0
  10. package/.releaseconfig.json +3 -0
  11. package/.travis/wiki.sh +28 -0
  12. package/.travis.yml +41 -0
  13. package/README.md +31 -8
  14. package/admin/admin.js +466 -482
  15. package/admin/i18n/de/translations.json +2 -2
  16. package/admin/index_m.html +1 -1
  17. package/admin/tab_m.html +3 -44
  18. package/admin/words.js +2 -2
  19. package/gulpfile.js +464 -0
  20. package/io-package.json +18 -25
  21. package/lib/backup.js +2 -2
  22. package/lib/binding.js +37 -32
  23. package/lib/colors.js +158 -163
  24. package/lib/commands.js +90 -99
  25. package/lib/developer.js +12 -9
  26. package/lib/devices.js +179 -169
  27. package/lib/exclude.js +36 -30
  28. package/lib/exposes.js +139 -163
  29. package/lib/groups.js +83 -81
  30. package/lib/json.js +6 -5
  31. package/lib/networkmap.js +3 -2
  32. package/lib/ota.js +18 -34
  33. package/lib/rgb.js +72 -114
  34. package/lib/seriallist.js +20 -25
  35. package/lib/states.js +526 -511
  36. package/lib/statescontroller.js +183 -206
  37. package/lib/utils.js +23 -24
  38. package/lib/zbBaseExtension.js +4 -4
  39. package/lib/zbDelayedAction.js +13 -5
  40. package/lib/zbDeviceAvailability.js +65 -69
  41. package/lib/zbDeviceConfigure.js +21 -9
  42. package/lib/zbDeviceEvent.js +4 -3
  43. package/lib/zigbeecontroller.js +103 -109
  44. package/main.js +147 -163
  45. package/package.json +15 -29
  46. package/test/integration.js +5 -0
  47. package/test/mocha.custom.opts +2 -0
  48. package/test/mocha.setup.js +14 -0
  49. package/test/package.js +5 -0
  50. package/test/unit.js +5 -0
  51. package/docs/de/img/CC2531.png +0 -0
  52. package/docs/de/img/CC2538_CC2592_PA.PNG +0 -0
  53. package/docs/de/img/CC2591.png +0 -0
  54. package/docs/de/img/boards.jpg +0 -0
  55. package/docs/de/img/cc26x2r.PNG +0 -0
  56. package/docs/de/img/results.jpg +0 -0
  57. package/docs/de/img/sku_429478_2.png +0 -0
  58. package/docs/de/img/sku_429601_2.png +0 -0
  59. package/docs/de/readme.md +0 -27
  60. package/docs/en/img/CC2531.png +0 -0
  61. package/docs/en/img/CC2591.png +0 -0
  62. package/docs/en/img/deconz.png +0 -0
  63. package/docs/en/img/sku_429478_2.png +0 -0
  64. package/docs/en/img/sku_429601_2.png +0 -0
  65. package/docs/en/readme.md +0 -30
  66. package/docs/flashing_via_arduino_(en).md +0 -110
  67. package/docs/ru/img/CC2531.png +0 -0
  68. package/docs/ru/img/CC2591.png +0 -0
  69. package/docs/ru/img/sku_429478_2.png +0 -0
  70. package/docs/ru/img/sku_429601_2.png +0 -0
  71. package/docs/ru/readme.md +0 -28
  72. package/docs/tutorial/CC2530_20190425.zip +0 -0
  73. package/docs/tutorial/CC2530_CC2591_20190515.zip +0 -0
  74. package/docs/tutorial/CC2530_CC2592_20190515.zip +0 -0
  75. package/docs/tutorial/CC2531_20190425.zip +0 -0
  76. package/docs/tutorial/adm5_1.PNG +0 -0
  77. package/docs/tutorial/adm5_2.PNG +0 -0
  78. package/docs/tutorial/cat.PNG +0 -0
  79. package/docs/tutorial/groups-1.png +0 -0
  80. package/docs/tutorial/groups-2.png +0 -0
  81. package/docs/tutorial/inst.PNG +0 -0
  82. package/docs/tutorial/reflash-finish.PNG +0 -0
  83. package/docs/tutorial/reflash-step0.png +0 -0
  84. package/docs/tutorial/reflash-step1.PNG +0 -0
  85. package/docs/tutorial/reflash-step2.PNG +0 -0
  86. package/docs/tutorial/settings.png +0 -0
  87. package/docs/tutorial/tab-dev-1.png +0 -0
  88. package/docs/tutorial/zigbee.png +0 -0
  89. package/docs/tutorial/zigbee15.png +0 -0
package/lib/exposes.js CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
4
- const statesDefs = require('./states.js').states;
5
- const rgb = require('./rgb.js');
6
- const utils = require('./utils.js');
7
- const colors = require('./colors.js');
4
+ const statesDefs = require(__dirname + '/states.js').states;
5
+ const rgb = require(__dirname + '/rgb.js');
6
+ const utils = require(__dirname + '/utils.js');
7
+ const colors = require(__dirname + '/colors.js');
8
8
  const ea = zigbeeHerdsmanConverters.exposes.access;
9
9
 
10
10
  function genState(expose, role, name, desc) {
@@ -29,9 +29,10 @@ function genState(expose, role, name, desc) {
29
29
  type: 'boolean',
30
30
  };
31
31
  if (readable) {
32
- state.getter = payload => payload[propName] === (expose.value_on || 'ON');
33
- } else {
34
- state.getter = payload => undefined;
32
+ state.getter = payload => (payload[propName] === (expose.value_on || 'ON'));
33
+ }
34
+ else {
35
+ state.getter = payload => ( undefined);
35
36
  }
36
37
  if (writable) {
37
38
  state.setter = (value) => (value) ? (expose.value_on || 'ON') : ((expose.value_off != undefined) ? expose.value_off : 'OFF');
@@ -71,7 +72,7 @@ function genState(expose, role, name, desc) {
71
72
  write: writable,
72
73
  read: true,
73
74
  type: 'string',
74
- states: expose.values.map(item => `${item}:${item}`).join(';'),
75
+ states: expose.values.map((item) => `${item}:${item}`).join(';'),
75
76
  };
76
77
  if (expose.endpoint) {
77
78
  state.epname = expose.endpoint;
@@ -102,6 +103,8 @@ function genState(expose, role, name, desc) {
102
103
  return state;
103
104
  }
104
105
 
106
+
107
+
105
108
  function createFromExposes(model, def) {
106
109
  const states = [];
107
110
  // make the different (set and get) part of state is updatable if different exposes is used for get and set
@@ -118,31 +121,30 @@ function createFromExposes(model, def) {
118
121
  if (state === undefined) {
119
122
  return 0;
120
123
  }
121
- if (access === undefined) {
122
- access = ea.ALL;
123
- }
124
+ if (access === undefined) access = ea.ALL;
124
125
  state.readable = (access & ea.STATE) > 0;
125
126
  state.writable = (access & ea.SET) > 0;
126
- const stateExists = states.findIndex((element, index, array) => element.id === state.id);
127
- if (stateExists < 0) {
127
+ const stateExists = states.findIndex( (element, index, array) => (element.id === state.id ));
128
+ if (stateExists < 0 ) {
128
129
  state.write = state.writable;
129
- if (!state.writable) {
130
- if (state.hasOwnProperty('setter')) {
130
+ if (! state.writable) {
131
+ if ( state.hasOwnProperty('setter') ) {
131
132
  delete state.setter;
132
133
  }
133
- if (state.hasOwnProperty('setattr')) {
134
+ if ( state.hasOwnProperty('setattr') ) {
134
135
  delete state.setattr;
135
136
  }
136
137
  }
137
- if (!state.readable) {
138
- if (state.hasOwnProperty('getter')) {
139
- // to awoid some warnings on unprocessed data
140
- state.getter = payload => undefined;
138
+ if (! state.readable) {
139
+ if (state.hasOwnProperty('getter') ) {
140
+ //to awid some worning on unprocessed data
141
+ state.getter = payload => ( undefined );
141
142
  }
142
143
  }
143
144
  return states.push(state);
144
- } else {
145
- if ((state.readable) && (!states[stateExists].readable)) {
145
+ }
146
+ else {
147
+ if ( (state.readable) && (! states[stateExists].readable ) ) {
146
148
  states[stateExists].read = state.read;
147
149
  // as state is readable, it can't be button or event
148
150
  if (states[stateExists].role === 'button') {
@@ -152,70 +154,69 @@ function createFromExposes(model, def) {
152
154
  delete states[stateExists].isEvent;
153
155
  }
154
156
  // we have to use the getter from "new" state
155
- if (state.hasOwnProperty('getter')) {
157
+ if ( state.hasOwnProperty('getter') ) {
156
158
  states[stateExists].getter = state.getter;
157
159
  }
158
160
  // trying to remove the `prop` property, as main key for get and set,
159
161
  // as it can be different in new and old states, and leave only:
160
162
  // setattr for old and id for new
161
- if ((state.hasOwnProperty('prop')) && (state.prop === state.id)) {
162
- if (states[stateExists].hasOwnProperty('prop')) {
163
+ if (( state.hasOwnProperty('prop') ) && (state.prop === state.id)) {
164
+ if ( states[stateExists].hasOwnProperty('prop') ) {
163
165
  if (states[stateExists].prop !== states[stateExists].id) {
164
- if (!states[stateExists].hasOwnProperty('setattr')) {
166
+ if (! states[stateExists].hasOwnProperty('setattr')) {
165
167
  states[stateExists].setattr = states[stateExists].prop;
166
168
  }
167
169
  }
168
170
  delete states[stateExists].prop;
169
171
  }
170
- } else if (state.hasOwnProperty('prop')) {
172
+ }
173
+ else if ( state.hasOwnProperty('prop') ) {
171
174
  states[stateExists].prop = state.prop;
172
175
  }
173
176
  states[stateExists].readable = true;
174
177
  }
175
- if ((state.writable) && (!states[stateExists].writable)) {
178
+ if ( (state.writable) && (! states[stateExists].writable ) ) {
176
179
  states[stateExists].write = state.writable;
177
180
  // use new state `setter`
178
- if (state.hasOwnProperty('setter')) {
181
+ if ( state.hasOwnProperty('setter') ) {
179
182
  states[stateExists].setter = state.setter;
180
183
  }
181
184
  // use new state `setterOpt`
182
- if (state.hasOwnProperty('setterOpt')) {
185
+ if ( state.hasOwnProperty('setterOpt') ) {
183
186
  states[stateExists].setterOpt = state.setterOpt;
184
187
  }
185
188
  // use new state `inOptions`
186
- if (state.hasOwnProperty('inOptions')) {
189
+ if ( state.hasOwnProperty('inOptions') ) {
187
190
  states[stateExists].inOptions = state.inOptions;
188
191
  }
189
192
  // as we have new state, responsible for set, we have to use new `isOption`
190
193
  // or remove it
191
- if (((!state.hasOwnProperty('isOption')) || (state.isOptions === false))
192
- && (states[stateExists].hasOwnProperty('isOption'))) {
194
+ if (((! state.hasOwnProperty('isOption') ) || (state.isOptions === false))
195
+ && (states[stateExists].hasOwnProperty('isOption'))) {
193
196
  delete states[stateExists].isOption;
194
- } else {
197
+ }
198
+ else {
195
199
  states[stateExists].isOption = state.isOption;
196
200
  }
197
-
198
201
  // use new `setattr` or `prop` as `setattr`
199
- if (state.hasOwnProperty('setattr')) {
202
+ if ( state.hasOwnProperty('setattr') ) {
200
203
  states[stateExists].setattr = state.setattr;
201
- } else if (state.hasOwnProperty('prop')) {
204
+ }
205
+ else if ( state.hasOwnProperty('prop') ) {
202
206
  states[stateExists].setattr = state.prop;
203
207
  }
204
-
205
208
  // remove `prop` equal to if, due to prop is uses as key in set and get
206
- if (states[stateExists].prop === states[stateExists].id) {
209
+ if ( states[stateExists].prop === states[stateExists].id) {
207
210
  delete states[stateExists].prop;
208
211
  }
209
- if (state.hasOwnProperty('epname')) {
212
+ if ( state.hasOwnProperty('epname') ) {
210
213
  states[stateExists].epname = state.epname;
211
214
  }
212
-
213
215
  states[stateExists].writable = true;
214
216
  }
215
217
  return states.length;
216
218
  }
217
219
  }
218
-
219
220
  const icon = utils.getDeviceIcon(def);
220
221
  for (const expose of def.exposes) {
221
222
  let state;
@@ -241,7 +242,6 @@ function createFromExposes(model, def) {
241
242
  }, prop.access);
242
243
  break;
243
244
  }
244
-
245
245
  case 'brightness': {
246
246
  const stateNameB = expose.endpoint ? `brightness_${expose.endpoint}` : 'brightness';
247
247
  pushToStates({
@@ -255,8 +255,12 @@ function createFromExposes(model, def) {
255
255
  min: 0, // ignore expose.value_min
256
256
  max: 100, // ignore expose.value_max
257
257
  inOptions: true,
258
- getter: payload => utils.bulbLevelToAdapterLevel(payload[stateNameB]),
259
- setter: value => utils.adapterLevelToBulbLevel(value),
258
+ getter: payload => {
259
+ return utils.bulbLevelToAdapterLevel(payload[stateNameB]);
260
+ },
261
+ setter: (value) => {
262
+ return utils.adapterLevelToBulbLevel(value);
263
+ },
260
264
  setterOpt: (value, options) => {
261
265
  const hasTransitionTime = options && options.hasOwnProperty('transition_time');
262
266
  const transitionTime = hasTransitionTime ? options.transition_time : 0;
@@ -264,7 +268,7 @@ function createFromExposes(model, def) {
264
268
  preparedOptions.brightness = utils.adapterLevelToBulbLevel(value);
265
269
  return preparedOptions;
266
270
  },
267
- readResponse: resp => {
271
+ readResponse: (resp) => {
268
272
  const respObj = resp[0];
269
273
  if (respObj.status === 0 && respObj.attrData != undefined) {
270
274
  return utils.bulbLevelToAdapterLevel(respObj.attrData);
@@ -278,30 +282,30 @@ function createFromExposes(model, def) {
278
282
  }
279
283
  case 'color_temp': {
280
284
  const stateNameT = expose.endpoint ? `colortemp_${expose.endpoint}` : 'colortemp';
281
- pushToStates(
282
- {
283
- id: stateNameT,
284
- prop: expose.endpoint ? `color_temp_${expose.endpoint}` : 'color_temp',
285
- name: `Color temperature ${expose.endpoint ? expose.endpoint : ''}`.trim(),
286
- icon: undefined,
287
- role: 'level.color.temperature',
288
- write: true,
289
- read: true,
290
- type: 'number',
291
- // Ignore min and max value, so setting mireds and Kelvin with conversion to mireds works.
292
- // https://github.com/ioBroker/ioBroker.zigbee/pull/1433#issuecomment-1113837035
293
- min: undefined,
294
- max: undefined,
295
- setter: value => utils.toMired(value),
296
- setterOpt: (value, options) => {
297
- const hasTransitionTime = options && options.hasOwnProperty('transition_time');
298
- const transitionTime = hasTransitionTime ? options.transition_time : 0;
299
- return {...options, transition: transitionTime};
300
- },
301
- epname: expose.endpoint,
302
- setattr: 'color_temp',
285
+ pushToStates({
286
+ id: stateNameT,
287
+ prop: expose.endpoint ? `color_temp_${expose.endpoint}` : 'color_temp',
288
+ name: `Color temperature ${expose.endpoint ? expose.endpoint : ''}`.trim(),
289
+ icon: undefined,
290
+ role: 'level.color.temperature',
291
+ write: true,
292
+ read: true,
293
+ type: 'number',
294
+ // Ignore min and max value, so setting mireds and Kelvin with conversion to mireds works.
295
+ // https://github.com/ioBroker/ioBroker.zigbee/pull/1433#issuecomment-1113837035
296
+ min: undefined,
297
+ max: undefined,
298
+ setter: (value) => {
299
+ return utils.toMired(value);
303
300
  },
304
- prop.access);
301
+ setterOpt: (value, options) => {
302
+ const hasTransitionTime = options && options.hasOwnProperty('transition_time');
303
+ const transitionTime = hasTransitionTime ? options.transition_time : 0;
304
+ return {...options, transition: transitionTime};
305
+ },
306
+ epname: expose.endpoint,
307
+ setattr: 'color_temp',
308
+ }, prop.access);
305
309
  pushToStates(statesDefs.colortemp_move, prop.access);
306
310
  break;
307
311
  }
@@ -316,8 +320,8 @@ function createFromExposes(model, def) {
316
320
  write: true,
317
321
  read: true,
318
322
  type: 'string',
319
- setter: value => {
320
- // convert RGB to XY for set
323
+ setter: (value) => {
324
+ // convert RGB to XY for set
321
325
  /*
322
326
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(value);
323
327
  let xy = [0, 0];
@@ -338,8 +342,9 @@ function createFromExposes(model, def) {
338
342
  xy = rgb.rgb_to_cie(rgbcolor.r, rgbcolor.g, rgbcolor.b);
339
343
  return {
340
344
  x: xy[0],
341
- y: xy[1],
345
+ y: xy[1]
342
346
  };
347
+
343
348
  },
344
349
  setterOpt: (value, options) => {
345
350
  const hasTransitionTime = options && options.hasOwnProperty('transition_time');
@@ -349,7 +354,7 @@ function createFromExposes(model, def) {
349
354
  getter: payload => {
350
355
  if (payload.color && payload.color.hasOwnProperty('x') && payload.color.hasOwnProperty('y')) {
351
356
  const colorval = rgb.cie_to_rgb(payload.color.x, payload.color.y);
352
- return `#${utils.decimalToHex(colorval[0])}${utils.decimalToHex(colorval[1])}${utils.decimalToHex(colorval[2])}`;
357
+ return '#' + utils.decimalToHex(colorval[0]) + utils.decimalToHex(colorval[1]) + utils.decimalToHex(colorval[2]);
353
358
  } else {
354
359
  return undefined;
355
360
  }
@@ -370,13 +375,14 @@ function createFromExposes(model, def) {
370
375
  write: true,
371
376
  read: true,
372
377
  type: 'string',
373
- setter: value => {
378
+ setter: (value) => {
374
379
  const _rgb = colors.ParseColor(value);
375
380
  const hsv = rgb.rgbToHSV(_rgb.r, _rgb.g, _rgb.b, true);
376
381
  return {
377
- hue: Math.min(Math.max(hsv.h, 1), 359),
382
+ hue: Math.min(Math.max(hsv.h,1),359),
378
383
  saturation: hsv.s,
379
384
  // brightness: Math.floor(hsv.v * 2.55),
385
+
380
386
  };
381
387
  },
382
388
  setterOpt: (value, options) => {
@@ -390,7 +396,7 @@ function createFromExposes(model, def) {
390
396
  pushToStates({
391
397
  id: expose.endpoint ? `hue_${expose.endpoint}` : 'hue',
392
398
  prop: expose.endpoint ? `color_${expose.endpoint}` : 'color',
393
- name: `Hue ${expose.endpoint || ''}`.trim(),
399
+ name: `Hue ${expose.endpoint ? expose.endpoint : ''}`.trim(),
394
400
  icon: undefined,
395
401
  role: 'level.color.hue',
396
402
  write: true,
@@ -411,28 +417,17 @@ function createFromExposes(model, def) {
411
417
  const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
412
418
  if (hasHueCalibrationTable)
413
419
  try {
414
- return {
415
- ...options,
416
- transition: transitionTime,
417
- hue_correction: JSON.parse(options.hue_calibration)
418
- };
419
- } catch {
420
+ return {...options, transition: transitionTime, hue_correction: JSON.parse(options.hue_calibration)};
421
+ }
422
+ catch {
420
423
  const hue_correction_table = [];
421
424
  options.hue_calibration.split(',').forEach(element => {
422
425
  const match = /([0-9]+):([0-9]+)/.exec(element);
423
- if (match && match.length === 3)
424
- hue_correction_table.push({
425
- in: Number(match[1]),
426
- out: Number(match[2])
427
- });
426
+ if (match && match.length ==3)
427
+ hue_correction_table.push({ in: Number(match[1]), out: Number(match[2])});
428
428
  });
429
- if (hue_correction_table.length > 0) {
430
- return {
431
- ...options,
432
- transition: transitionTime,
433
- hue_correction: hue_correction_table
434
- };
435
- }
429
+ if (hue_correction_table.length > 0)
430
+ return {...options, transition: transitionTime, hue_correction: hue_correction_table};
436
431
  }
437
432
  return {...options, transition: transitionTime};
438
433
  },
@@ -450,38 +445,29 @@ function createFromExposes(model, def) {
450
445
  min: 0,
451
446
  max: 100,
452
447
  inOptions: true,
453
- setter: (value, options) => ({
454
- hue: options.hue,
455
- saturation: value,
456
- }),
448
+ setter: (value, options) => {
449
+ return {
450
+ hue: options.hue,
451
+ saturation: value,
452
+ };
453
+ },
457
454
  setterOpt: (value, options) => {
458
455
  const hasTransitionTime = options && options.hasOwnProperty('transition_time');
459
456
  const transitionTime = hasTransitionTime ? options.transition_time : 0;
460
457
  const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
461
458
  if (hasHueCalibrationTable)
462
459
  try {
463
- return {
464
- ...options,
465
- transition: transitionTime,
466
- hue_correction: JSON.parse(options.hue_calibration)
467
- };
468
- } catch {
460
+ return {...options, transition: transitionTime, hue_correction: JSON.parse(options.hue_calibration)};
461
+ }
462
+ catch {
469
463
  const hue_correction_table = [];
470
464
  options.hue_calibration.split(',').forEach(element => {
471
465
  const match = /([0-9]+):([0-9]+)/.exec(element);
472
- if (match && match.length === 3)
473
- hue_correction_table.push({
474
- in: Number(match[1]),
475
- out: Number(match[2])
476
- });
466
+ if (match && match.length ==3)
467
+ hue_correction_table.push({ in: Number(match[1]), out: Number(match[2])});
477
468
  });
478
- if (hue_correction_table.length > 0) {
479
- return {
480
- ...options,
481
- transition: transitionTime,
482
- hue_correction: hue_correction_table
483
- };
484
- }
469
+ if (hue_correction_table.length > 0)
470
+ return {...options, transition: transitionTime, hue_correction: hue_correction_table};
485
471
  }
486
472
  return {...options, transition: transitionTime};
487
473
  },
@@ -499,42 +485,33 @@ function createFromExposes(model, def) {
499
485
  read: false,
500
486
  type: 'string',
501
487
  inOptions: true,
502
- setter: (value, options) => ({
503
- hue: options.hue,
504
- saturation: options.saturation,
505
- }),
488
+ setter: (value, options) => {
489
+ return {
490
+ hue: options.hue,
491
+ saturation: options.saturation,
492
+ };
493
+ },
506
494
  setterOpt: (value, options) => {
507
495
  const hasTransitionTime = options && options.hasOwnProperty('transition_time');
508
496
  const transitionTime = hasTransitionTime ? options.transition_time : 0;
509
497
  const hasHueCalibrationTable = options && options.hasOwnProperty('hue_calibration');
510
498
  if (hasHueCalibrationTable)
511
499
  try {
512
- return {
513
- ...options,
514
- transition: transitionTime,
515
- hue_correction: JSON.parse(options.hue_calibration)
516
- };
517
- } catch {
500
+ return {...options, transition: transitionTime, hue_correction: JSON.parse(options.hue_calibration)};
501
+ }
502
+ catch {
518
503
  const hue_correction_table = [];
519
504
  options.hue_calibration.split(',').forEach(element => {
520
505
  const match = /([0-9]+):([0-9]+)/.exec(element);
521
- if (match && match.length === 3) {
522
- hue_correction_table.push({
523
- in: Number(match[1]),
524
- out: Number(match[2])
525
- });
526
- }
506
+ if (match && match.length ==3)
507
+ hue_correction_table.push({ in: Number(match[1]), out: Number(match[2])});
527
508
  });
528
- if (hue_correction_table.length > 0) {
529
- return {
530
- ...options,
531
- transition: transitionTime,
532
- hue_correction: hue_correction_table
533
- };
534
- }
509
+ if (hue_correction_table.length > 0)
510
+ return {...options, transition: transitionTime, hue_correction: hue_correction_table};
535
511
  }
536
512
  return {...options, transition: transitionTime};
537
513
  },
514
+
538
515
  }, prop.access);
539
516
  break;
540
517
  }
@@ -605,20 +582,19 @@ function createFromExposes(model, def) {
605
582
  break;
606
583
  }
607
584
  }
608
- if (state) {
609
- pushToStates(state, expose.access);
610
- }
585
+ if (state) pushToStates(state, expose.access);
611
586
  break;
612
587
 
613
588
  case 'enum':
614
589
  switch (expose.name) {
615
590
  case 'action': {
616
- // Ansatz:
617
591
 
618
- // Action aufspalten in 2 Blöcke:
619
- // Action (bekommt text ausser hold und release, auto reset nach 250 ms)
620
- // Hold: wird gesetzt bei hold, gelöscht bei passendem Release
592
+ // Ansatz:
621
593
 
594
+ // Action aufspalten in 2 Blöcke:
595
+ // Action (bekommt text ausser hold und release, auto reset nach 250 ms)
596
+ // Hold: wird gesetzt bei hold, gelöscht bei passendem Release
597
+
622
598
  if (!Array.isArray(expose.values)) break;
623
599
  const hasHold = expose.values.find((actionName) => actionName.includes('hold'));
624
600
  const hasRelease = expose.values.find((actionName) => actionName.includes('release'));
@@ -637,7 +613,7 @@ function createFromExposes(model, def) {
637
613
  write: false,
638
614
  read: true,
639
615
  type: 'boolean',
640
- getter: payload => payload.action === actionName ? true : (payload.action === releaseActionName ? false : undefined),
616
+ getter: payload => (payload.action === actionName) ? true : (payload.action === releaseActionName) ? false : undefined,
641
617
  };
642
618
  } else {
643
619
  state = {
@@ -649,7 +625,7 @@ function createFromExposes(model, def) {
649
625
  write: false,
650
626
  read: true,
651
627
  type: 'boolean',
652
- getter: payload => payload.action === actionName ? true : undefined,
628
+ getter: payload => (payload.action === actionName) ? true : undefined,
653
629
  isEvent: true,
654
630
  };
655
631
  }
@@ -700,9 +676,7 @@ function createFromExposes(model, def) {
700
676
  break;
701
677
  }
702
678
  }
703
- if (state) {
704
- pushToStates(state, expose.access);
705
- }
679
+ if (state) pushToStates(state, expose.access);
706
680
  break;
707
681
 
708
682
  case 'text':
@@ -765,20 +739,22 @@ function createFromExposes(model, def) {
765
739
  return result;
766
740
  };
767
741
  st.setattr = expose.property;
768
- }
742
+ };
769
743
  // if we have a composite expose, the payload will be an object {expose.property : {prop.property: value}}
770
744
  if (prop.access & ea.STATE) {
771
745
  st.getter = payload => {
772
- if ((payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(prop.property)) {
773
- return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined;
774
- } else {
746
+ if ( (payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(prop.property)) {
747
+ return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined
748
+ }
749
+ else {
775
750
  return undefined;
776
751
  }
777
752
  };
778
- } else {
779
- st.getter = payload => undefined;
780
753
  }
781
-
754
+ else {
755
+ st.getter = payload => { return undefined };
756
+ }
757
+ ;
782
758
  pushToStates(st, prop.access);
783
759
  }
784
760
  break;
@@ -788,8 +764,8 @@ function createFromExposes(model, def) {
788
764
  }
789
765
  const newDev = {
790
766
  models: [model],
791
- icon,
792
- states,
767
+ icon: icon,
768
+ states: states,
793
769
  exposed: true,
794
770
  };
795
771
  // make the function code printable in log
@@ -799,11 +775,11 @@ function createFromExposes(model, def) {
799
775
  }
800
776
 
801
777
  function applyExposes(mappedDevices, byModel, allExcludesObj) {
802
- // for exclude search
778
+ // for exlude search
803
779
  const allExcludesStr = JSON.stringify(allExcludesObj);
804
780
  // create or update device from exposes
805
781
  for (const deviceDef of zigbeeHerdsmanConverters.definitions) {
806
- const strippedModel = (deviceDef.model) ? deviceDef.model.replace(/0.*$/g, '').trim() : '';
782
+ const strippedModel = (deviceDef.model) ? deviceDef.model.replace(/\0.*$/g, '').trim() : '';
807
783
  // check if device is mapped
808
784
  const existsMap = byModel.get(strippedModel);
809
785
 
@@ -818,7 +794,7 @@ function applyExposes(mappedDevices, byModel, allExcludesObj) {
818
794
  existsMap.exposed = true;
819
795
  }
820
796
  } catch (e) {
821
- console.log(`Wrong expose devicedefinition ${deviceDef.vendor} ${deviceDef.model}`);
797
+ console.log(`Wrong expose devicedefinition ${deviceDef.vendor} ${deviceDef.model}` );
822
798
  }
823
799
  }
824
800
  }