iobroker.govee-local 0.2.7 → 0.2.8
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 +5 -1
- package/admin/jsonConfig.json +13 -1
- package/build/main.js +28 -17
- package/build/main.js.map +2 -2
- package/io-package.json +15 -2
- package/package.json +14 -14
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,10 @@ 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.8 (2025-03-28)
|
|
28
|
+
|
|
29
|
+
- update dependencies
|
|
30
|
+
|
|
27
31
|
### 0.2.7 (2024-08-18)
|
|
28
32
|
|
|
29
33
|
- update core dependencies and min required node version to 18
|
|
@@ -97,7 +101,7 @@ For **Windows** Users: Please go to the settings and make sure you choose the co
|
|
|
97
101
|
|
|
98
102
|
MIT License
|
|
99
103
|
|
|
100
|
-
Copyright (c)
|
|
104
|
+
Copyright (c) 2025 Børge Grunicke
|
|
101
105
|
|
|
102
106
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
103
107
|
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
|
@@ -127,10 +127,7 @@ class GoveeLocal extends utils.Adapter {
|
|
|
127
127
|
},
|
|
128
128
|
native: {}
|
|
129
129
|
});
|
|
130
|
-
this.
|
|
131
|
-
val: messageObject.msg.data[key],
|
|
132
|
-
ack: true
|
|
133
|
-
});
|
|
130
|
+
await this.updateStateAsync(`${deviceName}.deviceInfo.${key}`, messageObject.msg.data[key]);
|
|
134
131
|
}
|
|
135
132
|
}
|
|
136
133
|
break;
|
|
@@ -153,10 +150,10 @@ class GoveeLocal extends utils.Adapter {
|
|
|
153
150
|
},
|
|
154
151
|
native: {}
|
|
155
152
|
});
|
|
156
|
-
this.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
await this.updateStateAsync(
|
|
154
|
+
`${sendingDevice}.devStatus.onOff`,
|
|
155
|
+
devStatusMessageObject.msg.data.onOff == 1
|
|
156
|
+
);
|
|
160
157
|
this.setObjectNotExists(`${sendingDevice}.devStatus.brightness`, {
|
|
161
158
|
type: "state",
|
|
162
159
|
common: {
|
|
@@ -168,10 +165,10 @@ class GoveeLocal extends utils.Adapter {
|
|
|
168
165
|
},
|
|
169
166
|
native: {}
|
|
170
167
|
});
|
|
171
|
-
this.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
168
|
+
await this.updateStateAsync(
|
|
169
|
+
`${sendingDevice}.devStatus.brightness`,
|
|
170
|
+
devStatusMessageObject.msg.data.brightness
|
|
171
|
+
);
|
|
175
172
|
this.setObjectNotExists(`${sendingDevice}.devStatus.color`, {
|
|
176
173
|
type: "state",
|
|
177
174
|
common: {
|
|
@@ -187,6 +184,10 @@ class GoveeLocal extends utils.Adapter {
|
|
|
187
184
|
val: "#" + (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),
|
|
188
185
|
ack: true
|
|
189
186
|
});
|
|
187
|
+
await this.updateStateAsync(
|
|
188
|
+
`${sendingDevice}.devStatus.color`,
|
|
189
|
+
`#${(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)}`
|
|
190
|
+
);
|
|
190
191
|
this.setObjectNotExists(`${sendingDevice}.devStatus.colorTemInKelvin`, {
|
|
191
192
|
type: "state",
|
|
192
193
|
common: {
|
|
@@ -198,10 +199,10 @@ class GoveeLocal extends utils.Adapter {
|
|
|
198
199
|
},
|
|
199
200
|
native: {}
|
|
200
201
|
});
|
|
201
|
-
this.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
await this.updateStateAsync(
|
|
203
|
+
`${sendingDevice}.devStatus.colorTemInKelvin`,
|
|
204
|
+
devStatusMessageObject.msg.data.colorTemInKelvin
|
|
205
|
+
);
|
|
205
206
|
}
|
|
206
207
|
break;
|
|
207
208
|
default:
|
|
@@ -236,9 +237,10 @@ class GoveeLocal extends utils.Adapter {
|
|
|
236
237
|
this.clearInterval(searchInterval);
|
|
237
238
|
this.clearInterval(refreshInterval);
|
|
238
239
|
socket.close();
|
|
239
|
-
this.
|
|
240
|
+
this.updateStateAsync("info.connection", false);
|
|
240
241
|
callback();
|
|
241
242
|
} catch (e) {
|
|
243
|
+
this.log.error(e.message);
|
|
242
244
|
callback();
|
|
243
245
|
}
|
|
244
246
|
}
|
|
@@ -288,6 +290,15 @@ class GoveeLocal extends utils.Adapter {
|
|
|
288
290
|
}
|
|
289
291
|
}
|
|
290
292
|
}
|
|
293
|
+
async updateStateAsync(fullName, state, acknowledged = true) {
|
|
294
|
+
const currentState = await this.getStateAsync(fullName);
|
|
295
|
+
if (currentState != state) {
|
|
296
|
+
this.setState(fullName, {
|
|
297
|
+
val: state,
|
|
298
|
+
ack: acknowledged
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
291
302
|
}
|
|
292
303
|
if (require.main !== module) {
|
|
293
304
|
module.exports = (options) => new GoveeLocal(options);
|
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": "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
|
|
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\tawait 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\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\tawait 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\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\tawait 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\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\tawait this.updateStateAsync(\n\t\t\t\t\t\t`${sendingDevice}.devStatus.color`,\n\t\t\t\t\t\t`#${componentToHex(devStatusMessageObject.msg.data.color.r)}${componentToHex(devStatusMessageObject.msg.data.color.g)}${componentToHex(devStatusMessageObject.msg.data.color.b)}`,\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\tawait 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\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.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\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\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\tthis.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// 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": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "govee-local",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.8",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.2.8": {
|
|
7
|
+
"en": "update dependencies",
|
|
8
|
+
"de": "aktualisierung der abhängigkeiten",
|
|
9
|
+
"ru": "обновление зависимостей",
|
|
10
|
+
"pt": "dependências",
|
|
11
|
+
"nl": "afhankelijkheden bijwerken",
|
|
12
|
+
"fr": "mettre à jour les dépendances",
|
|
13
|
+
"it": "aggiornamento dipendenze",
|
|
14
|
+
"es": "dependencias de actualización",
|
|
15
|
+
"pl": "aktualizacji zależności",
|
|
16
|
+
"uk": "оновлення залежності",
|
|
17
|
+
"zh-cn": "更新依赖关系"
|
|
18
|
+
},
|
|
6
19
|
"0.2.7": {
|
|
7
20
|
"en": "update core dependencies and min required node version to 18",
|
|
8
21
|
"de": "aktualisieren von kernabhängigkeiten und min benötigte knotenversion bis 18",
|
|
@@ -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.8",
|
|
4
4
|
"description": "Control Govee devices via local access (no cloud)",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Børge Grunicke",
|
|
@@ -19,10 +19,10 @@
|
|
|
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",
|
|
@@ -30,33 +30,33 @@
|
|
|
30
30
|
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
31
31
|
"@alcalzone/release-script-plugin-manual-review": "^3.7.0",
|
|
32
32
|
"@iobroker/adapter-dev": "^1.3.0",
|
|
33
|
-
"@iobroker/testing": "^
|
|
33
|
+
"@iobroker/testing": "^5.0.0",
|
|
34
34
|
"@tsconfig/node14": "^14.1.2",
|
|
35
35
|
"@tsconfig/node18": "^18.2.4",
|
|
36
36
|
"@tsconfig/node20": "^20.1.4",
|
|
37
37
|
"@types/chai": "^4.1.1",
|
|
38
|
-
"@types/chai-as-promised": "^
|
|
39
|
-
"@types/mocha": "^10.0.
|
|
40
|
-
"@types/node": "^
|
|
38
|
+
"@types/chai-as-promised": "^8.0.0",
|
|
39
|
+
"@types/mocha": "^10.0.9",
|
|
40
|
+
"@types/node": "^22.8.7",
|
|
41
41
|
"@types/proxyquire": "^1.3.31",
|
|
42
42
|
"@types/sinon": "^17.0.3",
|
|
43
43
|
"@types/sinon-chai": "^3.2.12",
|
|
44
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
45
|
-
"@typescript-eslint/parser": "^
|
|
46
|
-
"chai": "^4.
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^8.12.2",
|
|
45
|
+
"@typescript-eslint/parser": "^8.12.2",
|
|
46
|
+
"chai": "^4.5.0",
|
|
47
47
|
"chai-as-promised": "^8.0.0",
|
|
48
|
-
"eslint": "^8.57.
|
|
48
|
+
"eslint": "^8.57.1",
|
|
49
49
|
"eslint-config-prettier": "^9.1.0",
|
|
50
50
|
"eslint-plugin-prettier": "^5.2.1",
|
|
51
|
-
"mocha": "^10.
|
|
51
|
+
"mocha": "^10.8.2",
|
|
52
52
|
"prettier": "^3.3.3",
|
|
53
53
|
"proxyquire": "^2.1.3",
|
|
54
54
|
"rimraf": "^6.0.1",
|
|
55
|
-
"sinon": "^
|
|
55
|
+
"sinon": "^19.0.2",
|
|
56
56
|
"sinon-chai": "^3.7.0",
|
|
57
57
|
"source-map-support": "^0.5.21",
|
|
58
58
|
"ts-node": "^10.9.2",
|
|
59
|
-
"typescript": "^5.
|
|
59
|
+
"typescript": "^5.6.3"
|
|
60
60
|
},
|
|
61
61
|
"main": "build/main.js",
|
|
62
62
|
"files": [
|