homebridge-deconz 0.0.17 → 0.0.21
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/README.md +4 -4
- package/config.schema.json +7 -0
- package/homebridge-ui/public/index.html +249 -460
- package/homebridge-ui/public/index.old.html +506 -0
- package/lib/Deconz/Discovery.js +5 -2
- package/lib/Deconz/Resource.js +14 -0
- package/lib/DeconzAccessory/Gateway.js +5 -2
- package/lib/DeconzAccessory/index.js +6 -4
- package/lib/DeconzPlatform.js +5 -1
- package/lib/DeconzService/AirPurifier.js +1 -11
- package/lib/DeconzService/Button.js +4 -0
- package/lib/DeconzService/Consumption.js +9 -1
- package/lib/DeconzService/Light.js +10 -12
- package/lib/DeconzService/LightsResource.js +5 -5
- package/lib/DeconzService/Outlet.js +1 -1
- package/lib/DeconzService/Power.js +1 -1
- package/lib/DeconzService/Switch.js +33 -21
- package/package.json +6 -6
@@ -0,0 +1,506 @@
|
|
1
|
+
<!--
|
2
|
+
homebridge-deconz/homebridge-ui/public/index.html
|
3
|
+
|
4
|
+
Homebridge plug-in for deCONZ.
|
5
|
+
Copyright © 2022 Erik Baauw. All rights reserved.
|
6
|
+
-->
|
7
|
+
|
8
|
+
<link rel="stylesheet" href="style.css">
|
9
|
+
<p align="center">
|
10
|
+
<a href="https://github.com/ebaauw/homebridge-deconz/wiki/Configuration" target="_blank">
|
11
|
+
<img src="homebridge-deconz.png" height="200px">
|
12
|
+
</a>
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<script>
|
16
|
+
|
17
|
+
async function showFormPluginConfig () {
|
18
|
+
homebridge.showSpinner()
|
19
|
+
const pluginConfig = await homebridge.getPluginConfig()
|
20
|
+
console.log('pluginConfig: %o', pluginConfig)
|
21
|
+
// const pluginConfigSchema = await homebridge.getPluginConfigSchema()
|
22
|
+
// console.log('pluginConfigSchema: %o', pluginConfigSchema)
|
23
|
+
// const cachedAccessories = await homebridge.getCachedAccessories()
|
24
|
+
// console.log('cachedAccessories: %o', cachedAccessories)
|
25
|
+
// const discoveredGateways = await homebridge.request('discover')
|
26
|
+
// console.log('discovered gateways: %o', discoveredGateways)
|
27
|
+
for (const config of pluginConfig) {
|
28
|
+
if (config._bridge != null) {
|
29
|
+
const cachedAccessories = await homebridge.request('cachedAccessories', {
|
30
|
+
username: config._bridge.username
|
31
|
+
})
|
32
|
+
console.log('%s: cachedAccessories: %o', config.name, cachedAccessories)
|
33
|
+
const cachedGateways = cachedAccessories.filter((accessory) => {
|
34
|
+
return accessory.plugin === 'homebridge-deconz' &&
|
35
|
+
accessory.context != null &&
|
36
|
+
accessory.context.className === 'Gateway'
|
37
|
+
})
|
38
|
+
const result = {}
|
39
|
+
for (const gateway of cachedGateways) {
|
40
|
+
if (gateway.context.uiPort == null) {
|
41
|
+
continue
|
42
|
+
}
|
43
|
+
const pong = await homebridge.request(
|
44
|
+
'get', { uiPort: gateway.context.uiPort, path: '/ping' }
|
45
|
+
)
|
46
|
+
if (pong === 'pong') {
|
47
|
+
result[gateway.context.host] = gateway.context
|
48
|
+
}
|
49
|
+
}
|
50
|
+
const gateways = Object.keys(result).sort()
|
51
|
+
console.log('%s: gateways: %j',config.name, gateways)
|
52
|
+
}
|
53
|
+
}
|
54
|
+
homebridge.hideSpinner()
|
55
|
+
|
56
|
+
const form = homebridge.createForm(
|
57
|
+
{
|
58
|
+
schema: {
|
59
|
+
type: 'object',
|
60
|
+
properties: {
|
61
|
+
config: {
|
62
|
+
title: 'Gateways',
|
63
|
+
description: 'Configure a child bridge per deCONZ gateway. See <a href="https://github.com/ebaauw/homebridge-deconz/wiki/Configuration" target="_blank">wiki</a> for details.',
|
64
|
+
type: 'array',
|
65
|
+
disabled: true,
|
66
|
+
items: {
|
67
|
+
type: 'object',
|
68
|
+
properties: {
|
69
|
+
host: {
|
70
|
+
description: 'Gateway hostname and port.',
|
71
|
+
default: 'localhost:80',
|
72
|
+
type: 'string',
|
73
|
+
required: true
|
74
|
+
},
|
75
|
+
name: {
|
76
|
+
description: 'Homebridge log plugin name.',
|
77
|
+
default: 'deCONZ',
|
78
|
+
type: 'string'
|
79
|
+
},
|
80
|
+
_bridge: {
|
81
|
+
type: 'object',
|
82
|
+
required: true,
|
83
|
+
properties: {
|
84
|
+
name: {
|
85
|
+
type: 'string',
|
86
|
+
required: true
|
87
|
+
},
|
88
|
+
username: {
|
89
|
+
type: 'string',
|
90
|
+
pattern: '^([A-F0-9]{2}:){5}[A-F0-9]{2}$',
|
91
|
+
placeholder: 'AA:BB:CC:DD:EE:FF',
|
92
|
+
required: true
|
93
|
+
},
|
94
|
+
port: {
|
95
|
+
type: 'integer',
|
96
|
+
minimum: 1025,
|
97
|
+
// maximum: 65535,
|
98
|
+
required: true
|
99
|
+
},
|
100
|
+
manufacturer: {
|
101
|
+
type: 'string',
|
102
|
+
enabled: false,
|
103
|
+
required: true
|
104
|
+
},
|
105
|
+
model: {
|
106
|
+
type: 'string',
|
107
|
+
required: true
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
},
|
116
|
+
// layout: null
|
117
|
+
layout: [
|
118
|
+
{
|
119
|
+
type: 'tabarray',
|
120
|
+
title: '{{ value.name }}',
|
121
|
+
items: [
|
122
|
+
{
|
123
|
+
type: 'fieldset',
|
124
|
+
title: 'Gateway Settings',
|
125
|
+
key: 'config[]',
|
126
|
+
items: [
|
127
|
+
{
|
128
|
+
type: 'flex',
|
129
|
+
'flex-flow': 'row',
|
130
|
+
items: [
|
131
|
+
'config[].host',
|
132
|
+
'config[].name',
|
133
|
+
]
|
134
|
+
}
|
135
|
+
]
|
136
|
+
},
|
137
|
+
{
|
138
|
+
type: 'flex',
|
139
|
+
'flex-flow': 'row',
|
140
|
+
key: 'config[]',
|
141
|
+
items: [
|
142
|
+
{
|
143
|
+
type: 'button',
|
144
|
+
title: 'Connect',
|
145
|
+
key: 'config[].connect'
|
146
|
+
},
|
147
|
+
{
|
148
|
+
type: 'button',
|
149
|
+
title: 'Get API Key',
|
150
|
+
key: 'config[].getApiKey'
|
151
|
+
},
|
152
|
+
{
|
153
|
+
type: 'submit',
|
154
|
+
title: 'Configure',
|
155
|
+
key: 'config[].configure'
|
156
|
+
}
|
157
|
+
]
|
158
|
+
},
|
159
|
+
{
|
160
|
+
type: 'fieldset',
|
161
|
+
key: 'config[]._bridge',
|
162
|
+
// expandable: true,
|
163
|
+
title: 'Child Bridge Accessory Settings',
|
164
|
+
items: [
|
165
|
+
{
|
166
|
+
type: 'flex',
|
167
|
+
'flex-flow': 'row',
|
168
|
+
items: [
|
169
|
+
'config[]._bridge.username',
|
170
|
+
'config[]._bridge.port'
|
171
|
+
]
|
172
|
+
},
|
173
|
+
'config[]._bridge.name',
|
174
|
+
{
|
175
|
+
type: 'flex',
|
176
|
+
'flex-flow': 'row',
|
177
|
+
items: [
|
178
|
+
'config[]._bridge.manufacturer',
|
179
|
+
'config[]._bridge.model'
|
180
|
+
]
|
181
|
+
}
|
182
|
+
]
|
183
|
+
}
|
184
|
+
]
|
185
|
+
}
|
186
|
+
]
|
187
|
+
}, {
|
188
|
+
config: pluginConfig,
|
189
|
+
},
|
190
|
+
'Gateway Settings',
|
191
|
+
'Homebridge Settings'
|
192
|
+
)
|
193
|
+
form.onChange(async (form) => {
|
194
|
+
console.log('change: %o', form)
|
195
|
+
})
|
196
|
+
form.onSubmit(async (form) => {
|
197
|
+
console.log('submit: %o', form)
|
198
|
+
})
|
199
|
+
form.onCancel(async (form) => {
|
200
|
+
console.log('cancel: %o', form)
|
201
|
+
})
|
202
|
+
|
203
|
+
}
|
204
|
+
|
205
|
+
async function showFormGateways (gateway) {
|
206
|
+
homebridge.showSpinner()
|
207
|
+
const cachedAccessories = await homebridge.getCachedAccessories()
|
208
|
+
const cachedGateways = cachedAccessories.filter((accessory) => {
|
209
|
+
return accessory.plugin === 'homebridge-deconz' &&
|
210
|
+
accessory.context != null &&
|
211
|
+
accessory.context.className === 'Gateway'
|
212
|
+
})
|
213
|
+
const result = {}
|
214
|
+
for (const gateway of cachedGateways) {
|
215
|
+
if (gateway.context.uiPort == null) {
|
216
|
+
continue
|
217
|
+
}
|
218
|
+
const pong = await homebridge.request(
|
219
|
+
'get', { uiPort: gateway.context.uiPort, path: '/ping' }
|
220
|
+
)
|
221
|
+
if (pong === 'pong') {
|
222
|
+
result[gateway.context.host] = gateway.context
|
223
|
+
}
|
224
|
+
}
|
225
|
+
const gateways = Object.keys(result).sort()
|
226
|
+
homebridge.hideSpinner()
|
227
|
+
if (gateways.length === 0) {
|
228
|
+
homebridge.showSchemaForm()
|
229
|
+
return
|
230
|
+
}
|
231
|
+
// const form = homebridge.createForm({
|
232
|
+
// schema: {
|
233
|
+
// type: 'object',
|
234
|
+
// properties: {
|
235
|
+
// gateway: {
|
236
|
+
// title: 'Connected Gateways',
|
237
|
+
// type: 'string',
|
238
|
+
// oneOf: gateways.map((name) => {
|
239
|
+
// const config = result[name].context.config
|
240
|
+
// return {
|
241
|
+
// title: `${name}: dresden elektronik ${config.modelid} gateway v${config.swversion} / ${config.devicename} ${config.bridgeid}`,
|
242
|
+
// enum: [name]
|
243
|
+
// }
|
244
|
+
// }),
|
245
|
+
// required: true
|
246
|
+
// }
|
247
|
+
// }
|
248
|
+
// },
|
249
|
+
// layout: null,
|
250
|
+
// form: null
|
251
|
+
// }, {
|
252
|
+
// gateway: gateway != null ? gateway : gateways[0]
|
253
|
+
// }, 'Gateway Settings', 'Homebridge Settings')
|
254
|
+
const form = homebridge.createForm({
|
255
|
+
footerDisplay: 'For a detailed description, see the [wiki](https://github.com/ebaauw/homebridge-deconz/wiki/Configuration).',
|
256
|
+
schema: {
|
257
|
+
type: 'object',
|
258
|
+
properties: {
|
259
|
+
name: {
|
260
|
+
description: 'Plugin name as displayed in the Homebridge log.',
|
261
|
+
type: 'string',
|
262
|
+
required: true,
|
263
|
+
default: 'deCONZ'
|
264
|
+
},
|
265
|
+
gateways: {
|
266
|
+
title: 'Gateways',
|
267
|
+
type: 'array',
|
268
|
+
disabled: true,
|
269
|
+
items: {
|
270
|
+
type: 'object',
|
271
|
+
properties: {
|
272
|
+
host: {
|
273
|
+
description: 'Hostname and port of the deCONZ gateway.',
|
274
|
+
type: 'string'
|
275
|
+
},
|
276
|
+
expose: {
|
277
|
+
description: 'Expose gateway to HomeKit.',
|
278
|
+
type: 'boolean'
|
279
|
+
}
|
280
|
+
}
|
281
|
+
}
|
282
|
+
|
283
|
+
}
|
284
|
+
}
|
285
|
+
} //,
|
286
|
+
// layout: [
|
287
|
+
// 'name',
|
288
|
+
// {
|
289
|
+
// key: 'gateways',
|
290
|
+
// type: 'array',
|
291
|
+
// buttonText: 'Add Gateway',
|
292
|
+
// items: [
|
293
|
+
// {
|
294
|
+
// type: 'section',
|
295
|
+
// htmlClass: 'row',
|
296
|
+
// items: [
|
297
|
+
// {
|
298
|
+
// type: 'section',
|
299
|
+
// htmlClass: 'col',
|
300
|
+
// items: [
|
301
|
+
// 'gateways[].host'
|
302
|
+
// ]
|
303
|
+
// },
|
304
|
+
// {
|
305
|
+
// type: 'section',
|
306
|
+
// htmlClass: 'col',
|
307
|
+
// items: [
|
308
|
+
// {
|
309
|
+
// key: 'gateways[].expose',
|
310
|
+
// disabled: true
|
311
|
+
// }
|
312
|
+
// ]
|
313
|
+
// }
|
314
|
+
// ]
|
315
|
+
// }
|
316
|
+
// ]
|
317
|
+
// }
|
318
|
+
// ]
|
319
|
+
}, {
|
320
|
+
|
321
|
+
}, 'Gateway Settings', 'Homebridge Settings')
|
322
|
+
form.onChange(async (form) => {
|
323
|
+
// showFormGatewaySettings(result[form.gateway])
|
324
|
+
})
|
325
|
+
form.onSubmit(async (form) => {
|
326
|
+
await showFormGatewaySettings(result[form.gateways])
|
327
|
+
})
|
328
|
+
form.onCancel(() => { homebridge.showSchemaForm() })
|
329
|
+
}
|
330
|
+
|
331
|
+
async function showFormGatewaySettings (gateway, device) {
|
332
|
+
homebridge.showSpinner()
|
333
|
+
const data = await homebridge.request(
|
334
|
+
'get', {
|
335
|
+
uiPort: gateway.uiPort,
|
336
|
+
path: '/gateways/' + gateway.id
|
337
|
+
}
|
338
|
+
)
|
339
|
+
const values = {}
|
340
|
+
for (const rtype in data.deviceByRidByRtype) {
|
341
|
+
values[rtype] = []
|
342
|
+
for (const rid in data.deviceByRidByRtype[rtype]) {
|
343
|
+
const device = data.deviceByRidByRtype[rtype][rid]
|
344
|
+
values[rtype].push({
|
345
|
+
title: ['', rtype, rid].join('/') + ': ' +
|
346
|
+
device.resourceBySubtype[device.primary].body.name,
|
347
|
+
enum: [device.id]
|
348
|
+
})
|
349
|
+
}
|
350
|
+
}
|
351
|
+
data.lightsDevice = values.lights[0].enum[0]
|
352
|
+
data.sensorsDevice = values.sensors[0].enum[0]
|
353
|
+
data.groupsDevice = values.groups[0].enum[0]
|
354
|
+
homebridge.hideSpinner()
|
355
|
+
const form = homebridge.createForm({
|
356
|
+
schema: {
|
357
|
+
type: 'object',
|
358
|
+
properties: {
|
359
|
+
expose: {
|
360
|
+
title: 'Expose',
|
361
|
+
type: 'boolean'
|
362
|
+
},
|
363
|
+
lights: {
|
364
|
+
title: 'Lights',
|
365
|
+
type: 'boolean',
|
366
|
+
},
|
367
|
+
sensors: {
|
368
|
+
title: 'Sensors',
|
369
|
+
type: 'boolean',
|
370
|
+
},
|
371
|
+
groups: {
|
372
|
+
title: 'Groups',
|
373
|
+
type: 'boolean',
|
374
|
+
},
|
375
|
+
schedules: {
|
376
|
+
title: 'Schedules',
|
377
|
+
type: 'boolean',
|
378
|
+
},
|
379
|
+
logLevel: {
|
380
|
+
title: 'Log Level',
|
381
|
+
type: 'string',
|
382
|
+
oneOf: ['0', '1', '2', '3'].map((level) => { return { title: level, enum: [level] } }),
|
383
|
+
required: true,
|
384
|
+
condition: {
|
385
|
+
functionBody: 'return model.expose'
|
386
|
+
}
|
387
|
+
},
|
388
|
+
lightsDevice: {
|
389
|
+
title: 'Device',
|
390
|
+
type: 'string',
|
391
|
+
oneOf: values.lights,
|
392
|
+
required: true
|
393
|
+
},
|
394
|
+
sensorsDevice: {
|
395
|
+
title: 'Device',
|
396
|
+
type: 'string',
|
397
|
+
oneOf: values.sensors,
|
398
|
+
required: true
|
399
|
+
},
|
400
|
+
groupsDevice: {
|
401
|
+
title: 'Device',
|
402
|
+
type: 'string',
|
403
|
+
oneOf: values.groups,
|
404
|
+
required: true
|
405
|
+
}
|
406
|
+
}
|
407
|
+
},
|
408
|
+
layout: [
|
409
|
+
{
|
410
|
+
type: 'fieldset',
|
411
|
+
title: `${gateway.context.host} Gateway Settings`
|
412
|
+
},
|
413
|
+
'expose',
|
414
|
+
'logLevel',
|
415
|
+
{
|
416
|
+
type: 'flex',
|
417
|
+
'flex-flow': 'row',
|
418
|
+
title: 'Automatically Expose New',
|
419
|
+
items: [
|
420
|
+
'lights',
|
421
|
+
'sensors',
|
422
|
+
'groups',
|
423
|
+
'schedules'
|
424
|
+
],
|
425
|
+
condition: {
|
426
|
+
functionBody: 'return model.expose'
|
427
|
+
}
|
428
|
+
},
|
429
|
+
{
|
430
|
+
type: 'fieldset',
|
431
|
+
items: [
|
432
|
+
{
|
433
|
+
type: 'tabs',
|
434
|
+
tabs: [
|
435
|
+
{
|
436
|
+
title: 'Lights',
|
437
|
+
items: [
|
438
|
+
'lightsDevice'
|
439
|
+
]
|
440
|
+
},
|
441
|
+
{
|
442
|
+
title: 'Sensors',
|
443
|
+
items: [
|
444
|
+
'sensorsDevice'
|
445
|
+
]
|
446
|
+
},
|
447
|
+
{
|
448
|
+
title: 'Groups',
|
449
|
+
items: [
|
450
|
+
'groupsDevice'
|
451
|
+
]
|
452
|
+
}
|
453
|
+
]
|
454
|
+
}
|
455
|
+
],
|
456
|
+
condition: {
|
457
|
+
functionBody: 'return model.expose'
|
458
|
+
}
|
459
|
+
}
|
460
|
+
]
|
461
|
+
}, data, 'Device Settings', 'Done')
|
462
|
+
form.onChange((form) => {})
|
463
|
+
form.onSubmit((form) => {
|
464
|
+
showFormDeviceSettings(gateway, form.lightsDevice)
|
465
|
+
})
|
466
|
+
form.onCancel((form) => {
|
467
|
+
showFormGateways(gateway.context.host)
|
468
|
+
})
|
469
|
+
}
|
470
|
+
|
471
|
+
async function showFormDeviceSettings (gateway, device) {
|
472
|
+
homebridge.showSpinner()
|
473
|
+
homebridge.hideSpinner()
|
474
|
+
const form = homebridge.createForm({
|
475
|
+
schema: {
|
476
|
+
type: 'object',
|
477
|
+
properties: {
|
478
|
+
gateway: {
|
479
|
+
type: 'string'
|
480
|
+
},
|
481
|
+
device: {
|
482
|
+
type: 'string'
|
483
|
+
}
|
484
|
+
}
|
485
|
+
}
|
486
|
+
}, {
|
487
|
+
gateway: gateway.context.host,
|
488
|
+
device: device
|
489
|
+
}, 'OK', 'Cancel')
|
490
|
+
form.onChange((form) => {})
|
491
|
+
form.onSubmit((form) => {
|
492
|
+
showFormGatewaySettings(gateway)
|
493
|
+
})
|
494
|
+
form.onCancel((form) => {
|
495
|
+
showFormGatewaySettings(gateway)
|
496
|
+
})
|
497
|
+
}
|
498
|
+
|
499
|
+
(async () => {
|
500
|
+
try {
|
501
|
+
await showFormPluginConfig()
|
502
|
+
} catch (error) {
|
503
|
+
console.error(error)
|
504
|
+
}
|
505
|
+
})()
|
506
|
+
</script>
|
package/lib/Deconz/Discovery.js
CHANGED
@@ -78,12 +78,15 @@ class Discovery extends events.EventEmitter {
|
|
78
78
|
if (
|
79
79
|
body != null && typeof body === 'object' &&
|
80
80
|
typeof body.apiversion === 'string' &&
|
81
|
-
/
|
81
|
+
/[0-9A-Fa-f]{16}/.test(body.bridgeid) &&
|
82
82
|
typeof body.devicename === 'string' &&
|
83
83
|
typeof body.name === 'string' &&
|
84
84
|
typeof body.swversion === 'string'
|
85
85
|
) {
|
86
|
-
|
86
|
+
if (body.bridgeid.startsWith('00212E')) {
|
87
|
+
return body
|
88
|
+
}
|
89
|
+
throw new Error(`${body.bridgeid}: not a RaspBee/ConBee mac address`)
|
87
90
|
}
|
88
91
|
throw new Error('not a deCONZ gateway')
|
89
92
|
}
|
package/lib/Deconz/Resource.js
CHANGED
@@ -339,6 +339,7 @@ class Resource {
|
|
339
339
|
case 'CLIPPresence': return 'Motion'
|
340
340
|
case 'ZHAPressure':
|
341
341
|
case 'CLIPPressure': return 'AirPressure'
|
342
|
+
case 'ZHARelativeRotary': return 'Switch'
|
342
343
|
case 'ZHASpectral': return ''
|
343
344
|
case 'ZGPSwitch':
|
344
345
|
case 'ZHASwitch':
|
@@ -882,6 +883,18 @@ class Resource {
|
|
882
883
|
break
|
883
884
|
}
|
884
885
|
break
|
886
|
+
case 'RDM002': // Hue tap dial switch
|
887
|
+
dots = true
|
888
|
+
if (this.endpoint === '01') {
|
889
|
+
buttons.push([1, '1', SINGLE | LONG, true])
|
890
|
+
buttons.push([2, '2', SINGLE | LONG, true])
|
891
|
+
buttons.push([3, '3', SINGLE | LONG, true])
|
892
|
+
buttons.push([4, '4', SINGLE | LONG, true])
|
893
|
+
} else if (this.endpoint === '14') {
|
894
|
+
buttons.push([5, 'Right Turn', SINGLE])
|
895
|
+
buttons.push([6, 'Left Turn', SINGLE])
|
896
|
+
}
|
897
|
+
break
|
885
898
|
case 'ROM001': // Hue smart button
|
886
899
|
buttons.push([1, 'Button', SINGLE | LONG, true])
|
887
900
|
break
|
@@ -935,6 +948,7 @@ class Resource {
|
|
935
948
|
break
|
936
949
|
case 'Sunricher':
|
937
950
|
switch (this.model) {
|
951
|
+
case 'ZG2833K4_EU06': // Sunricher 4-button remote
|
938
952
|
case 'ZG2833K8_EU05': // Sunricher 8-button remote, see #529.
|
939
953
|
if (this.endpoint === '01') {
|
940
954
|
buttons.push([1, 'On 1', SINGLE | LONG])
|
@@ -70,7 +70,10 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
70
70
|
// end migration
|
71
71
|
}
|
72
72
|
if (this.context.fullState != null) {
|
73
|
-
this.analyseFullState(this.context.fullState, {
|
73
|
+
this.analyseFullState(this.context.fullState, {
|
74
|
+
analyseOnly: true,
|
75
|
+
logUnsupported: true
|
76
|
+
})
|
74
77
|
}
|
75
78
|
|
76
79
|
this.addPropertyDelegate({
|
@@ -774,7 +777,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
774
777
|
* @param {Object} fullState - The gateway full state, as returned by
|
775
778
|
* {@link DeconzAccessory.Gateway#poll poll()}.
|
776
779
|
* @param {Object} params - Parameters
|
777
|
-
* @param {boolean} [params.
|
780
|
+
* @param {boolean} [params.logUnsupported=false] - Issue debug
|
778
781
|
* messsages for unsupported resources.
|
779
782
|
* @param {boolean} [params.analyseOnly=false]
|
780
783
|
*/
|
@@ -144,13 +144,15 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
|
|
144
144
|
if (params.serviceName === 'Battery') {
|
145
145
|
service = this.serviceByServiceName.Battery
|
146
146
|
} else if (params.serviceName === 'Consumption') {
|
147
|
-
service = this.serviceByServiceName.
|
147
|
+
service = this.serviceByServiceName.Outlet ||
|
148
|
+
this.serviceByServiceName.Light ||
|
148
149
|
this.serviceByServiceName.Power
|
149
150
|
if (service != null) {
|
150
151
|
service.addResource(resource)
|
151
152
|
}
|
152
153
|
} else if (params.serviceName === 'Power') {
|
153
|
-
service = this.serviceByServiceName.
|
154
|
+
service = this.serviceByServiceName.Outlet ||
|
155
|
+
this.serviceByServiceName.Light ||
|
154
156
|
this.serviceByServiceName.Consumption
|
155
157
|
if (service != null) {
|
156
158
|
service.addResource(resource)
|
@@ -187,8 +189,8 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
|
|
187
189
|
}
|
188
190
|
this.serviceBySubtype[resource.subtype] = service
|
189
191
|
this.serviceByRpath[resource.rpath] = service
|
190
|
-
if (this.serviceByServiceName[
|
191
|
-
this.serviceByServiceName[
|
192
|
+
if (this.serviceByServiceName[params.serviceName] == null) {
|
193
|
+
this.serviceByServiceName[params.serviceName] = service
|
192
194
|
}
|
193
195
|
if (
|
194
196
|
resource.body.config != null &&
|
package/lib/DeconzPlatform.js
CHANGED
@@ -25,6 +25,7 @@ class DeconzPlatform extends homebridgeLib.Platform {
|
|
25
25
|
|
26
26
|
parseConfigJson (configJson) {
|
27
27
|
this.config = {
|
28
|
+
brightnessAdjustment: 100,
|
28
29
|
forceHttp: false,
|
29
30
|
hosts: [],
|
30
31
|
noResponse: false,
|
@@ -44,6 +45,7 @@ class DeconzPlatform extends homebridgeLib.Platform {
|
|
44
45
|
})
|
45
46
|
.stringKey('name')
|
46
47
|
.stringKey('platform')
|
48
|
+
.intKey('brightnessAdjustment', 10, 100)
|
47
49
|
.boolKey('forceHttp')
|
48
50
|
.stringKey('host')
|
49
51
|
.arrayKey('hosts')
|
@@ -61,6 +63,7 @@ class DeconzPlatform extends homebridgeLib.Platform {
|
|
61
63
|
|
62
64
|
try {
|
63
65
|
optionParser.parse(configJson)
|
66
|
+
this.config.brightnessAdjustment /= 100
|
64
67
|
if (this.config.host != null) {
|
65
68
|
this.config.hosts.push(this.config.host)
|
66
69
|
}
|
@@ -170,7 +173,8 @@ class DeconzPlatform extends homebridgeLib.Platform {
|
|
170
173
|
}
|
171
174
|
for (const id in this.gatewayMap) {
|
172
175
|
const gateway = this.gatewayMap[id]
|
173
|
-
dumpInfo.gatewayMap[id] = gateway.context
|
176
|
+
dumpInfo.gatewayMap[id] = Object.assign({}, gateway.context)
|
177
|
+
dumpInfo.gatewayMap[id].deviceById = gateway.deviceById
|
174
178
|
}
|
175
179
|
await this.createDumpFile(dumpInfo)
|
176
180
|
} catch (error) { this.error(error) }
|
@@ -47,7 +47,7 @@ class FilterMaintenance extends DeconzService.SensorsResource {
|
|
47
47
|
)
|
48
48
|
}
|
49
49
|
if (state.replacefilter != null) {
|
50
|
-
this.values.filterChange = state.
|
50
|
+
this.values.filterChange = state.replacefilter
|
51
51
|
? this.Characteristics.hap.FilterChangeIndication.CHANGE_FILTER
|
52
52
|
: this.Characteristics.hap.FilterChangeIndication.FILTER_OK
|
53
53
|
}
|
@@ -158,16 +158,6 @@ class AirPurifier extends DeconzService.SensorsResource {
|
|
158
158
|
}
|
159
159
|
|
160
160
|
updateState (state) {
|
161
|
-
if (this.values.filterLifeTime != null && state.filterruntime != null) {
|
162
|
-
this.values.filterLifeLevel = 100 - Math.round(
|
163
|
-
100 * state.filterruntime / this.values.filterLifeTime
|
164
|
-
)
|
165
|
-
}
|
166
|
-
if (state.replacefilter != null) {
|
167
|
-
this.values.filterChange = state.filterChange
|
168
|
-
? this.Characteristics.hap.FilterChangeIndication.CHANGE_FILTER
|
169
|
-
: this.Characteristics.hap.FilterChangeIndication.FILTER_OK
|
170
|
-
}
|
171
161
|
if (state.speed != null) {
|
172
162
|
this.values.active = state.speed > 0
|
173
163
|
? this.Characteristics.hap.Active.ACTIVE
|