homebridge-deconz 1.3.5 → 1.3.6-0
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/cli/deconz.js +1 -2
- package/cli/otau.js +1 -2
- package/cli/ui.js +36 -36
- package/jsdoc.json +1 -1
- package/lib/Deconz/Resource.js +8 -9
- package/lib/DeconzAccessory/Gateway.js +18 -8
- package/lib/DeconzAccessory/index.js +27 -19
- package/lib/DeconzService/Light.js +1 -3
- package/package.json +4 -4
package/cli/deconz.js
CHANGED
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
//
|
|
6
6
|
// Command line interface to deCONZ gateway.
|
|
7
7
|
|
|
8
|
-
import { createRequire } from 'node:module'
|
|
9
|
-
|
|
10
8
|
import { DeconzTool } from 'hb-deconz-tools/DeconzTool'
|
|
11
9
|
|
|
10
|
+
import { createRequire } from 'node:module'
|
|
12
11
|
const require = createRequire(import.meta.url)
|
|
13
12
|
const packageJson = require('../package.json')
|
|
14
13
|
|
package/cli/otau.js
CHANGED
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
//
|
|
6
6
|
// Command line interface to deCONZ gateway.
|
|
7
7
|
|
|
8
|
-
import { createRequire } from 'node:module'
|
|
9
|
-
|
|
10
8
|
import { OtauTool } from 'hb-deconz-tools/OtauTool'
|
|
11
9
|
|
|
10
|
+
import { createRequire } from 'node:module'
|
|
12
11
|
const require = createRequire(import.meta.url)
|
|
13
12
|
const packageJson = require('../package.json')
|
|
14
13
|
|
package/cli/ui.js
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// homebridge-deconz/cli/
|
|
3
|
+
// homebridge-deconz/cli/ui.js
|
|
4
4
|
// Copyright © 2018-2026 Erik Baauw. All rights reserved.
|
|
5
5
|
//
|
|
6
6
|
// Command line interface to Homebridge deCONZ UI Server.
|
|
7
7
|
|
|
8
8
|
import { readFile } from 'node:fs/promises'
|
|
9
|
-
import { createRequire } from 'node:module'
|
|
10
9
|
|
|
11
|
-
import { CommandLineParser } from 'hb-lib-tools/
|
|
12
|
-
import { CommandLineTool } from 'hb-lib-tools/CommandLineTool'
|
|
10
|
+
import { CommandLineTool, CommandLineParser, UsageError, b, u } from 'hb-lib-tools/CommandLineTool'
|
|
13
11
|
import { HttpClient } from 'hb-lib-tools/HttpClient'
|
|
14
12
|
import { JsonFormatter } from 'hb-lib-tools/JsonFormatter'
|
|
15
|
-
import {
|
|
13
|
+
import { patterns, toInt, toPath, toString } from 'hb-lib-tools/OptionParser'
|
|
16
14
|
|
|
15
|
+
import { createRequire } from 'node:module'
|
|
17
16
|
const require = createRequire(import.meta.url)
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const { b, u } = CommandLineTool
|
|
21
|
-
const { UsageError } = CommandLineParser
|
|
17
|
+
const defaultPackageJson = require('../package.json')
|
|
18
|
+
// import defaultPackageJson from '../package.json' with { type: 'json' }
|
|
22
19
|
|
|
23
20
|
const usage = {
|
|
24
21
|
ui: `${b('ui')} [${b('-hVD')}] [${b('-U')} ${u('username')}] [${b('-G')} ${u('gateway')}] [${b('-t')} ${u('timeout')}] ${u('command')} [${u('argument')} ...]`,
|
|
@@ -181,38 +178,38 @@ Parameters:
|
|
|
181
178
|
}
|
|
182
179
|
|
|
183
180
|
class Main extends CommandLineTool {
|
|
184
|
-
constructor () {
|
|
185
|
-
super({ mode: 'command', debug: false })
|
|
181
|
+
constructor (packageJson) {
|
|
182
|
+
super(packageJson ?? defaultPackageJson, { mode: 'command', debug: false })
|
|
186
183
|
this.usage = usage.deconz
|
|
187
184
|
}
|
|
188
185
|
|
|
189
186
|
parseArguments () {
|
|
190
|
-
const parser = new CommandLineParser(
|
|
187
|
+
const parser = new CommandLineParser(this)
|
|
191
188
|
const clargs = {
|
|
192
189
|
options: {
|
|
193
190
|
timeout: 5
|
|
194
191
|
}
|
|
195
192
|
}
|
|
196
193
|
parser
|
|
197
|
-
.
|
|
198
|
-
.
|
|
199
|
-
.
|
|
194
|
+
.helpFlag('h', 'help', help.ui)
|
|
195
|
+
.versionFlag('V', 'version')
|
|
196
|
+
.debugFlag('D', 'debug')
|
|
200
197
|
.option('U', 'username', (value) => {
|
|
201
|
-
clargs.username =
|
|
202
|
-
'username',
|
|
198
|
+
clargs.username = toString(
|
|
199
|
+
value, { key: 'username', nonEmpty: true, userInput: true }
|
|
203
200
|
).toUpperCase()
|
|
204
|
-
if (!
|
|
201
|
+
if (!patterns.mac.test(clargs.username)) {
|
|
205
202
|
throw new UsageError(`${clargs.username}: invalid username`)
|
|
206
203
|
}
|
|
207
204
|
})
|
|
208
205
|
.option('G', 'gateway', (value) => {
|
|
209
|
-
clargs.gateway =
|
|
210
|
-
'gateway',
|
|
206
|
+
clargs.gateway = toString(
|
|
207
|
+
value, { key: 'gateway', nonEmpty: true, userInput: true }
|
|
211
208
|
).toUpperCase()
|
|
212
209
|
})
|
|
213
210
|
.option('t', 'timeout', (value) => {
|
|
214
|
-
clargs.options.timeout =
|
|
215
|
-
'timeout',
|
|
211
|
+
clargs.options.timeout = toInt(
|
|
212
|
+
value, { key: 'timeout', min: 1, max: 60, userInput: true }
|
|
216
213
|
)
|
|
217
214
|
})
|
|
218
215
|
.parameter('command', (value) => {
|
|
@@ -342,7 +339,7 @@ class Main extends CommandLineTool {
|
|
|
342
339
|
timeout: this.clargs.options.timeout
|
|
343
340
|
})
|
|
344
341
|
const response = await client.get('/ping')
|
|
345
|
-
if (response.
|
|
342
|
+
if (response.jsonBody !== 'pong') {
|
|
346
343
|
throw new Error(`${host}: cannot ping`)
|
|
347
344
|
}
|
|
348
345
|
return client
|
|
@@ -382,12 +379,12 @@ class Main extends CommandLineTool {
|
|
|
382
379
|
}
|
|
383
380
|
|
|
384
381
|
async discover (platforms, ...args) {
|
|
385
|
-
const parser = new CommandLineParser(
|
|
382
|
+
const parser = new CommandLineParser(this)
|
|
386
383
|
const clargs = {
|
|
387
384
|
options: {}
|
|
388
385
|
}
|
|
389
386
|
parser
|
|
390
|
-
.
|
|
387
|
+
.helpFlag('h', 'help', help.get)
|
|
391
388
|
.flag('s', 'sortKeys', () => { clargs.options.sortKeys = true })
|
|
392
389
|
.flag('n', 'noWhiteSpace', () => {
|
|
393
390
|
clargs.options.noWhiteSpace = true
|
|
@@ -405,12 +402,12 @@ class Main extends CommandLineTool {
|
|
|
405
402
|
}
|
|
406
403
|
|
|
407
404
|
async get (...args) {
|
|
408
|
-
const parser = new CommandLineParser(
|
|
405
|
+
const parser = new CommandLineParser(this)
|
|
409
406
|
const clargs = {
|
|
410
407
|
options: {}
|
|
411
408
|
}
|
|
412
409
|
parser
|
|
413
|
-
.
|
|
410
|
+
.helpFlag('h', 'help', help.get)
|
|
414
411
|
.flag('s', 'sortKeys', () => { clargs.options.sortKeys = true })
|
|
415
412
|
.flag('n', 'noWhiteSpace', () => {
|
|
416
413
|
clargs.options.noWhiteSpace = true
|
|
@@ -423,7 +420,7 @@ class Main extends CommandLineTool {
|
|
|
423
420
|
.flag('k', 'keysOnly', () => { clargs.options.keysOnly = true })
|
|
424
421
|
.flag('v', 'valuesOnly', () => { clargs.options.valuesOnly = true })
|
|
425
422
|
.parameter('resource', (value) => {
|
|
426
|
-
clargs.resource =
|
|
423
|
+
clargs.resource = toPath(value, { key: 'resource', userInput: true })
|
|
427
424
|
})
|
|
428
425
|
.parse(...args)
|
|
429
426
|
if (clargs.resource === '/') {
|
|
@@ -434,23 +431,23 @@ class Main extends CommandLineTool {
|
|
|
434
431
|
) {
|
|
435
432
|
clargs.resource = '/gateways/' + this.gid + clargs.resource
|
|
436
433
|
}
|
|
437
|
-
const {
|
|
434
|
+
const { jsonBody } = await this.client.get(clargs.resource)
|
|
438
435
|
const jsonFormatter = new JsonFormatter(clargs.options)
|
|
439
|
-
this.print(jsonFormatter.stringify(
|
|
436
|
+
this.print(jsonFormatter.stringify(jsonBody))
|
|
440
437
|
}
|
|
441
438
|
|
|
442
439
|
async put (...args) {
|
|
443
|
-
const parser = new CommandLineParser(
|
|
440
|
+
const parser = new CommandLineParser(this)
|
|
444
441
|
const clargs = {
|
|
445
442
|
options: {}
|
|
446
443
|
}
|
|
447
444
|
parser
|
|
448
|
-
.
|
|
445
|
+
.helpFlag('h', 'help', help.put)
|
|
449
446
|
.parameter('resource', (value) => {
|
|
450
|
-
clargs.resource =
|
|
447
|
+
clargs.resource = toPath(value, { key: 'resource', userInput: true })
|
|
451
448
|
})
|
|
452
449
|
.parameter('body', (value) => {
|
|
453
|
-
value =
|
|
450
|
+
value = toString(value, { key: 'body', nonEmpty: true, userInput: true })
|
|
454
451
|
try {
|
|
455
452
|
clargs.body = JSON.parse(value)
|
|
456
453
|
} catch (error) {
|
|
@@ -468,8 +465,11 @@ class Main extends CommandLineTool {
|
|
|
468
465
|
}
|
|
469
466
|
clargs.resource += '/settings'
|
|
470
467
|
const jsonFormatter = new JsonFormatter(clargs.options)
|
|
471
|
-
const {
|
|
472
|
-
|
|
468
|
+
const { jsonBody } = await this.client.put(clargs.resource, clargs.body)
|
|
469
|
+
for (const error of jsonBody.errors || []) {
|
|
470
|
+
this.warn(error) // TODO: include request details.
|
|
471
|
+
}
|
|
472
|
+
this.print(jsonFormatter.stringify(jsonBody.success))
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
|
package/jsdoc.json
CHANGED
package/lib/Deconz/Resource.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Homebridge plugin for deCONZ.
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { toInstance, toInt, toObject, toString } from 'homebridge-lib/OptionParser'
|
|
7
7
|
|
|
8
8
|
import { ApiClient } from 'hb-deconz-tools/ApiClient'
|
|
9
9
|
|
|
@@ -13,7 +13,6 @@ import '../DeconzAccessory/Gateway.js'
|
|
|
13
13
|
import { DeconzService } from '../DeconzService/index.js'
|
|
14
14
|
import '../DeconzService/Button.js'
|
|
15
15
|
|
|
16
|
-
const { toInstance, toInt, toObject, toString } = OptionParser
|
|
17
16
|
const { buttonEvent } = ApiClient
|
|
18
17
|
const { SINGLE, DOUBLE, LONG } = DeconzService.Button
|
|
19
18
|
const rtypes = ['lights', 'sensors', 'groups', 'alarmsystems']
|
|
@@ -91,7 +90,7 @@ class Resource {
|
|
|
91
90
|
* @return {object} The MultiCLIP `id`, `endpoint`, and `cluster`.
|
|
92
91
|
*/
|
|
93
92
|
static parseClipId (uniqueid) {
|
|
94
|
-
toString(
|
|
93
|
+
toString(uniqueid, { key: 'uniqueid', nonEmpty: true })
|
|
95
94
|
const a = patterns.clipId.exec(uniqueid.replace(/:/g, '').toUpperCase())
|
|
96
95
|
return {
|
|
97
96
|
id: a?.[1],
|
|
@@ -124,12 +123,12 @@ class Resource {
|
|
|
124
123
|
* @param {object} body - The body of the resource.
|
|
125
124
|
*/
|
|
126
125
|
constructor (gateway, rtype, rid, body) {
|
|
127
|
-
toInstance(
|
|
126
|
+
toInstance(gateway, { key: 'gateway', class: DeconzAccessory.Gateway })
|
|
128
127
|
|
|
129
128
|
/** The resource type of the resource: `groups`, `lights`, or `sensors`.
|
|
130
129
|
* @type {string}
|
|
131
130
|
*/
|
|
132
|
-
this.rtype = toString(
|
|
131
|
+
this.rtype = toString(rtype, { key: 'rtype', nonEmpty: true })
|
|
133
132
|
if (!(rtypes.includes(rtype))) {
|
|
134
133
|
throw new RangeError(`rtype: ${rtype}: not a valid resource type`)
|
|
135
134
|
}
|
|
@@ -137,20 +136,20 @@ class Resource {
|
|
|
137
136
|
/** The resource ID of the resource.
|
|
138
137
|
* @type {integer}
|
|
139
138
|
*/
|
|
140
|
-
this.rid = toInt('rid'
|
|
139
|
+
this.rid = toInt(rid, { key: 'rid' })
|
|
141
140
|
|
|
142
141
|
/** The body of the resource.
|
|
143
142
|
* @type {object}
|
|
144
143
|
*/
|
|
145
|
-
this.body = toObject('body'
|
|
146
|
-
toString(
|
|
144
|
+
this.body = toObject(body, { key: 'body' })
|
|
145
|
+
toString(body.name, { key: 'body.name', nonEmpty: true })
|
|
147
146
|
body.name = body.name.replace(/[^\p{L}\p{N} ']/ug, ' ')
|
|
148
147
|
.replace(/^[ ']*/, '')
|
|
149
148
|
.replace(/[ ']*$/, '')
|
|
150
149
|
if (rtype === 'alarmsystems') {
|
|
151
150
|
body.type = 'AlarmSystem'
|
|
152
151
|
}
|
|
153
|
-
toString(
|
|
152
|
+
toString(body.type, { key: 'body.type', nonEmpty: true })
|
|
154
153
|
|
|
155
154
|
let realDevice = false
|
|
156
155
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { timeout } from 'homebridge-lib'
|
|
7
7
|
import { AccessoryDelegate } from 'homebridge-lib/AccessoryDelegate'
|
|
8
|
-
import { OptionParser } from 'homebridge-lib/OptionParser'
|
|
8
|
+
import { OptionParser, toBool } from 'homebridge-lib/OptionParser'
|
|
9
9
|
|
|
10
10
|
import { ApiClient } from 'hb-deconz-tools/ApiClient'
|
|
11
11
|
import { ApiError } from 'hb-deconz-tools/ApiError'
|
|
@@ -882,12 +882,17 @@ class Gateway extends AccessoryDelegate {
|
|
|
882
882
|
if (path.length === 0) {
|
|
883
883
|
return { status: 405 } // Method Not Allowed
|
|
884
884
|
}
|
|
885
|
+
const responseBody = {
|
|
886
|
+
success: {},
|
|
887
|
+
errors: []
|
|
888
|
+
}
|
|
885
889
|
if (path[0] === 'settings') {
|
|
886
890
|
const settings = {}
|
|
887
891
|
const optionParser = new OptionParser(settings, true)
|
|
888
892
|
optionParser
|
|
889
893
|
.on('userInputError', (error) => {
|
|
890
|
-
this.warn(error)
|
|
894
|
+
this.warn('ui error: %s', error)
|
|
895
|
+
responseBody.errors.push(error.message)
|
|
891
896
|
})
|
|
892
897
|
.boolKey('autoExpose')
|
|
893
898
|
.boolKey('expose')
|
|
@@ -904,12 +909,11 @@ class Gateway extends AccessoryDelegate {
|
|
|
904
909
|
}
|
|
905
910
|
optionParser.parse(body)
|
|
906
911
|
|
|
907
|
-
const responseBody = {}
|
|
908
912
|
for (const key in settings) {
|
|
909
913
|
switch (key) {
|
|
910
914
|
case 'brightnessAdjustment':
|
|
911
915
|
this.values[key] = settings[key] / 100
|
|
912
|
-
responseBody[key] = this.values[key]
|
|
916
|
+
responseBody.success[key] = this.values[key]
|
|
913
917
|
break
|
|
914
918
|
case 'autoExpose':
|
|
915
919
|
case 'expose':
|
|
@@ -921,7 +925,7 @@ class Gateway extends AccessoryDelegate {
|
|
|
921
925
|
case 'search':
|
|
922
926
|
case 'unlock':
|
|
923
927
|
this.values[key] = settings[key]
|
|
924
|
-
responseBody[key] = this.values[key]
|
|
928
|
+
responseBody.success[key] = this.values[key]
|
|
925
929
|
break
|
|
926
930
|
default:
|
|
927
931
|
break
|
|
@@ -951,10 +955,16 @@ class Gateway extends AccessoryDelegate {
|
|
|
951
955
|
return { status: 404 } // Not Found
|
|
952
956
|
}
|
|
953
957
|
if (body.expose != null) {
|
|
954
|
-
|
|
955
|
-
|
|
958
|
+
try {
|
|
959
|
+
toBool(body.expose, { key: 'expose', userInput: true })
|
|
960
|
+
this.exposeDevice(id, body.expose)
|
|
961
|
+
responseBody.success.expose = body.expose
|
|
962
|
+
} catch (error) {
|
|
963
|
+
this.warn('ui error: %s', error)
|
|
964
|
+
responseBody.errors.push(error.message)
|
|
965
|
+
}
|
|
956
966
|
}
|
|
957
|
-
return { status: 200 }
|
|
967
|
+
return { status: 200, body: responseBody }
|
|
958
968
|
}
|
|
959
969
|
}
|
|
960
970
|
return { status: 403 } // Forbidden
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// Homebridge plugin for deCONZ.
|
|
5
5
|
|
|
6
6
|
import { AccessoryDelegate } from 'homebridge-lib/AccessoryDelegate'
|
|
7
|
-
import {
|
|
7
|
+
import { toBool, toInt, toString, UserInputError } from 'homebridge-lib/OptionParser'
|
|
8
8
|
|
|
9
9
|
import { ApiClient } from 'hb-deconz-tools/ApiClient'
|
|
10
10
|
|
|
@@ -262,21 +262,25 @@ class DeconzAccessory extends AccessoryDelegate {
|
|
|
262
262
|
return { status: 200, body }
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
// TODO: userInputErrors are logged in Homebridge log, but not returned in the UI response.
|
|
265
266
|
onUiPut (body) {
|
|
266
267
|
let reExpose = false
|
|
267
|
-
const responseBody = {
|
|
268
|
+
const responseBody = {
|
|
269
|
+
success: {},
|
|
270
|
+
errors: []
|
|
271
|
+
}
|
|
268
272
|
for (const key in body) {
|
|
269
273
|
try {
|
|
270
274
|
let value
|
|
271
275
|
switch (key) {
|
|
272
276
|
case 'expose':
|
|
273
|
-
value =
|
|
277
|
+
value = toBool(body[key], { key, userInput: true })
|
|
274
278
|
if (value) {
|
|
275
279
|
reExpose = true
|
|
276
280
|
} else {
|
|
277
281
|
this.gateway.exposeDevice(this.id, value)
|
|
278
282
|
}
|
|
279
|
-
responseBody[key] = value
|
|
283
|
+
responseBody.success[key] = value
|
|
280
284
|
continue
|
|
281
285
|
// Settings for the primary service.
|
|
282
286
|
case 'anyOn':
|
|
@@ -284,52 +288,52 @@ class DeconzAccessory extends AccessoryDelegate {
|
|
|
284
288
|
case 'exposeScenes':
|
|
285
289
|
case 'venetianBlind':
|
|
286
290
|
if (this.service.values[key] != null) {
|
|
287
|
-
value =
|
|
291
|
+
value = toBool(body[key], { key, userInput: true })
|
|
288
292
|
this.service.values[key] = value
|
|
289
293
|
reExpose = true
|
|
290
|
-
responseBody[key] = value
|
|
294
|
+
responseBody.success[key] = value
|
|
291
295
|
continue
|
|
292
296
|
}
|
|
293
297
|
break
|
|
294
298
|
case 'logLevel':
|
|
295
|
-
value =
|
|
299
|
+
value = toInt(body[key], { key, min: 0, max: 3, userInput: true })
|
|
296
300
|
this.values[key] = value
|
|
297
|
-
responseBody[key] = value
|
|
301
|
+
responseBody.success[key] = value
|
|
298
302
|
continue
|
|
299
303
|
case 'lowBatteryThreshold':
|
|
300
304
|
if (this.servicesByServiceName.Battery?.[0] != null) {
|
|
301
|
-
value =
|
|
305
|
+
value = toInt(body[key], { key, min: 10, max: 100, userInput: true })
|
|
302
306
|
this.servicesByServiceName.Battery[0].values[key] = value
|
|
303
|
-
responseBody[key] = value
|
|
307
|
+
responseBody.success[key] = value
|
|
304
308
|
continue
|
|
305
309
|
}
|
|
306
310
|
break
|
|
307
311
|
case 'pin':
|
|
308
312
|
if (this.service.values[key] != null) {
|
|
309
|
-
value =
|
|
313
|
+
value = toString(body[key], { key, userInput: true })
|
|
310
314
|
this.service.values[key] = value
|
|
311
|
-
responseBody[key] = value
|
|
315
|
+
responseBody.success[key] = value
|
|
312
316
|
continue
|
|
313
317
|
}
|
|
314
318
|
break
|
|
315
319
|
case 'serviceName':
|
|
316
320
|
if (this.values.serviceName != null) {
|
|
317
|
-
value =
|
|
318
|
-
if (['Light', 'Outlet', 'Switch', 'Valve'].includes(value)
|
|
319
|
-
throw new
|
|
321
|
+
value = toString(body[key], { key, nonEmpty: true, userInput: true })
|
|
322
|
+
if (!['Light', 'Outlet', 'Switch', 'Valve'].includes(value)) {
|
|
323
|
+
throw new UserInputError(`${value}: not a valid serviceName`)
|
|
320
324
|
}
|
|
321
325
|
this.values.serviceName = value
|
|
322
326
|
reExpose = true
|
|
323
|
-
responseBody[key] = value
|
|
327
|
+
responseBody.success[key] = value
|
|
324
328
|
continue
|
|
325
329
|
}
|
|
326
330
|
break
|
|
327
331
|
case 'useExternalTemperature':
|
|
328
332
|
case 'wallSwitch':
|
|
329
333
|
if (this.service.values[key] != null) {
|
|
330
|
-
value =
|
|
334
|
+
value = toBool(body[key], { key, userInput: true })
|
|
331
335
|
this.service.values[key] = value
|
|
332
|
-
responseBody[key] = value
|
|
336
|
+
responseBody.success[key] = value
|
|
333
337
|
continue
|
|
334
338
|
}
|
|
335
339
|
break
|
|
@@ -337,7 +341,11 @@ class DeconzAccessory extends AccessoryDelegate {
|
|
|
337
341
|
break
|
|
338
342
|
}
|
|
339
343
|
this.warn('ui error: %s: invalid key', key)
|
|
340
|
-
|
|
344
|
+
responseBody.errors.push(`${key}: invalid key`)
|
|
345
|
+
} catch (error) {
|
|
346
|
+
this.warn('ui error: %s', error)
|
|
347
|
+
responseBody.errors.push(error.message)
|
|
348
|
+
}
|
|
341
349
|
}
|
|
342
350
|
if (reExpose) {
|
|
343
351
|
this.gateway.reExposeAccessory(this.id)
|
|
@@ -5,14 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
import { timeout } from 'homebridge-lib'
|
|
7
7
|
import { AdaptiveLighting } from 'homebridge-lib/AdaptiveLighting'
|
|
8
|
-
import {
|
|
8
|
+
import { defaultGamut, xyToHsv, hsvToXy, ctToXy, hsvToRgb } from 'homebridge-lib/Colour'
|
|
9
9
|
import { ServiceDelegate } from 'homebridge-lib/ServiceDelegate'
|
|
10
10
|
|
|
11
11
|
import { DeconzService } from '../DeconzService/index.js'
|
|
12
12
|
import '../DeconzService/LightsResource.js'
|
|
13
13
|
|
|
14
|
-
const { defaultGamut, xyToHsv, hsvToXy, ctToXy, hsvToRgb } = Colour
|
|
15
|
-
|
|
16
14
|
class Light extends DeconzService.LightsResource {
|
|
17
15
|
constructor (accessory, resource, params = {}) {
|
|
18
16
|
params.Service = accessory.Services.hap.Lightbulb
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"ebaauw"
|
|
8
8
|
],
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
|
-
"version": "1.3.
|
|
10
|
+
"version": "1.3.6-0",
|
|
11
11
|
"keywords": [
|
|
12
12
|
"homebridge-plugin",
|
|
13
13
|
"homekit",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"engines": {
|
|
29
29
|
"deCONZ": "2.33.2",
|
|
30
30
|
"homebridge": "^2.4.0",
|
|
31
|
-
"node": "^24||^22"
|
|
31
|
+
"node": "^26||^24||^22"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"hb-deconz-tools": "~3.0.
|
|
35
|
-
"homebridge-lib": "~
|
|
34
|
+
"hb-deconz-tools": "~3.0.8-0",
|
|
35
|
+
"homebridge-lib": "~9.0.0-0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"prepare": "standard && rm -rf out && jsdoc -c jsdoc.json",
|