iobroker.zigbee 1.8.0 → 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 +32 -9
  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 +19 -26
  21. package/lib/backup.js +2 -2
  22. package/lib/binding.js +24 -23
  23. package/lib/colors.js +14 -16
  24. package/lib/commands.js +82 -89
  25. package/lib/developer.js +7 -6
  26. package/lib/devices.js +153 -144
  27. package/lib/exclude.js +36 -30
  28. package/lib/exposes.js +111 -106
  29. package/lib/groups.js +54 -53
  30. package/lib/json.js +4 -3
  31. package/lib/networkmap.js +2 -2
  32. package/lib/ota.js +15 -23
  33. package/lib/rgb.js +44 -47
  34. package/lib/seriallist.js +16 -21
  35. package/lib/states.js +496 -482
  36. package/lib/statescontroller.js +164 -170
  37. package/lib/utils.js +21 -22
  38. package/lib/zbBaseExtension.js +4 -4
  39. package/lib/zbDelayedAction.js +13 -5
  40. package/lib/zbDeviceAvailability.js +44 -47
  41. package/lib/zbDeviceConfigure.js +19 -7
  42. package/lib/zbDeviceEvent.js +4 -3
  43. package/lib/zigbeecontroller.js +96 -88
  44. package/main.js +133 -149
  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
@@ -7,8 +7,9 @@ const getZbId = require('./utils').getZbId;
7
7
  const fs = require('fs');
8
8
  const request = require('request');
9
9
 
10
- let savedDeviceNames = {};
11
- let knownUndefinedDevices = {};
10
+ var savedDeviceNames = {};
11
+ var knownUndefinedDevices = {};
12
+
12
13
 
13
14
  class StatesController extends EventEmitter {
14
15
  constructor(adapter) {
@@ -17,16 +18,19 @@ class StatesController extends EventEmitter {
17
18
  this.adapter.on('stateChange', this.onStateChange.bind(this));
18
19
  this.query_device_block = [];
19
20
  this.debugDevices = undefined;
20
- const fn = adapter.expandFileName('dev_names.json');
21
+ let fn = adapter.expandFileName('dev_names.json');
21
22
  this.dev_names_fn = fn.replace('.', '_');
22
23
  this.retTimeoutHandle = null;
23
24
  fs.readFile(this.dev_names_fn, (err, data) => {
24
25
  if (!err) {
25
- try {
26
+ try
27
+ {
26
28
  savedDeviceNames = JSON.parse(data);
27
- } catch {
29
+ }
30
+ catch
31
+ {
28
32
  savedDeviceNames = {};
29
- }
33
+ };
30
34
  }
31
35
  });
32
36
  }
@@ -51,77 +55,68 @@ class StatesController extends EventEmitter {
51
55
  this.adapter.sendError(error, message);
52
56
  }
53
57
 
54
- retainDeviceNames() {
58
+ retainDeviceNames()
59
+ {
55
60
  clearTimeout(this.retTimeoutHandle);
56
- this.retTimeoutHanlde = setTimeout(() => {
57
- fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNames, null, 2), err => {
58
- if (err) {
59
- this.error(`error saving device names: ${JSON.stringify(err)}`);
60
- } else {
61
+ this.retTimeoutHanlde = setTimeout(()=> {
62
+ fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNames, null, 2), (err) => {
63
+ if (err)
64
+ this.error('error saving device names: ' + JSON.Stringify(err));
65
+ else
61
66
  this.debug('saved device names');
62
- }
63
- });
64
- }, 5000);
67
+ });},5000);
65
68
  }
66
69
 
