iobroker.zigbee 1.8.3 → 1.8.7

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 (87) hide show
  1. package/README.md +6 -0
  2. package/admin/adapter-settings.js +244 -0
  3. package/admin/admin.js +520 -494
  4. package/admin/index_m.html +1171 -1001
  5. package/admin/tab_m.html +44 -2
  6. package/docs/de/img/CC2531.png +0 -0
  7. package/docs/de/img/CC2538_CC2592_PA.PNG +0 -0
  8. package/docs/de/img/CC2591.png +0 -0
  9. package/docs/de/img/boards.jpg +0 -0
  10. package/docs/de/img/cc26x2r.PNG +0 -0
  11. package/docs/de/img/results.jpg +0 -0
  12. package/docs/de/img/sku_429478_2.png +0 -0
  13. package/docs/de/img/sku_429601_2.png +0 -0
  14. package/docs/de/readme.md +27 -0
  15. package/docs/en/img/CC2531.png +0 -0
  16. package/docs/en/img/CC2591.png +0 -0
  17. package/docs/en/img/deconz.png +0 -0
  18. package/docs/en/img/sku_429478_2.png +0 -0
  19. package/docs/en/img/sku_429601_2.png +0 -0
  20. package/docs/en/readme.md +30 -0
  21. package/docs/flashing_via_arduino_(en).md +110 -0
  22. package/docs/ru/img/CC2531.png +0 -0
  23. package/docs/ru/img/CC2591.png +0 -0
  24. package/docs/ru/img/sku_429478_2.png +0 -0
  25. package/docs/ru/img/sku_429601_2.png +0 -0
  26. package/docs/ru/readme.md +28 -0
  27. package/docs/tutorial/CC2530_20190425.zip +0 -0
  28. package/docs/tutorial/CC2530_CC2591_20190515.zip +0 -0
  29. package/docs/tutorial/CC2530_CC2592_20190515.zip +0 -0
  30. package/docs/tutorial/CC2531_20190425.zip +0 -0
  31. package/docs/tutorial/adm5_1.PNG +0 -0
  32. package/docs/tutorial/adm5_2.PNG +0 -0
  33. package/docs/tutorial/cat.PNG +0 -0
  34. package/docs/tutorial/groups-1.png +0 -0
  35. package/docs/tutorial/groups-2.png +0 -0
  36. package/docs/tutorial/inst.PNG +0 -0
  37. package/docs/tutorial/reflash-finish.PNG +0 -0
  38. package/docs/tutorial/reflash-step0.png +0 -0
  39. package/docs/tutorial/reflash-step1.PNG +0 -0
  40. package/docs/tutorial/reflash-step2.PNG +0 -0
  41. package/docs/tutorial/settings.png +0 -0
  42. package/docs/tutorial/tab-dev-1.png +0 -0
  43. package/docs/tutorial/zigbee.png +0 -0
  44. package/docs/tutorial/zigbee15.png +0 -0
  45. package/io-package.json +34 -33
  46. package/lib/backup.js +2 -2
  47. package/lib/binding.js +32 -37
  48. package/lib/colors.js +163 -158
  49. package/lib/commands.js +100 -91
  50. package/lib/developer.js +9 -12
  51. package/lib/devices.js +168 -178
  52. package/lib/exclude.js +30 -36
  53. package/lib/exposes.js +168 -143
  54. package/lib/groups.js +81 -83
  55. package/lib/json.js +5 -6
  56. package/lib/networkmap.js +2 -3
  57. package/lib/ota.js +34 -18
  58. package/lib/rgb.js +114 -72
  59. package/lib/seriallist.js +25 -20
  60. package/lib/statescontroller.js +206 -183
  61. package/lib/utils.js +29 -23
  62. package/lib/zbBaseExtension.js +4 -4
  63. package/lib/zbDelayedAction.js +5 -13
  64. package/lib/zbDeviceAvailability.js +69 -65
  65. package/lib/zbDeviceConfigure.js +9 -21
  66. package/lib/zbDeviceEvent.js +3 -4
  67. package/lib/zigbeecontroller.js +133 -128
  68. package/main.js +169 -154
  69. package/package.json +28 -14
  70. package/.eslintignore +0 -2
  71. package/.eslintrc.json +0 -37
  72. package/.github/FUNDING.yml +0 -3
  73. package/.github/auto-merge.yml +0 -17
  74. package/.github/dependabot.yml +0 -24
  75. package/.github/stale.yml +0 -13
  76. package/.github/workflows/codeql.yml +0 -41
  77. package/.github/workflows/dependabot-automerge.yml +0 -22
  78. package/.github/workflows/test-and-release.yml +0 -149
  79. package/.releaseconfig.json +0 -3
  80. package/.travis/wiki.sh +0 -28
  81. package/.travis.yml +0 -41
  82. package/gulpfile.js +0 -464
  83. package/test/integration.js +0 -5
  84. package/test/mocha.custom.opts +0 -2
  85. package/test/mocha.setup.js +0 -14
  86. package/test/package.js +0 -5
  87. package/test/unit.js +0 -5
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 ? padding = 2 : padding;
83
+ padding = typeof padding === 'undefined' || padding === null ? 2 : padding;
84
84
 
