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.
package/lib/utils.js CHANGED
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * Converts a bulb level of range [0...254] to an adapter level of range [0...100]
3
+ *
4
+ * @param bulbLevel
3
5
  */
4
6
  function bulbLevelToAdapterLevel(bulbLevel) {
5
7
  // Convert from bulb levels [0...254] to adapter levels [0...100]:
@@ -19,14 +21,16 @@ function bulbLevelToAdapterLevel(bulbLevel) {
19
21
  if (bulbLevel >= 2) {
20
22
  // Perform linear mapping of range [2...254] to [1...100]
21
23
  return Math.round(((bulbLevel - 2) * 99) / 252) + 1;
22
- } else {
24
+ }
23
25
  // The bulb is considered off. Even a bulb level of "1" is considered as off.
24
26
  return 0;
25
- } // else
27
+ // else
26
28
  }
27
29
 
28
30
  /**
29
31
  * Converts an adapter level of range [0...100] to a bulb level of range [0...254]
32
+ *
33
+ * @param adapterLevel
30
34
  */
31
35
  function adapterLevelToBulbLevel(adapterLevel) {
32
36
  // Convert from adapter levels [0...100] to bulb levels [0...254].
@@ -35,13 +39,17 @@ function adapterLevelToBulbLevel(adapterLevel) {
35
39
  if (adapterLevel) {
36
40
  // Perform linear mapping of range [1...100] to [2...254]
37
41
  return Math.round(((adapterLevel - 1) * 252) / 99) + 2;
38
- } else {
42
+ }
39
43
  // Switch the bulb off. Some bulbs need "0" (IKEA), others "1" (HUE), and according to the
40
44
  // ZigBee docs "1" is the "minimum possible level"... we choose "0" here which seems to work.
41
45
  return 0;
42
- } // else
46
+ // else
43
47
  }
44
48
 
