iobroker.govee-local 0.2.7 → 0.2.9
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 +12 -1
- package/admin/jsonConfig.json +13 -1
- package/build/main.js +104 -47
- package/build/main.js.map +2 -2
- package/build/tools/hexTool.js +1 -1
- package/build/tools/hexTool.js.map +2 -2
- package/io-package.json +28 -15
- package/package.json +18 -21
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2025 Børge Grunicke <boerge@grunicke.de>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -24,6 +24,17 @@ For **Windows** Users: Please go to the settings and make sure you choose the co
|
|
|
24
24
|
Placeholder for the next version (at the beginning of the line):
|
|
25
25
|
### **WORK IN PROGRESS**
|
|
26
26
|
-->
|
|
27
|
+
### 0.2.9 (2025-08-22)
|
|
28
|
+
|
|
29
|
+
- update dependencies
|
|
30
|
+
- add support for node 24
|
|
31
|
+
- update to ESlint 9
|
|
32
|
+
|
|
33
|
+
### 0.2.8 (2025-03-28)
|
|
34
|
+
|
|
35
|
+
- update dependencies
|
|
36
|
+
- avoid repeated overriding of states
|
|
37
|
+
|
|
27
38
|
### 0.2.7 (2024-08-18)
|
|
28
39
|
|
|
29
40
|
- update core dependencies and min required node version to 18
|
|
@@ -97,7 +108,7 @@ For **Windows** Users: Please go to the settings and make sure you choose the co
|
|
|
97
108
|
|
|
98
109
|
MIT License
|
|
99
110
|
|
|
100
|
-
Copyright (c)
|
|
111
|
+
Copyright (c) 2025 Børge Grunicke
|
|
101
112
|
|
|
102
113
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
103
114
|
of this software and associated documentation files (the "Software"), to deal
|
package/admin/jsonConfig.json
CHANGED
|
@@ -4,27 +4,33 @@
|
|
|
4
4
|
"items": {
|
|
5
5
|
"_description": {
|
|
6
6
|
"type": "staticText",
|
|
7
|
+
"xs": 12,
|
|
7
8
|
"sm": 12,
|
|
8
9
|
"md": 12,
|
|
9
10
|
"lg": 12,
|
|
11
|
+
"xl": 12,
|
|
10
12
|
"text": "_configDescription"
|
|
11
13
|
},
|
|
12
14
|
"searchInterval": {
|
|
13
15
|
"type": "number",
|
|
14
16
|
"min": 1,
|
|
15
17
|
"max": 1000,
|
|
18
|
+
"xs": 12,
|
|
16
19
|
"sm": 6,
|
|
17
20
|
"md": 3,
|
|
18
21
|
"lg": 2,
|
|
22
|
+
"xl": 2,
|
|
19
23
|
"label": "_searchInterval"
|
|
20
24
|
},
|
|
21
25
|
"deviceStatusRefreshInterval": {
|
|
22
26
|
"type": "number",
|
|
23
27
|
"min": 1,
|
|
24
28
|
"max": 1000,
|
|
29
|
+
"xs": 12,
|
|
25
30
|
"sm": 6,
|
|
26
31
|
"md": 3,
|
|
27
32
|
"lg": 2,
|
|
33
|
+
"xl": 2,
|
|
28
34
|
"label": "_deviceStatusRefreshInterval"
|
|
29
35
|
},
|
|
30
36
|
"interface": {
|
|
@@ -33,22 +39,28 @@
|
|
|
33
39
|
"onlyIp4": true,
|
|
34
40
|
"label": "_networkInterface",
|
|
35
41
|
"newLine": true,
|
|
42
|
+
"xs": 12,
|
|
36
43
|
"sm": 12,
|
|
37
44
|
"md": 6,
|
|
38
|
-
"lg": 4
|
|
45
|
+
"lg": 4,
|
|
46
|
+
"xl": 4
|
|
39
47
|
},
|
|
40
48
|
"_descriptionExtendedLogging": {
|
|
41
49
|
"type": "staticText",
|
|
50
|
+
"xs": 12,
|
|
42
51
|
"sm": 12,
|
|
43
52
|
"md": 12,
|
|
44
53
|
"lg": 12,
|
|
54
|
+
"xl": 12,
|
|
45
55
|
"text": "_extendedLoggingDescription"
|
|
46
56
|
},
|
|
47
57
|
"extendedLogging": {
|
|
48
58
|
"type": "checkbox",
|
|
59
|
+
"xs": 12,
|
|
49
60
|
"sm": 12,
|
|
50
61
|
"md": 6,
|
|
51
62
|
"lg": 3,
|
|
63
|
+
"xl": 3,
|
|
52
64
|
"label": "_extendedLogging"
|
|
53
65
|
}
|
|
54
66
|
}
|
package/build/main.js
CHANGED
|
@@ -5,6 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
8
12
|
var __copyProps = (to, from, except, desc) => {
|
|
9
13
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
14
|
for (let key of __getOwnPropNames(from))
|
|
@@ -21,6 +25,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
25
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var main_exports = {};
|
|
30
|
+
__export(main_exports, {
|
|
31
|
+
GoveeLocal: () => GoveeLocal,
|
|
32
|
+
getDatapointDescription: () => getDatapointDescription
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(main_exports);
|
|
24
35
|
var utils = __toESM(require("@iobroker/adapter-core"));
|
|
25
36
|
var dgram = __toESM(require("node:dgram"));
|
|
26
37
|
var import_hexTool = require("./tools/hexTool");
|
|
@@ -49,7 +60,7 @@ class GoveeLocal extends utils.Adapter {
|
|
|
49
60
|
* Is called when databases are connected and adapter received configuration.
|
|
50
61
|
*/
|
|
51
62
|
async onReady() {
|
|
52
|
-
this.setObjectNotExists("info.connection", {
|
|
63
|
+
void this.setObjectNotExists("info.connection", {
|
|
53
64
|
type: "state",
|
|
54
65
|
common: {
|
|
55
66
|
name: "Device discovery running",
|
|
@@ -62,14 +73,15 @@ class GoveeLocal extends utils.Adapter {
|
|
|
62
73
|
});
|
|
63
74
|
socket.on("message", this.onUdpMessage.bind(this));
|
|
64
75
|
socket.on("error", (error) => {
|
|
65
|
-
this.log.error(
|
|
66
|
-
this.setStateChanged("info.connection", { val: false, ack: true });
|
|
76
|
+
this.log.error(`server bind error : ${error.message}`);
|
|
77
|
+
void this.setStateChanged("info.connection", { val: false, ack: true });
|
|
67
78
|
});
|
|
68
79
|
if (this.config.extendedLogging) {
|
|
69
80
|
this.log.debug("running with extended logging");
|
|
70
81
|
}
|
|
71
|
-
socket.bind({ address: this.config.interface, port: LOCAL_PORT }, this.serverBound.bind(this));
|
|
72
|
-
this.subscribeStates("*.devStatus.*");
|
|
82
|
+
void socket.bind({ address: this.config.interface, port: LOCAL_PORT }, this.serverBound.bind(this));
|
|
83
|
+
void this.subscribeStates("*.devStatus.*");
|
|
84
|
+
return Promise.resolve();
|
|
73
85
|
}
|
|
74
86
|
/**
|
|
75
87
|
* handles when udp socket is up
|
|
@@ -81,8 +93,8 @@ class GoveeLocal extends utils.Adapter {
|
|
|
81
93
|
socket.setMulticastTTL(128);
|
|
82
94
|
socket.setMulticastInterface(this.config.interface);
|
|
83
95
|
socket.addMembership(M_CAST);
|
|
84
|
-
this.setStateChanged("info.connection", { val: true, ack: true });
|
|
85
|
-
this.log.debug(
|
|
96
|
+
void this.setStateChanged("info.connection", { val: true, ack: true });
|
|
97
|
+
this.log.debug(`UDP listening on ${socket.address().address}:${socket.address().port}`);
|
|
86
98
|
const deviceSearchInterval = this.setInterval(this.sendScan.bind(this), this.config.searchInterval * 1e3);
|
|
87
99
|
if (deviceSearchInterval) {
|
|
88
100
|
searchInterval = deviceSearchInterval;
|
|
@@ -94,21 +106,23 @@ class GoveeLocal extends utils.Adapter {
|
|
|
94
106
|
if (deviceRefreshInterval) {
|
|
95
107
|
refreshInterval = deviceRefreshInterval;
|
|
96
108
|
}
|
|
109
|
+
return Promise.resolve();
|
|
97
110
|
}
|
|
98
111
|
/**
|
|
99
112
|
* handle icoming messages on the udp socket
|
|
113
|
+
*
|
|
100
114
|
* @param message the message itself
|
|
101
115
|
* @param remote the sender of the message
|
|
102
116
|
*/
|
|
103
117
|
async onUdpMessage(message, remote) {
|
|
104
118
|
const messageObject = JSON.parse(message.toString());
|
|
105
119
|
switch (messageObject.msg.cmd) {
|
|
106
|
-
case "scan":
|
|
120
|
+
case "scan": {
|
|
107
121
|
for (const key of Object.keys(messageObject.msg.data)) {
|
|
108
122
|
if (key != "device") {
|
|
109
123
|
const deviceName = messageObject.msg.data.device.replace(this.FORBIDDEN_CHARS, "_");
|
|
110
124
|
devices[remote.address] = deviceName;
|
|
111
|
-
this.setObjectNotExists(deviceName, {
|
|
125
|
+
void this.setObjectNotExists(deviceName, {
|
|
112
126
|
type: "device",
|
|
113
127
|
common: {
|
|
114
128
|
name: messageObject.msg.data.sku,
|
|
@@ -116,7 +130,7 @@ class GoveeLocal extends utils.Adapter {
|
|
|
116
130
|
},
|
|
117
131
|
native: {}
|
|
118
132
|
});
|
|
119
|
-
this.setObjectNotExists(`${deviceName}.deviceInfo.${key}`, {
|
|
133
|
+
void this.setObjectNotExists(`${deviceName}.deviceInfo.${key}`, {
|
|
120
134
|
type: "state",
|
|
121
135
|
common: {
|
|
122
136
|
name: getDatapointDescription(key),
|
|
@@ -127,14 +141,12 @@ class GoveeLocal extends utils.Adapter {
|
|
|
127
141
|
},
|
|
128
142
|
native: {}
|
|
129
143
|
});
|
|
130
|
-
this.
|
|
131
|
-
val: messageObject.msg.data[key],
|
|
132
|
-
ack: true
|
|
133
|
-
});
|
|
144
|
+
void this.updateStateAsync(`${deviceName}.deviceInfo.${key}`, messageObject.msg.data[key]);
|
|
134
145
|
}
|
|
135
146
|
}
|
|
136
147
|
break;
|
|
137
|
-
|
|
148
|
+
}
|
|
149
|
+
case "devStatus": {
|
|
138
150
|
const sendingDevice = devices[remote.address];
|
|
139
151
|
if (sendingDevice) {
|
|
140
152
|
if (this.config.extendedLogging && !loggedDevices.includes(remote.address.toString())) {
|
|
@@ -142,7 +154,7 @@ class GoveeLocal extends utils.Adapter {
|
|
|
142
154
|
loggedDevices.push(remote.address.toString());
|
|
143
155
|
}
|
|
144
156
|
const devStatusMessageObject = JSON.parse(message.toString());
|
|
145
|
-
this.setObjectNotExists(`${sendingDevice}.devStatus.onOff`, {
|
|
157
|
+
void this.setObjectNotExists(`${sendingDevice}.devStatus.onOff`, {
|
|
146
158
|
type: "state",
|
|
147
159
|
common: {
|
|
148
160
|
name: "On / Off state of the lamp",
|
|
@@ -153,11 +165,11 @@ class GoveeLocal extends utils.Adapter {
|
|
|
153
165
|
},
|
|
154
166
|
native: {}
|
|
155
167
|
});
|
|
156
|
-
this.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
this.setObjectNotExists(`${sendingDevice}.devStatus.brightness`, {
|
|
168
|
+
void this.updateStateAsync(
|
|
169
|
+
`${sendingDevice}.devStatus.onOff`,
|
|
170
|
+
devStatusMessageObject.msg.data.onOff == 1
|
|
171
|
+
);
|
|
172
|
+
void this.setObjectNotExists(`${sendingDevice}.devStatus.brightness`, {
|
|
161
173
|
type: "state",
|
|
162
174
|
common: {
|
|
163
175
|
name: "Brightness of the light",
|
|
@@ -168,11 +180,11 @@ class GoveeLocal extends utils.Adapter {
|
|
|
168
180
|
},
|
|
169
181
|
native: {}
|
|
170
182
|
});
|
|
171
|
-
this.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
this.setObjectNotExists(`${sendingDevice}.devStatus.color`, {
|
|
183
|
+
void this.updateStateAsync(
|
|
184
|
+
`${sendingDevice}.devStatus.brightness`,
|
|
185
|
+
devStatusMessageObject.msg.data.brightness
|
|
186
|
+
);
|
|
187
|
+
void this.setObjectNotExists(`${sendingDevice}.devStatus.color`, {
|
|
176
188
|
type: "state",
|
|
177
189
|
common: {
|
|
178
190
|
name: "Current showing color of the lamp",
|
|
@@ -183,11 +195,13 @@ class GoveeLocal extends utils.Adapter {
|
|
|
183
195
|
},
|
|
184
196
|
native: {}
|
|
185
197
|
});
|
|
186
|
-
|
|
187
|
-
|
|
198
|
+
const colorString = `#${(0, import_hexTool.componentToHex)(devStatusMessageObject.msg.data.color.r)}${(0, import_hexTool.componentToHex)(devStatusMessageObject.msg.data.color.g)}${(0, import_hexTool.componentToHex)(devStatusMessageObject.msg.data.color.b)}`;
|
|
199
|
+
void this.setState(`${sendingDevice}.devStatus.color`, {
|
|
200
|
+
val: colorString,
|
|
188
201
|
ack: true
|
|
189
202
|
});
|
|
190
|
-
this.
|
|
203
|
+
void this.updateStateAsync(`${sendingDevice}.devStatus.color`, colorString);
|
|
204
|
+
void this.setObjectNotExists(`${sendingDevice}.devStatus.colorTemInKelvin`, {
|
|
191
205
|
type: "state",
|
|
192
206
|
common: {
|
|
193
207
|
name: "If staying in white light, the color temperature",
|
|
@@ -198,71 +212,91 @@ class GoveeLocal extends utils.Adapter {
|
|
|
198
212
|
},
|
|
199
213
|
native: {}
|
|
200
214
|
});
|
|
201
|
-
this.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
215
|
+
void this.updateStateAsync(
|
|
216
|
+
`${sendingDevice}.devStatus.colorTemInKelvin`,
|
|
217
|
+
devStatusMessageObject.msg.data.colorTemInKelvin
|
|
218
|
+
);
|
|
205
219
|
}
|
|
206
220
|
break;
|
|
207
|
-
|
|
208
|
-
|
|
221
|
+
}
|
|
222
|
+
default: {
|
|
223
|
+
this.log.error(`message from: ${remote.address}:${remote.port} - ${message.toString()}`);
|
|
224
|
+
}
|
|
209
225
|
}
|
|
226
|
+
return Promise.resolve();
|
|
210
227
|
}
|
|
211
228
|
async refreshAllDevices() {
|
|
212
229
|
for (const ip in devices) {
|
|
213
230
|
this.requestDeviceStatus(ip);
|
|
214
231
|
}
|
|
232
|
+
return Promise.resolve();
|
|
215
233
|
}
|
|
216
234
|
/**
|
|
217
235
|
* sends the device status request to one specific device
|
|
236
|
+
*
|
|
218
237
|
* @param receiver the ip ( / hsotname ) of the device that should be queried
|
|
219
238
|
*/
|
|
220
239
|
requestDeviceStatus(receiver) {
|
|
221
240
|
const requestDeviceStatusBuffer = Buffer.from(JSON.stringify(requestStatusMessage));
|
|
222
|
-
socket.send(requestDeviceStatusBuffer, 0, requestDeviceStatusBuffer.length, CONTROL_PORT, receiver);
|
|
241
|
+
void socket.send(requestDeviceStatusBuffer, 0, requestDeviceStatusBuffer.length, CONTROL_PORT, receiver);
|
|
223
242
|
}
|
|
224
243
|
/**
|
|
225
244
|
* send the scan message to the udp multicast address
|
|
226
245
|
*/
|
|
227
246
|
async sendScan() {
|
|
228
247
|
const scanMessageBuffer = Buffer.from(JSON.stringify(scanMessage));
|
|
229
|
-
socket.send(scanMessageBuffer, 0, scanMessageBuffer.length, SEND_SCAN_PORT, M_CAST);
|
|
248
|
+
void socket.send(scanMessageBuffer, 0, scanMessageBuffer.length, SEND_SCAN_PORT, M_CAST);
|
|
249
|
+
return Promise.resolve();
|
|
230
250
|
}
|
|
231
251
|
/**
|
|
232
252
|
* Is called when adapter shuts down - callback has to be called under any circumstances!
|
|
253
|
+
*
|
|
254
|
+
* @param callback Callback-Funktion, die nach Abschluss des Unload-Prozesses aufgerufen wird.
|
|
233
255
|
*/
|
|
234
256
|
onUnload(callback) {
|
|
235
257
|
try {
|
|
236
258
|
this.clearInterval(searchInterval);
|
|
237
259
|
this.clearInterval(refreshInterval);
|
|
238
260
|
socket.close();
|
|
239
|
-
this.
|
|
261
|
+
void this.updateStateAsync("info.connection", false);
|
|
240
262
|
callback();
|
|
241
263
|
} catch (e) {
|
|
264
|
+
this.log.error(e.message);
|
|
242
265
|
callback();
|
|
243
266
|
}
|
|
244
267
|
}
|
|
245
268
|
/**
|
|
246
269
|
* Is called if a subscribed state changes
|
|
270
|
+
*
|
|
271
|
+
* @param id Die ID des geänderten States.
|
|
272
|
+
* @param state Das neue State-Objekt oder null/undefined.
|
|
247
273
|
*/
|
|
248
274
|
async onStateChange(id, state) {
|
|
249
275
|
var _a, _b;
|
|
250
276
|
if (state && !state.ack) {
|
|
251
|
-
const ipOfDevice = await this.getStateAsync(id.split(".")[2]
|
|
277
|
+
const ipOfDevice = await this.getStateAsync(`${id.split(".")[2]}.deviceInfo.ip`);
|
|
252
278
|
if (ipOfDevice) {
|
|
253
279
|
const receiver = (_a = ipOfDevice.val) == null ? void 0 : _a.toString();
|
|
254
280
|
switch (id.split(".")[4]) {
|
|
255
|
-
case "onOff":
|
|
281
|
+
case "onOff": {
|
|
256
282
|
const turnMessage = { msg: { cmd: "turn", data: { value: state.val ? 1 : 0 } } };
|
|
257
283
|
const turnMessageBuffer = Buffer.from(JSON.stringify(turnMessage));
|
|
258
|
-
socket.send(turnMessageBuffer, 0, turnMessageBuffer.length, CONTROL_PORT, receiver);
|
|
284
|
+
void socket.send(turnMessageBuffer, 0, turnMessageBuffer.length, CONTROL_PORT, receiver);
|
|
259
285
|
break;
|
|
260
|
-
|
|
286
|
+
}
|
|
287
|
+
case "brightness": {
|
|
261
288
|
const brightnessMessage = { msg: { cmd: "brightness", data: { value: state.val } } };
|
|
262
289
|
const brightnessMessageBuffer = Buffer.from(JSON.stringify(brightnessMessage));
|
|
263
|
-
socket.send(
|
|
290
|
+
void socket.send(
|
|
291
|
+
brightnessMessageBuffer,
|
|
292
|
+
0,
|
|
293
|
+
brightnessMessageBuffer.length,
|
|
294
|
+
CONTROL_PORT,
|
|
295
|
+
receiver
|
|
296
|
+
);
|
|
264
297
|
break;
|
|
265
|
-
|
|
298
|
+
}
|
|
299
|
+
case "colorTemInKelvin": {
|
|
266
300
|
const colorTempMessageBuffer = Buffer.from(
|
|
267
301
|
JSON.stringify({
|
|
268
302
|
msg: {
|
|
@@ -271,22 +305,40 @@ class GoveeLocal extends utils.Adapter {
|
|
|
271
305
|
}
|
|
272
306
|
})
|
|
273
307
|
);
|
|
274
|
-
socket.send(
|
|
308
|
+
void socket.send(
|
|
309
|
+
colorTempMessageBuffer,
|
|
310
|
+
0,
|
|
311
|
+
colorTempMessageBuffer.length,
|
|
312
|
+
CONTROL_PORT,
|
|
313
|
+
receiver
|
|
314
|
+
);
|
|
275
315
|
break;
|
|
276
|
-
|
|
316
|
+
}
|
|
317
|
+
case "color": {
|
|
277
318
|
const colorValue = (_b = state.val) == null ? void 0 : _b.toString();
|
|
278
319
|
if (colorValue) {
|
|
279
320
|
const rgb = (0, import_hexTool.hexToRgb)(colorValue);
|
|
280
321
|
const colorMessage = { msg: { cmd: "colorwc", data: { color: rgb } } };
|
|
281
322
|
const colorMessageBuffer = Buffer.from(JSON.stringify(colorMessage));
|
|
282
|
-
socket.send(colorMessageBuffer, 0, colorMessageBuffer.length, CONTROL_PORT, receiver);
|
|
323
|
+
void socket.send(colorMessageBuffer, 0, colorMessageBuffer.length, CONTROL_PORT, receiver);
|
|
283
324
|
}
|
|
284
325
|
break;
|
|
326
|
+
}
|
|
285
327
|
}
|
|
286
328
|
} else {
|
|
287
329
|
this.log.error("device not found");
|
|
288
330
|
}
|
|
289
331
|
}
|
|
332
|
+
return Promise.resolve();
|
|
333
|
+
}
|
|
334
|
+
async updateStateAsync(fullName, state, acknowledged = true) {
|
|
335
|
+
const currentState = await this.getStateAsync(fullName);
|
|
336
|
+
if (currentState != state) {
|
|
337
|
+
void this.setState(fullName, {
|
|
338
|
+
val: state,
|
|
339
|
+
ack: acknowledged
|
|
340
|
+
});
|
|
341
|
+
}
|
|
290
342
|
}
|
|
291
343
|
}
|
|
292
344
|
if (require.main !== module) {
|
|
@@ -312,4 +364,9 @@ function getDatapointDescription(name) {
|
|
|
312
364
|
return "";
|
|
313
365
|
}
|
|
314
366
|
}
|
|
367
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
368
|
+
0 && (module.exports = {
|
|
369
|
+
GoveeLocal,
|
|
370
|
+
getDatapointDescription
|
|
371
|
+
});
|
|
315
372
|
//# sourceMappingURL=main.js.map
|
package/build/main.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["/*\n * Created with @iobroker/create-adapter v2.3.0\n */\n\n// The adapter-core module gives you access to the core ioBroker functions\n// you need to create an adapter\nimport * as utils from '@iobroker/adapter-core';\nimport * as dgram from 'node:dgram';\nimport { componentToHex, hexToRgb } from './tools/hexTool';\n\n// Load your modules here, e.g.:\n\nconst LOCAL_PORT = 4002;\nconst SEND_SCAN_PORT = 4001;\nconst CONTROL_PORT = 4003;\nconst M_CAST = '239.255.255.250';\n\nconst socket = dgram.createSocket({ type: 'udp4' });\n\nconst scanMessage = { msg: { cmd: 'scan', data: { account_topic: 'reserved' } } };\nconst requestStatusMessage = { msg: { cmd: 'devStatus', data: {} } };\n\nlet searchInterval: ioBroker.Interval;\nlet refreshInterval: ioBroker.Interval;\n\nconst devices: { [ip: string]: string } = {};\n\nconst loggedDevices = [] as string[];\n\nclass GoveeLocal extends utils.Adapter {\n\tpublic constructor(options: Partial<utils.AdapterOptions> = {}) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\tname: 'govee-local',\n\t\t});\n\t\tthis.on('ready', this.onReady.bind(this));\n\t\tthis.on('stateChange', this.onStateChange.bind(this));\n\t\t// this.on('objectChange', this.onObjectChange.bind(this));\n\t\t// this.on('message', this.onMessage.bind(this));\n\t\tthis.on('unload', this.onUnload.bind(this));\n\t}\n\n\t/**\n\t * Is called when databases are connected and adapter received configuration.\n\t */\n\tprivate async onReady(): Promise<void> {\n\t\tthis.setObjectNotExists('info.connection', {\n\t\t\ttype: 'state',\n\t\t\tcommon: {\n\t\t\t\tname: 'Device discovery running',\n\t\t\t\ttype: 'boolean',\n\t\t\t\trole: 'indicator.connected',\n\t\t\t\tread: true,\n\t\t\t\twrite: false,\n\t\t\t},\n\t\t\tnative: {},\n\t\t});\n\t\tsocket.on('message', this.onUdpMessage.bind(this));\n\t\tsocket.on('error', (error) => {\n\t\t\tthis.log.error('server bind error : ' + error.message);\n\t\t\tthis.setStateChanged('info.connection', { val: false, ack: true });\n\t\t});\n\n\t\tif (this.config.extendedLogging) {\n\t\t\tthis.log.debug('running with extended logging');\n\t\t}\n\n\t\tsocket.bind({ address: this.config.interface, port: LOCAL_PORT }, this.serverBound.bind(this));\n\t\tthis.subscribeStates('*.devStatus.*');\n\t}\n\n\t/**\n\t * handles when udp socket is up\n\t * configure multicast membership\n\t * start periodic scan for devices\n\t */\n\tprivate async serverBound(): Promise<void> {\n\t\tsocket.setBroadcast(true);\n\t\tsocket.setMulticastTTL(128);\n\t\tsocket.setMulticastInterface(this.config.interface);\n\t\tsocket.addMembership(M_CAST);\n\t\tthis.setStateChanged('info.connection', { val: true, ack: true });\n\t\tthis.log.debug('UDP listening on ' + socket.address().address + ':' + socket.address().port);\n\n\t\tconst deviceSearchInterval = this.setInterval(this.sendScan.bind(this), this.config.searchInterval * 1000);\n\t\tif (deviceSearchInterval) {\n\t\t\tsearchInterval = deviceSearchInterval;\n\t\t}\n\n\t\tconst deviceRefreshInterval = this.setInterval(\n\t\t\tthis.refreshAllDevices.bind(this),\n\t\t\tthis.config.deviceStatusRefreshInterval * 1000,\n\t\t);\n\t\tif (deviceRefreshInterval) {\n\t\t\trefreshInterval = deviceRefreshInterval;\n\t\t}\n\t}\n\n\t/**\n\t * handle icoming messages on the udp socket\n\t * @param message the message itself\n\t * @param remote the sender of the message\n\t */\n\tprivate async onUdpMessage(message: Buffer, remote: dgram.RemoteInfo): Promise<void> {\n\t\tconst messageObject = JSON.parse(message.toString());\n\t\tswitch (messageObject.msg.cmd) {\n\t\t\tcase 'scan':\n\t\t\t\tfor (const key of Object.keys(messageObject.msg.data)) {\n\t\t\t\t\tif (key != 'device') {\n\t\t\t\t\t\tconst deviceName = messageObject.msg.data.device.replace(this.FORBIDDEN_CHARS, '_');\n\t\t\t\t\t\tdevices[remote.address] = deviceName;\n\t\t\t\t\t\tthis.setObjectNotExists(deviceName, {\n\t\t\t\t\t\t\ttype: 'device',\n\t\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\t\tname: messageObject.msg.data.sku,\n\t\t\t\t\t\t\t\trole: 'group',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnative: {},\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.setObjectNotExists(`${deviceName}.deviceInfo.${key}`, {\n\t\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\t\tname: getDatapointDescription(key),\n\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\trole: 'state',\n\t\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnative: {},\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.setState(`${deviceName}.deviceInfo.${key}`, {\n\t\t\t\t\t\t\tval: messageObject.msg.data[key],\n\t\t\t\t\t\t\tack: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'devStatus':\n\t\t\t\tconst sendingDevice = devices[remote.address];\n\t\t\t\tif (sendingDevice) {\n\t\t\t\t\t// const devices = await this.getStatesAsync(`${this.name}.${this.instance}.*.deviceInfo.ip`);\n\t\t\t\t\tif (this.config.extendedLogging && !loggedDevices.includes(remote.address.toString())) {\n\t\t\t\t\t\tthis.log.info(`deivce status message data: ${JSON.stringify(messageObject)}`);\n\t\t\t\t\t\tloggedDevices.push(remote.address.toString());\n\t\t\t\t\t}\n\t\t\t\t\tconst devStatusMessageObject = JSON.parse(message.toString());\n\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.onOff`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'On / Off state of the lamp',\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\trole: 'switch',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.setState(`${sendingDevice}.devStatus.onOff`, {\n\t\t\t\t\t\tval: devStatusMessageObject.msg.data.onOff == 1,\n\t\t\t\t\t\tack: true,\n\t\t\t\t\t});\n\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.brightness`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'Brightness of the light',\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\trole: 'level.dimmer',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.setState(`${sendingDevice}.devStatus.brightness`, {\n\t\t\t\t\t\tval: devStatusMessageObject.msg.data.brightness,\n\t\t\t\t\t\tack: true,\n\t\t\t\t\t});\n\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.color`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'Current showing color of the lamp',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\trole: 'level.color.rgb',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.setState(`${sendingDevice}.devStatus.color`, {\n\t\t\t\t\t\tval:\n\t\t\t\t\t\t\t'#' +\n\t\t\t\t\t\t\tcomponentToHex(devStatusMessageObject.msg.data.color.r) +\n\t\t\t\t\t\t\tcomponentToHex(devStatusMessageObject.msg.data.color.g) +\n\t\t\t\t\t\t\tcomponentToHex(devStatusMessageObject.msg.data.color.b),\n\t\t\t\t\t\tack: true,\n\t\t\t\t\t});\n\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.colorTemInKelvin`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'If staying in white light, the color temperature',\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\trole: 'level.color.temperature',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tthis.setState(`${sendingDevice}.devStatus.colorTemInKelvin`, {\n\t\t\t\t\t\tval: devStatusMessageObject.msg.data.colorTemInKelvin,\n\t\t\t\t\t\tack: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.log.error('message from: ' + remote.address + ':' + remote.port + ' - ' + message);\n\t\t}\n\t}\n\n\tprivate async refreshAllDevices(): Promise<void> {\n\t\tfor (const ip in devices) {\n\t\t\tthis.requestDeviceStatus(ip);\n\t\t}\n\t}\n\n\t/**\n\t * sends the device status request to one specific device\n\t * @param receiver the ip ( / hsotname ) of the device that should be queried\n\t */\n\tprivate requestDeviceStatus(receiver: string): void {\n\t\tconst requestDeviceStatusBuffer = Buffer.from(JSON.stringify(requestStatusMessage));\n\t\tsocket.send(requestDeviceStatusBuffer, 0, requestDeviceStatusBuffer.length, CONTROL_PORT, receiver);\n\t}\n\n\t/**\n\t * send the scan message to the udp multicast address\n\t */\n\tprivate async sendScan(): Promise<void> {\n\t\tconst scanMessageBuffer = Buffer.from(JSON.stringify(scanMessage));\n\t\tsocket.send(scanMessageBuffer, 0, scanMessageBuffer.length, SEND_SCAN_PORT, M_CAST);\n\t}\n\n\t/**\n\t * Is called when adapter shuts down - callback has to be called under any circumstances!\n\t */\n\tprivate onUnload(callback: () => void): void {\n\t\ttry {\n\t\t\tthis.clearInterval(searchInterval);\n\t\t\tthis.clearInterval(refreshInterval);\n\t\t\tsocket.close();\n\t\t\tthis.setState('info.connection', { val: false, ack: true });\n\t\t\tcallback();\n\t\t} catch (e) {\n\t\t\tcallback();\n\t\t}\n\t}\n\n\t/**\n\t * Is called if a subscribed state changes\n\t */\n\tprivate async onStateChange(id: string, state: ioBroker.State | null | undefined): Promise<void> {\n\t\tif (state && !state.ack) {\n\t\t\tconst ipOfDevice = await this.getStateAsync(id.split('.')[2] + '.deviceInfo.ip');\n\t\t\tif (ipOfDevice) {\n\t\t\t\tconst receiver = ipOfDevice.val?.toString();\n\t\t\t\tswitch (id.split('.')[4]) {\n\t\t\t\t\tcase 'onOff':\n\t\t\t\t\t\tconst turnMessage = { msg: { cmd: 'turn', data: { value: state.val ? 1 : 0 } } };\n\t\t\t\t\t\tconst turnMessageBuffer = Buffer.from(JSON.stringify(turnMessage));\n\t\t\t\t\t\tsocket.send(turnMessageBuffer, 0, turnMessageBuffer.length, CONTROL_PORT, receiver);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'brightness':\n\t\t\t\t\t\tconst brightnessMessage = { msg: { cmd: 'brightness', data: { value: state.val } } };\n\t\t\t\t\t\tconst brightnessMessageBuffer = Buffer.from(JSON.stringify(brightnessMessage));\n\t\t\t\t\t\tsocket.send(brightnessMessageBuffer, 0, brightnessMessageBuffer.length, CONTROL_PORT, receiver);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'colorTemInKelvin':\n\t\t\t\t\t\tconst colorTempMessageBuffer = Buffer.from(\n\t\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\t\tmsg: {\n\t\t\t\t\t\t\t\t\tcmd: 'colorwc',\n\t\t\t\t\t\t\t\t\tdata: { color: { r: '0', g: '0', b: '0' }, colorTemInKelvin: state.val },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tsocket.send(colorTempMessageBuffer, 0, colorTempMessageBuffer.length, CONTROL_PORT, receiver);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'color':\n\t\t\t\t\t\tconst colorValue = state.val?.toString();\n\t\t\t\t\t\tif (colorValue) {\n\t\t\t\t\t\t\tconst rgb = hexToRgb(colorValue);\n\t\t\t\t\t\t\tconst colorMessage = { msg: { cmd: 'colorwc', data: { color: rgb } } };\n\t\t\t\t\t\t\tconst colorMessageBuffer = Buffer.from(JSON.stringify(colorMessage));\n\t\t\t\t\t\t\tsocket.send(colorMessageBuffer, 0, colorMessageBuffer.length, CONTROL_PORT, receiver);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.log.error('device not found');\n\t\t\t}\n\t\t}\n\t}\n}\n\nif (require.main !== module) {\n\t// Export the constructor in compact mode\n\tmodule.exports = (options: Partial<utils.AdapterOptions> | undefined) => new GoveeLocal(options);\n} else {\n\t// otherwise start the instance directly\n\t(() => new GoveeLocal())();\n}\n\n/**\n * This method returns the description for device information datapoints\n * to unbloat the upper methods.\n * tanslations would be great here\n * @param name the name of the parameter retrieved from the device\n * @returns the description, that should be set to the datapoint\n */\nfunction getDatapointDescription(name: string): string {\n\tswitch (name) {\n\t\tcase 'model':\n\t\t\treturn 'Specific model of the Lamp';\n\t\tcase 'ip':\n\t\t\treturn 'IP address of the Lamp';\n\t\tcase 'bleVersionHard':\n\t\t\treturn 'Bluetooth Low Energy Hardware Version';\n\t\tcase 'bleVersionSoft':\n\t\t\treturn 'Bluetooth Low Energy Software Version';\n\t\tcase 'wifiVersionHard':\n\t\t\treturn 'WiFi Hardware Version';\n\t\tcase 'wifiVersionSoft':\n\t\t\treturn 'WiFi Software Version';\n\t\tdefault:\n\t\t\treturn '';\n\t}\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/*\n * Created with @iobroker/create-adapter v2.3.0\n */\n\n// The adapter-core module gives you access to the core ioBroker functions\n// you need to create an adapter\nimport * as utils from '@iobroker/adapter-core';\nimport * as dgram from 'node:dgram';\nimport { componentToHex, hexToRgb } from './tools/hexTool';\n\n// Load your modules here, e.g.:\n\nconst LOCAL_PORT = 4002;\nconst SEND_SCAN_PORT = 4001;\nconst CONTROL_PORT = 4003;\nconst M_CAST = '239.255.255.250';\n\nconst socket = dgram.createSocket({ type: 'udp4' });\n\nconst scanMessage = { msg: { cmd: 'scan', data: { account_topic: 'reserved' } } };\nconst requestStatusMessage = { msg: { cmd: 'devStatus', data: {} } };\n\nlet searchInterval: ioBroker.Interval;\nlet refreshInterval: ioBroker.Interval;\n\nconst devices: { [ip: string]: string } = {};\n\nconst loggedDevices = [] as string[];\n\nexport class GoveeLocal extends utils.Adapter {\n\tpublic constructor(options: Partial<utils.AdapterOptions> = {}) {\n\t\tsuper({\n\t\t\t...options,\n\t\t\tname: 'govee-local',\n\t\t});\n\t\tthis.on('ready', this.onReady.bind(this));\n\t\tthis.on('stateChange', this.onStateChange.bind(this));\n\t\t// this.on('objectChange', this.onObjectChange.bind(this));\n\t\t// this.on('message', this.onMessage.bind(this));\n\t\tthis.on('unload', this.onUnload.bind(this));\n\t}\n\n\t/**\n\t * Is called when databases are connected and adapter received configuration.\n\t */\n\tprivate async onReady(): Promise<void> {\n\t\tvoid this.setObjectNotExists('info.connection', {\n\t\t\ttype: 'state',\n\t\t\tcommon: {\n\t\t\t\tname: 'Device discovery running',\n\t\t\t\ttype: 'boolean',\n\t\t\t\trole: 'indicator.connected',\n\t\t\t\tread: true,\n\t\t\t\twrite: false,\n\t\t\t},\n\t\t\tnative: {},\n\t\t});\n\t\tsocket.on('message', this.onUdpMessage.bind(this));\n\t\tsocket.on('error', (error) => {\n\t\t\tthis.log.error(`server bind error : ${error.message}`);\n\t\t\tvoid this.setStateChanged('info.connection', { val: false, ack: true });\n\t\t});\n\n\t\tif (this.config.extendedLogging) {\n\t\t\tthis.log.debug('running with extended logging');\n\t\t}\n\n\t\tvoid socket.bind({ address: this.config.interface, port: LOCAL_PORT }, this.serverBound.bind(this));\n\t\tvoid this.subscribeStates('*.devStatus.*');\n\t\treturn Promise.resolve();\n\t}\n\n\t/**\n\t * handles when udp socket is up\n\t * configure multicast membership\n\t * start periodic scan for devices\n\t */\n\tprivate async serverBound(): Promise<void> {\n\t\tsocket.setBroadcast(true);\n\t\tsocket.setMulticastTTL(128);\n\t\tsocket.setMulticastInterface(this.config.interface);\n\t\tsocket.addMembership(M_CAST);\n\t\tvoid this.setStateChanged('info.connection', { val: true, ack: true });\n\t\tthis.log.debug(`UDP listening on ${(socket.address() as any).address}:${(socket.address() as any).port}`);\n\n\t\tconst deviceSearchInterval = this.setInterval(this.sendScan.bind(this), this.config.searchInterval * 1000);\n\t\tif (deviceSearchInterval) {\n\t\t\tsearchInterval = deviceSearchInterval;\n\t\t}\n\n\t\tconst deviceRefreshInterval = this.setInterval(\n\t\t\tthis.refreshAllDevices.bind(this),\n\t\t\tthis.config.deviceStatusRefreshInterval * 1000,\n\t\t);\n\t\tif (deviceRefreshInterval) {\n\t\t\trefreshInterval = deviceRefreshInterval;\n\t\t}\n\t\treturn Promise.resolve();\n\t}\n\n\t/**\n\t * handle icoming messages on the udp socket\n\t *\n\t * @param message the message itself\n\t * @param remote the sender of the message\n\t */\n\tprivate async onUdpMessage(message: Buffer, remote: dgram.RemoteInfo): Promise<void> {\n\t\tconst messageObject = JSON.parse(message.toString());\n\t\tswitch (messageObject.msg.cmd) {\n\t\t\tcase 'scan': {\n\t\t\t\tfor (const key of Object.keys(messageObject.msg.data)) {\n\t\t\t\t\tif (key != 'device') {\n\t\t\t\t\t\tconst deviceName = messageObject.msg.data.device.replace(this.FORBIDDEN_CHARS, '_');\n\t\t\t\t\t\tdevices[remote.address] = deviceName;\n\t\t\t\t\t\tvoid this.setObjectNotExists(deviceName, {\n\t\t\t\t\t\t\ttype: 'device',\n\t\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\t\tname: messageObject.msg.data.sku,\n\t\t\t\t\t\t\t\trole: 'group',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnative: {},\n\t\t\t\t\t\t});\n\t\t\t\t\t\tvoid this.setObjectNotExists(`${deviceName}.deviceInfo.${key}`, {\n\t\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\t\tname: getDatapointDescription(key),\n\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\trole: 'state',\n\t\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnative: {},\n\t\t\t\t\t\t});\n\t\t\t\t\t\tvoid this.updateStateAsync(`${deviceName}.deviceInfo.${key}`, messageObject.msg.data[key]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'devStatus': {\n\t\t\t\tconst sendingDevice = devices[remote.address];\n\t\t\t\tif (sendingDevice) {\n\t\t\t\t\tif (this.config.extendedLogging && !loggedDevices.includes(remote.address.toString())) {\n\t\t\t\t\t\tthis.log.info(`deivce status message data: ${JSON.stringify(messageObject)}`);\n\t\t\t\t\t\tloggedDevices.push(remote.address.toString());\n\t\t\t\t\t}\n\t\t\t\t\tconst devStatusMessageObject = JSON.parse(message.toString());\n\t\t\t\t\tvoid this.setObjectNotExists(`${sendingDevice}.devStatus.onOff`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'On / Off state of the lamp',\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\trole: 'switch',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tvoid this.updateStateAsync(\n\t\t\t\t\t\t`${sendingDevice}.devStatus.onOff`,\n\t\t\t\t\t\tdevStatusMessageObject.msg.data.onOff == 1,\n\t\t\t\t\t);\n\t\t\t\t\tvoid this.setObjectNotExists(`${sendingDevice}.devStatus.brightness`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'Brightness of the light',\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\trole: 'level.dimmer',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tvoid this.updateStateAsync(\n\t\t\t\t\t\t`${sendingDevice}.devStatus.brightness`,\n\t\t\t\t\t\tdevStatusMessageObject.msg.data.brightness,\n\t\t\t\t\t);\n\t\t\t\t\tvoid this.setObjectNotExists(`${sendingDevice}.devStatus.color`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'Current showing color of the lamp',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\trole: 'level.color.rgb',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tconst colorString = `#${componentToHex(devStatusMessageObject.msg.data.color.r)}${componentToHex(devStatusMessageObject.msg.data.color.g)}${componentToHex(devStatusMessageObject.msg.data.color.b)}`;\n\t\t\t\t\tvoid this.setState(`${sendingDevice}.devStatus.color`, {\n\t\t\t\t\t\tval: colorString,\n\t\t\t\t\t\tack: true,\n\t\t\t\t\t});\n\t\t\t\t\tvoid this.updateStateAsync(`${sendingDevice}.devStatus.color`, colorString);\n\t\t\t\t\tvoid this.setObjectNotExists(`${sendingDevice}.devStatus.colorTemInKelvin`, {\n\t\t\t\t\t\ttype: 'state',\n\t\t\t\t\t\tcommon: {\n\t\t\t\t\t\t\tname: 'If staying in white light, the color temperature',\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\trole: 'level.color.temperature',\n\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\twrite: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tnative: {},\n\t\t\t\t\t});\n\t\t\t\t\tvoid this.updateStateAsync(\n\t\t\t\t\t\t`${sendingDevice}.devStatus.colorTemInKelvin`,\n\t\t\t\t\t\tdevStatusMessageObject.msg.data.colorTemInKelvin,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthis.log.error(`message from: ${remote.address}:${remote.port} - ${message.toString()}`);\n\t\t\t}\n\t\t}\n\t\treturn Promise.resolve();\n\t}\n\n\tprivate async refreshAllDevices(): Promise<void> {\n\t\tfor (const ip in devices) {\n\t\t\tthis.requestDeviceStatus(ip);\n\t\t}\n\t\treturn Promise.resolve();\n\t}\n\n\t/**\n\t * sends the device status request to one specific device\n\t *\n\t * @param receiver the ip ( / hsotname ) of the device that should be queried\n\t */\n\tprivate requestDeviceStatus(receiver: string): void {\n\t\tconst requestDeviceStatusBuffer = Buffer.from(JSON.stringify(requestStatusMessage));\n\t\tvoid socket.send(requestDeviceStatusBuffer, 0, requestDeviceStatusBuffer.length, CONTROL_PORT, receiver);\n\t}\n\n\t/**\n\t * send the scan message to the udp multicast address\n\t */\n\tprivate async sendScan(): Promise<void> {\n\t\tconst scanMessageBuffer = Buffer.from(JSON.stringify(scanMessage));\n\t\tvoid socket.send(scanMessageBuffer, 0, scanMessageBuffer.length, SEND_SCAN_PORT, M_CAST);\n\t\treturn Promise.resolve();\n\t}\n\n\t/**\n\t * Is called when adapter shuts down - callback has to be called under any circumstances!\n\t *\n\t * @param callback Callback-Funktion, die nach Abschluss des Unload-Prozesses aufgerufen wird.\n\t */\n\tprivate onUnload(callback: () => void): void {\n\t\ttry {\n\t\t\tthis.clearInterval(searchInterval);\n\t\t\tthis.clearInterval(refreshInterval);\n\t\t\tsocket.close();\n\t\t\tvoid this.updateStateAsync('info.connection', false);\n\t\t\tcallback();\n\t\t} catch (e: any) {\n\t\t\tthis.log.error(e.message);\n\t\t\tcallback();\n\t\t}\n\t}\n\n\t/**\n\t * Is called if a subscribed state changes\n\t *\n\t * @param id Die ID des ge\u00E4nderten States.\n\t * @param state Das neue State-Objekt oder null/undefined.\n\t */\n\tprivate async onStateChange(id: string, state: ioBroker.State | null | undefined): Promise<void> {\n\t\tif (state && !state.ack) {\n\t\t\tconst ipOfDevice = await this.getStateAsync(`${id.split('.')[2]}.deviceInfo.ip`);\n\t\t\tif (ipOfDevice) {\n\t\t\t\tconst receiver = ipOfDevice.val?.toString();\n\t\t\t\tswitch (id.split('.')[4]) {\n\t\t\t\t\tcase 'onOff': {\n\t\t\t\t\t\tconst turnMessage = { msg: { cmd: 'turn', data: { value: state.val ? 1 : 0 } } };\n\t\t\t\t\t\tconst turnMessageBuffer = Buffer.from(JSON.stringify(turnMessage));\n\t\t\t\t\t\tvoid socket.send(turnMessageBuffer, 0, turnMessageBuffer.length, CONTROL_PORT, receiver);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'brightness': {\n\t\t\t\t\t\tconst brightnessMessage = { msg: { cmd: 'brightness', data: { value: state.val } } };\n\t\t\t\t\t\tconst brightnessMessageBuffer = Buffer.from(JSON.stringify(brightnessMessage));\n\t\t\t\t\t\tvoid socket.send(\n\t\t\t\t\t\t\tbrightnessMessageBuffer,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tbrightnessMessageBuffer.length,\n\t\t\t\t\t\t\tCONTROL_PORT,\n\t\t\t\t\t\t\treceiver,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'colorTemInKelvin': {\n\t\t\t\t\t\tconst colorTempMessageBuffer = Buffer.from(\n\t\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\t\tmsg: {\n\t\t\t\t\t\t\t\t\tcmd: 'colorwc',\n\t\t\t\t\t\t\t\t\tdata: { color: { r: '0', g: '0', b: '0' }, colorTemInKelvin: state.val },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tvoid socket.send(\n\t\t\t\t\t\t\tcolorTempMessageBuffer,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tcolorTempMessageBuffer.length,\n\t\t\t\t\t\t\tCONTROL_PORT,\n\t\t\t\t\t\t\treceiver,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'color': {\n\t\t\t\t\t\tconst colorValue = state.val?.toString();\n\t\t\t\t\t\tif (colorValue) {\n\t\t\t\t\t\t\tconst rgb = hexToRgb(colorValue);\n\t\t\t\t\t\t\tconst colorMessage = { msg: { cmd: 'colorwc', data: { color: rgb } } };\n\t\t\t\t\t\t\tconst colorMessageBuffer = Buffer.from(JSON.stringify(colorMessage));\n\t\t\t\t\t\t\tvoid socket.send(colorMessageBuffer, 0, colorMessageBuffer.length, CONTROL_PORT, receiver);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.log.error('device not found');\n\t\t\t}\n\t\t}\n\t\treturn Promise.resolve();\n\t}\n\n\tprivate async updateStateAsync(fullName: string, state: any, acknowledged = true): Promise<void> {\n\t\tconst currentState = await this.getStateAsync(fullName);\n\t\tif (currentState != state) {\n\t\t\tvoid this.setState(fullName, {\n\t\t\t\tval: state,\n\t\t\t\tack: acknowledged,\n\t\t\t});\n\t\t}\n\t}\n}\n\nif (require.main !== module) {\n\t// Exportiere eine Factory-Funktion f\u00FCr ioBroker, aber die Klasse ist jetzt auch als ES6-Export verf\u00FCgbar\n\tmodule.exports = (options: Partial<utils.AdapterOptions> | undefined) => new GoveeLocal(options);\n} else {\n\t// otherwise start the instance directly\n\t(() => new GoveeLocal())();\n}\n\n/**\n * This method returns the description for device information datapoints\n * to unbloat the upper methods.\n * tanslations would be great here\n *\n * @param name the name of the parameter retrieved from the device\n * @returns the description, that should be set to the datapoint\n */\nexport function getDatapointDescription(name: string): string {\n\tswitch (name) {\n\t\tcase 'model':\n\t\t\treturn 'Specific model of the Lamp';\n\t\tcase 'ip':\n\t\t\treturn 'IP address of the Lamp';\n\t\tcase 'bleVersionHard':\n\t\t\treturn 'Bluetooth Low Energy Hardware Version';\n\t\tcase 'bleVersionSoft':\n\t\t\treturn 'Bluetooth Low Energy Software Version';\n\t\tcase 'wifiVersionHard':\n\t\t\treturn 'WiFi Hardware Version';\n\t\tcase 'wifiVersionSoft':\n\t\t\treturn 'WiFi Software Version';\n\t\tdefault:\n\t\t\treturn '';\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,YAAuB;AACvB,YAAuB;AACvB,qBAAyC;AAIzC,MAAM,aAAa;AACnB,MAAM,iBAAiB;AACvB,MAAM,eAAe;AACrB,MAAM,SAAS;AAEf,MAAM,SAAS,MAAM,aAAa,EAAE,MAAM,OAAO,CAAC;AAElD,MAAM,cAAc,EAAE,KAAK,EAAE,KAAK,QAAQ,MAAM,EAAE,eAAe,WAAW,EAAE,EAAE;AAChF,MAAM,uBAAuB,EAAE,KAAK,EAAE,KAAK,aAAa,MAAM,CAAC,EAAE,EAAE;AAEnE,IAAI;AACJ,IAAI;AAEJ,MAAM,UAAoC,CAAC;AAE3C,MAAM,gBAAgB,CAAC;AAEhB,MAAM,mBAAmB,MAAM,QAAQ;AAAA,EACtC,YAAY,UAAyC,CAAC,GAAG;AAC/D,UAAM;AAAA,MACL,GAAG;AAAA,MACH,MAAM;AAAA,IACP,CAAC;AACD,SAAK,GAAG,SAAS,KAAK,QAAQ,KAAK,IAAI,CAAC;AACxC,SAAK,GAAG,eAAe,KAAK,cAAc,KAAK,IAAI,CAAC;AAGpD,SAAK,GAAG,UAAU,KAAK,SAAS,KAAK,IAAI,CAAC;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,UAAyB;AACtC,SAAK,KAAK,mBAAmB,mBAAmB;AAAA,MAC/C,MAAM;AAAA,MACN,QAAQ;AAAA,QACP,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MACR;AAAA,MACA,QAAQ,CAAC;AAAA,IACV,CAAC;AACD,WAAO,GAAG,WAAW,KAAK,aAAa,KAAK,IAAI,CAAC;AACjD,WAAO,GAAG,SAAS,CAAC,UAAU;AAC7B,WAAK,IAAI,MAAM,uBAAuB,MAAM,OAAO,EAAE;AACrD,WAAK,KAAK,gBAAgB,mBAAmB,EAAE,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,IACvE,CAAC;AAED,QAAI,KAAK,OAAO,iBAAiB;AAChC,WAAK,IAAI,MAAM,+BAA+B;AAAA,IAC/C;AAEA,SAAK,OAAO,KAAK,EAAE,SAAS,KAAK,OAAO,WAAW,MAAM,WAAW,GAAG,KAAK,YAAY,KAAK,IAAI,CAAC;AAClG,SAAK,KAAK,gBAAgB,eAAe;AACzC,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,cAA6B;AAC1C,WAAO,aAAa,IAAI;AACxB,WAAO,gBAAgB,GAAG;AAC1B,WAAO,sBAAsB,KAAK,OAAO,SAAS;AAClD,WAAO,cAAc,MAAM;AAC3B,SAAK,KAAK,gBAAgB,mBAAmB,EAAE,KAAK,MAAM,KAAK,KAAK,CAAC;AACrE,SAAK,IAAI,MAAM,oBAAqB,OAAO,QAAQ,EAAU,OAAO,IAAK,OAAO,QAAQ,EAAU,IAAI,EAAE;AAExG,UAAM,uBAAuB,KAAK,YAAY,KAAK,SAAS,KAAK,IAAI,GAAG,KAAK,OAAO,iBAAiB,GAAI;AACzG,QAAI,sBAAsB;AACzB,uBAAiB;AAAA,IAClB;AAEA,UAAM,wBAAwB,KAAK;AAAA,MAClC,KAAK,kBAAkB,KAAK,IAAI;AAAA,MAChC,KAAK,OAAO,8BAA8B;AAAA,IAC3C;AACA,QAAI,uBAAuB;AAC1B,wBAAkB;AAAA,IACnB;AACA,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,aAAa,SAAiB,QAAyC;AACpF,UAAM,gBAAgB,KAAK,MAAM,QAAQ,SAAS,CAAC;AACnD,YAAQ,cAAc,IAAI,KAAK;AAAA,MAC9B,KAAK,QAAQ;AACZ,mBAAW,OAAO,OAAO,KAAK,cAAc,IAAI,IAAI,GAAG;AACtD,cAAI,OAAO,UAAU;AACpB,kBAAM,aAAa,cAAc,IAAI,KAAK,OAAO,QAAQ,KAAK,iBAAiB,GAAG;AAClF,oBAAQ,OAAO,OAAO,IAAI;AAC1B,iBAAK,KAAK,mBAAmB,YAAY;AAAA,cACxC,MAAM;AAAA,cACN,QAAQ;AAAA,gBACP,MAAM,cAAc,IAAI,KAAK;AAAA,gBAC7B,MAAM;AAAA,cACP;AAAA,cACA,QAAQ,CAAC;AAAA,YACV,CAAC;AACD,iBAAK,KAAK,mBAAmB,GAAG,UAAU,eAAe,GAAG,IAAI;AAAA,cAC/D,MAAM;AAAA,cACN,QAAQ;AAAA,gBACP,MAAM,wBAAwB,GAAG;AAAA,gBACjC,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,OAAO;AAAA,cACR;AAAA,cACA,QAAQ,CAAC;AAAA,YACV,CAAC;AACD,iBAAK,KAAK,iBAAiB,GAAG,UAAU,eAAe,GAAG,IAAI,cAAc,IAAI,KAAK,GAAG,CAAC;AAAA,UAC1F;AAAA,QACD;AACA;AAAA,MACD;AAAA,MACA,KAAK,aAAa;AACjB,cAAM,gBAAgB,QAAQ,OAAO,OAAO;AAC5C,YAAI,eAAe;AAClB,cAAI,KAAK,OAAO,mBAAmB,CAAC,cAAc,SAAS,OAAO,QAAQ,SAAS,CAAC,GAAG;AACtF,iBAAK,IAAI,KAAK,+BAA+B,KAAK,UAAU,aAAa,CAAC,EAAE;AAC5E,0BAAc,KAAK,OAAO,QAAQ,SAAS,CAAC;AAAA,UAC7C;AACA,gBAAM,yBAAyB,KAAK,MAAM,QAAQ,SAAS,CAAC;AAC5D,eAAK,KAAK,mBAAmB,GAAG,aAAa,oBAAoB;AAAA,YAChE,MAAM;AAAA,YACN,QAAQ;AAAA,cACP,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,YACA,QAAQ,CAAC;AAAA,UACV,CAAC;AACD,eAAK,KAAK;AAAA,YACT,GAAG,aAAa;AAAA,YAChB,uBAAuB,IAAI,KAAK,SAAS;AAAA,UAC1C;AACA,eAAK,KAAK,mBAAmB,GAAG,aAAa,yBAAyB;AAAA,YACrE,MAAM;AAAA,YACN,QAAQ;AAAA,cACP,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,YACA,QAAQ,CAAC;AAAA,UACV,CAAC;AACD,eAAK,KAAK;AAAA,YACT,GAAG,aAAa;AAAA,YAChB,uBAAuB,IAAI,KAAK;AAAA,UACjC;AACA,eAAK,KAAK,mBAAmB,GAAG,aAAa,oBAAoB;AAAA,YAChE,MAAM;AAAA,YACN,QAAQ;AAAA,cACP,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,YACA,QAAQ,CAAC;AAAA,UACV,CAAC;AACD,gBAAM,cAAc,QAAI,+BAAe,uBAAuB,IAAI,KAAK,MAAM,CAAC,CAAC,OAAG,+BAAe,uBAAuB,IAAI,KAAK,MAAM,CAAC,CAAC,OAAG,+BAAe,uBAAuB,IAAI,KAAK,MAAM,CAAC,CAAC;AACnM,eAAK,KAAK,SAAS,GAAG,aAAa,oBAAoB;AAAA,YACtD,KAAK;AAAA,YACL,KAAK;AAAA,UACN,CAAC;AACD,eAAK,KAAK,iBAAiB,GAAG,aAAa,oBAAoB,WAAW;AAC1E,eAAK,KAAK,mBAAmB,GAAG,aAAa,+BAA+B;AAAA,YAC3E,MAAM;AAAA,YACN,QAAQ;AAAA,cACP,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,YACA,QAAQ,CAAC;AAAA,UACV,CAAC;AACD,eAAK,KAAK;AAAA,YACT,GAAG,aAAa;AAAA,YAChB,uBAAuB,IAAI,KAAK;AAAA,UACjC;AAAA,QACD;AACA;AAAA,MACD;AAAA,MACA,SAAS;AACR,aAAK,IAAI,MAAM,iBAAiB,OAAO,OAAO,IAAI,OAAO,IAAI,MAAM,QAAQ,SAAS,CAAC,EAAE;AAAA,MACxF;AAAA,IACD;AACA,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA,EAEA,MAAc,oBAAmC;AAChD,eAAW,MAAM,SAAS;AACzB,WAAK,oBAAoB,EAAE;AAAA,IAC5B;AACA,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoB,UAAwB;AACnD,UAAM,4BAA4B,OAAO,KAAK,KAAK,UAAU,oBAAoB,CAAC;AAClF,SAAK,OAAO,KAAK,2BAA2B,GAAG,0BAA0B,QAAQ,cAAc,QAAQ;AAAA,EACxG;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,WAA0B;AACvC,UAAM,oBAAoB,OAAO,KAAK,KAAK,UAAU,WAAW,CAAC;AACjE,SAAK,OAAO,KAAK,mBAAmB,GAAG,kBAAkB,QAAQ,gBAAgB,MAAM;AACvF,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,SAAS,UAA4B;AAC5C,QAAI;AACH,WAAK,cAAc,cAAc;AACjC,WAAK,cAAc,eAAe;AAClC,aAAO,MAAM;AACb,WAAK,KAAK,iBAAiB,mBAAmB,KAAK;AACnD,eAAS;AAAA,IACV,SAAS,GAAQ;AAChB,WAAK,IAAI,MAAM,EAAE,OAAO;AACxB,eAAS;AAAA,IACV;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,cAAc,IAAY,OAAyD;AA5QlG;AA6QE,QAAI,SAAS,CAAC,MAAM,KAAK;AACxB,YAAM,aAAa,MAAM,KAAK,cAAc,GAAG,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,gBAAgB;AAC/E,UAAI,YAAY;AACf,cAAM,YAAW,gBAAW,QAAX,mBAAgB;AACjC,gBAAQ,GAAG,MAAM,GAAG,EAAE,CAAC,GAAG;AAAA,UACzB,KAAK,SAAS;AACb,kBAAM,cAAc,EAAE,KAAK,EAAE,KAAK,QAAQ,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI,EAAE,EAAE,EAAE;AAC/E,kBAAM,oBAAoB,OAAO,KAAK,KAAK,UAAU,WAAW,CAAC;AACjE,iBAAK,OAAO,KAAK,mBAAmB,GAAG,kBAAkB,QAAQ,cAAc,QAAQ;AACvF;AAAA,UACD;AAAA,UACA,KAAK,cAAc;AAClB,kBAAM,oBAAoB,EAAE,KAAK,EAAE,KAAK,cAAc,MAAM,EAAE,OAAO,MAAM,IAAI,EAAE,EAAE;AACnF,kBAAM,0BAA0B,OAAO,KAAK,KAAK,UAAU,iBAAiB,CAAC;AAC7E,iBAAK,OAAO;AAAA,cACX;AAAA,cACA;AAAA,cACA,wBAAwB;AAAA,cACxB;AAAA,cACA;AAAA,YACD;AACA;AAAA,UACD;AAAA,UACA,KAAK,oBAAoB;AACxB,kBAAM,yBAAyB,OAAO;AAAA,cACrC,KAAK,UAAU;AAAA,gBACd,KAAK;AAAA,kBACJ,KAAK;AAAA,kBACL,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,kBAAkB,MAAM,IAAI;AAAA,gBACxE;AAAA,cACD,CAAC;AAAA,YACF;AACA,iBAAK,OAAO;AAAA,cACX;AAAA,cACA;AAAA,cACA,uBAAuB;AAAA,cACvB;AAAA,cACA;AAAA,YACD;AACA;AAAA,UACD;AAAA,UACA,KAAK,SAAS;AACb,kBAAM,cAAa,WAAM,QAAN,mBAAW;AAC9B,gBAAI,YAAY;AACf,oBAAM,UAAM,yBAAS,UAAU;AAC/B,oBAAM,eAAe,EAAE,KAAK,EAAE,KAAK,WAAW,MAAM,EAAE,OAAO,IAAI,EAAE,EAAE;AACrE,oBAAM,qBAAqB,OAAO,KAAK,KAAK,UAAU,YAAY,CAAC;AACnE,mBAAK,OAAO,KAAK,oBAAoB,GAAG,mBAAmB,QAAQ,cAAc,QAAQ;AAAA,YAC1F;AACA;AAAA,UACD;AAAA,QACD;AAAA,MACD,OAAO;AACN,aAAK,IAAI,MAAM,kBAAkB;AAAA,MAClC;AAAA,IACD;AACA,WAAO,QAAQ,QAAQ;AAAA,EACxB;AAAA,EAEA,MAAc,iBAAiB,UAAkB,OAAY,eAAe,MAAqB;AAChG,UAAM,eAAe,MAAM,KAAK,cAAc,QAAQ;AACtD,QAAI,gBAAgB,OAAO;AAC1B,WAAK,KAAK,SAAS,UAAU;AAAA,QAC5B,KAAK;AAAA,QACL,KAAK;AAAA,MACN,CAAC;AAAA,IACF;AAAA,EACD;AACD;AAEA,IAAI,QAAQ,SAAS,QAAQ;AAE5B,SAAO,UAAU,CAAC,YAAuD,IAAI,WAAW,OAAO;AAChG,OAAO;AAEN,GAAC,MAAM,IAAI,WAAW,GAAG;AAC1B;AAUO,SAAS,wBAAwB,MAAsB;AAC7D,UAAQ,MAAM;AAAA,IACb,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/tools/hexTool.js
CHANGED
|
@@ -24,7 +24,7 @@ __export(hexTool_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(hexTool_exports);
|
|
25
25
|
function componentToHex(c) {
|
|
26
26
|
const hex = c.toString(16);
|
|
27
|
-
return hex.length == 1 ?
|
|
27
|
+
return hex.length == 1 ? `0${hex}` : hex;
|
|
28
28
|
}
|
|
29
29
|
function hexToRgb(hexString) {
|
|
30
30
|
if (!/^#[0-9a-fA-F]{6}$/i.test(hexString)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/tools/hexTool.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n *
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["/**\n * Konvertiert eine Zahl (<255) in einen zweistelligen Hex-String f\u00FCr Farbwerte.\n *\n * @param c Die Zahl, die konvertiert werden soll (0-255)\n * @returns Der Hex-Wert als String\n */\nexport function componentToHex(c: number): string {\n\tconst hex = c.toString(16);\n\treturn hex.length == 1 ? `0${hex}` : hex;\n}\n\n/**\n * Wandelt einen Hex-Farbstring (#RRGGBB) in ein Color-Objekt um.\n *\n * @param hexString Hex-Farbwert als String (Format: #RRGGBB)\n * @returns Ein Objekt mit den Farbwerten r, g und b\n */\nexport function hexToRgb(hexString: string): Color {\n\tif (!/^#[0-9a-fA-F]{6}$/i.test(hexString)) {\n\t\tthrow new Error('Invalid hex string');\n\t}\n\treturn {\n\t\tr: parseInt(hexString.slice(1, 3), 16),\n\t\tg: parseInt(hexString.slice(3, 5), 16),\n\t\tb: parseInt(hexString.slice(5, 7), 16),\n\t};\n}\n\n/**\n * Farbobjekt mit Werten f\u00FCr Rot, Gr\u00FCn und Blau\n */\ntype Color = {\n\tr: number;\n\tg: number;\n\tb: number;\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,SAAS,eAAe,GAAmB;AACjD,QAAM,MAAM,EAAE,SAAS,EAAE;AACzB,SAAO,IAAI,UAAU,IAAI,IAAI,GAAG,KAAK;AACtC;AAQO,SAAS,SAAS,WAA0B;AAClD,MAAI,CAAC,qBAAqB,KAAK,SAAS,GAAG;AAC1C,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACrC;AACA,SAAO;AAAA,IACN,GAAG,SAAS,UAAU,MAAM,GAAG,CAAC,GAAG,EAAE;AAAA,IACrC,GAAG,SAAS,UAAU,MAAM,GAAG,CAAC,GAAG,EAAE;AAAA,IACrC,GAAG,SAAS,UAAU,MAAM,GAAG,CAAC,GAAG,EAAE;AAAA,EACtC;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "govee-local",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.9",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.2.9": {
|
|
7
|
+
"en": "update dependencies\nadd support for node 24\nupdate to ESlint 9",
|
|
8
|
+
"de": "aktualisierung der abhängigkeiten\nunterstützung für knoten 24 hinzufügen\nupdate auf ESlint 9",
|
|
9
|
+
"ru": "обновление зависимостей\nдобавить поддержку node 24\nобновление для ESlint 9",
|
|
10
|
+
"pt": "atualizar dependências\nadicionar suporte para o nó 24\natualização para ESlint 9",
|
|
11
|
+
"nl": "afhankelijkheden bijwerken\nondersteuning voor node 24 toevoegen\nupdate naar ESlint 9",
|
|
12
|
+
"fr": "mettre à jour les dépendances\najouter un support pour le nœud 24\nmise à jour de ESlint 9",
|
|
13
|
+
"it": "aggiornamento dipendenze\naggiungere supporto per nodo 24\naggiornamento a ESlint 9",
|
|
14
|
+
"es": "dependencias de actualización\nañadir soporte para nodo 24\nactualización a ESlint 9",
|
|
15
|
+
"pl": "aktualizacji zależności\ndodaj obsługę węzła 24\naktualizacja do ESlint 9",
|
|
16
|
+
"uk": "оновлення залежності\nдодати підтримку для вузла 24\nоновлення до ESlint 9",
|
|
17
|
+
"zh-cn": "更新依赖关系\n添加节点24的支持\n更新到 Eslint 9"
|
|
18
|
+
},
|
|
19
|
+
"0.2.8": {
|
|
20
|
+
"en": "update dependencies",
|
|
21
|
+
"de": "aktualisierung der abhängigkeiten",
|
|
22
|
+
"ru": "обновление зависимостей",
|
|
23
|
+
"pt": "dependências",
|
|
24
|
+
"nl": "afhankelijkheden bijwerken",
|
|
25
|
+
"fr": "mettre à jour les dépendances",
|
|
26
|
+
"it": "aggiornamento dipendenze",
|
|
27
|
+
"es": "dependencias de actualización",
|
|
28
|
+
"pl": "aktualizacji zależności",
|
|
29
|
+
"uk": "оновлення залежності",
|
|
30
|
+
"zh-cn": "更新依赖关系"
|
|
31
|
+
},
|
|
6
32
|
"0.2.7": {
|
|
7
33
|
"en": "update core dependencies and min required node version to 18",
|
|
8
34
|
"de": "aktualisieren von kernabhängigkeiten und min benötigte knotenversion bis 18",
|
|
@@ -67,19 +93,6 @@
|
|
|
67
93
|
"pl": "remontowanie Off / wszystkie inne działania Fiksy #65\nusunąć z powodu dzikiej karty",
|
|
68
94
|
"uk": "ремонт наОфф / всі інші дії Виправлення: #65\nфіксація спамерування колод через дикийкарт",
|
|
69
95
|
"zh-cn": "b. 修理效率/所有其他行动 固定: #65\nfix 由于野生素卡的投机"
|
|
70
|
-
},
|
|
71
|
-
"0.2.0": {
|
|
72
|
-
"en": "support controlling the color\nextended logging mode",
|
|
73
|
-
"de": "unterstützung controlling der farbe\nerweiterter logging-modus",
|
|
74
|
-
"ru": "поддержка контролируя цвет\nрасширенный режим входа",
|
|
75
|
-
"pt": "suporte controlando a cor\nmodo de registro estendido",
|
|
76
|
-
"nl": "de kleur controleren\nverlengde logging mode",
|
|
77
|
-
"fr": "support de contrôle de la couleur\nmode d ' enregistrement élargi",
|
|
78
|
-
"it": "supporto che controlla il colore\nmodalità di registrazione estesa",
|
|
79
|
-
"es": "soporte controlando el color\nmodo de registro ampliado",
|
|
80
|
-
"pl": "kontrolować kolor\nrozszerzony tryb logowania",
|
|
81
|
-
"uk": "супровід управління кольором\nрозширений режим входу",
|
|
82
|
-
"zh-cn": "控制颜色的支助\n扩大的伐木模式"
|
|
83
96
|
}
|
|
84
97
|
},
|
|
85
98
|
"titleLang": {
|
|
@@ -142,7 +155,7 @@
|
|
|
142
155
|
],
|
|
143
156
|
"globalDependencies": [
|
|
144
157
|
{
|
|
145
|
-
"admin": ">=
|
|
158
|
+
"admin": ">=7.4.10"
|
|
146
159
|
}
|
|
147
160
|
]
|
|
148
161
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.govee-local",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "Control Govee devices via local access (no cloud)",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Børge Grunicke",
|
|
@@ -19,44 +19,41 @@
|
|
|
19
19
|
"url": "git@github.com:boergegrunicke/ioBroker.govee-local.git"
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
22
|
-
"node": ">=
|
|
22
|
+
"node": ">= 20.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@iobroker/adapter-core": "^3.
|
|
25
|
+
"@iobroker/adapter-core": "^3.2.3"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@alcalzone/release-script": "^3.8.0",
|
|
29
29
|
"@alcalzone/release-script-plugin-iobroker": "^3.7.2",
|
|
30
30
|
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
31
31
|
"@alcalzone/release-script-plugin-manual-review": "^3.7.0",
|
|
32
|
-
"@iobroker/adapter-dev": "^1.
|
|
33
|
-
"@iobroker/
|
|
34
|
-
"@
|
|
32
|
+
"@iobroker/adapter-dev": "^1.4.0",
|
|
33
|
+
"@iobroker/eslint-config": "^2.0.2",
|
|
34
|
+
"@iobroker/testing": "^5.0.4",
|
|
35
|
+
"@tsconfig/node14": "^14.1.3",
|
|
35
36
|
"@tsconfig/node18": "^18.2.4",
|
|
36
|
-
"@tsconfig/node20": "^20.1.
|
|
37
|
+
"@tsconfig/node20": "^20.1.6",
|
|
37
38
|
"@types/chai": "^4.1.1",
|
|
38
|
-
"@types/chai-as-promised": "^
|
|
39
|
-
"@types/mocha": "^10.0.
|
|
40
|
-
"@types/node": "^
|
|
39
|
+
"@types/chai-as-promised": "^8.0.2",
|
|
40
|
+
"@types/mocha": "^10.0.10",
|
|
41
|
+
"@types/node": "^24.0.8",
|
|
41
42
|
"@types/proxyquire": "^1.3.31",
|
|
42
|
-
"@types/sinon": "^17.0.
|
|
43
|
+
"@types/sinon": "^17.0.4",
|
|
43
44
|
"@types/sinon-chai": "^3.2.12",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"eslint": "^8.57.0",
|
|
49
|
-
"eslint-config-prettier": "^9.1.0",
|
|
50
|
-
"eslint-plugin-prettier": "^5.2.1",
|
|
51
|
-
"mocha": "^10.7.0",
|
|
45
|
+
"chai": "^4.5.0",
|
|
46
|
+
"chai-as-promised": "^8.0.1",
|
|
47
|
+
"eslint": "^9.32.0",
|
|
48
|
+
"mocha": "^11.7.1",
|
|
52
49
|
"prettier": "^3.3.3",
|
|
53
50
|
"proxyquire": "^2.1.3",
|
|
54
51
|
"rimraf": "^6.0.1",
|
|
55
|
-
"sinon": "^
|
|
52
|
+
"sinon": "^21.0.0",
|
|
56
53
|
"sinon-chai": "^3.7.0",
|
|
57
54
|
"source-map-support": "^0.5.21",
|
|
58
55
|
"ts-node": "^10.9.2",
|
|
59
|
-
"typescript": "^5.
|
|
56
|
+
"typescript": "^5.6.3"
|
|
60
57
|
},
|
|
61
58
|
"main": "build/main.js",
|
|
62
59
|
"files": [
|