iobroker.govee-local 0.0.3

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Børge Grunicke <boerge@grunicke.de>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ ## govee-local adapter for ioBroker
2
+
3
+ Control Govee devices via local access (no cloud)
4
+
5
+ To be able to control govee deivce locally, the feature needs to be explicitely turned on in the settings of the govve application settings as described in their [documentation](<https://app-h5.govee.com/user-manual/wlan-guide#:~:text=Supported%20Product%20Models%20(continually%20updated)>)
6
+ As I currently only have the H6051 lamp, this is the only device I can test with.
7
+
8
+ ## Changelog
9
+ ### 0.0.3 (2023-04-01)
10
+
11
+ - update dependecies
12
+
13
+ ### 0.0.2
14
+
15
+ - frequently searching for devices and requesting their specific state
16
+ - on / off state, brightness and and color temperature can be controlled
17
+
18
+ ## License
19
+
20
+ MIT License
21
+
22
+ Copyright (c) 2023 Børge Grunicke
23
+
24
+ Permission is hereby granted, free of charge, to any person obtaining a copy
25
+ of this software and associated documentation files (the "Software"), to deal
26
+ in the Software without restriction, including without limitation the rights
27
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28
+ copies of the Software, and to permit persons to whom the Software is
29
+ furnished to do so, subject to the following conditions:
30
+
31
+ The above copyright notice and this permission notice shall be included in all
32
+ copies or substantial portions of the Software.
33
+
34
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40
+ SOFTWARE.
Binary file
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Adaptereinstellungen für govee-local",
3
+ "option1": "Option 1",
4
+ "option2": "Option 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Adapter settings for govee-local",
3
+ "option1": "option1",
4
+ "option2": "option2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Ajustes del adaptador para govee-local",
3
+ "option1": "Opción 1",
4
+ "option2": "opcion 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Paramètres d'adaptateur pour govee-local",
3
+ "option1": "Option 1",
4
+ "option2": "Option 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Impostazioni dell'adattatore per govee-local",
3
+ "option1": "opzione 1",
4
+ "option2": "opzione 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Adapterinstellingen voor govee-local",
3
+ "option1": "Optie 1",
4
+ "option2": "Optie 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Ustawienia adaptera dla govee-local",
3
+ "option1": "opcja 1",
4
+ "option2": "Opcja 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Configurações do adaptador para govee-local",
3
+ "option1": "Opção 1",
4
+ "option2": "opção 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Настройки адаптера для govee-local",
3
+ "option1": "Опция 1",
4
+ "option2": "вариант 2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "Adapter settings for govee-local",
3
+ "option1": "option1",
4
+ "option2": "option2"
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "govee-local adapter settings": "govee-local的适配器设置",
3
+ "option1": "选项1",
4
+ "option2": "选项2"
5
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "i18n": true,
3
+ "type": "panel",
4
+ "items": {
5
+ "option1": {
6
+ "type": "checkbox",
7
+ "label": "option1",
8
+ "newLine": true
9
+ },
10
+ "option2": {
11
+ "type": "text",
12
+ "label": "option2",
13
+ "newLine": true
14
+ }
15
+ }
16
+ }
package/build/main.js ADDED
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
18
+ mod
19
+ ));
20
+ var utils = __toESM(require("@iobroker/adapter-core"));
21
+ var dgram = __toESM(require("node:dgram"));
22
+ const LOCAL_PORT = 4002;
23
+ const SEND_SCAN_PORT = 4001;
24
+ const CONTROL_PORT = 4003;
25
+ const M_CAST = "239.255.255.250";
26
+ const server = dgram.createSocket("udp4");
27
+ const client = dgram.createSocket("udp4");
28
+ const scanMessage = { msg: { cmd: "scan", data: { account_topic: "reserved" } } };
29
+ const requestStatusMessage = { msg: { cmd: "devStatus", data: {} } };
30
+ let searchInterval;
31
+ class GoveeLocal extends utils.Adapter {
32
+ constructor(options = {}) {
33
+ super({
34
+ ...options,
35
+ name: "govee-local"
36
+ });
37
+ this.on("ready", this.onReady.bind(this));
38
+ this.on("stateChange", this.onStateChange.bind(this));
39
+ this.on("unload", this.onUnload.bind(this));
40
+ }
41
+ async onReady() {
42
+ this.setObjectNotExists("info.connection", {
43
+ type: "state",
44
+ common: {
45
+ name: "Device discovery running",
46
+ type: "boolean",
47
+ role: "indicator.connected",
48
+ read: true,
49
+ write: false
50
+ },
51
+ native: {}
52
+ });
53
+ server.on("message", this.onUdpMessage.bind(this));
54
+ server.bind(LOCAL_PORT, this.serverBound.bind(this));
55
+ this.subscribeStates("*.devStatus.*");
56
+ }
57
+ async serverBound() {
58
+ server.setBroadcast(true);
59
+ server.setMulticastTTL(128);
60
+ server.addMembership(M_CAST);
61
+ this.setState("info.connection", { val: true, ack: true });
62
+ this.log.info("UDP listening on " + server.address().address + ":" + server.address().port);
63
+ if (this.config.searchInterval == void 0) {
64
+ this.config.searchInterval = 1e4;
65
+ }
66
+ searchInterval = this.setInterval(this.sendScan.bind(this), this.config.searchInterval);
67
+ }
68
+ async onUdpMessage(message, remote) {
69
+ const messageObject = JSON.parse(message.toString());
70
+ switch (messageObject.msg.cmd) {
71
+ case "scan":
72
+ for (const key of Object.keys(messageObject.msg.data)) {
73
+ if (key != "device") {
74
+ this.setObjectNotExists(messageObject.msg.data.device, {
75
+ type: "device",
76
+ common: {
77
+ name: messageObject.msg.data.sku,
78
+ role: "group"
79
+ },
80
+ native: {}
81
+ });
82
+ this.setObjectNotExists(`${messageObject.msg.data.device}.deviceInfo.${key}`, {
83
+ type: "state",
84
+ common: {
85
+ name: getDatapointDescription(key),
86
+ type: "string",
87
+ role: "state",
88
+ read: true,
89
+ write: false
90
+ },
91
+ native: {}
92
+ });
93
+ this.setState(`${messageObject.msg.data.device}.deviceInfo.${key}`, {
94
+ val: messageObject.msg.data[key],
95
+ ack: true
96
+ });
97
+ }
98
+ }
99
+ this.requestDeviceStatus(remote.address);
100
+ break;
101
+ case "devStatus":
102
+ const devices = await this.getStatesAsync(this.name + "." + this.instance + ".*.deviceInfo.ip");
103
+ for (const key in devices) {
104
+ if (devices[key].val == remote.address) {
105
+ const sendingDevice = key.split(".")[2];
106
+ const devStatusMessageObject = JSON.parse(message.toString());
107
+ this.setObjectNotExists(`${sendingDevice}.devStatus.onOff`, {
108
+ type: "state",
109
+ common: {
110
+ name: "On / Off state of the lamp",
111
+ type: "boolean",
112
+ role: "switch",
113
+ read: true,
114
+ write: true
115
+ },
116
+ native: {}
117
+ });
118
+ this.setState(`${sendingDevice}.devStatus.onOff`, {
119
+ val: devStatusMessageObject.msg.data.onOff == 1,
120
+ ack: true
121
+ });
122
+ this.setObjectNotExists(`${sendingDevice}.devStatus.brightness`, {
123
+ type: "state",
124
+ common: {
125
+ name: "Brightness of the light",
126
+ type: "number",
127
+ role: "level.dimmer",
128
+ read: true,
129
+ write: true
130
+ },
131
+ native: {}
132
+ });
133
+ this.setState(`${sendingDevice}.devStatus.brightness`, {
134
+ val: devStatusMessageObject.msg.data.brightness,
135
+ ack: true
136
+ });
137
+ this.setObjectNotExists(`${sendingDevice}.devStatus.color`, {
138
+ type: "state",
139
+ common: {
140
+ name: "Current showing color of the lamp",
141
+ type: "string",
142
+ role: "level.color.rgb",
143
+ read: true,
144
+ write: true
145
+ },
146
+ native: {}
147
+ });
148
+ this.setState(`${sendingDevice}.devStatus.color`, {
149
+ val: "#" + componentToHex(devStatusMessageObject.msg.data.color.r) + componentToHex(devStatusMessageObject.msg.data.color.g) + componentToHex(devStatusMessageObject.msg.data.color.b),
150
+ ack: true
151
+ });
152
+ this.setObjectNotExists(`${sendingDevice}.devStatus.colorTemInKelvin`, {
153
+ type: "state",
154
+ common: {
155
+ name: "If staying in white light, the color temperature",
156
+ type: "number",
157
+ role: "level.color.temperature",
158
+ read: true,
159
+ write: true
160
+ },
161
+ native: {}
162
+ });
163
+ this.setState(`${sendingDevice}.devStatus.colorTemInKelvin`, {
164
+ val: devStatusMessageObject.msg.data.colorTemInKelvin,
165
+ ack: true
166
+ });
167
+ }
168
+ }
169
+ break;
170
+ default:
171
+ this.log.info("message from: " + remote.address + ":" + remote.port + " - " + message);
172
+ }
173
+ }
174
+ async requestDeviceStatus(receiver) {
175
+ const requestDeviceStatusBuffer = Buffer.from(JSON.stringify(requestStatusMessage));
176
+ client.send(requestDeviceStatusBuffer, 0, requestDeviceStatusBuffer.length, CONTROL_PORT, receiver);
177
+ }
178
+ async sendScan() {
179
+ const scanMessageBuffer = Buffer.from(JSON.stringify(scanMessage));
180
+ client.send(scanMessageBuffer, 0, scanMessageBuffer.length, SEND_SCAN_PORT, M_CAST);
181
+ }
182
+ onUnload(callback) {
183
+ try {
184
+ this.clearInterval(searchInterval);
185
+ client.close();
186
+ server.close();
187
+ this.setState("info.connection", { val: false, ack: true });
188
+ callback();
189
+ } catch (e) {
190
+ callback();
191
+ }
192
+ }
193
+ async onStateChange(id, state) {
194
+ var _a;
195
+ if (state && !state.ack) {
196
+ this.log.info(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
197
+ const ipOfDevice = await this.getStateAsync(id.split(".")[2] + ".deviceInfo.ip");
198
+ if (ipOfDevice) {
199
+ this.log.info("should send to ip : " + ipOfDevice.val);
200
+ const receiver = (_a = ipOfDevice.val) == null ? void 0 : _a.toString();
201
+ switch (id.split(".")[4]) {
202
+ case "onOff":
203
+ const turnMessage = { msg: { cmd: "turn", data: { value: state.val ? 1 : 0 } } };
204
+ const turnMessageBuffer = Buffer.from(JSON.stringify(turnMessage));
205
+ client.send(turnMessageBuffer, 0, turnMessageBuffer.length, CONTROL_PORT, receiver);
206
+ break;
207
+ case "brightness":
208
+ const brightnessMessage = { msg: { cmd: "brightness", data: { value: state.val } } };
209
+ const brightnessMessageBuffer = Buffer.from(JSON.stringify(brightnessMessage));
210
+ client.send(brightnessMessageBuffer, 0, brightnessMessageBuffer.length, CONTROL_PORT, receiver);
211
+ break;
212
+ case "colorTemInKelvin":
213
+ const colorTempMessage = { msg: { cmd: "colorTemInKelvin", data: { value: state.val } } };
214
+ const colorTempMessageBuffer = Buffer.from(JSON.stringify(colorTempMessage));
215
+ client.send(colorTempMessageBuffer, 0, colorTempMessageBuffer.length, CONTROL_PORT, receiver);
216
+ }
217
+ } else {
218
+ this.log.error("device not found");
219
+ }
220
+ }
221
+ }
222
+ }
223
+ if (require.main !== module) {
224
+ module.exports = (options) => new GoveeLocal(options);
225
+ } else {
226
+ (() => new GoveeLocal())();
227
+ }
228
+ function getDatapointDescription(name) {
229
+ switch (name) {
230
+ case "model":
231
+ return "Specific model of the Lamp";
232
+ case "ip":
233
+ return "Specific model of the Lamp";
234
+ case "bleVersionHard":
235
+ return "Bluetooth Low Energy Hardware Version";
236
+ case "bleVersionSoft":
237
+ return "Bluetooth Low Energy Software Version";
238
+ case "wifiVersionHard":
239
+ return "WiFi Hardware Version";
240
+ case "wifiVersionSoft":
241
+ return "WiFi Software Version";
242
+ default:
243
+ return "";
244
+ }
245
+ }
246
+ function componentToHex(c) {
247
+ const hex = c.toString(16);
248
+ return hex.length == 1 ? "0" + hex : hex;
249
+ }
250
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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';\n\n// Load your modules here, e.g.:\n// import * as fs from \"fs\";\n\nconst LOCAL_PORT = 4002;\nconst SEND_SCAN_PORT = 4001;\nconst CONTROL_PORT = 4003;\nconst M_CAST = '239.255.255.250';\n\nconst server = dgram.createSocket('udp4');\nconst client = dgram.createSocket('udp4');\n\nconst scanMessage = { msg: { cmd: 'scan', data: { account_topic: 'reserved' } } };\nconst requestStatusMessage = { msg: { cmd: 'devStatus', data: {} } };\n\nlet searchInterval: ioBroker.Interval;\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\tserver.on('message', this.onUdpMessage.bind(this));\n\n\t\tserver.bind(LOCAL_PORT, this.serverBound.bind(this));\n\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\tserver.setBroadcast(true);\n\t\tserver.setMulticastTTL(128);\n\t\tserver.addMembership(M_CAST);\n\t\tthis.setState('info.connection', { val: true, ack: true });\n\t\tthis.log.info('UDP listening on ' + server.address().address + ':' + server.address().port);\n\n\t\tif (this.config.searchInterval == undefined) {\n\t\t\tthis.config.searchInterval = 10000;\n\t\t}\n\t\tsearchInterval = this.setInterval(this.sendScan.bind(this), this.config.searchInterval);\n\t\t// this.sendScan();\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\tthis.setObjectNotExists(messageObject.msg.data.device, {\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(`${messageObject.msg.data.device}.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(`${messageObject.msg.data.device}.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\n\t\t\t\tthis.requestDeviceStatus(remote.address);\n\t\t\t\tbreak;\n\t\t\tcase 'devStatus':\n\t\t\t\tconst devices = await this.getStatesAsync(this.name + '.' + this.instance + '.*.deviceInfo.ip');\n\t\t\t\tfor (const key in devices) {\n\t\t\t\t\tif (devices[key as keyof typeof devices].val == remote.address) {\n\t\t\t\t\t\tconst sendingDevice = key.split('.')[2];\n\t\t\t\t\t\tconst devStatusMessageObject = JSON.parse(message.toString());\n\t\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.onOff`, {\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: 'On / Off state of the lamp',\n\t\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\t\trole: 'switch',\n\t\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\t\twrite: true,\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(`${sendingDevice}.devStatus.onOff`, {\n\t\t\t\t\t\t\tval: devStatusMessageObject.msg.data.onOff == 1,\n\t\t\t\t\t\t\tack: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.brightness`, {\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: 'Brightness of the light',\n\t\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\t\trole: 'level.dimmer',\n\t\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\t\twrite: true,\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(`${sendingDevice}.devStatus.brightness`, {\n\t\t\t\t\t\t\tval: devStatusMessageObject.msg.data.brightness,\n\t\t\t\t\t\t\tack: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.color`, {\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: 'Current showing color of the lamp',\n\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\trole: 'level.color.rgb',\n\t\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\t\twrite: true,\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(`${sendingDevice}.devStatus.color`, {\n\t\t\t\t\t\t\tval:\n\t\t\t\t\t\t\t\t'#' +\n\t\t\t\t\t\t\t\tcomponentToHex(devStatusMessageObject.msg.data.color.r) +\n\t\t\t\t\t\t\t\tcomponentToHex(devStatusMessageObject.msg.data.color.g) +\n\t\t\t\t\t\t\t\tcomponentToHex(devStatusMessageObject.msg.data.color.b),\n\t\t\t\t\t\t\tack: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.setObjectNotExists(`${sendingDevice}.devStatus.colorTemInKelvin`, {\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: 'If staying in white light, the color temperature',\n\t\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\t\trole: 'level.color.temperature',\n\t\t\t\t\t\t\t\tread: true,\n\t\t\t\t\t\t\t\twrite: true,\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(`${sendingDevice}.devStatus.colorTemInKelvin`, {\n\t\t\t\t\t\t\tval: devStatusMessageObject.msg.data.colorTemInKelvin,\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\tdefault:\n\t\t\t\tthis.log.info('message from: ' + remote.address + ':' + remote.port + ' - ' + message);\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 async requestDeviceStatus(receiver: string): Promise<void> {\n\t\tconst requestDeviceStatusBuffer = Buffer.from(JSON.stringify(requestStatusMessage));\n\t\tclient.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\tclient.send(scanMessageBuffer, 0, scanMessageBuffer.length, SEND_SCAN_PORT, M_CAST);\n\t\t//this.log.info('send message ' + scanMessageBuffer);\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\tclient.close();\n\t\t\tserver.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\tthis.log.info(`state ${id} changed: ${state.val} (ack = ${state.ack})`);\n\t\t\tconst ipOfDevice = await this.getStateAsync(id.split('.')[2] + '.deviceInfo.ip');\n\t\t\tif (ipOfDevice) {\n\t\t\t\tthis.log.info('should send to ip : ' + ipOfDevice.val);\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\tclient.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\tclient.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 colorTempMessage = { msg: { cmd: 'colorTemInKelvin', data: { value: state.val } } };\n\t\t\t\t\t\tconst colorTempMessageBuffer = Buffer.from(JSON.stringify(colorTempMessage));\n\t\t\t\t\t\tclient.send(colorTempMessageBuffer, 0, colorTempMessageBuffer.length, CONTROL_PORT, receiver);\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 'Specific model 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\n/**\n * Convert number (<255) to two digit hex for colorcode\n * @param the int value, should me < 255\n * @returns the hex value as string\n */\nfunction componentToHex(c: number): string {\n\tconst hex = c.toString(16);\n\treturn hex.length == 1 ? '0' + hex : hex;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "common": {
3
+ "name": "govee-local",
4
+ "version": "0.0.3",
5
+ "news": {
6
+ "0.0.3": {
7
+ "en": "update dependecies",
8
+ "de": "aktualisierung der abhängigkeiten",
9
+ "ru": "обновление зависимостей",
10
+ "pt": "atualizações",
11
+ "nl": "vertaling:",
12
+ "fr": "mettre à jour les dépendances",
13
+ "it": "dipendenze di aggiornamento",
14
+ "es": "dependencias de actualización",
15
+ "pl": "aktualizacja",
16
+ "uk": "оновлення залежності",
17
+ "zh-cn": "a. 最新依赖情况"
18
+ },
19
+ "0.0.2": {
20
+ "en": "initial release",
21
+ "de": "erstausstrahlung",
22
+ "ru": "начальный выпуск",
23
+ "pt": "lançamento inicial",
24
+ "nl": "niet",
25
+ "fr": "initial release",
26
+ "it": "rilascio iniziale",
27
+ "es": "liberación inicial",
28
+ "pl": "pierwsze wydanie",
29
+ "uk": "початковий реліз",
30
+ "zh-cn": "初步释放"
31
+ },
32
+ "0.0.1": {
33
+ "en": "initial release",
34
+ "de": "Erstveröffentlichung",
35
+ "ru": "Начальная версия",
36
+ "pt": "lançamento inicial",
37
+ "nl": "Eerste uitgave",
38
+ "fr": "Première version",
39
+ "it": "Versione iniziale",
40
+ "es": "Versión inicial",
41
+ "pl": "Pierwsze wydanie",
42
+ "zh-cn": "首次出版"
43
+ }
44
+ },
45
+ "title": "Govee Local",
46
+ "titleLang": {
47
+ "en": "Govee Local",
48
+ "de": "Govee Lokal",
49
+ "ru": "Гови Местный",
50
+ "pt": "Govee local",
51
+ "nl": "Govee Lokaal",
52
+ "fr": "Gouverner local",
53
+ "it": "Govee Local",
54
+ "es": "Gobierno Local",
55
+ "pl": "Lokalny Govee",
56
+ "zh-cn": "当地政府"
57
+ },
58
+ "desc": {
59
+ "en": "Control Govee devices via local access (no cloud)",
60
+ "de": "Steuerung von Govee-Geräten über lokalen Zugriff (keine Cloud)",
61
+ "ru": "Управляйте устройствами Govee через локальный доступ (без облака)",
62
+ "pt": "Controle os dispositivos Govee via acesso local (sem nuvem)",
63
+ "nl": "Bedien Govee-apparaten via lokale toegang (geen cloud)",
64
+ "fr": "Contrôlez les appareils Govee via un accès local (pas de cloud)",
65
+ "it": "Controlla i dispositivi Govee tramite accesso locale (no cloud)",
66
+ "es": "Controle los dispositivos Govee a través del acceso local (sin nube)",
67
+ "pl": "Steruj urządzeniami Govee przez dostęp lokalny (bez chmury)",
68
+ "zh-cn": "通过本地访问控制 Govee 设备(无云)"
69
+ },
70
+ "authors": [
71
+ "Børge Grunicke <boerge@grunicke.de>"
72
+ ],
73
+ "keywords": [
74
+ "govee",
75
+ "light",
76
+ "local"
77
+ ],
78
+ "license": "MIT",
79
+ "platform": "Javascript/Node.js",
80
+ "main": "build/main.js",
81
+ "icon": "govee-local.png",
82
+ "enabled": true,
83
+ "extIcon": "https://raw.githubusercontent.com/boergegrunicke/ioBroker.govee-local/main/admin/govee-local.png",
84
+ "readme": "https://github.com/boergegrunicke/ioBroker.govee-local/blob/main/README.md",
85
+ "loglevel": "info",
86
+ "mode": "daemon",
87
+ "type": "lighting",
88
+ "compact": true,
89
+ "connectionType": "local",
90
+ "dataSource": "poll",
91
+ "adminUI": {
92
+ "config": "json"
93
+ },
94
+ "dependencies": [
95
+ {
96
+ "js-controller": ">=3.3.22"
97
+ }
98
+ ],
99
+ "globalDependencies": [
100
+ {
101
+ "admin": ">=5.1.13"
102
+ }
103
+ ]
104
+ },
105
+ "native": {
106
+ "option1": true,
107
+ "option2": "42"
108
+ },
109
+ "objects": [],
110
+ "instanceObjects": []
111
+ }
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "iobroker.govee-local",
3
+ "version": "0.0.3",
4
+ "description": "Control Govee devices via local access (no cloud)",
5
+ "author": {
6
+ "name": "Børge Grunicke",
7
+ "email": "boerge@grunicke.de"
8
+ },
9
+ "homepage": "https://github.com/boergegrunicke/ioBroker.govee-local",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "govee",
13
+ "light",
14
+ "local"
15
+ ],
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git@github.com:boergegrunicke/ioBroker.govee-local.git"
19
+ },
20
+ "engines": {
21
+ "node": ">= 14"
22
+ },
23
+ "dependencies": {
24
+ "@iobroker/adapter-core": "^2.6.7"
25
+ },
26
+ "devDependencies": {
27
+ "@alcalzone/release-script": "^3.5.9",
28
+ "@alcalzone/release-script-plugin-iobroker": "^3.5.9",
29
+ "@alcalzone/release-script-plugin-license": "^3.5.9",
30
+ "@alcalzone/release-script-plugin-manual-review": "^3.5.9",
31
+ "@iobroker/adapter-dev": "^1.2.0",
32
+ "@iobroker/testing": "^4.1.0",
33
+ "@tsconfig/node14": "^1.0.3",
34
+ "@types/chai": "^4.3.4",
35
+ "@types/chai-as-promised": "^7.1.5",
36
+ "@types/mocha": "^10.0.1",
37
+ "@types/node": "^18.15.11",
38
+ "@types/proxyquire": "^1.3.28",
39
+ "@types/sinon": "^10.0.13",
40
+ "@types/sinon-chai": "^3.2.9",
41
+ "@typescript-eslint/eslint-plugin": "^5.54.0",
42
+ "@typescript-eslint/parser": "^5.54.0",
43
+ "chai": "^4.3.7",
44
+ "chai-as-promised": "^7.1.1",
45
+ "eslint": "^8.37.0",
46
+ "eslint-config-prettier": "^8.6.0",
47
+ "eslint-plugin-prettier": "^4.2.1",
48
+ "mocha": "^10.2.0",
49
+ "prettier": "^2.8.7",
50
+ "proxyquire": "^2.1.3",
51
+ "rimraf": "^4.4.1",
52
+ "sinon-chai": "^3.7.0",
53
+ "sinon": "^15.0.1",
54
+ "source-map-support": "^0.5.21",
55
+ "ts-node": "^10.9.1",
56
+ "typescript": "~5.0.3"
57
+ },
58
+ "main": "build/main.js",
59
+ "files": [
60
+ "admin{,/!(src)/**}/!(tsconfig|tsconfig.*|.eslintrc).json",
61
+ "admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js}",
62
+ "build/",
63
+ "www/",
64
+ "io-package.json",
65
+ "LICENSE"
66
+ ],
67
+ "scripts": {
68
+ "prebuild": "rimraf build",
69
+ "build": "build-adapter ts",
70
+ "watch": "build-adapter ts --watch",
71
+ "prebuild:ts": "rimraf build",
72
+ "build:ts": "build-adapter ts",
73
+ "watch:ts": "build-adapter ts --watch",
74
+ "test:ts": "mocha --config test/mocharc.custom.json src/**/*.test.ts",
75
+ "test:package": "mocha test/package --exit",
76
+ "test:integration": "mocha test/integration --exit",
77
+ "test": "npm run test:ts && npm run test:package",
78
+ "check": "tsc --noEmit",
79
+ "lint": "eslint --ext .ts src/",
80
+ "translate": "translate-adapter",
81
+ "release": "release-script"
82
+ },
83
+ "bugs": {
84
+ "url": "https://github.com/boergegrunicke/ioBroker.govee-local/issues"
85
+ },
86
+ "readmeFilename": "README.md"
87
+ }