85
85
  while (hex.length < padding) {
86
86
  hex = '0' + hex;
@@ -91,24 +91,25 @@ function decimalToHex(decimal, padding) {
91
91
 
92
92
  function getZbId(adapterDevId) {
93
93
  const idx = adapterDevId.indexOf('group');
94
- if (idx > 0) return adapterDevId.substr(idx+6);
95
- return '0x' + adapterDevId.split('.')[2];
94
+ if (idx > 0) {
95
+ return adapterDevId.substr(idx + 6);
96
+ }
97
+ return `0x${adapterDevId.split('.')[2]}`;
96
98
  }
97
99
 
98
100
  function getAdId(adapter, id) {
99
- return adapter.namespace + '.' + id.split('.')[2]; // iobroker device id
101
+ return `${adapter.namespace}.${id.split('.')[2]}`; // iobroker device id
100
102
  }
101
103
 
102
104
  function flatten(arr) {
103
- return arr.reduce((flat, toFlatten) => {
104
- return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
105
- }, []);
105
+ return arr.reduce((flat, toFlatten) =>
106
+ flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten), []);
106
107
  }
107
108
 
108
109
  const forceEndDevice = flatten(
109
110
  ['QBKG03LM', 'QBKG04LM', 'ZNMS13LM', 'ZNMS12LM']
110
- .map((model) => zigbeeHerdsmanConverters.devices.find((d) => d.model === model))
111
- .map((mappedModel) => mappedModel.zigbeeModel));
111
+ .map(model => zigbeeHerdsmanConverters.devices.find((d) => d.model === model))
112
+ .map(mappedModel => mappedModel.zigbeeModel));
112
113
 
113
114
  // Xiaomi uses 4151 and 4447 (lumi.plug) as manufacturer ID.
114
115
  const xiaomiManufacturerID = [4151, 4447];
@@ -117,7 +118,7 @@ const ikeaTradfriManufacturerID = [4476];
117
118
  function sanitizeImageParameter(parameter) {
118
119
  const replaceByDash = [/\?/g, /&/g, /[^a-z\d\-_./:]/gi, /[/]/gi];
119
120
  let sanitized = parameter;
120
- replaceByDash.forEach((r) => sanitized = sanitized.replace(r, '-'));
121
+ replaceByDash.forEach(r => sanitized = sanitized.replace(r, '-'));
121
122
  return sanitized;
122
123
  }
123
124
 
@@ -131,8 +132,12 @@ function getDeviceIcon(definition) {
131
132
  }
132
133
  return icon;
133
134
  }
135
+ function getModelRegEx( model) {
136
+ const stripModel = (model) ? model.replace(/\0.*$/g, '').trim() : '';
137
+ return stripModel;
138
+ }
134
139
 
135
- exports.secondsToMilliseconds = (seconds) => seconds * 1000;
140
+ exports.secondsToMilliseconds = seconds => seconds * 1000;
136
141
  exports.bulbLevelToAdapterLevel = bulbLevelToAdapterLevel;
137
142
  exports.adapterLevelToBulbLevel = adapterLevelToBulbLevel;
138
143
  exports.bytesArrayToWordArray = bytesArrayToWordArray;
@@ -141,11 +146,12 @@ exports.miredKelvinConversion = miredKelvinConversion;
141
146
  exports.decimalToHex = decimalToHex;
