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/LICENSE +1 -1
- package/README.md +20 -245
- package/io-package.json +54 -55
- package/lib/check.js +6 -0
- package/lib/colors.js +26 -6
- package/lib/deviceController.js +69 -17
- package/lib/exposes.js +123 -157
- package/lib/imageController.js +52 -3
- package/lib/messages.js +10 -0
- package/lib/mqttServerController.js +21 -5
- package/lib/nonGenericDevicesExtension.js +6 -2
- package/lib/rgb.js +81 -27
- package/lib/statesController.js +62 -11
- package/lib/utils.js +54 -7
- package/lib/websocketController.js +29 -0
- package/lib/z2mController.js +19 -0
- package/main.js +8 -10
- package/package.json +16 -31
package/lib/imageController.js
CHANGED
|
@@ -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)
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
`
|
|
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
|
-
|
|
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
|
-
`
|
|
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.
|
|
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
|
-
}
|
|
43
|
+
}
|
|
40
44
|
return [];
|
|
41
|
-
|
|
45
|
+
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
module.exports = {
|
package/lib/rgb.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
61
|
+
|
|
58
62
|
const X = (Y / y) * x;
|
|
59
|
-
|
|
63
|
+
|
|
60
64
|
const Z = (Y / y) * z;
|
|
61
65
|
|
|
62
66
|
//Convert to RGB using Wide RGB D65 conversion
|
|
63
|
-
|
|
67
|
+
|
|
64
68
|
let red = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
|
|
65
|
-
|
|
69
|
+
|
|
66
70
|
let green = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
|
|
67
|
-
|
|
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
|
-
*
|
|
113
|
-
* @param {
|
|
114
|
-
* @param {
|
|
115
|
-
* @
|
|
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
|
-
|
|
137
|
+
|
|
133
138
|
if (isNaN(x)) {
|
|
134
|
-
|
|
139
|
+
|
|
135
140
|
x = 0;
|
|
136
141
|
}
|
|
137
142
|
|
|
138
|
-
|
|
143
|
+
|
|
139
144
|
if (isNaN(y)) {
|
|
140
|
-
|
|
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
|
-
|
|
220
|
-
|
|
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
|
-
|
|
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'))
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
}
|
|
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
|
}
|
package/lib/statesController.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
155
|
+
await this.setStateWithTimeoutAsync(stateName, gettr, 450);
|
|
139
156
|
} else {
|
|
140
|
-
await this.setStateSafelyAsync(stateName,
|
|
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]);
|