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
@@ -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
- onStateChange(id, state) {
104
- if (!this.adapter.zbController || !this.adapter.zbController.connected()) {
105
- return;
106
- }
107
- if (this.debugDevices === undefined) {
108
- this.getDebugDevices();
109
- }
104
+ onStateChange(id, state){
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.includes(addressPart)) {
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
  }
@@ -159,12 +153,12 @@ class StatesController extends EventEmitter {
159
153
  async collectOptions(devId, model, callback) {
160
154
  const result = {};
161
155
  // find model states for options and get it values
162
- const devStates = await this.getDevStates('0x' + devId, model);
156
+ const devStates = await this.getDevStates('0x'+devId, model);
163
157
  if (!devStates) {
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,29 +178,29 @@ 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;
202
194
  } else {
203
195
  stateModel = statesMapping.findModel(model);
204
196
  if (!stateModel) {
205
- if (knownUndefinedDevices[deviceId]) {
197
+ if (knownUndefinedDevices[deviceId])
198
+ {
206
199
  knownUndefinedDevices[deviceId]++;
207
- } else {
200
+ }
201
+ else {
208
202
  knownUndefinedDevices[deviceId] = 1;
209
- this.error(`Device ${deviceId} "${model}" not described in statesMapping.`);
203
+ this.error('Device ' + deviceId + ' "' + model + '" not described in statesMapping.');
210
204
  }
211
205
  this.adapter.setStateAsync(`info.undefinedDevices`, JSON.stringify(knownUndefinedDevices), true);
212
206
  states = statesMapping.commonStates;
@@ -215,12 +209,11 @@ class StatesController extends EventEmitter {
215
209
  }
216
210
  if (typeof states === 'function' && !states.prototype) {
217
211
  const entity = await this.adapter.zbController.resolveEntity(deviceId);
218
- if (entity) {
212
+ if (entity)
219
213
  states = states(entity);
220
- }
221
214
  }
222
215
  }
223
- return {states, stateModel};
216
+ return {states: states, stateModel: stateModel};
224
217
  } catch (error) {
225
218
  this.sendError(error);
226
219
  this.error(`Error getDevStates for ${deviceId}. Error: ${error.stack}`);
@@ -231,7 +224,8 @@ class StatesController extends EventEmitter {
231
224
  if (this.debugDevices === undefined) this.getDebugDevices();
232
225
  this.debug(`Change state '${stateKey}' at device ${deviceId} type '${model}'`);
233
226
  for (const addressPart of this.debugDevices) {
234
- if (typeof deviceId === 'string' && deviceId.includes(addressPart)) {
227
+ if (typeof(deviceId) == 'string' && deviceId.indexOf(addressPart) > -1)
228
+ {
235
229
  this.warn(`ELEVATED Change state '${stateKey}' at device ${deviceId} type '${model}'`);
236
230
  break;
237
231
  }
@@ -240,8 +234,8 @@ class StatesController extends EventEmitter {
240
234
  if (!devStates) {
241
235
  return;
242
236
  }
243
- const commonStates = statesMapping.commonStates.find(statedesc => stateKey === statedesc.id);
244
- 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);
245
239
  const stateModel = devStates.stateModel;
246
240
  if (!stateDesc) {
247
241
  this.error(`No state available for '${model}' with key '${stateKey}'`);
@@ -249,20 +243,20 @@ class StatesController extends EventEmitter {
249
243
  }
250
244
 
251
245
  const value = state.val;
252
- if (value === undefined || value === '') {
246
+ if (value === undefined || value === '')
253
247
  return;
254
- }
255
248
  let stateList = [{stateDesc: stateDesc, value: value, index: 0, timeout: 0}];
256
249
  if (stateModel && stateModel.linkedStates) {
257
- stateModel.linkedStates.forEach(linkedFunct => {
250
+ stateModel.linkedStates.forEach((linkedFunct) => {
258
251
  try {
259
252
  if (typeof linkedFunct === 'function') {
260
253
  const res = linkedFunct(stateDesc, value, options, this.adapter.config.disableQueue);
261
254
  if (res) {
262
255
  stateList = stateList.concat(res);
263
256
  }
264
- } else {
265
- this.warn(`publish from State - LinkedState is not a function ${JSON.stringify(linkedFunct)}`);
257
+ }
258
+ else {
259
+ this.warn('publish from State - LinkedState is not a function ' + JSON.stringify(linkedFunct));
266
260
  }
267
261
  } catch (e) {
268
262
  this.sendError(e);
@@ -271,14 +265,17 @@ class StatesController extends EventEmitter {
271
265
 
272
266
  });
273
267
  // sort by index
274
- stateList.sort((a, b) => a.index - b.index);
268
+ stateList.sort((a, b) => {
269
+ return a.index - b.index;
270
+ });
275
271
  }
276
272
 
277
- // holds the states for read after write requests
273
+ // holds the states for for read after write requests
278
274
  let readAfterWriteStates = [];
279
275
  if (stateModel && stateModel.readAfterWriteStates) {
280
- stateModel.readAfterWriteStates.forEach((readAfterWriteStateDesc) =>
281
- readAfterWriteStates = readAfterWriteStates.concat(readAfterWriteStateDesc.id));
276
+ stateModel.readAfterWriteStates.forEach((readAfterWriteStateDesc) => {
277
+ readAfterWriteStates = readAfterWriteStates.concat(readAfterWriteStateDesc.id);
278
+ });
282
279
  }
283
280
 
284
281
  this.emit('changed', deviceId, model, stateModel, stateList, options);
@@ -290,42 +287,42 @@ class StatesController extends EventEmitter {
290
287
  }
291
288
 
292
289
  setDeviceActivated(id, active) {
293
- this.adapter.extendObject(id, {common: {deactivated: active}});
290
+ this.adapter.extendObject(id, {common: {deactivated: active }})
294
291
  }
295
292
 
296
293
  storeDeviceName(id, name) {
297
- savedDeviceNames[id.replace(`${this.adapter.namespace}.`, '')] = name;
298
- this.retainDeviceNames();
294
+ savedDeviceNames[id.replace(`${this.adapter.namespace}.`, '')] = name;
295
+ this.retainDeviceNames();
299
296
  }
300
297
 
301
298
  verifyDeviceName(id, name) {
302
- const savedId = id.replace(`${this.adapter.namespace}.`, '');
303
- if (!savedDeviceNames.hasOwnProperty(savedId)) {
304
- savedDeviceNames[savedId] = name;
305
- this.retainDeviceNames();
306
- }
307
- 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];
308
305
  }
309
306
 
310
307
  deleteDeviceStates(devId, callback) {
311
308
  this.adapter.getStatesOf(devId, (err, states) => {
312
309
  if (!err && states) {
313
- states.forEach(state =>
314
- this.adapter.deleteState(devId, null, state._id));
310
+ states.forEach((state) => {
311
+ this.adapter.deleteState(devId, null, state._id);
312
+ });
315
313
  }
316
- this.adapter.deleteDevice(devId, () =>
317
- callback && callback());
314
+ this.adapter.deleteDevice(devId, () => {
315
+ callback && callback();
316
+ });
318
317
  });
319
318
  }
320
319
 
321
320
  async deleteDeviceStatesAsync(devId) {
322
- const states = await this.adapter.getStatesOf(devId);
323
- if (states) {
324
- for (const state of states) {
325
- await this.adapter.deleteState(devId, null, state._id);
326
- }
327
- }
328
- 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);
329
326
  }
330
327
 
331
328
  // eslint-disable-next-line no-unused-vars
@@ -341,22 +338,20 @@ class StatesController extends EventEmitter {
341
338
  if (arr[1] === undefined) {
342
339
  this.warn(`unable to extract id from state ${statename}`);
343
340
  const idx = statename.lastIndexOf('.');
344
- if (idx > -1) {
345
- statename = statename.slice(idx + 1);
346
- }
341
+ if (idx > -1) statename = statename.slice(idx+1);
347
342
  } else {
348
343
  statename = arr[1];
349
344
  }
350
- if (commonStates.find(statedesc => statename === statedesc.id) === undefined &&
351
- devStates.states.find(statedesc => statename === statedesc.id) === undefined
352
- ) {
345
+ if (commonStates.find((statedesc) => statename === statedesc.id) === undefined &&
346
+ devStates.states.find((statedesc) => statename === statedesc.id) === undefined) {
353
347
  if (state.common.hasOwnProperty('custom') && !force) {
354
348
  this.info(`keeping disconnected state ${JSON.stringify(statename)} of ${devId} `);
355
349
  } else {
356
350
  this.info(`deleting disconnected state ${JSON.stringify(statename)} of ${devId} `);
357
351
  this.adapter.deleteState(devId, null, state._id);
358
352
  }
359
- } else {
353
+ }
354
+ else {
360
355
  this.debug(`keeping connecte state ${JSON.stringify(statename)} of ${devId} `);
361
356
  }
362
357
  });
@@ -413,11 +408,10 @@ class StatesController extends EventEmitter {
413
408
  let hasChanges = false;
414
409
  if (stobj) {
415
410
  // update state - not change name and role (user can it changed)
416
- if (stobj.common.name) {
411
+ if (stobj.common.name)
417
412
  delete new_common.name;
418
- } else {
419
- new_common.name = `${new_name} ${new_common.name}`;
420
- }
413
+ else
414
+ new_common.name = new_name + ' ' + new_common.name;
421
415
  delete new_common.role;
422
416
 
423
417
  // check whether any common property is different
@@ -438,58 +432,54 @@ class StatesController extends EventEmitter {
438
432
 
439
433
  // only change object when any common property has changed
440
434
  if (hasChanges) {
441
- this.adapter.extendObject(id, {type: 'state', common: new_common, native: {}}, () =>
442
- 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
+ });
443
438
  } else if (value !== undefined) {
444
439
  this.setState_typed(id, value, true, stobj.common.type);
445
440
  }
446
441
 
447
442
  });
448
- } else {
449
- this.debug(`UpdateState: Device is deactivated ${devId} ${JSON.stringify(obj)}`);
450
443
  }
444
+ else this.debug(`UpdateState: Device is deactivated ${devId} ${JSON.stringify(obj)}`);
451
445
  } else {
452
446
  this.debug(`UpdateState: missing device ${devId} ${JSON.stringify(obj)}`);
453
447
  }
454
448
  });
455
449
  }
456
450
 
457
- setState_typed(id, value, ack, type, callback) {
451
+ setState_typed(id, value, ack, type, callback)
452
+ {
458
453
  // never set a null or undefined value
459
454
  if (value === null || value === undefined) return;
460
455
  if (!type) {
461
- this.debug('SetState_typed called without type');
456
+ this.debug("SetState_typed called without type");
462
457
  // identify datatype, recursively call this function with set datatype
463
458
  this.adapter.getObject(id, (err, obj) => {
464
- if (obj && obj.common) {
465
- this.setState_typed(id, value, ack, obj.common.type, callback);
466
- } else {
459
+ if (obj && obj.common)
460
+ this.setState_typed(id, value, ack, obj.common.type, callback);
461
+ else {
467
462
  this.setState_typed(id, value, ack, 'noobj', callback);
468
463
  }
469
464
  });
470
465
  return;
471
466
  }
472
- if (typeof value !== type) {
473
- 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);
474
469
  switch (type) {
475
470
  case 'number':
476
471
  value = parseFloat(value);
477
- if (isNaN(value)) {
478
- value = 0;
479
- }
472
+ if (isNaN (value)) value = 0;
480
473
  break;
481
474
  case 'string':
482
- case 'text':
483
- value = JSON.stringify(value);
484
- break;
485
- case 'boolean': {
475
+ case 'text': value = JSON.stringify(value); break;
476
+ case 'boolean':
486
477
  if (typeof value == 'number') {
487
- value = value !== 0;
478
+ value = (value != 0);
488
479
  break;
489
480
  }
490
481
  const sval = JSON.stringify(value).toLowerCase().trim();
491
- value = sval === 'true' || sval === 'yes' || sval === 'on';
492
- }
482
+ value = (sval == 'true' || sval == 'yes' || sval == 'on');
493
483
  break;
494
484
  }
495
485
  }
@@ -501,68 +491,60 @@ class StatesController extends EventEmitter {
501
491
  const id = '' + dev_id;
502
492
  const modelDesc = statesMapping.findModel(model);
503
493
  let icon = (modelDesc && modelDesc.icon) ? modelDesc.icon : 'img/unknown.png';
504
-
494
+
505
495
  // download icon if it external and not undef
506
- if (model === undefined) {
496
+ if (model === undefined) {
507
497
  this.warn(`download icon ${__dev_name} for undefined Device not available. Check your devices.`);
508
498
  } else {
509
- const model_modif = model.replace(/\//g, '-');
510
- 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';
511
501
 
512
- if (icon.startsWith('http')) {
513
- try {
502
+ if (icon.startsWith('http')) {
503
+ try {
514
504
  if (!fs.existsSync(pathToIcon)) {
515
505
  this.warn(`download icon from ${icon} saved into ${pathToIcon}`);
516
- this.downloadIcon(icon, pathToIcon);
506
+ this.downloadIcon(icon, pathToIcon);
517
507
  }
518
- icon = `img/${model_modif}.png`;
508
+ icon = 'img/' + model_modif + '.png';
519
509
  } catch (e) {
520
510
  this.debug(`ERROR : icon not found from ${icon} saved into ${pathToIcon}`);
521
511
  }
522
512
  }
523
513
  }
524
-
514
+
525
515
  this.adapter.setObjectNotExists(id, {
526
516
  type: 'device',
527
517
  // actually this is an error, so device.common has no attribute type. It must be in native part
528
- common: {
529
- name: __dev_name,
530
- type: model,
531
- icon,
532
- color: null,
533
- statusStates: {onlineId: `${this.adapter.namespace}.${dev_id}.available`}
534
- },
518
+ common: {name: __dev_name, type: model, icon: icon, color: null, statusStates: {onlineId: `${this.adapter.namespace}.${dev_id}.available`}},
535
519
  native: {id: dev_id}
536
520
  }, () => {
537
521
  // update type and icon
538
- this.adapter.extendObject(id, {
539
- common: {
540
- type: model,
541
- icon,
542
- color: null,
543
- statusStates: {onlineId: `${this.adapter.namespace}.${dev_id}.available`}
544
- }
545
- }, callback);
522
+ this.adapter.extendObject(id, {common: {type: model, icon: icon, color: null, statusStates: {onlineId: `${this.adapter.namespace}.${dev_id}.available`}}}, callback);
546
523
  });
547
524
  }
548
525
 
549
526
  async downloadIcon(url, image_path) {
550
- if (!fs.existsSync(image_path)) {
551
- return new Promise((resolve, reject) => {
552
- request.head(url, (err, res, body) => {
553
- if (err) {
554
- return reject(err);
555
- }
556
- const stream = request(url);
557
- stream.pipe(
558
- fs.createWriteStream(image_path)
559
- .on('error', err => reject(err)))
560
- .on('close', () => resolve());
561
- });
562
- });
563
- }
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
+ }
564
546
  }
565
-
547
+
566
548
  async syncDevStates(dev, model) {
567
549
  const devId = dev.ieeeAddr.substr(2);
568
550
  // devId - iobroker device id
@@ -573,25 +555,20 @@ class StatesController extends EventEmitter {
573
555
  const states = statesMapping.commonStates.concat(devStates.states);
574
556
 
575
557
  for (const stateInd in states) {
576
- if (!states.hasOwnProperty(stateInd)) {
577
- continue;
578
- }
558
+ if (!states.hasOwnProperty(stateInd)) continue;
579
559
 
580
560
  const statedesc = states[stateInd];
581
- if (statedesc === undefined) {
561
+ if (statedesc === undefined)
562
+ {
582
563
  this.error(`syncDevStates: Illegal state in ${JSON.stringify(dev)} - ${JSON.stringify(stateInd)}`);
583
564
  return;
584
565
  }
585
566
  // Filter out non routers or devices that are battery driven for the availability flag
586
- if (statedesc.id === 'available') {
587
- if (!(dev.type === 'Router') || dev.powerSource === 'Battery') {
567
+ if (statedesc.id === 'available')
568
+ if (!(dev.type === 'Router') || dev.powerSource === 'Battery')
588
569
  continue;
589
- }
590
- }
591
570
  // lazy states
592
- if (statedesc.lazy) {
593
- continue;
594
- }
571
+ if (statedesc.lazy) continue;
595
572
 
596
573
  const common = {
597
574
  name: statedesc.name,
@@ -609,16 +586,19 @@ class StatesController extends EventEmitter {
609
586
  }
610
587
  }
611
588
 
589
+
612
590
  async getExcludeExposes(allExcludesObj) {
613
591
  statesMapping.fillStatesWithExposes(allExcludesObj);
614
592
  }
615
593
 
594
+
616
595
  async publishToState(devId, model, payload) {
617
- const devStates = await this.getDevStates(`0x${devId}`, model);
618
- let has_debug = false;
596
+ const devStates = await this.getDevStates('0x'+devId, model);
597
+ let has_debug=false;
619
598
  if (this.debugDevices === undefined) this.getDebugDevices();
620
599
  for (const addressPart of this.debugDevices) {
621
- if (typeof devId === 'string' && devId.includes(addressPart)) {
600
+ if (typeof(devId) == 'string' && devId.indexOf(addressPart) > -1)
601
+ {
622
602
  if (payload.hasOwnProperty('msg_from_zigbee')) break;
623
603
  this.warn(`ELEVATED publishToState: message received '${JSON.stringify(payload)}' from device ${devId} type '${model}'`);
624
604
  has_debug = true;
@@ -631,8 +611,8 @@ class StatesController extends EventEmitter {
631
611
  // find states for payload
632
612
  if (devStates.states !== undefined) {
633
613
  const states = statesMapping.commonStates.concat(
634
- devStates.states.filter(statedesc => payload.hasOwnProperty(statedesc.prop || statedesc.id)));
635
-
614
+ devStates.states.filter((statedesc) => payload.hasOwnProperty(statedesc.prop || statedesc.id))
615
+ );
636
616
  for (const stateInd in states) {
637
617
  const statedesc = states[stateInd];
638
618
  let value;
@@ -642,12 +622,10 @@ class StatesController extends EventEmitter {
642
622
  value = payload[statedesc.prop || statedesc.id];
643
623
  }
644
624
  // checking value
645
- if (value === undefined || value === null) {
646
- continue;
647
- }
625
+ if (value === undefined || value === null) continue;
648
626
  let stateID = statedesc.id;
649
627
 
650
- if (has_debug && statedesc.id !== 'msg_from_zigbee') {
628
+ if (has_debug && statedesc.id != 'msg_from_zigbee') {
651
629
  this.warn(`ELEVATED publishToState: value generated '${JSON.stringify(value)}' from device ${devId} for '${statedesc.name}'`);
652
630
  }
653
631
 
@@ -662,25 +640,24 @@ class StatesController extends EventEmitter {
662
640
  min: statedesc.min,
663
641
  max: statedesc.max,
664
642
  };
665
-
666
- if (typeof value === 'object' && value.hasOwnProperty('stateid')) {
667
- stateID = `${stateID}.${value.stateid}`;
668
- if (value.hasOwnProperty('unit')) {
669
- common.unit = value.unit;
670
- }
671
- common.name = value.name ? value.name : value.stateid;
672
- common.role = value.role ? `value.${value.role}` : 'number';
643
+ if ( (typeof(value)== 'object') && (value.hasOwnProperty('stateid'))) {
644
+ stateID = stateID + '.' + value.stateid;
645
+ if (value.hasOwnProperty('unit')) common.unit = value.unit;
646
+ common.name = (value.name? value.name:value.stateid);
647
+ common.role = (value.role ? 'value.'+value.role:'number');
673
648
  value = value.value;
674
- }
675
649
 
676
- // if needs to return value to back after timeout
650
+ }
651
+ // if need return value to back after timeout
677
652
  if (statedesc.isEvent) {
678
653
  this.updateStateWithTimeout(devId, statedesc.id, value, common, 300, !value);
679
654
  } else {
680
655
  if (statedesc.prepublish) {
681
- this.collectOptions(devId, model, options =>
682
- statedesc.prepublish(devId, value, newvalue =>
683
- 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
+ });
684
661
  } else {
685
662
  this.updateState(devId, stateID, value, common);
686
663
  }