142
147
  exports.getZbId = getZbId;
143
148
  exports.getAdId = getAdId;
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;
149
+ exports.getModelRegEx = getModelRegEx;
150
+ exports.isRouter = device => device.type === 'Router' && !forceEndDevice.includes(device.modelID);
151
+ exports.isBatteryPowered = device => device.powerSource && device.powerSource === 'Battery';
152
+ exports.isXiaomiDevice = device =>
153
+ device.modelID !== 'lumi.router' &&
154
+ xiaomiManufacturerID.includes(device.manufacturerID) &&
155
+ (!device.manufacturerName || !device.manufacturerName.startsWith('Trust'));
156
+ exports.isIkeaTradfriDevice = device => ikeaTradfriManufacturerID.includes(device.manufacturerID);
157
+ 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,12 +8,11 @@ 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
- if (typeof(options) != 'object') return false;
16
- return true;
15
+ return typeof options === 'object';
17
16
  }
18
17
 
19
18
 
@@ -30,11 +29,7 @@ class DelayedAction extends BaseExtension {
30
29
  // return false;
31
30
  // }
32
31
 
33
- if (device.interviewing === true) {
34
- return false;
35
- }
36
-
37
- return true;
32
+ return device.interviewing !== true;
38
33
  }
39
34
 
40
35
  async onZigbeeStarted() {
@@ -97,10 +92,7 @@ class DelayedAction extends BaseExtension {
97
92
  }
98
93
  const foundDev = await this.zigbee.getDevice(device.ieeeAddr);
99
94
  if (!foundDev) {
100
- this.debug(
101
- `No found device ${device.ieeeAddr} ${device.modelID}, ` +
102
- `for doAction`
103
- );
95
+ this.debug(`No found device ${device.ieeeAddr} ${device.modelID}, for doAction`);
104
96
  delete this.actions[device.ieeeAddr];
105
97
  return;
106
98
  }
@@ -120,7 +112,7 @@ class DelayedAction extends BaseExtension {
120
112
  try {
121
113
  // do action
122
114
  await actionDef.action(device);
123
- this.info(`Do action succesfully ${device.ieeeAddr} ${device.modelID}`);
115
+ this.info(`Do action successfully ${device.ieeeAddr} ${device.modelID}`);
124
116
  toDelete.push(actionDef);
125
117
  } catch (error) {
126
118
  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,65 +44,76 @@ 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);
49
- }, 1000);
47
+ setTimeout(() =>
48
+ this.publishAvailability(entity.device, true, true), 1000);
50
49
  });
51
50
  this.startDevicePingQueue = []; // simple fifo array for starting device pings
52
51
  this.startDevicePingTimeout = null; // handle for the timeout which empties the queue
53
52
  this.startDevicePingDelay = 200; // 200 ms delay between starting the ping timeout
54
- this.name = "DeviceAvailability";
53
+ this.name = 'DeviceAvailability';
55
54
  this.elevate_debug = false;
56
55
  }
57
56
 
58
57
  setOptions(options) {
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);
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
+ }
64
73
  return true;
65
74
  }
66
75
 
