iobroker.zigbee2mqtt 3.0.9 → 3.0.13

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.
@@ -1,23 +1,42 @@
1
1
  const axios = require('axios').default;
2
2
  const sharp = require('sharp');
3
3
 
4
+ /**
5
+ *
6
+ */
4
7
  class ImageController {
8
+ /**
9
+ *
10
+ * @param adapter
11
+ */
5
12
  constructor(adapter) {
6
13
  this.adapter = adapter;
7
14
  }
8
15
 
16
+ /**
17
+ *
18
+ * @param modelName
19
+ */
9
20
  sanitizeModelIDForImageUrl(modelName) {
10
21
  const modelNameString = modelName.replace('/', '_');
11
22
  // eslint-disable-next-line no-control-regex
12
23
  return modelNameString.replace(/\u0000/g, '');
13
24
  }
14
25
 
26
+ /**
27
+ *
28
+ * @param deviceName
29
+ */
15
30
  sanitizeZ2MDeviceName(deviceName) {
16
31
  const deviceNameString = deviceName.replace(/:|\s|\//g, '-');
17
32
  // eslint-disable-next-line no-control-regex
18
33
  return deviceName ? deviceNameString.replace(/\u0000/g, '') : 'NA';
19
34
  }
20
35
 
36
+ /**
37
+ *
38
+ * @param device
39
+ */
21
40
  getZ2mDeviceImageModelJPG(device) {
22
41
  if (device && device.definition && device.definition.model) {
23
42
  const icoString = `https://www.zigbee2mqtt.io/images/devices/${this.sanitizeZ2MDeviceName(device.definition.model)}.jpg`;
@@ -26,6 +45,10 @@ class ImageController {
26
45
  }
27
46
  }
28
47
 
48
+ /**
49
+ *
50
+ * @param device
51
+ */
29
52
  getZ2mDeviceImageModelPNG(device) {
30
53
  if (device && device.definition && device.definition.model) {
31
54
  const icoString = `https://www.zigbee2mqtt.io/images/devices/${this.sanitizeZ2MDeviceName(device.definition.model)}.png`;
@@ -35,6 +58,10 @@ class ImageController {
35
58
  }
36
59
 
37
60
 
61
+ /**
62
+ *
63
+ * @param device
64
+ */
38
65
  getSlsDeviceImage(device) {
39
66
  if (device && device.model_id) {
40
67
  const icoString = `https://www.zigbee2mqtt.io/images/devices/${this.sanitizeModelIDForImageUrl(device.model_id)}.png`;
@@ -43,8 +70,14 @@ class ImageController {
43
70
  }
44
71
  }
45
72
 
73
+ /**
74
+ *
75
+ * @param device
76
+ */
46
77
  async getDeviceIcon(device) {
47
- if (!this.adapter.config.useDeviceIcons) return '';
78
+ if (!this.adapter.config.useDeviceIcons) {
79
+ return '';
80
+ }
48
81
 
49
82
  const imageSize = this.adapter.config.deviceIconsSize;
50
83
 
@@ -78,7 +111,7 @@ class ImageController {
78
111
  if (!iconFound) {
79
112
  this.adapter.log.warn(`Failed to download image for device model: ${device.definition.model} - ${device.definition.description}`);
80
113
  return '';
81
- } else {
114
+ }
82
115
  // Load image from the Meta-Store
83
116
  const icon = await this.adapter.readFileAsync(this.adapter.namespace, iconFileName);
84
117
  // Load Image Metadata
@@ -106,8 +139,12 @@ class ImageController {
106
139
 
107
140
  // Create and output Base64
108
141
  return `data:image/png;base64,${icon.file.toString('base64')}`;
109
- }
142
+
110
143
  }
144
+ /**
145
+ *
146
+ * @param url
147
+ */
111
148
  getFileNameWithExtension(url) {
112
149
  const path = new URL(url).pathname;
113
150
  const filename = path.split('/').pop();
@@ -115,6 +152,12 @@ class ImageController {
115
152
  return filename.replace(/\u0000/g, '');
116
153
  }
117
154
 
155
+ /**
156
+ *
157
+ * @param adapter
158
+ * @param url
159
+ * @param namespace
160
+ */
118
161
  async downloadIcon(adapter, url, namespace) {
119
162
  try {
120
163
  const res = await axios.get(url, { responseType: 'arraybuffer' });
@@ -125,6 +168,12 @@ class ImageController {
125
168
  return false;
126
169
  }
127
170
  }
171
+ /**
172
+ *
173
+ * @param z2mIconFileNameJPG
174
+ * @param z2mIconFileNamePNG
175
+ * @param slsIconFileName
176
+ */
128
177
  async getExistingIconFileName(z2mIconFileNameJPG, z2mIconFileNamePNG, slsIconFileName) {
129
178
  if (await this.adapter.fileExistsAsync(this.adapter.namespace, z2mIconFileNameJPG)) {
130
179
  return z2mIconFileNameJPG;
package/lib/messages.js CHANGED
@@ -1,3 +1,8 @@
1
+ /**
2
+ *
3
+ * @param config
4
+ * @param log
5
+ */
1
6
  async function adapterInfo(config, log) {
2
7
  log.info('================================= Adapter Config =================================');
3
8
  log.info(`|| Zigbee2MQTT Frontend Scheme: ${config.webUIScheme}`);
@@ -41,6 +46,11 @@ async function adapterInfo(config, log) {
41
46
  log.info('==================================================================================');
42
47
  }
43
48
 
49
+ /**
50
+ *
51
+ * @param payload
52
+ * @param log
53
+ */
44
54
  async function zigbee2mqttInfo(payload, log) {
45
55
  log.info('============================ Zigbee2MQTT Information =============================');
46
56
  log.info(`|| Zigbee2MQTT Version: ${payload.version} `);
@@ -3,11 +3,21 @@ const Aedes = require('aedes');
3
3
  const net = require('net');
4
4
  let mqttServer;
5
5
 
6
+ /**
7
+ *
8
+ */
6
9
  class MqttServerController {
10
+ /**
11
+ *
12
+ * @param adapter
13
+ */
7
14
  constructor(adapter) {
8
15
  this.adapter = adapter;
9
16
  }
10
17
 
18
+ /**
19
+ *
20
+ */
11
21
  async createMQTTServer() {
12
22
  try {
13
23
  const NedbPersistence = require('aedes-persistence-nedb');
@@ -15,12 +25,12 @@ class MqttServerController {
15
25
  path: `${core.getAbsoluteInstanceDataDir(this.adapter)}/mqttData`,
16
26
  prefix: '',
17
27
  });
18
- // @ts-ignore
28
+
19
29
  const aedes = Aedes({ persistence: db });
20
30
  mqttServer = net.createServer(aedes.handle);
21
31
  mqttServer.listen(this.adapter.config.mqttServerPort, this.adapter.config.mqttServerIPBind, () => {
22
32
  this.adapter.log.info(
23
- `Statring MQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`
33
+ `Starting MQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`
24
34
  );
25
35
  });
26
36
  } catch (err) {
@@ -28,14 +38,17 @@ class MqttServerController {
28
38
  }
29
39
  }
30
40
 
41
+ /**
42
+ *
43
+ */
31
44
  async createDummyMQTTServer() {
32
45
  try {
33
- // @ts-ignore
46
+
34
47
  const aedes = Aedes();
35
48
  mqttServer = net.createServer(aedes.handle);
36
49
  mqttServer.listen(this.adapter.config.mqttServerPort, this.adapter.config.mqttServerIPBind, () => {
37
50
  this.adapter.log.info(
38
- `Statring DummyMQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`
51
+ `Starting DummyMQTT-Server on IP ${this.adapter.config.mqttServerIPBind} and Port ${this.adapter.config.mqttServerPort}`
39
52
  );
40
53
  });
41
54
  } catch (err) {
@@ -43,8 +56,11 @@ class MqttServerController {
43
56
  }
44
57
  }
45
58
 
59
+ /**
60
+ *
61
+ */
46
62
  closeServer() {
47
- if (mqttServer && !mqttServer.closed()) {
63
+ if (mqttServer && !mqttServer.close()) {
48
64
  mqttServer.close();
49
65
  }
50
66
  }
@@ -32,13 +32,17 @@ const nonGenDevStatesDefs = {
32
32
  ],
33
33
  };
34
34
 
35
+ /**
36
+ *
37
+ * @param model
38
+ */
35
39
  function getStateDefinition(model) {
36
40
  const stateDef = nonGenDevStatesDefs[model];
37
41
  if (stateDef) {
38
42
  return stateDef;
39
- } else {
43
+ }
40
44
  return [];
41
- }
45
+
42
46
  }
43
47
 
44
48
  module.exports = {
package/lib/rgb.js CHANGED
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-prototype-builtins */
1
+
2
2
  /*
3
3
  With these functions you can convert the CIE color space to the RGB color space and vice versa.
4
4
 
@@ -44,7 +44,11 @@ const colors = require('./colors.js');
44
44
 
45
45
  /**
46
46
  * Converts CIE color space to RGB color space
47
- * @return {Array} Array that contains the color values for red, green and blue
47
+ *
48
+ * @param x
49
+ * @param y
50
+ * @param brightness
51
+ * @returns {Array} Array that contains the color values for red, green and blue
48
52
  */
49
53
  function cie_to_rgb(x, y, brightness) {
50
54
  //Set to maximum brightness if no custom value was given (Not the slick ECMAScript 6 way for compatibility reasons)
@@ -54,17 +58,17 @@ function cie_to_rgb(x, y, brightness) {
54
58
 
55
59
  const z = 1.0 - x - y;
56
60
  const Y = (brightness / 254).toFixed(2);
57
- // @ts-ignore
61
+
58
62
  const X = (Y / y) * x;
59
- // @ts-ignore
63
+
60
64
  const Z = (Y / y) * z;
61
65
 
62
66
  //Convert to RGB using Wide RGB D65 conversion
63
- // @ts-ignore
67
+
64
68
  let red = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
65
- // @ts-ignore
69
+
66
70
  let green = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
67
- // @ts-ignore
71
+
68
72
  let blue = X * 0.051713 - Y * 0.121364 + Z * 1.01153;
69
73
 
70
74
  //If red, green or blue is larger than 1.0 set it back to the maximum of 1.0
@@ -109,10 +113,11 @@ function cie_to_rgb(x, y, brightness) {
109
113
 
110
114
  /**
111
115
  * Converts RGB color space to CIE color space
112
- * @param {Number} red
113
- * @param {Number} green
114
- * @param {Number} blue
115
- * @return {Array} Array that contains the CIE color values for x and y
116
+ *
117
+ * @param {number} red
118
+ * @param {number} green
119
+ * @param {number} blue
120
+ * @returns {Array} Array that contains the CIE color values for x and y
116
121
  */
117
122
  function rgb_to_cie(red, green, blue) {
118
123
  // Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
@@ -129,21 +134,27 @@ function rgb_to_cie(red, green, blue) {
129
134
  let x = (X / (X + Y + Z)).toFixed(4);
130
135
  let y = (Y / (X + Y + Z)).toFixed(4);
131
136
 
132
- // @ts-ignore
137
+
133
138
  if (isNaN(x)) {
134
- // @ts-ignore
139
+
135
140
  x = 0;
136
141
  }
137
142
 
138
- // @ts-ignore
143
+
139
144
  if (isNaN(y)) {
140
- // @ts-ignore
145
+
141
146
  y = 0;
142
147
  }
143
148
 
144
149
  return [x, y];
145
150
  }
146
151
 
152
+ /**
153
+ *
154
+ * @param h
155
+ * @param s
156
+ * @param v
157
+ */
147
158
  function hsvToRGB(h, s, v) {
148
159
  h = (h % 360) / 360;
149
160
  s = s / 100;
@@ -187,6 +198,13 @@ function hsvToRGB(h, s, v) {
187
198
  };
188
199
  }
189
200
 
201
+ /**
202
+ *
203
+ * @param r
204
+ * @param g
205
+ * @param b
206
+ * @param numeric
207
+ */
190
208
  function rgbToHSV(r, g, b, numeric) {
191
209
  if (arguments.length === 1) {
192
210
  (g = r.g), (b = r.b), (r = r.r);
@@ -215,21 +233,26 @@ function rgbToHSV(r, g, b, numeric) {
215
233
  h /= 6 * d;
216
234
  break;
217
235
  }
218
- if (numeric)
219
- return {
220
- // @ts-ignore
236
+ if (numeric) {
237
+ return {
238
+
221
239
  h: Math.round(h * 360),
222
240
  s: Math.round(s * 100),
223
241
  v: Math.round(v * 100),
224
242
  };
243
+ }
225
244
  return {
226
- // @ts-ignore
245
+
227
246
  h: (h * 360).toFixed(3),
228
247
  s: (s * 100).toFixed(3),
229
248
  v: (v * 100).toFixed(3),
230
249
  };
231
250
  }
232
251
 
252
+ /**
253
+ *
254
+ * @param value
255
+ */
233
256
  function colorArrayFromString(value) {
234
257
  if (typeof value === 'string') {
235
258
  const rv = [];
@@ -241,6 +264,10 @@ function colorArrayFromString(value) {
241
264
  return [{ r: 0, g: 128, b: 255 }];
242
265
  }
243
266
 
267
+ /**
268
+ *
269
+ * @param payload
270
+ */
244
271
  function colorStringFromRGBArray(payload) {
245
272
  const rv = [];
246
273
  payload.forEach((element) => {
@@ -249,6 +276,12 @@ function colorStringFromRGBArray(payload) {
249
276
  return rv.toString();
250
277
  }
251
278
 
279
+ /**
280
+ *
281
+ * @param h
282
+ * @param s
283
+ * @param v
284
+ */
252
285
  function hsv_to_cie(h, s, v) {
253
286
  const rgb = hsvToRGB(h, s, v);
254
287
  return rgb_to_cie(rgb.r, rgb.g, rgb.b);
@@ -256,20 +289,35 @@ function hsv_to_cie(h, s, v) {
256
289
 
257
290
  function rgb_to_rgbstring(element) {
258
291
  let col = '#';
259
- if (element && element.hasOwnProperty('r')) col = col + element.r.toString(16).padStart(2, '0');
260
- else col = col + '00';
261
- if (element && element.hasOwnProperty('g')) col = col + element.g.toString(16).padStart(2, '0');
262
- else col = col + '00';
263
- if (element && element.hasOwnProperty('b')) col = col + element.b.toString(16).padStart(2, '0');
264
- else col = col + '00';
292
+ if (element && element.hasOwnProperty('r')) {
293
+ col = col + element.r.toString(16).padStart(2, '0');
294
+ } else {
295
+ col = `${col }00`;
296
+ }
297
+ if (element && element.hasOwnProperty('g')) {
298
+ col = col + element.g.toString(16).padStart(2, '0');
299
+ } else {
300
+ col = `${col }00`;
301
+ }
302
+ if (element && element.hasOwnProperty('b')) {
303
+ col = col + element.b.toString(16).padStart(2, '0');
304
+ } else {
305
+ col = `${col }00`;
306
+ }
265
307
  return col;
266
308
  }
267
309
 
310
+ /**
311
+ *
312
+ * @param h
313
+ * @param s
314
+ * @param b
315
+ */
268
316
  function hsbToRGB(h, s, b) {
269
317
  const br = Math.round(b * 2.55);
270
318
  if (s == 0) {
271
319
  return [br, br, br];
272
- } else {
320
+ }
273
321
  const hue = h % 360;
274
322
  const f = hue % 60;
275
323
  const p = Math.round(b * (100 - s) * 0.0255);
@@ -289,10 +337,16 @@ function hsbToRGB(h, s, b) {
289
337
  case 5:
290
338
  return [br, p, q];
291
339
  }
292
- }
340
+
293
341
  return false;
294
342
  }
295
343
 
344
+ /**
345
+ *
346
+ * @param h
347
+ * @param s
348
+ * @param v
349
+ */
296
350
  function hsvToRGBString(h, s, v) {
297
351
  return rgb_to_rgbstring(hsvToRGB(h, s, v));
298
352
  }
@@ -2,7 +2,18 @@ const utils = require('./utils');
2
2
  const incStatsQueue = [];
3
3
  const timeOutCache = {};
4
4
 
5
+ /**
6
+ *
7
+ */
5
8
  class StatesController {
9
+ /**
10
+ *
11
+ * @param adapter
12
+ * @param deviceCache
13
+ * @param groupCache
14
+ * @param logCustomizations
15
+ * @param createCache
16
+ */
6
17
  constructor(adapter, deviceCache, groupCache, logCustomizations, createCache) {
7
18
  this.adapter = adapter;
8
19
  this.groupCache = groupCache;
@@ -11,6 +22,10 @@ class StatesController {
11
22
  this.createCache = createCache;
12
23
  }
13
24
 
25
+ /**
26
+ *
27
+ * @param messageObj
28
+ */
14
29
  processDeviceMessage(messageObj) {
15
30
  // Is payload present?
16
31
  if (messageObj.payload == '') {
@@ -30,6 +45,11 @@ class StatesController {
30
45
  }
31
46
  }
32
47
 
48
+ /**
49
+ *
50
+ * @param messageObj
51
+ * @param device
52
+ */
33
53
  async setDeviceStateSafely(messageObj, device) {
34
54
  if (this.logCustomizations.debugDevices.includes(device.ieee_address)) {
35
55
  this.adapter.log.warn(`--->>> fromZ2M -> ${device.ieee_address} states: ${JSON.stringify(messageObj)}`);
@@ -103,19 +123,15 @@ class StatesController {
103
123
  // Is an action
104
124
  if (state.prop && state.prop == 'action') {
105
125
  actionStates.push(state);
106
- }
107
- // Is not an action
126
+ } else if (
127
+ // Is not an action
108
128
  // check if its a motion sensor (occupancy state) and if configuration is set to update state every time
109
129
  // if yes, use setStateSafelyAsync instead of setStateChangedSafelyAsync
110
- else if (
111
- this.adapter.config.allwaysUpdateOccupancyState === true &&
112
- state.id === 'occupancy' &&
113
- value === true
130
+ this.adapter.config.allwaysUpdateOccupancyState === true && state.id === 'occupancy' && value === true
114
131
  ) {
115
132
  await this.setStateSafelyAsync(stateName, value);
116
- }
117
- // end section for motion sensor update
118
- else {
133
+ } else {
134
+ // end section for motion sensor update
119
135
  if (state.getter) {
120
136
  await this.setStateChangedSafelyAsync(stateName, state.getter(messageObj.payload));
121
137
  } else {
@@ -134,11 +150,17 @@ class StatesController {
134
150
 
135
151
  try {
136
152
  if (state.isEvent && state.isEvent == true) {
153
+ const gettr = state.getter(messageObj.payload);
137
154
  if (state.type == 'boolean') {
138
- await this.setStateWithTimeoutAsync(stateName, state.getter(messageObj.payload), 450);
155
+ await this.setStateWithTimeoutAsync(stateName, gettr, 450);
139
156
  } else {
140
- await this.setStateSafelyAsync(stateName, state.getter(messageObj.payload));
157
+ await this.setStateSafelyAsync(stateName, gettr);
141
158
  }
159
+ // publish the action into action dp
160
+ if (state.prop && state.prop == 'action') {
161
+ await this.setStateSafelyAsync(`${device.ieee_address}.action`, messageObj.payload.action);
162
+ }
163
+
142
164
  } else {
143
165
  await this.setStateChangedSafelyAsync(stateName, state.getter(messageObj.payload));
144
166
  }
@@ -149,6 +171,11 @@ class StatesController {
149
171
  }
150
172
  }
151
173
 
174
+ /**
175
+ *
176
+ * @param stateName
177
+ * @param value
178
+ */
152
179
  async setStateSafelyAsync(stateName, value) {
153
180
  if (value === undefined || value === null) {
154
181
  return;
@@ -156,6 +183,11 @@ class StatesController {
156
183
  await this.adapter.setStateAsync(stateName, value, true);
157
184
  }
158
185
 
186
+ /**
187
+ *
188
+ * @param stateName
189
+ * @param value
190
+ */
159
191
  async setStateChangedSafelyAsync(stateName, value) {
160
192
  if (value === undefined || value === null) {
161
193
  return;
@@ -163,6 +195,12 @@ class StatesController {
163
195
  await this.adapter.setStateChangedAsync(stateName, value, true);
164
196
  }
165
197
 
198
+ /**
199
+ *
200
+ * @param stateName
201
+ * @param value
202
+ * @param timeout
203
+ */
166
204
  async setStateWithTimeoutAsync(stateName, value, timeout) {
167
205
  if (value === undefined || value === null) {
168
206
  return;
@@ -174,9 +212,13 @@ class StatesController {
174
212
  }
175
213
  timeOutCache[stateName] = setTimeout(() => {
176
214
  this.adapter.setStateAsync(stateName, !value, true);
215
+
177
216
  }, timeout);
178
217
  }
179
218
 
219
+ /**
220
+ *
221
+ */
180
222
  processQueue() {
181
223
  const oldIncStatsQueue = [];
182
224
  utils.moveArray(incStatsQueue, oldIncStatsQueue);
@@ -185,6 +227,9 @@ class StatesController {
185
227
  }
186
228
  }
187
229
 
230
+ /**
231
+ *
232
+ */
188
233
  async subscribeWritableStates() {
189
234
  await this.adapter.unsubscribeObjectsAsync('*');
190
235
  for (const device of this.groupCache.concat(this.deviceCache)) {
@@ -199,6 +244,9 @@ class StatesController {
199
244
  this.adapter.subscribeStates('info.coordinator_check');
200
245
  }
201
246
 
247
+ /**
248
+ *
249
+ */
202
250
  async setAllAvailableToFalse() {
203
251
  const availableStates = await this.adapter.getStatesAsync('*.available');
204
252
  for (const availableState in availableStates) {
@@ -206,6 +254,9 @@ class StatesController {
206
254
  }
207
255
  }
208
256
 
257
+ /**
258
+ *
259
+ */
209
260
  async allTimerClear() {
210
261
  for (const timer in timeOutCache) {
211
262
  clearTimeout(timeOutCache[timer]);