67
70
  getDebugDevices() {
68
71
  this.debugDevices = [];
69
- this.adapter.getState(`${this.adapter.namespace}.info.debugmessages`, (err, state) => {
72
+ this.adapter.getState(this.adapter.namespace + '.info.debugmessages', (err, state) => {
70
73
  if (state) {
71
- if (typeof(state.val) == 'string' && state.val.length > 2) {
72
- this.debugDevices = state.val.split(';');
73
- }
74
- this.info(`debug devices set to ${JSON.stringify(this.debugDevices)}`);
74
+ if (typeof(state.val) == 'string' && state.val.length > 2) this.debugDevices = state.val.split(';');
75
+ this.info('debug devices set to ' + JSON.stringify(this.debugDevices));
75
76
  } else {
76
77
  this.adapter.setObject('info.debugmessages', {
77
- type: 'state',
78
- common: {
79
- name: 'Log changes as warnings for',
80
- role: '',
81
- type: 'string',
82
- read: true,
83
- write: true,
78
+ 'type': 'state',
79
+ 'common': {
80
+ 'name': 'Log changes as warnings for',
81
+ 'role': '',
82
+ 'type': 'string',
83
+ 'read': true,
84
+ 'write': true,
84
85
  },
85
- native: {},
86
+ 'native': {},
86
87
  });
87
88
  }
88
89
  });
89
90
  this.adapter.setObject('info.undefinedDevices', {
90
- type: 'state',
91
- common: {
92
- name: 'Recorded undefined devices',
93
- role: '',
94
- type: 'string',
95
- read: true,
96
- write: false,
91
+ 'type': 'state',
92
+ 'common': {
93
+ 'name': 'Recorded undefined devices',
94
+ 'role': '',
95
+ 'type': 'string',
96
+ 'read': true,
97
+ 'write': false,
97
98
  },
98
- native: {},
99
+ 'native': {},
99
100
  });
100
101
  this.adapter.setStateAsync(`info.undefinedDevices`, JSON.stringify(knownUndefinedDevices), true);
101
102
  }
102
103
 
103
104
  onStateChange(id, state){
104
- if (!this.adapter.zbController || !this.adapter.zbController.connected()) {
105
- return;
106
- }
107
- if (this.debugDevices === undefined) {
108
- this.getDebugDevices();
109
- }
105
+ if (!this.adapter.zbController || !this.adapter.zbController.connected()) return;
106
+ if (this.debugDevices === undefined) this.getDebugDevices();
110
107
  if (state && !state.ack) {
111
- if (id.endsWith('pairingCountdown') || id.endsWith('pairingMessage') || id.endsWith('connection')) {
112
- return;
113
- }
108
+ if (id.endsWith('pairingCountdown') || id.endsWith('pairingMessage') || id.endsWith('connection')) return;
114
109
  if (id.endsWith('debugmessages')) {
115
- if (typeof(state.val) == 'string' && state.val.length > 2) {
110
+ if (typeof(state.val) == 'string' && state.val.length > 2)
116
111
  this.debugDevices = state.val.split(';');
117
-
118
- } else {
112
+ else {
119
113
  this.debugDevices = [];
120
114
  }
121
115
  return;
122
116
  }
123
117
  for (const addressPart of this.debugDevices) {
124
- if (typeof(id) == 'string' && id.indexOf(addressPart) > -1) {
118
+ if (typeof(id) == 'string' && id.indexOf(addressPart) > -1)
119
+ {
125
120
  this.warn(`ELEVATED: User stateChange ${id} ${JSON.stringify(state)}`);
126
121
  break;
127
122
  }
@@ -139,9 +134,7 @@ class StatesController extends EventEmitter {
139
134
  this.adapter.getObject(devId, (err, obj) => {
140
135
  if (obj) {
141
136
  const model = obj.common.type;
142
- if (!model) {
143
- return;
144
- }
137
+ if (!model) return;
145
138
  if (obj.common.deactivated) {
146
139
  this.debug('State Change detected on deactivated Device - ignored');
147
140
  return;
@@ -149,8 +142,9 @@ class StatesController extends EventEmitter {
149
142
  if (model === 'group') {
150
143
  deviceId = parseInt(deviceId.replace('0xgroup_', ''));
151
144
  }
152
- this.collectOptions(id.split('.')[2], model, options =>
153
- this.publishFromState(deviceId, model, stateKey, state, options));
145
+ this.collectOptions(id.split('.')[2], model, options => {
146
+ this.publishFromState(deviceId, model, stateKey, state, options);
147
+ });
154
148
  }
155
149
  });
156
150
  }
@@ -164,7 +158,7 @@ class StatesController extends EventEmitter {
164
158
  callback(result);
165
159
  return;
166
160
  }
167
- const states = devStates.states.filter(statedesc => statedesc.isOption || statedesc.inOptions);
161
+ const states = devStates.states.filter((statedesc) => statedesc.isOption || statedesc.inOptions);
168
162
  if (!states) {
169
163
  callback(result);
170
164
  return;
@@ -173,7 +167,7 @@ class StatesController extends EventEmitter {
173
167
  try {
174
168
  const len = states.length;
175
169
  states.forEach(statedesc => {
176
- const id = `${this.adapter.namespace}.${devId}.${statedesc.id}`;
170
+ const id = this.adapter.namespace + '.' + devId + '.' + statedesc.id;
177
171
  this.adapter.getState(id, (err, state) => {
178
172
  cnt = cnt + 1;
179
173
  if (!err && state) {
@@ -184,18 +178,16 @@ class StatesController extends EventEmitter {
184
178
  }
185
179
  });
186
180
  });
187
- if (!len) {
188
- callback(result);
189
- }
190
- } catch (error) {
181
+ if (!len) callback(result);
182
+ } catch (error) {
191
183
  this.sendError(error);
192
184
  this.error(`Error collectOptions for ${devId}. Error: ${error.stack}`);
193
- }
185
+ }
194
186
  }
195
187
 
196
188
  async getDevStates(deviceId, model) {
197
189
  try {
198
- let states;
190
+ let states = [];
199
191
  let stateModel;
200
192
  if (model === 'group') {
201
193
  states = statesMapping.groupStates;
@@ -208,7 +200,7 @@ class StatesController extends EventEmitter {
208
200
  }
209
201
  else {
210
202
  knownUndefinedDevices[deviceId] = 1;
211
- this.error(`Device ${deviceId} "${model}" not described in statesMapping.`);
203
+ this.error('Device ' + deviceId + ' "' + model + '" not described in statesMapping.');
212
204
  }
213
205
  this.adapter.setStateAsync(`info.undefinedDevices`, JSON.stringify(knownUndefinedDevices), true);
214
206
  states = statesMapping.commonStates;
@@ -217,12 +209,11 @@ class StatesController extends EventEmitter {
217
209
  }
218
210
  if (typeof states === 'function' && !states.prototype) {
219
211
  const entity = await this.adapter.zbController.resolveEntity(deviceId);
220
- if (entity) {
212
+ if (entity)
221
213
  states = states(entity);
222
- }
223
214
  }
224
215
  }
225
- return {states, stateModel};
216
+ return {states: states, stateModel: stateModel};
226
217
  } catch (error) {
227
218
  this.sendError(error);
228
219
  this.error(`Error getDevStates for ${deviceId}. Error: ${error.stack}`);
@@ -233,7 +224,8 @@ class StatesController extends EventEmitter {
233
224
  if (this.debugDevices === undefined) this.getDebugDevices();
234
225
  this.debug(`Change state '${stateKey}' at device ${deviceId} type '${model}'`);
235
226
  for (const addressPart of this.debugDevices) {
236
- if (typeof(deviceId) == 'string' && deviceId.includes(addressPart)) {
227
+ if (typeof(deviceId) == 'string' && deviceId.indexOf(addressPart) > -1)
228
+ {
237
229
  this.warn(`ELEVATED Change state '${stateKey}' at device ${deviceId} type '${model}'`);
238
230
  break;
239
231
  }
@@ -242,8 +234,8 @@ class StatesController extends EventEmitter {
242
234
  if (!devStates) {
243
235
  return;
244
236
  }
245
- const commonStates = statesMapping.commonStates.find(statedesc => stateKey === statedesc.id);
246
- const stateDesc = (commonStates === undefined ? devStates.states.find(statedesc => stateKey === statedesc.id) : commonStates);
237
+ const commonStates = statesMapping.commonStates.find((statedesc) => stateKey === statedesc.id);
238
+ const stateDesc = (commonStates === undefined ? devStates.states.find((statedesc) => stateKey === statedesc.id) : commonStates);
247
239
  const stateModel = devStates.stateModel;
248
240
  if (!stateDesc) {
249
241
  this.error(`No state available for '${model}' with key '${stateKey}'`);
@@ -251,12 +243,11 @@ class StatesController extends EventEmitter {
251
243
  }
252
244
 
253
245
  const value = state.val;
254
- if (value === undefined || value === '') {
246
+ if (value === undefined || value === '')
255
247
  return;
256
- }
257
248
  let stateList = [{stateDesc: stateDesc, value: value, index: 0, timeout: 0}];
258
249
  if (stateModel && stateModel.linkedStates) {
259
- stateModel.linkedStates.forEach(linkedFunct => {
250
+ stateModel.linkedStates.forEach((linkedFunct) => {
260
251
  try {
261
252
  if (typeof linkedFunct === 'function') {
262
253
  const res = linkedFunct(stateDesc, value, options, this.adapter.config.disableQueue);
@@ -265,7 +256,7 @@ class StatesController extends EventEmitter {
265
256
  }
266
257
  }
267
258
  else {
268
- this.warn(`publish from State - LinkedState is not a function ${JSON.stringify(linkedFunct)}`);
259
+ this.warn('publish from State - LinkedState is not a function ' + JSON.stringify(linkedFunct));
269
260
  }
270
261
  } catch (e) {
271
262
  this.sendError(e);
@@ -274,14 +265,17 @@ class StatesController extends EventEmitter {
274
265
 
275
266
  });
276
267
  // sort by index
277
- stateList.sort((a, b) => a.index - b.index);
268
+ stateList.sort((a, b) => {
269
+ return a.index - b.index;
270
+ });
278
271
  }
279
272
 
280
- // holds the states for read after write requests
273
+ // holds the states for for read after write requests
281
274
  let readAfterWriteStates = [];
282
275
  if (stateModel && stateModel.readAfterWriteStates) {
283
- stateModel.readAfterWriteStates.forEach((readAfterWriteStateDesc) =>
284
- readAfterWriteStates = readAfterWriteStates.concat(readAfterWriteStateDesc.id));
276
+ stateModel.readAfterWriteStates.forEach((readAfterWriteStateDesc) => {
277
+ readAfterWriteStates = readAfterWriteStates.concat(readAfterWriteStateDesc.id);
278
+ });
285
279
  }
286
280
 
287
281
  this.emit('changed', deviceId, model, stateModel, stateList, options);
@@ -293,42 +287,42 @@ class StatesController extends EventEmitter {
293
287
  }
294
288
 
295
289
  setDeviceActivated(id, active) {
296
- this.adapter.extendObject(id, {common: {deactivated: active }})
290
+ this.adapter.extendObject(id, {common: {deactivated: active }})
297
291
  }
298
292
 
299
293
  storeDeviceName(id, name) {
300
- savedDeviceNames[id.replace(`${this.adapter.namespace}.`, '')] = name;
301
- this.retainDeviceNames();
294
+ savedDeviceNames[id.replace(`${this.adapter.namespace}.`, '')] = name;
295
+ this.retainDeviceNames();
302
296
  }
303
297
 
304
298
  verifyDeviceName(id, name) {
305
- const savedId = id.replace(`${this.adapter.namespace}.`, '');
306
- if (!savedDeviceNames.hasOwnProperty(savedId)) {
307
- savedDeviceNames[savedId] = name;
308
- this.retainDeviceNames();
309
- }
310
- return savedDeviceNames[savedId];
299
+ const savedId = id.replace(`${this.adapter.namespace}.`, '');
300
+ if (!savedDeviceNames.hasOwnProperty(savedId)) {
301
+ savedDeviceNames[savedId] = name;
302
+ this.retainDeviceNames();
303
+ }
304
+ return savedDeviceNames[savedId];
311
305
  }
312
306
 
313
307
  deleteDeviceStates(devId, callback) {
314
308
  this.adapter.getStatesOf(devId, (err, states) => {
315
309
  if (!err && states) {
316
- states.forEach(state =>
317
- this.adapter.deleteState(devId, null, state._id));
310
+ states.forEach((state) => {
311
+ this.adapter.deleteState(devId, null, state._id);
312
+ });
318
313
  }
319
- this.adapter.deleteDevice(devId, () =>
320
- callback && callback());
314
+ this.adapter.deleteDevice(devId, () => {
315
+ callback && callback();
316
+ });
321
317
  });
322
318
  }
323
319
 
324
320
  async deleteDeviceStatesAsync(devId) {
325
- const states = await this.adapter.getStatesOf(devId);
326
- if (states) {
327
- for (const state of states) {
328
- await this.adapter.deleteState(devId, null, state._id);
329
- }
330
- }
331
- await this.adapter.deleteDevice(devId);
321
+ const states = await this.adapter.getStatesOf(devId);
322
+ if (states) {
323
+ await this.adapter.deleteState(devId, null, state._id);
324
+ }
325
+ await this.adapter.deleteDevice(devId);
332
326
  }
333
327
 
334
328
  // eslint-disable-next-line no-unused-vars
@@ -348,16 +342,16 @@ class StatesController extends EventEmitter {
348
342
  } else {
349
343
  statename = arr[1];
350
344
  }
351
- if (commonStates.find(statedesc => statename === statedesc.id) === undefined &&
352
- devStates.states.find(statedesc => statename === statedesc.id) === undefined
353
- ) {
345
+ if (commonStates.find((statedesc) => statename === statedesc.id) === undefined &&
346
+ devStates.states.find((statedesc) => statename === statedesc.id) === undefined) {
354
347
  if (state.common.hasOwnProperty('custom') && !force) {
355
348
  this.info(`keeping disconnected state ${JSON.stringify(statename)} of ${devId} `);
356
349
  } else {
357
350
  this.info(`deleting disconnected state ${JSON.stringify(statename)} of ${devId} `);
358
351
  this.adapter.deleteState(devId, null, state._id);
359
352
  }
360
- } else {
353
+ }
354
+ else {
361
355
  this.debug(`keeping connecte state ${JSON.stringify(statename)} of ${devId} `);
362
356
  }
363
357
  });
@@ -414,11 +408,10 @@ class StatesController extends EventEmitter {
414
408
  let hasChanges = false;
415
409
  if (stobj) {
416
410
  // update state - not change name and role (user can it changed)
417
- if (stobj.common.name) {
411
+ if (stobj.common.name)
418
412
  delete new_common.name;
419
- } else {
420
- new_common.name = `${new_name} ${new_common.name}`;
421
- }
413
+ else
414
+ new_common.name = new_name + ' ' + new_common.name;
422
415
  delete new_common.role;
423
416
 
424
417
  // check whether any common property is different
@@ -439,8 +432,9 @@ class StatesController extends EventEmitter {
439
432
 
440
433
  // only change object when any common property has changed
441
434
  if (hasChanges) {
442
- this.adapter.extendObject(id, {type: 'state', common: new_common, native: {} }, () =>
443
- value !== undefined && this.setState_typed(id, value, true, stobj ? stobj.common.type : new_common.type));
435
+ this.adapter.extendObject(id, {type: 'state', common: new_common, native: {} }, () => {
436
+ value !== undefined && this.setState_typed(id, value, true, (stobj) ? stobj.common.type : new_common.type);
437
+ });
444
438
  } else if (value !== undefined) {
445
439
  this.setState_typed(id, value, true, stobj.common.type);
446
440
  }
@@ -459,19 +453,19 @@ class StatesController extends EventEmitter {
459
453
  // never set a null or undefined value
460
454
  if (value === null || value === undefined) return;
461
455
  if (!type) {
462
- this.debug('SetState_typed called without type');
456
+ this.debug("SetState_typed called without type");
463
457
  // identify datatype, recursively call this function with set datatype
464
458
  this.adapter.getObject(id, (err, obj) => {
465
- if (obj && obj.common) {
466
- this.setState_typed(id, value, ack, obj.common.type, callback);
467
- } else {
459
+ if (obj && obj.common)
460
+ this.setState_typed(id, value, ack, obj.common.type, callback);
461
+ else {
468
462
  this.setState_typed(id, value, ack, 'noobj', callback);
469
463
  }
470
464
  });
471
465
  return;
472
466
  }
473
- if (typeof value !== type) {
474
- this.debug(`SetState_typed : converting ${JSON.stringify(value)} for ${id} from ${typeof value} to ${type}`);
467
+ if (typeof value != type) {
468
+ this.debug("SetState_typed : converting " + JSON.stringify(value) + " for " + id + " from " + typeof value + " to " + type);
475
469
  switch (type) {
476
470
  case 'number':
477
471
  value = parseFloat(value);
@@ -479,14 +473,13 @@ class StatesController extends EventEmitter {
479
473
  break;
480
474
  case 'string':
481
475
  case 'text': value = JSON.stringify(value); break;
482
- case 'boolean': {
476
+ case 'boolean':
483
477
  if (typeof value == 'number') {
484
- value = value !== 0;
478
+ value = (value != 0);
485
479
  break;
486
480
  }
487
481
  const sval = JSON.stringify(value).toLowerCase().trim();
488
- value = sval === 'true' || sval === 'yes' || sval === 'on';
489
- }
482
+ value = (sval == 'true' || sval == 'yes' || sval == 'on');
490
483
  break;
491
484
  }
492
485
  }
@@ -498,27 +491,27 @@ class StatesController extends EventEmitter {
498
491
  const id = '' + dev_id;
499
492
  const modelDesc = statesMapping.findModel(model);
500
493
  let icon = (modelDesc && modelDesc.icon) ? modelDesc.icon : 'img/unknown.png';
501
-
494
+
502
495
  // download icon if it external and not undef
503
- if (model === undefined) {
496
+ if (model === undefined) {
504
497
  this.warn(`download icon ${__dev_name} for undefined Device not available. Check your devices.`);
505
498
  } else {
506
- const model_modif = model.replace(/\//g, '-');
507
- const pathToIcon = `${this.adapter.adapterDir}/admin/img/${model_modif}.png`;
499
+ const model_modif = model.replace(/\//g, '-');
500
+ const pathToIcon = this.adapter.adapterDir + '/admin/img/' + model_modif + '.png';
508
501
 
509
- if (icon.startsWith('http')) {
510
- try {
502
+ if (icon.startsWith('http')) {
503
+ try {
511
504
  if (!fs.existsSync(pathToIcon)) {
512
505
  this.warn(`download icon from ${icon} saved into ${pathToIcon}`);
513
- this.downloadIcon(icon, pathToIcon);
506
+ this.downloadIcon(icon, pathToIcon);
514
507
  }
515
- icon = `img/${model_modif}.png`;
508
+ icon = 'img/' + model_modif + '.png';
516
509
  } catch (e) {
517
510
  this.debug(`ERROR : icon not found from ${icon} saved into ${pathToIcon}`);
518
511
  }
519
512
  }
520
513
  }
521
-
514
+
522
515
  this.adapter.setObjectNotExists(id, {
523
516
  type: 'device',
524
517
  // actually this is an error, so device.common has no attribute type. It must be in native part
@@ -531,22 +524,27 @@ class StatesController extends EventEmitter {
531
524
  }
532
525
 
533
526
  async downloadIcon(url, image_path) {
534
- if (!fs.existsSync(image_path)) {
535
- return new Promise((resolve, reject) => {
536
- request.head(url, (err, res, body) => {
537
- if (err) {
538
- return reject(err);
539
- }
540
- const stream = request(url);
541
- stream.pipe(
542
- fs.createWriteStream(image_path)
543
- .on('error', err => reject(err)))
544
- .on('close', () => resolve());
545
- });
546
- });
547
- }
527
+ if (!fs.existsSync(image_path)) {
528
+ return new Promise((resolve, reject) => {
529
+ request.head(url, function (err, res, body) {
530
+ if (err) {
531
+ return reject(err);
532
+ }
533
+ let stream = request(url);
534
+ stream.pipe(
535
+ fs.createWriteStream(image_path)
536
+ .on('error', err => {
537
+ reject(err);
538
+ })
539
+ )
540
+ .on('close', function () {
541
+ resolve();
542
+ });
543
+ });
544
+ });
545
+ }
548
546
  }
549
-
547
+
550
548
  async syncDevStates(dev, model) {
551
549
  const devId = dev.ieeeAddr.substr(2);
552
550
  // devId - iobroker device id
@@ -557,25 +555,20 @@ class StatesController extends EventEmitter {
557
555
  const states = statesMapping.commonStates.concat(devStates.states);
558
556
 
559
557
  for (const stateInd in states) {
560
- if (!states.hasOwnProperty(stateInd)) {
561
- continue;
562
- }
558
+ if (!states.hasOwnProperty(stateInd)) continue;
563
559
 
564
560
  const statedesc = states[stateInd];
565
- if (statedesc === undefined) {
561
+ if (statedesc === undefined)
562
+ {
566
563
  this.error(`syncDevStates: Illegal state in ${JSON.stringify(dev)} - ${JSON.stringify(stateInd)}`);
567
564
  return;
568
565
  }
569
566
  // Filter out non routers or devices that are battery driven for the availability flag
570
- if (statedesc.id === 'available') {
571
- if (!(dev.type === 'Router') || dev.powerSource === 'Battery') {
567
+ if (statedesc.id === 'available')
568
+ if (!(dev.type === 'Router') || dev.powerSource === 'Battery')
572
569
  continue;
573
- }
574
- }
575
570
  // lazy states
576
- if (statedesc.lazy) {
577
- continue;
578
- }
571
+ if (statedesc.lazy) continue;
579
572
 
580
573
  const common = {
581
574
  name: statedesc.name,
@@ -593,16 +586,19 @@ class StatesController extends EventEmitter {
593
586
  }
594
587
  }
595
588
 
589
+
596
590
  async getExcludeExposes(allExcludesObj) {
597
591
  statesMapping.fillStatesWithExposes(allExcludesObj);
598
592
  }
599
593
 
594
+
600
595
  async publishToState(devId, model, payload) {
601
- const devStates = await this.getDevStates(`0x${devId}`, model);
596
+ const devStates = await this.getDevStates('0x'+devId, model);
602
597
  let has_debug=false;
603
598
  if (this.debugDevices === undefined) this.getDebugDevices();
604
599
  for (const addressPart of this.debugDevices) {
605
- if (typeof(devId) == 'string' && devId.includes(addressPart)) {
600
+ if (typeof(devId) == 'string' && devId.indexOf(addressPart) > -1)
601
+ {
606
602
  if (payload.hasOwnProperty('msg_from_zigbee')) break;
607
603
  this.warn(`ELEVATED publishToState: message received '${JSON.stringify(payload)}' from device ${devId} type '${model}'`);
608
604
  has_debug = true;
@@ -615,8 +611,8 @@ class StatesController extends EventEmitter {
615
611
  // find states for payload
616
612
  if (devStates.states !== undefined) {
617
613
  const states = statesMapping.commonStates.concat(
618
- devStates.states.filter(statedesc => payload.hasOwnProperty(statedesc.prop || statedesc.id)));
619
-
614
+ devStates.states.filter((statedesc) => payload.hasOwnProperty(statedesc.prop || statedesc.id))
615
+ );
620
616
  for (const stateInd in states) {
621
617
  const statedesc = states[stateInd];
622
618
  let value;
@@ -626,12 +622,10 @@ class StatesController extends EventEmitter {
626
622
  value = payload[statedesc.prop || statedesc.id];
627
623
  }
628
624
  // checking value
629
- if (value === undefined || value === null) {
630
- continue;
631
- }
625
+ if (value === undefined || value === null) continue;
632
626
  let stateID = statedesc.id;
633
627
 
634
- if (has_debug && statedesc.id !== 'msg_from_zigbee') {
628
+ if (has_debug && statedesc.id != 'msg_from_zigbee') {
635
629
  this.warn(`ELEVATED publishToState: value generated '${JSON.stringify(value)}' from device ${devId} for '${statedesc.name}'`);
636
630
  }
637
631
 
@@ -646,24 +640,24 @@ class StatesController extends EventEmitter {
646
640
  min: statedesc.min,
647
641
  max: statedesc.max,
648
642
  };
649
- if (typeof value === 'object' && value.hasOwnProperty('stateid')) {
650
- stateID = `${stateID}.${value.stateid}`;
651
- if (value.hasOwnProperty('unit')) {
652
- common.unit = value.unit;
653
- }
643
+ if ( (typeof(value)== 'object') && (value.hasOwnProperty('stateid'))) {
644
+ stateID = stateID + '.' + value.stateid;
645
+ if (value.hasOwnProperty('unit')) common.unit = value.unit;
654
646
  common.name = (value.name? value.name:value.stateid);
655
- common.role = (value.role ? `value.${value.role}` : 'number');
647
+ common.role = (value.role ? 'value.'+value.role:'number');
656
648
  value = value.value;
657
649
 
658
650
  }
659
- // if needs to return value to back after timeout
651
+ // if need return value to back after timeout
660
652
  if (statedesc.isEvent) {
661
653
  this.updateStateWithTimeout(devId, statedesc.id, value, common, 300, !value);
662
654
  } else {
663
655
  if (statedesc.prepublish) {
664
- this.collectOptions(devId, model, options =>
665
- statedesc.prepublish(devId, value, newvalue =>
666
- this.updateState(devId, stateID, newvalue, common), options));
656
+ this.collectOptions(devId, model, (options) => {
657
+ statedesc.prepublish(devId, value, (newvalue) => {
658
+ this.updateState(devId, stateID, newvalue, common);
659
+ }, options);
660
+ });
667
661
  } else {
668
662
  this.updateState(devId, stateID, value, common);
669
663
  }