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/utils.js CHANGED
@@ -24,7 +24,7 @@ function bulbLevelToAdapterLevel(bulbLevel) {
24
24
  // - Bulb level range [2...254] is linearly mapped to adapter level range [1...100].
25
25
  if (bulbLevel >= 2) {
26
26
  // Perform linear mapping of range [2...254] to [1...100]
27
- return Math.round((bulbLevel - 2) * 99 / 252) + 1;
27
+ return (Math.round((bulbLevel - 2) * 99 / 252) + 1);
28
28
  } else {
29
29
  // The bulb is considered off. Even a bulb level of "1" is considered as off.
30
30
  return 0;
@@ -42,7 +42,7 @@ function adapterLevelToBulbLevel(adapterLevel) {
42
42
  // Please read the comments there regarding the rules applied here for mapping the values.
43
43
  if (adapterLevel) {
44
44
  // Perform linear mapping of range [1...100] to [2...254]
45
- return Math.round((adapterLevel - 1) * 252 / 99) + 2;
45
+ return (Math.round((adapterLevel - 1) * 252 / 99) + 2);
46
46
  } else {
47
47
  // Switch the bulb off. Some bulbs need "0" (IKEA), others "1" (HUE), and according to the
48
48
  // ZigBee docs "1" is the "minimum possible level"... we choose "0" here which seems to work.
@@ -53,7 +53,7 @@ function adapterLevelToBulbLevel(adapterLevel) {
53
53
  function bytesArrayToWordArray(ba) {
54
54
  const wa = [];
55
55
  for (let i = 0; i < ba.length; i++) {
56
- wa[(i / 2) | 0] |= ba[i] << (8 * (i % 2));
56
+ wa[(i / 2) | 0] |= ba[i] << (8*(i % 2));
57
57
  }
58
58
  return wa;
59
59
  }
@@ -62,7 +62,7 @@ function bytesArrayToWordArray(ba) {
62
62
  // If smaller, it is assumed to be mired.
63
63
  function toMired(t) {
64
64
  let miredValue = t;
65
- if (t > 1000) {
65
+ if (t > 1000){
66
66
  miredValue = miredKelvinConversion(t);
67
67
  }
68
68
  return miredValue;
@@ -80,7 +80,7 @@ function miredKelvinConversion(t) {
80
80
  */
81
81
  function decimalToHex(decimal, padding) {
82
82
  let hex = Number(decimal).toString(16);
83
- padding = typeof padding === 'undefined' || padding === null ? 2 : padding;
83
+ padding = typeof (padding) === 'undefined' || padding === null ? padding = 2 : padding;
84
84
 
85
85
  while (hex.length < padding) {
86
86
  hex = '0' + hex;
@@ -91,25 +91,24 @@ function decimalToHex(decimal, padding) {
91
91
 
92
92
  function getZbId(adapterDevId) {
93
93
  const idx = adapterDevId.indexOf('group');
94
- if (idx > 0) {
95
- return adapterDevId.substr(idx + 6);
96
- }
97
- return `0x${adapterDevId.split('.')[2]}`;
94
+ if (idx > 0) return adapterDevId.substr(idx+6);
95
+ return '0x' + adapterDevId.split('.')[2];
98
96
  }
99
97
 
100
98
  function getAdId(adapter, id) {
101
- return `${adapter.namespace}.${id.split('.')[2]}`; // iobroker device id
99
+ return adapter.namespace + '.' + id.split('.')[2]; // iobroker device id
102
100
  }
103
101
 
104
102
  function flatten(arr) {
105
- return arr.reduce((flat, toFlatten) =>
106
- flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten), []);
103
+ return arr.reduce((flat, toFlatten) => {
104
+ return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
105
+ }, []);
107
106
  }
108
107
 
109
108
  const forceEndDevice = flatten(
110
109
  ['QBKG03LM', 'QBKG04LM', 'ZNMS13LM', 'ZNMS12LM']
111
- .map(model => zigbeeHerdsmanConverters.devices.find((d) => d.model === model))
112
- .map(mappedModel => mappedModel.zigbeeModel));
110
+ .map((model) => zigbeeHerdsmanConverters.devices.find((d) => d.model === model))
111
+ .map((mappedModel) => mappedModel.zigbeeModel));
113
112
 
114
113
  // Xiaomi uses 4151 and 4447 (lumi.plug) as manufacturer ID.
115
114
  const xiaomiManufacturerID = [4151, 4447];
@@ -118,7 +117,7 @@ const ikeaTradfriManufacturerID = [4476];
118
117
  function sanitizeImageParameter(parameter) {
119
118
  const replaceByDash = [/\?/g, /&/g, /[^a-z\d\-_./:]/gi, /[/]/gi];
120
119
  let sanitized = parameter;
121
- replaceByDash.forEach(r => sanitized = sanitized.replace(r, '-'));
120
+ replaceByDash.forEach((r) => sanitized = sanitized.replace(r, '-'));
122
121
  return sanitized;
123
122
  }
124
123
 
@@ -133,7 +132,7 @@ function getDeviceIcon(definition) {
133
132
  return icon;
134
133
  }
135
134
 
136
- exports.secondsToMilliseconds = seconds => seconds * 1000;
135
+ exports.secondsToMilliseconds = (seconds) => seconds * 1000;
137
136
  exports.bulbLevelToAdapterLevel = bulbLevelToAdapterLevel;
138
137
  exports.adapterLevelToBulbLevel = adapterLevelToBulbLevel;
139
138
  exports.bytesArrayToWordArray = bytesArrayToWordArray;
@@ -142,11 +141,11 @@ exports.miredKelvinConversion = miredKelvinConversion;
142
141
  exports.decimalToHex = decimalToHex;
143
142
  exports.getZbId = getZbId;
144
143
  exports.getAdId = getAdId;
145
- exports.isRouter = device => device.type === 'Router' && !forceEndDevice.includes(device.modelID);
146
- exports.isBatteryPowered = device => device.powerSource && device.powerSource === 'Battery';
147
- exports.isXiaomiDevice = device =>
148
- device.modelID !== 'lumi.router' &&
149
- xiaomiManufacturerID.includes(device.manufacturerID) &&
150
- (!device.manufacturerName || !device.manufacturerName.startsWith('Trust'));
151
- exports.isIkeaTradfriDevice = device => ikeaTradfriManufacturerID.includes(device.manufacturerID);
152
- exports.getDeviceIcon = getDeviceIcon;
144
+ exports.isRouter = (device) => device.type === 'Router' && !forceEndDevice.includes(device.modelID);
145
+ exports.isBatteryPowered = (device) => device.powerSource && device.powerSource === 'Battery';
146
+ exports.isXiaomiDevice = (device) => {
147
+ return device.modelID !== 'lumi.router' && xiaomiManufacturerID.includes(device.manufacturerID) &&
148
+ (!device.manufacturerName || !device.manufacturerName.startsWith('Trust'));
149
+ };
150
+ exports.isIkeaTradfriDevice = (device) => ikeaTradfriManufacturerID.includes(device.manufacturerID);
151
+ exports.getDeviceIcon = getDeviceIcon;
@@ -14,18 +14,18 @@ class BaseExtension {
14
14
  }
15
15
 
16
16
  error(message, data) {
17
- this.zigbee.error(`${this.name}:${message}`, data);
17
+ this.zigbee.error(this.name + ':' + message, data);
18
18
  }
19
19
 
20
20
  warn(message, data) {
21
- this.zigbee.warn(`${this.name}:${message}`, data);
21
+ this.zigbee.warn(this.name + ':' + message, data);
22
22
  }
23
23
 
24
24
  debug(message, data) {
25
25
  if (this.elevate_debug)
26
- this.zigbee.warn(`DE ${this.name}:${message}`, data);
26
+ this.zigbee.warn('DE ' + this.name + ':' + message, data);
27
27
  else
28
- this.zigbee.debug(`${this.name}:${message}`, data);
28
+ this.zigbee.debug(this.name + ':' + message, data);
29
29
  }
30
30
 
31
31
  sendError(error, message) {
@@ -8,11 +8,12 @@ class DelayedAction extends BaseExtension {
8
8
 
9
9
  this.actions = {};
10
10
  this.zigbee.delayAction = this.delayAction.bind(this);
11
- this.name = 'DelayedAction';
11
+ this.name = "DelayedAction";
12
12
  }
13
13
 
14
14
  setOptions(options) {
15
- return typeof options === 'object';
15
+ if (typeof(options) != 'object') return false;
16
+ return true;
16
17
  }
17
18
 
18
19
 
@@ -29,7 +30,11 @@ class DelayedAction extends BaseExtension {
29
30
  // return false;
30
31
  // }
31
32
 
32
- return device.interviewing !== true;
33
+ if (device.interviewing === true) {
34
+ return false;
35
+ }
36
+
37
+ return true;
33
38
  }
34
39
 
35
40
  async onZigbeeStarted() {
@@ -92,7 +97,10 @@ class DelayedAction extends BaseExtension {
92
97
  }
93
98
  const foundDev = await this.zigbee.getDevice(device.ieeeAddr);
94
99
  if (!foundDev) {
95
- this.debug(`No found device ${device.ieeeAddr} ${device.modelID}, for doAction`);
100
+ this.debug(
101
+ `No found device ${device.ieeeAddr} ${device.modelID}, ` +
102
+ `for doAction`
103
+ );
96
104
  delete this.actions[device.ieeeAddr];
97
105
  return;
98
106
  }
@@ -112,7 +120,7 @@ class DelayedAction extends BaseExtension {
112
120
  try {
113
121
  // do action
114
122
  await actionDef.action(device);
115
- this.info(`Do action successfully ${device.ieeeAddr} ${device.modelID}`);
123
+ this.info(`Do action succesfully ${device.ieeeAddr} ${device.modelID}`);
116
124
  toDelete.push(actionDef);
117
125
  } catch (error) {
118
126
  this.sendError(error);
@@ -20,7 +20,7 @@ const forcedPingable = [
20
20
  // will result in warnings "illegal state x,y" or "illegal state h,s" for color
21
21
  // and possibly sudden changes in value due to the support for color_temp
22
22
  // in mired and Kelvin.
23
- const toZigbeeCandidates = ['local_temperature', 'state', 'brightness']; //, 'color', 'color_temp'];
23
+ const toZigbeeCandidates = ['local_temperature','state', 'brightness']; //, 'color', 'color_temp'];
24
24
  const Hours25 = 1000 * 60 * 60 * 25;
25
25
  const MinAvailabilityTimeout = 300; // ping every 5 minutes with few devices
26
26
  const MaxAvailabilityTimeout = 1800; // ping every 30 minutes with many devices;
@@ -44,76 +44,65 @@ class DeviceAvailability extends BaseExtension {
44
44
  // force publish availability for new devices
45
45
  this.zigbee.on('new', (entity) => {
46
46
  // wait for 1s for creating device states
47
- setTimeout(() =>
48
- this.publishAvailability(entity.device, true, true), 1000);
47
+ setTimeout(() => {
48
+ this.publishAvailability(entity.device, true, true);
49
+ }, 1000);
49
50
  });
50
51
  this.startDevicePingQueue = []; // simple fifo array for starting device pings
51
52
  this.startDevicePingTimeout = null; // handle for the timeout which empties the queue
52
53
  this.startDevicePingDelay = 200; // 200 ms delay between starting the ping timeout
53
- this.name = 'DeviceAvailability';
54
+ this.name = "DeviceAvailability";
54
55
  this.elevate_debug = false;
55
56
  }
56
57
 
57
58
  setOptions(options) {
58
- if (typeof options !== 'object') {
59
- return false;
60
- }
61
- if (options.disableActivePing) {
62
- this.active_ping = false;
63
- }
64
- if (options.disableForcedPing) {
65
- this.forced_ping = false;
66
- }
67
- if (typeof options.pingTimeout === 'number') {
68
- this.availability_timeout = Math.min(60, options.pingTimeout);
69
- }
70
- if (typeof options.pingCount === 'number') {
71
- this.max_ping = Math.min(2, options.pingCount);
72
- }
59
+ if (typeof(options) != 'object') return false;
60
+ if (options.disableActivePing) this.active_ping = false;
61
+ if (options.disableForcedPing) this.forced_ping = false;
62
+ if (typeof(options.pingTimeout)=='number') this.availability_timeout = Math.min(60,options.pingTimeout);
63
+ if (typeof(options.pingCount)=='number') this.max_ping = Math.min(2, options.pingCount);
73
64
  return true;
74
65
  }
75
66
 
76
67
  isPingable(device) {
77
- if (this.active_ping) {
78
- if (this.forced_ping && forcedPingable.find(d => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
68
+ if (this.active_ping)
69
+ {
70
+ if (this.forced_ping && forcedPingable.find((d) => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
79
71
  return true;
80
72
  }
81
73
 
82
- return utils.isRouter(device) && !utils.isBatteryPowered(device);
74
+ const result = utils.isRouter(device) && !utils.isBatteryPowered(device);
75
+ return result;
83
76
  }
84
77
  return false;
85
78
  }
86
79
 
87
80
  async getAllPingableDevices() {
88
81
  const clients = await this.zigbee.getClients();
89
- return clients.filter(d => this.isPingable(d));
82
+ return clients.filter((d) => this.isPingable(d));
90
83
  }
91
84
 
92
85
  async registerDevicePing(device, entity) {
93
- this.debug(`register device Ping for ${JSON.stringify(device.ieeeAddr)}`);
86
+ this.debug('register device Ping for ' + JSON.stringify(device.ieeeAddr));
94
87
  this.forcedNonPingable[device.ieeeAddr] = false;
95
88
  // this.warn(`Called registerDevicePing for '${device}' of '${entity}'`);
96
- if (!this.isPingable(device)) {
97
- return;
98
- }
89
+ if (!this.isPingable(device)) return;
99
90
  // ensure we do not already have this device in the queue
100
- // TODO: Following does not work, may be `if (this.startDevicePingQueue.find(item => item && item.device === device)) { return; }`
101
91
  this.startDevicePingQueue.forEach(item => {
102
- if (item && item.device == device) {
92
+ if (item && item.device == device)
103
93
  return;
104
- }
105
94
  });
106
95
  this.number_of_registered_devices++;
107
- this.availability_timeout = Math.max(Math.min(this.number_of_registered_devices * AverageTimeBetweenPings, MaxAvailabilityTimeout), MinAvailabilityTimeout);
108
- this.startDevicePingQueue.push({device, entity});
109
- if (this.startDevicePingTimeout == null) {
110
- this.startDevicePingTimeout = setTimeout(async () =>
111
- await this.startDevicePing(), this.startDevicePingDelay);
112
- }
96
+ this.availability_timeout = Math.max(Math.min(this.number_of_registered_devices * AverageTimeBetweenPings,MaxAvailabilityTimeout ),MinAvailabilityTimeout);
97
+ this.startDevicePingQueue.push({device:device, entity:entity});
98
+ if (this.startDevicePingTimeout == null)
99
+ this.startDevicePingTimeout = setTimeout(async() => {
100
+ await this.startDevicePing();
101
+ }, this.startDevicePingDelay);
113
102
  }
114
103
 
115
104
  async deregisterDevicePing(device) {
116
- this.info(`deregister device Ping for deactivated device ${JSON.stringify(device.ieeeAddr)}`);
105
+ this.info('deregister device Ping for deactivated device ' + JSON.stringify(device.ieeeAddr));
117
106
  this.forcedNonPingable[device.ieeeAddr] = true;
118
107
  if (this.timers[device.ieeeAddr]) {
119
108
  clearTimeout(this.timers[device.ieeeAddr]);
@@ -124,15 +113,15 @@ class DeviceAvailability extends BaseExtension {
124
113
  // this.warn(JSON.stringify(this));
125
114
  this.startDevicePingTimeout = null;
126
115
  const item = this.startDevicePingQueue.shift();
127
- if (this.startDevicePingQueue.length > 0) {
128
- this.startDevicePingTimeout = setTimeout(async () =>
129
- await this.startDevicePing(), this.startDevicePingDelay);
116
+ if (this.startDevicePingQueue.length >0) {
117
+ this.startDevicePingTimeout = setTimeout(async() => {
118
+ await this.startDevicePing();
119
+ }, this.startDevicePingDelay);
130
120
  }
131
121
  if (item && item.hasOwnProperty('device')) {
132
122
  this.handleIntervalPingable(item.device, item.entity);
133
123
  }
134
124
  }
135
-
136
125
  async onZigbeeStarted() {
137
126
  // As some devices are not checked for availability (e.g. battery powered devices)
138
127
  // we mark these device as online by default.
@@ -142,20 +131,22 @@ class DeviceAvailability extends BaseExtension {
142
131
  const clients = await this.zigbee.getClients();
143
132
  // this.warn('onZigbeeStarted called');
144
133
  for (const device of clients) {
134
+
145
135
  if (this.isPingable(device)) {
146
136
  // this.setTimerPingable(device);
147
137
  } else {
148
138
  // this.warn(`Setting '${device.ieeeAddr}' as available - battery driven`);
149
139
  this.publishAvailability(device, true);
150
- this.timers[device.ieeeAddr] = setInterval(() =>
151
- this.handleIntervalNotPingable(device), utils.secondsToMilliseconds(this.availability_timeout));
140
+ this.timers[device.ieeeAddr] = setInterval(() => {
141
+ this.handleIntervalNotPingable(device);
142
+ },utils.secondsToMilliseconds(this.availability_timeout));
152
143
  }
153
144
  }
154
145
  }
155
146
 
156
147
  async handleIntervalPingable(device, entity) {
157
148
  const ieeeAddr = device.ieeeAddr;
158
- const resolvedEntity = entity ? entity : await this.zigbee.resolveEntity(ieeeAddr);
149
+ const resolvedEntity = (entity ? entity: await this.zigbee.resolveEntity(ieeeAddr));
159
150
  if (!resolvedEntity) {
160
151
  this.debug(`Stop pinging '${ieeeAddr}' ${device.modelID}, device is not known anymore`);
161
152
  return;
@@ -163,8 +154,8 @@ class DeviceAvailability extends BaseExtension {
163
154
  if (this.isPingable(device)) {
164
155
  let pingCount = this.ping_counters[device.ieeeAddr];
165
156
  if (pingCount === undefined) {
166
- this.ping_counters[device.ieeeAddr] = {failed: 0, reported: 0};
167
- pingCount = {failed: 0, reported: 0};
157
+ this.ping_counters[device.ieeeAddr] = { failed: 0, reported: 0};
158
+ pingCount = { failed: 0, reported: 0};
168
159
  }
169
160
 
170
161
  // first see if we can "ping" the device by reading a Status
@@ -179,7 +170,8 @@ class DeviceAvailability extends BaseExtension {
179
170
  return;
180
171
  }
181
172
  }
182
- } catch (error) {
173
+ }
174
+ catch (error) {
183
175
  this.sendError(error);
184
176
  this.debug(`Exception in readState of '${device.ieeeAddr}' - error : '${error}'`);
185
177
  // intentionally empty: Just present to ensure we cause no harm
@@ -193,22 +185,26 @@ class DeviceAvailability extends BaseExtension {
193
185
  this.ping_counters[device.ieeeAddr].failed = 0;
194
186
  } catch (error) {
195
187
  this.publishAvailability(device, false);
196
- if (pingCount.failed++ <= this.max_ping) {
188
+ if (pingCount.failed++ <= this.max_ping)
189
+ {
197
190
  if (pingCount.failed < 2 && pingCount.reported < this.max_ping) {
198
191
  this.warn(`Failed to ping ${ieeeAddr} ${device.modelID}`);
199
192
  pingCount.reported++;
200
- } else {
193
+ }
194
+ else {
201
195
  this.debug(`Failed to ping ${ieeeAddr} ${device.modelID} on ${pingCount} consecutive attempts`);
202
196
  }
203
197
  this.setTimerPingable(device, pingCount.failed);
204
- this.ping_counters[device.ieeeAddr] = pingCount;
205
- } else {
198
+ this.ping_counters[device.ieeeAddr]= pingCount;
199
+ }
200
+ else {
206
201
  this.warn(`Stopping to ping ${ieeeAddr} ${device.modelID} after ${pingCount.failed} ping attempts`);
207
202
  }
208
203
  }
209
204
  }
210
205
  }
211
206
 
207
+
212
208
  async handleIntervalNotPingable(device) {
213
209
  const entity = await this.zigbee.resolveEntity(device.ieeeAddr);
214
210
  if (!entity || !device.lastSeen) {
@@ -224,14 +220,13 @@ class DeviceAvailability extends BaseExtension {
224
220
  }
225
221
 
226
222
  setTimerPingable(device, factor) {
227
- if (factor === undefined || factor < 1) {
228
- factor = 1;
229
- }
223
+ if (factor === undefined || factor < 1) factor = 1;
230
224
  if (this.timers[device.ieeeAddr]) {
231
225
  clearTimeout(this.timers[device.ieeeAddr]);
232
226
  }
233
- this.timers[device.ieeeAddr] = setTimeout(async () =>
234
- await this.handleIntervalPingable(device), utils.secondsToMilliseconds(this.availability_timeout * factor));
227
+ this.timers[device.ieeeAddr] = setTimeout(async() => {
228
+ await this.handleIntervalPingable(device);
229
+ }, utils.secondsToMilliseconds(this.availability_timeout * factor));
235
230
  }
236
231
 
237
232
  async stop() {
@@ -239,7 +234,7 @@ class DeviceAvailability extends BaseExtension {
239
234
  clearTimeout(timer);
240
235
  }
241
236
  const clients = await this.zigbee.getClients();
242
- clients.forEach(device => this.publishAvailability(device, false));
237
+ clients.forEach((device) => this.publishAvailability(device, false));
243
238
  }
244
239
 
245
240
  async onReconnect(device) {
@@ -274,8 +269,8 @@ class DeviceAvailability extends BaseExtension {
274
269
  const payload = {available: available};
275
270
  this.debug(`Publish available for ${ieeeAddr} = ${available}`);
276
271
  this.zigbee.emit('publish', ieeeAddr.substr(2), entity.mapped.model, payload);
277
- this.debug(`Publish LQ for ${ieeeAddr} = ${(available ? 10 : 0)}`);
278
- this.zigbee.emit('publish', ieeeAddr.substr(2), entity.mapped.model, {linkquality: (available ? 10 : 0)});
272
+ this.debug(`Publish LQ for ${ieeeAddr} = ${(available ? 10: 0)}`);
273
+ this.zigbee.emit('publish', ieeeAddr.substr(2), entity.mapped.model, { linkquality: (available ? 10: 0) });
279
274
  }
280
275
  }
281
276
  }
@@ -294,22 +289,23 @@ class DeviceAvailability extends BaseExtension {
294
289
  this.setTimerPingable(device, 1);
295
290
  const pc = this.ping_counters[device.ieeeAddr];
296
291
  if (pc == undefined) {
297
- this.ping_counters[device.ieeeAddr] = {failed: 0, reported: 0};
298
- } else {
292
+ this.ping_counters[device.ieeeAddr] = { failed:0, reported:0 };
293
+ }
294
+ else {
299
295
  this.ping_counters[device.ieeeAddr].failed++;
300
296
  }
301
297
 
302
298
  const online = this.state.hasOwnProperty(device.ieeeAddr) && this.state[device.ieeeAddr];
303
299
  if (online && data.type === 'deviceAnnounce' && !utils.isIkeaTradfriDevice(device)) {
304
300
  /**
305
- * In case the device is powered off AND on within the availability timeout,
306
- * zigbee2qmtt does not detect the device as offline (device is still marked online).
307
- * When a device is turned on again the state could be out of sync.
308
- * https://github.com/Koenkk/zigbee2mqtt/issues/1383#issuecomment-489412168
309
- * endDeviceAnnce is typically send when a device comes online.
310
- *
311
- * This isn't needed for TRADFRI devices as they already send the state themself.
312
- */
301
+ * In case the device is powered off AND on within the availability timeout,
302
+ * zigbee2qmtt does not detect the device as offline (device is still marked online).
303
+ * When a device is turned on again the state could be out of sync.
304
+ * https://github.com/Koenkk/zigbee2mqtt/issues/1383#issuecomment-489412168
305
+ * endDeviceAnnce is typically send when a device comes online.
306
+ *
307
+ * This isn't needed for TRADFRI devices as they already send the state themself.
308
+ */
313
309
  this.onReconnect(device);
314
310
  }
315
311
  }
@@ -10,17 +10,20 @@ const forcedConfigureOnEachStart = [
10
10
  zigbeeHerdsmanConverters.devices.find((d) => d.model === 'ZK03840')
11
11
  ];
12
12
 
13
+
14
+
13
15
  class DeviceConfigure extends BaseExtension {
14
16
  constructor(zigbee, options) {
15
17
  super(zigbee, options);
16
18
 
17
19
  this.configuring = new Set();
18
20
  this.attempts = {};
19
- this.name = 'DeviceConfigure';
21
+ this.name = "DeviceConfigure";
20
22
  }
21
23
 
22
24
  setOptions(options) {
23
- return typeof options === 'object';
25
+ if (typeof(options) != 'object') return false;
26
+ return true;
24
27
  }
25
28
 
26
29
  shouldConfigure(device, mappedDevice) {
@@ -34,8 +37,11 @@ class DeviceConfigure extends BaseExtension {
34
37
  zigbeeHerdsmanConverters.getConfigureKey(mappedDevice)) {
35
38
  return false;
36
39
  }
40
+ if (device.interviewing === true) {
41
+ return false;
42
+ }
37
43
 
38
- return device.interviewing !== true;
44
+ return true;
39
45
  }
40
46
 
41
47
  async onZigbeeStarted() {
@@ -47,7 +53,7 @@ class DeviceConfigure extends BaseExtension {
47
53
 
48
54
  if (forcedConfigureOnEachStart.find((d) => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
49
55
  this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} forced by adapter config`);
50
- device.meta.configured = -1; // Force a reconfiguration for this device
56
+ device.meta.configured = -1; // Force a reconfigure for this device
51
57
  }
52
58
  if (this.shouldConfigure(device, mappedDevice)) {
53
59
  this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} needed`);
@@ -58,7 +64,9 @@ class DeviceConfigure extends BaseExtension {
58
64
  }
59
65
  } catch (error) {
60
66
  this.sendError(error);
61
- this.error(`Failed to DeviceConfigure.onZigbeeStarted (${error.stack})`);
67
+ this.error(
68
+ `Failed to DeviceConfigure.onZigbeeStarted (${error.stack})`,
69
+ );
62
70
  }
63
71
  }
64
72
 
@@ -70,11 +78,13 @@ class DeviceConfigure extends BaseExtension {
70
78
  }
71
79
  } catch (error) {
72
80
  this.sendError(error);
73
- this.error(`Failed to DeviceConfigure.onZigbeeEvent (${error.stack})`);
81
+ this.error(
82
+ `Failed to DeviceConfigure.onZigbeeEvent (${error.stack})`,
83
+ );
74
84
  }
75
85
  }
76
86
 
77
- onDeviceRemove(device) {
87
+ onDeviceRemove(device){
78
88
  try {
79
89
  if (this.configuring.has(device.ieeeAddr)) {
80
90
  this.configuring.delete(device.ieeeAddr);
@@ -85,11 +95,13 @@ class DeviceConfigure extends BaseExtension {
85
95
  }
86
96
  } catch (error) {
87
97
  this.sendError(error);
88
- this.error(`Failed to DeviceConfigure.onDeviceRemove (${error.stack})`);
98
+ this.error(
99
+ `Failed to DeviceConfigure.onDeviceRemove (${error.stack})`,
100
+ );
89
101
  }
90
102
  }
91
103
 
92
- onDeviceLeave(data, entity) {
104
+ onDeviceLeave(data, entity){
93
105
  if (entity) {
94
106
  this.onDeviceRemove(entity.device);
95
107
  } else {
@@ -6,9 +6,10 @@ const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
6
6
  class DeviceEvent extends BaseExtension {
7
7
  constructor(zigbee, options) {
8
8
  super(zigbee, options);
9
- this.name = 'DeviceEvent';
9
+ this.name = "DeviceEvent";
10
10
  }
11
11
 
12
+
12
13
  async onZigbeeStarted() {
13
14
  for (const device of await this.zigbee.getClients()) {
14
15
  this.callOnEvent(device, 'start', {});
@@ -16,8 +17,8 @@ class DeviceEvent extends BaseExtension {
16
17
  }
17
18
 
18
19
  setOptions(options) {
19
- return typeof options === 'object';
20
-
20
+ if (typeof(options) != 'object') return false;
21
+ return true;
21
22
  }
22
23
 
23
24
  onZigbeeEvent(data, mappedDevice) {