67
76
  isPingable(device) {
68
- if (this.active_ping)
69
- {
70
- if (this.forced_ping && forcedPingable.find((d) => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
77
+ if (this.active_ping) {
78
+ if (this.forced_ping && forcedPingable.find(d => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
71
79
  return true;
72
80
  }
73
81
 
74
- const result = utils.isRouter(device) && !utils.isBatteryPowered(device);
75
- return result;
82
+ return utils.isRouter(device) && !utils.isBatteryPowered(device);
76
83
  }
77
84
  return false;
78
85
  }
79
86
 
80
87
  async getAllPingableDevices() {
81
88
  const clients = await this.zigbee.getClients();
82
- return clients.filter((d) => this.isPingable(d));
89
+ return clients.filter(d => this.isPingable(d));
83
90
  }
84
91
 
85
92
  async registerDevicePing(device, entity) {
86
- this.debug('register device Ping for ' + JSON.stringify(device.ieeeAddr));
93
+ this.debug(`register device Ping for ${JSON.stringify(device.ieeeAddr)}`);
87
94
  this.forcedNonPingable[device.ieeeAddr] = false;
88
95
  // this.warn(`Called registerDevicePing for '${device}' of '${entity}'`);
89
- if (!this.isPingable(device)) return;
96
+ if (!this.isPingable(device)) {
97
+ return;
98
+ }
90
99
  // 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; }`
91
101
  this.startDevicePingQueue.forEach(item => {
92
- if (item && item.device == device)
102
+ if (item && item.device == device) {
93
103
  return;
104
+ }
94
105
  });
95
106
  this.number_of_registered_devices++;
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);
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
+ }
102
113
  }
103
114
 
104
115
  async deregisterDevicePing(device) {
105
- this.info('deregister device Ping for deactivated device ' + JSON.stringify(device.ieeeAddr));
116
+ this.info(`deregister device Ping for deactivated device ${JSON.stringify(device.ieeeAddr)}`);
106
117
  this.forcedNonPingable[device.ieeeAddr] = true;
107
118
  if (this.timers[device.ieeeAddr]) {
108
119
  clearTimeout(this.timers[device.ieeeAddr]);
@@ -113,15 +124,15 @@ class DeviceAvailability extends BaseExtension {
113
124
  // this.warn(JSON.stringify(this));
114
125
  this.startDevicePingTimeout = null;
115
126
  const item = this.startDevicePingQueue.shift();
116
- if (this.startDevicePingQueue.length >0) {
117
- this.startDevicePingTimeout = setTimeout(async() => {
118
- await this.startDevicePing();
119
- }, this.startDevicePingDelay);
127
+ if (this.startDevicePingQueue.length > 0) {
128
+ this.startDevicePingTimeout = setTimeout(async () =>
129
+ await this.startDevicePing(), this.startDevicePingDelay);
120
130
  }
121
131
  if (item && item.hasOwnProperty('device')) {
122
132
  this.handleIntervalPingable(item.device, item.entity);
123
133
  }
124
134
  }
135
+
125
136
  async onZigbeeStarted() {
126
137
  // As some devices are not checked for availability (e.g. battery powered devices)
127
138
  // we mark these device as online by default.
@@ -131,22 +142,20 @@ class DeviceAvailability extends BaseExtension {
131
142
  const clients = await this.zigbee.getClients();
132
143
  // this.warn('onZigbeeStarted called');
133
144
  for (const device of clients) {
134
-
135
145
  if (this.isPingable(device)) {
136
146
  // this.setTimerPingable(device);
137
147
  } else {
138
148
  // this.warn(`Setting '${device.ieeeAddr}' as available - battery driven`);
139
149
  this.publishAvailability(device, true);
140
- this.timers[device.ieeeAddr] = setInterval(() => {
141
- this.handleIntervalNotPingable(device);
142
- },utils.secondsToMilliseconds(this.availability_timeout));
150
+ this.timers[device.ieeeAddr] = setInterval(() =>
151
+ this.handleIntervalNotPingable(device), utils.secondsToMilliseconds(this.availability_timeout));
143
152
  }
144
153
  }
145
154
  }
146
155
 
147
156
  async handleIntervalPingable(device, entity) {
148
157
  const ieeeAddr = device.ieeeAddr;
149
- const resolvedEntity = (entity ? entity: await this.zigbee.resolveEntity(ieeeAddr));
158
+ const resolvedEntity = entity ? entity : await this.zigbee.resolveEntity(ieeeAddr);
150
159
  if (!resolvedEntity) {
151
160
  this.debug(`Stop pinging '${ieeeAddr}' ${device.modelID}, device is not known anymore`);
152
161
  return;
@@ -154,8 +163,8 @@ class DeviceAvailability extends BaseExtension {
154
163
  if (this.isPingable(device)) {
155
164
  let pingCount = this.ping_counters[device.ieeeAddr];
156
165
  if (pingCount === undefined) {
157
- this.ping_counters[device.ieeeAddr] = { failed: 0, reported: 0};
158
- pingCount = { failed: 0, reported: 0};
166
+ this.ping_counters[device.ieeeAddr] = {failed: 0, reported: 0};
167
+ pingCount = {failed: 0, reported: 0};
159
168
  }
160
169
 
161
170
  // first see if we can "ping" the device by reading a Status
@@ -170,8 +179,7 @@ class DeviceAvailability extends BaseExtension {
170
179
  return;
171
180
  }
172
181
  }
173
- }
174
- catch (error) {
182
+ } catch (error) {
175
183
  this.sendError(error);
176
184
  this.debug(`Exception in readState of '${device.ieeeAddr}' - error : '${error}'`);
177
185
  // intentionally empty: Just present to ensure we cause no harm
@@ -185,26 +193,22 @@ class DeviceAvailability extends BaseExtension {
185
193
  this.ping_counters[device.ieeeAddr].failed = 0;
186
194
  } catch (error) {
187
195
  this.publishAvailability(device, false);
188
- if (pingCount.failed++ <= this.max_ping)
189
- {
196
+ if (pingCount.failed++ <= this.max_ping) {
190
197
  if (pingCount.failed < 2 && pingCount.reported < this.max_ping) {
191
198
  this.warn(`Failed to ping ${ieeeAddr} ${device.modelID}`);
192
199
  pingCount.reported++;
193
- }
194
- else {
200
+ } else {
195
201
  this.debug(`Failed to ping ${ieeeAddr} ${device.modelID} on ${pingCount} consecutive attempts`);
196
202
  }
197
203
  this.setTimerPingable(device, pingCount.failed);
198
- this.ping_counters[device.ieeeAddr]= pingCount;
199
- }
200
- else {
204
+ this.ping_counters[device.ieeeAddr] = pingCount;
205
+ } else {
201
206
  this.warn(`Stopping to ping ${ieeeAddr} ${device.modelID} after ${pingCount.failed} ping attempts`);
202
207
  }
203
208
  }
204
209
  }
205
210
  }
206
211
 
207
-
208
212
  async handleIntervalNotPingable(device) {
209
213
  const entity = await this.zigbee.resolveEntity(device.ieeeAddr);
210
214
  if (!entity || !device.lastSeen) {
@@ -220,13 +224,14 @@ class DeviceAvailability extends BaseExtension {
220
224
  }
221
225
 
222
226
  setTimerPingable(device, factor) {
223
- if (factor === undefined || factor < 1) factor = 1;
227
+ if (factor === undefined || factor < 1) {
228
+ factor = 1;
229
+ }
224
230
  if (this.timers[device.ieeeAddr]) {
225
231
  clearTimeout(this.timers[device.ieeeAddr]);
226
232
  }
227
- this.timers[device.ieeeAddr] = setTimeout(async() => {
228
- await this.handleIntervalPingable(device);
229
- }, utils.secondsToMilliseconds(this.availability_timeout * factor));
233
+ this.timers[device.ieeeAddr] = setTimeout(async () =>
234
+ await this.handleIntervalPingable(device), utils.secondsToMilliseconds(this.availability_timeout * factor));
230
235
  }
231
236
 
232
237
  async stop() {
@@ -234,7 +239,7 @@ class DeviceAvailability extends BaseExtension {
234
239
  clearTimeout(timer);
235
240
  }
236
241
  const clients = await this.zigbee.getClients();
237
- clients.forEach((device) => this.publishAvailability(device, false));
242
+ clients.forEach(device => this.publishAvailability(device, false));
238
243
  }
239
244
 
240
245
  async onReconnect(device) {
@@ -269,8 +274,8 @@ class DeviceAvailability extends BaseExtension {
269
274
  const payload = {available: available};
270
275
  this.debug(`Publish available for ${ieeeAddr} = ${available}`);
271
276
  this.zigbee.emit('publish', ieeeAddr.substr(2), entity.mapped.model, payload);
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) });
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)});
274
279
  }
275
280
  }
276
281
  }
@@ -289,23 +294,22 @@ class DeviceAvailability extends BaseExtension {
289
294
  this.setTimerPingable(device, 1);
290
295
  const pc = this.ping_counters[device.ieeeAddr];
291
296
  if (pc == undefined) {
292
- this.ping_counters[device.ieeeAddr] = { failed:0, reported:0 };
293
- }
294
- else {
297
+ this.ping_counters[device.ieeeAddr] = {failed: 0, reported: 0};
298
+ } else {
295
299
  this.ping_counters[device.ieeeAddr].failed++;
296
300
  }
297
301
 
298
302
  const online = this.state.hasOwnProperty(device.ieeeAddr) && this.state[device.ieeeAddr];
299
303
  if (online && data.type === 'deviceAnnounce' && !utils.isIkeaTradfriDevice(device)) {
300
304
  /**
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
- */
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
+ */
309
313
  this.onReconnect(device);
310
314
  }
311
315
  }
@@ -10,20 +10,17 @@ const forcedConfigureOnEachStart = [
10
10
  zigbeeHerdsmanConverters.devices.find((d) => d.model === 'ZK03840')
11
11
  ];
12
12
 
13
-
14
-
15
13
  class DeviceConfigure extends BaseExtension {
16
14
  constructor(zigbee, options) {
17
15
  super(zigbee, options);
18
16
 
19
17
  this.configuring = new Set();
20
18
  this.attempts = {};
21
- this.name = "DeviceConfigure";
19
+ this.name = 'DeviceConfigure';
22
20
  }
23
21
 
24
22
  setOptions(options) {
25
- if (typeof(options) != 'object') return false;
26
- return true;
23
+ return typeof options === 'object';
27
24
  }
28
25
 
29
26
  shouldConfigure(device, mappedDevice) {
@@ -37,11 +34,8 @@ class DeviceConfigure extends BaseExtension {
37
34
  zigbeeHerdsmanConverters.getConfigureKey(mappedDevice)) {
38
35
  return false;
39
36
  }
40
- if (device.interviewing === true) {
41
- return false;
42
- }
43
37
 
44
- return true;
38
+ return device.interviewing !== true;
45
39
  }
46
40
 
47
41
  async onZigbeeStarted() {
@@ -53,7 +47,7 @@ class DeviceConfigure extends BaseExtension {
53
47
 
54
48
  if (forcedConfigureOnEachStart.find((d) => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
55
49
  this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} forced by adapter config`);
56
- device.meta.configured = -1; // Force a reconfigure for this device
50
+ device.meta.configured = -1; // Force a reconfiguration for this device
57
51
  }
58
52
  if (this.shouldConfigure(device, mappedDevice)) {
59
53
  this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} needed`);
@@ -64,9 +58,7 @@ class DeviceConfigure extends BaseExtension {
64
58
  }
65
59
  } catch (error) {
66
60
  this.sendError(error);
67
- this.error(
68
- `Failed to DeviceConfigure.onZigbeeStarted (${error.stack})`,
69
- );
61
+ this.error(`Failed to DeviceConfigure.onZigbeeStarted (${error.stack})`);
70
62
  }
71
63
  }
72
64
 
@@ -78,13 +70,11 @@ class DeviceConfigure extends BaseExtension {
78
70
  }
79
71
  } catch (error) {
80
72
  this.sendError(error);
81
- this.error(
82
- `Failed to DeviceConfigure.onZigbeeEvent (${error.stack})`,
83
- );
73
+ this.error(`Failed to DeviceConfigure.onZigbeeEvent (${error.stack})`);
84
74
  }
85
75
  }
86
76
 
87
- onDeviceRemove(device){
77
+ onDeviceRemove(device) {
88
78
  try {
89
79
  if (this.configuring.has(device.ieeeAddr)) {
90
80
  this.configuring.delete(device.ieeeAddr);
@@ -95,13 +85,11 @@ class DeviceConfigure extends BaseExtension {
95
85
  }
96
86
  } catch (error) {
97
87
  this.sendError(error);
98
- this.error(
99
- `Failed to DeviceConfigure.onDeviceRemove (${error.stack})`,
100
- );
88
+ this.error(`Failed to DeviceConfigure.onDeviceRemove (${error.stack})`);
101
89
  }
102
90
  }
103
91
 
104
- onDeviceLeave(data, entity){
92
+ onDeviceLeave(data, entity) {
105
93
  if (entity) {
106
94
  this.onDeviceRemove(entity.device);
107
95
  } else {
@@ -6,10 +6,9 @@ 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
-
13
12
  async onZigbeeStarted() {
14
13
  for (const device of await this.zigbee.getClients()) {
15
14
  this.callOnEvent(device, 'start', {});
@@ -17,8 +16,8 @@ class DeviceEvent extends BaseExtension {
17
16
  }
18
17
 
19
18
  setOptions(options) {
20
- if (typeof(options) != 'object') return false;
21
- return true;
19
+ return typeof options === 'object';
20
+
22
21
  }
23
22
 
24
23
  onZigbeeEvent(data, mappedDevice) {