49
+ /**
50
+ *
51
+ * @param ba
52
+ */
45
53
  function bytesArrayToWordArray(ba) {
46
54
  const wa = [];
47
55
  for (let i = 0; i < ba.length; i++) {
@@ -52,6 +60,10 @@ function bytesArrayToWordArray(ba) {
52
60
 
53
61
  // If the value is greater than 1000, kelvin is assumed.
54
62
  // If smaller, it is assumed to be mired.
63
+ /**
64
+ *
65
+ * @param t
66
+ */
55
67
  function toMired(t) {
56
68
  let miredValue = t;
57
69
  if (t > 1000) {
@@ -60,12 +72,19 @@ function toMired(t) {
60
72
  return miredValue;
61
73
  }
62
74
 
75
+ /**
76
+ *
77
+ * @param t
78
+ */
63
79
  function miredKelvinConversion(t) {
64
80
  return Math.round(1000000 / t);
65
81
  }
66
82
 
67
83
  /**
68
84
  * Converts a decimal number to a hex string with zero-padding
85
+ *
86
+ * @param decimal
87
+ * @param padding
69
88
  */
70
89
  function decimalToHex(decimal, padding) {
71
90
  let hex = Number(decimal).toString(16);
@@ -78,32 +97,60 @@ function decimalToHex(decimal, padding) {
78
97
  return hex;
79
98
  }
80
99
 
100
+ /**
101
+ *
102
+ * @param adapterDevId
103
+ */
81
104
  function getZbId(adapterDevId) {
82
105
  const idx = adapterDevId.indexOf('group');
83
- if (idx > 0) return adapterDevId.substr(idx + 6);
84
- return '0x' + adapterDevId.split('.')[2];
106
+ if (idx > 0) {
107
+ return adapterDevId.substr(idx + 6);
108
+ }
109
+ return `0x${ adapterDevId.split('.')[2]}`;
85
110
  }
86
111
 
112
+ /**
113
+ *
114
+ * @param adapter
115
+ * @param id
116
+ */
87
117
  function getAdId(adapter, id) {
88
- return adapter.namespace + '.' + id.split('.')[2]; // iobroker device id
118
+ return `${adapter.namespace }.${ id.split('.')[2]}`; // iobroker device id
89
119
  }
90
120
 
121
+ /**
122
+ *
123
+ * @param array
124
+ */
91
125
  function clearArray(array) {
92
126
  while (array.length > 0) {
93
127
  array.pop();
94
128
  }
95
129
  }
96
130
 
131
+ /**
132
+ *
133
+ * @param source
134
+ * @param target
135
+ */
97
136
  function moveArray(source, target) {
98
137
  while (source.length > 0) {
99
138
  target.push(source.shift());
100
139
  }
101
140
  }
102
141
 
142
+ /**
143
+ *
144
+ * @param item
145
+ */
103
146
  function isObject(item) {
104
147
  return typeof item === 'object' && !Array.isArray(item) && item !== null;
105
148
  }
106
149
 
150
+ /**
151
+ *
152
+ * @param item
153
+ */
107
154
  function isJson(item) {
108
155
  let value = typeof item !== 'string' ? JSON.stringify(item) : item;
109
156
  try {
@@ -6,11 +6,21 @@ let ping;
6
6
  let pingTimeout;
7
7
  let autoRestartTimeout;
8
8
 
9
+ /**
10
+ *
11
+ */
9
12
  class WebsocketController {
13
+ /**
14
+ *
15
+ * @param adapter
16
+ */
10
17
  constructor(adapter) {
11
18
  this.adapter = adapter;
12
19
  }
13
20
 
21
+ /**
22
+ *
23
+ */
14
24
  initWsClient() {
15
25
  try {
16
26
  let wsURL = `${this.adapter.config.wsScheme}://${this.adapter.config.wsServerIP}:${this.adapter.config.wsServerPort}/api`;
@@ -53,6 +63,10 @@ class WebsocketController {
53
63
  }
54
64
  }
55
65
 
66
+ /**
67
+ *
68
+ * @param message
69
+ */
56
70
  send(message) {
57
71
  if (wsClient.readyState !== WebSocket.OPEN) {
58
72
  this.adapter.log.warn('Cannot set State, no websocket connection to Zigbee2MQTT!');
@@ -61,6 +75,9 @@ class WebsocketController {
61
75
  wsClient.send(message);
62
76
  }
63
77
 
78
+ /**
79
+ *
80
+ */
64
81
  sendPingToServer() {
65
82
  //this.logDebug('Send ping to server');
66
83
  wsClient.ping();
@@ -69,6 +86,9 @@ class WebsocketController {
69
86
  }, wsHeartbeatIntervall);
70
87
  }
71
88
 
89
+ /**
90
+ *
91
+ */
72
92
  wsHeartbeat() {
73
93
  clearTimeout(pingTimeout);
74
94
  pingTimeout = setTimeout(() => {
@@ -77,6 +97,9 @@ class WebsocketController {
77
97
  }, wsHeartbeatIntervall + 3000);
78
98
  }
79
99
 
100
+ /**
101
+ *
102
+ */
80
103
  async autoRestart() {
81
104
  this.adapter.log.warn(`Start try again in ${restartTimeout / 1000} seconds...`);
82
105
  autoRestartTimeout = setTimeout(() => {
@@ -84,12 +107,18 @@ class WebsocketController {
84
107
  }, restartTimeout);
85
108
  }
86
109
 
110
+ /**
111
+ *
112
+ */
87
113
  closeConnection() {
88
114
  if (wsClient && wsClient.readyState !== WebSocket.CLOSED) {
89
115
  wsClient.close();
90
116
  }
91
117
  }
92
118
 
119
+ /**
120
+ *
121
+ */
93
122
  async allTimerClear() {
94
123
  clearTimeout(pingTimeout);
95
124
  clearTimeout(ping);
@@ -1,4 +1,14 @@
1
+ /**
2
+ *
3
+ */
1
4
  class Z2mController {
5
+ /**
6
+ *
7
+ * @param adapter
8
+ * @param deviceCache
9
+ * @param groupCache
10
+ * @param logCustomizations
11
+ */
2
12
  constructor(adapter, deviceCache, groupCache, logCustomizations) {
3
13
  this.adapter = adapter;
4
14
  this.groupCache = groupCache;
@@ -6,6 +16,11 @@ class Z2mController {
6
16
  this.logCustomizations = logCustomizations;
7
17
  }
8
18
 
19
+ /**
20
+ *
21
+ * @param id
22
+ * @param state
23
+ */
9
24
  async createZ2MMessage(id, state) {
10
25
  const splitedID = id.split('.');
11
26
  if (splitedID.length < 4) {
@@ -114,6 +129,10 @@ class Z2mController {
114
129
  return controlObj;
115
130
  }
116
131
 
132
+ /**
133
+ *
134
+ * @param messageObj
135
+ */
117
136
  async proxyZ2MLogs(messageObj) {
118
137
  const logMessage = messageObj.payload.message;
119
138
  if (this.logCustomizations.logfilter.some((x) => logMessage.includes(x))) {
package/main.js CHANGED
@@ -68,8 +68,7 @@ class Zigbee2mqtt extends core.Adapter {
68
68
  }
69
69
 
70
70
  const logfilterState = await this.getStateAsync('info.logfilter');
71
- if (logfilterState && logfilterState.val) {
72
- // @ts-ignore
71
+ if (logfilterState && logfilterState.val) {
73
72
  logCustomizations.logfilter = String(logfilterState.val)
74
73
  .split(';')
75
74
  .filter((x) => x); // filter removes empty strings here
@@ -111,9 +110,8 @@ class Zigbee2mqtt extends core.Adapter {
111
110
  `mqtt://${this.config.externalMqttServerIP}:${this.config.externalMqttServerPort}`,
112
111
  mqttClientOptions
113
112
  );
114
- }
113
+ } else {
115
114
  // Internal MQTT-Server
116
- else {
117
115
  mqttServerController = new MqttServerController(this);
118
116
  await mqttServerController.createMQTTServer();
119
117
  await this.delay(1500);
@@ -137,9 +135,8 @@ class Zigbee2mqtt extends core.Adapter {
137
135
  const newMessage = `{"payload":${payload.toString() == '' ? '"null"' : payload.toString()},"topic":"${topic.slice(topic.search('/') + 1)}"}`;
138
136
  this.messageParse(newMessage);
139
137
  });
140
- }
138
+ } else if (this.config.connectionType == 'ws') {
141
139
  // Websocket
142
- else if (this.config.connectionType == 'ws') {
143
140
  if (this.config.wsServerIP == '') {
144
141
  this.log.warn('Please configure the Websoket connection!');
145
142
  return;
@@ -316,9 +313,8 @@ class Zigbee2mqtt extends core.Adapter {
316
313
  } catch (e) {
317
314
  this.log.error(e);
318
315
  }
319
- }
316
+ } else if (this.config.connectionType == 'ws') {
320
317
  // Websocket
321
- else if (this.config.connectionType == 'ws') {
322
318
  try {
323
319
  if (websocketController) {
324
320
  websocketController.closeConnection();
@@ -352,6 +348,8 @@ class Zigbee2mqtt extends core.Adapter {
352
348
  this.log.error(e);
353
349
  }
354
350
 
351
+ this.setState('info.connection', false, true);
352
+
355
353
  callback();
356
354
  }
357
355
 
@@ -382,8 +380,8 @@ class Zigbee2mqtt extends core.Adapter {
382
380
  if (require.main !== module) {
383
381
  // Export the constructor in compact mode
384
382
  /**
385
- * @param {Partial<core.AdapterOptions>} [options={}]
386
- */
383
+ * @param {Partial<core.AdapterOptions>} [options]
384
+ */
387
385
  module.exports = (options) => new Zigbee2mqtt(options);
388
386
  } else {
389
387
  // otherwise start the instance directly
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee2mqtt",
3
- "version": "3.0.9",
3
+ "version": "3.0.13",
4
4
  "description": "Zigbee2MQTT adapter for ioBroker",
5
5
  "author": {
6
6
  "name": "Dennis Rathjen and Arthur Rupp",
@@ -24,43 +24,28 @@
24
24
  "node": ">= 20"
25
25
  },
26
26
  "dependencies": {
27
- "@iobroker/adapter-core": "^3.2.3",
27
+ "@iobroker/adapter-core": "^3.3.2",
28
28
  "@iobroker/dm-utils": "^1.0.10",
29
29
  "aedes": "^0.51.3",
30
30
  "aedes-persistence-nedb": "^2.0.3",
31
- "mqtt": "^5.10.4",
31
+ "mqtt": "^5.14.1",
32
32
  "net": "^1.0.2",
33
33
  "node-schedule": "^2.1.1",
34
- "sharp": "^0.33.5",
35
- "ws": "^8.18.2"
34
+ "sharp": "^0.34.5",
35
+ "ws": "^8.18.3"
36
36
  },
37
37
  "devDependencies": {
38
- "@alcalzone/release-script": "^3.8.0",
39
- "@alcalzone/release-script-plugin-iobroker": "^3.7.0",
40
- "@alcalzone/release-script-plugin-license": "^3.7.0",
41
- "@alcalzone/release-script-plugin-manual-review": "^3.7.0",
42
- "@iobroker/adapter-dev": "^1.4.0",
43
- "@iobroker/testing": "^5.0.4",
44
- "@tsconfig/node14": "^14.1.3",
45
- "@types/chai": "^5.2.2",
46
- "@types/chai-as-promised": "^8.0.2",
47
- "@types/mocha": "^10.0.10",
48
- "@types/node": "^22.15.29",
49
- "@types/node-schedule": "^2.1.7",
50
- "@types/proxyquire": "^1.3.31",
51
- "@types/sinon": "^17.0.3",
52
- "@types/sinon-chai": "^4.0.0",
53
- "chai": "^5.2.0",
54
- "chai-as-promised": "^8.0.1",
55
- "eslint": "^9.25.1",
56
- "eslint-config-prettier": "^10.1.5",
57
- "eslint-plugin-prettier": "^5.2.3",
58
- "mocha": "^11.0.1",
59
- "prettier": "^3.5.3",
60
- "proxyquire": "^2.1.3",
61
- "sinon": "^19.0.2",
62
- "sinon-chai": "^4.0.0",
63
- "typescript": "~5.8.2"
38
+ "@alcalzone/release-script": "^5.0.0",
39
+ "@alcalzone/release-script-plugin-iobroker": "^4.0.0",
40
+ "@alcalzone/release-script-plugin-license": "^4.0.0",
41
+ "@alcalzone/release-script-plugin-manual-review": "^4.0.0",
42
+ "@iobroker/adapter-dev": "^1.5.0",
43
+ "@iobroker/testing": "^5.2.2",
44
+ "@iobroker/eslint-config": "^2.1.0",
45
+ "@tsconfig/node14": "^14.1.8",
46
+ "@types/node": "^25.0.3",
47
+ "@types/node-schedule": "^2.1.8",
48
+ "typescript": "~5.9.2"
64
49
  },
65
50
  "main": "main.js",
66
51
  "files": [