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 +21 -0
- package/README.md +40 -0
- package/admin/govee-local.png +0 -0
- package/admin/i18n/de/translations.json +5 -0
- package/admin/i18n/en/translations.json +5 -0
- package/admin/i18n/es/translations.json +5 -0
- package/admin/i18n/fr/translations.json +5 -0
- package/admin/i18n/it/translations.json +5 -0
- package/admin/i18n/nl/translations.json +5 -0
- package/admin/i18n/pl/translations.json +5 -0
- package/admin/i18n/pt/translations.json +5 -0
- package/admin/i18n/ru/translations.json +5 -0
- package/admin/i18n/uk/translations.json +5 -0
- package/admin/i18n/zh-cn/translations.json +5 -0
- package/admin/jsonConfig.json +16 -0
- package/build/main.js +250 -0
- package/build/main.js.map +7 -0
- package/io-package.json +111 -0
- package/package.json +87 -0
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
|
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
|
+
}
|
package/io-package.json
ADDED
|
@@ -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
|
+
}
|