homebridge-deconz 0.0.13 → 0.0.16
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 +6 -4
- package/cli/deconz.js +2 -2
- package/config.schema.json +2 -2
- package/{homebridge-deconz.png → homebridge-ui/public/homebridge-deconz.png} +0 -0
- package/homebridge-ui/public/index.html +488 -8
- package/homebridge-ui/server.js +40 -25
- package/lib/Deconz/ApiClient.js +1 -1
- package/lib/Deconz/Discovery.js +2 -2
- package/lib/Deconz/Resource.js +3 -3
- package/lib/DeconzAccessory/Gateway.js +79 -28
- package/lib/DeconzAccessory/index.js +1 -1
- package/lib/DeconzPlatform.js +81 -15
- package/lib/DeconzService/Consumption.js +1 -1
- package/lib/DeconzService/Light.js +50 -36
- package/lib/DeconzService/Motion.js +1 -1
- package/lib/DeconzService/Power.js +1 -1
- package/lib/DeconzService/Switch.js +2 -2
- package/lib/DeconzService/Temperature.js +1 -0
- package/lib/DeconzService/Thermostat.js +2 -1
- package/lib/DeconzService/WindowCovering.js +8 -15
- package/lib/DeconzService/index.js +3 -0
- package/package.json +5 -6
package/README.md
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
<p align="center">
|
2
|
-
<img src="homebridge-deconz.png" height="200px">
|
3
|
-
</p
|
2
|
+
<img src="homebridge-ui/public/homebridge-deconz.png" height="200px">
|
3
|
+
</p>
|
4
|
+
<span align="center">
|
4
5
|
|
5
6
|
# Homebridge deCONZ
|
6
7
|
[](https://www.npmjs.com/package/homebridge-deconz)
|
7
8
|
[](https://www.npmjs.com/package/homebridge-deconz)
|
8
|
-
[](https://discord.gg/
|
9
|
+
[](https://discord.gg/zUhSZSNb4P)
|
10
|
+
[](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
|
9
11
|
|
10
12
|
[](https://github.com/ebaauw/homebridge-deconz/issues)
|
11
13
|
[](https://github.com/ebaauw/homebridge-deconz/pulls)
|
@@ -22,7 +24,7 @@ See [Future Development of Homebridge Hue](https://github.com/ebaauw/homebridge-
|
|
22
24
|
Homebridge deCONZ is still under development.
|
23
25
|
See [Releases](https://github.com/ebaauw/homebridge-deconz/releases) for more details.
|
24
26
|
|
25
|
-
If you have a question, please post a message to the **#
|
27
|
+
If you have a question, please post a message to the **#deconz** channel of the Homebridge community on [Discord](https://discord.gg/zUhSZSNb4P).
|
26
28
|
|
27
29
|
### Introduction
|
28
30
|
This [Homebridge](https://github.com/homebridge/homebridge) plugin exposes to Apple's [HomeKit](http://www.apple.com/ios/home/) ZigBee devices (lights, plugs, sensors, switches, ...) and virtual devices on a deCONZ gateway by dresden elektronik.
|
package/cli/deconz.js
CHANGED
@@ -703,7 +703,7 @@ class Main extends homebridgeLib.CommandLineTool {
|
|
703
703
|
const { websocketport } = await this.client.get('/config')
|
704
704
|
options.host = this.client.host + ':' + websocketport
|
705
705
|
this.wsMonitor = new Deconz.WsClient(options)
|
706
|
-
this.setOptions({ mode
|
706
|
+
this.setOptions({ mode })
|
707
707
|
this.wsMonitor
|
708
708
|
.on('error', (error) => { this.error(error) })
|
709
709
|
.on('listening', (url) => { this.log('listening on %s', url) })
|
@@ -813,7 +813,7 @@ class Main extends homebridgeLib.CommandLineTool {
|
|
813
813
|
.parse(...args)
|
814
814
|
const apiKey = await this.client.getApiKey('deconz')
|
815
815
|
this.print(jsonFormatter.stringify(apiKey))
|
816
|
-
this.gateways[this.bridgeid] = { apiKey
|
816
|
+
this.gateways[this.bridgeid] = { apiKey }
|
817
817
|
if (this.client.fingerprint != null) {
|
818
818
|
this.gateways[this.bridgeid].fingerprint = this.client.fingerprint
|
819
819
|
}
|
package/config.schema.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"pluginAlias": "deCONZ",
|
3
3
|
"pluginType": "platform",
|
4
4
|
"singular": true,
|
5
|
-
"customUi":
|
5
|
+
"customUi": false,
|
6
6
|
"headerDisplay": "Homebridge plugin for deCONZ",
|
7
7
|
"footerDisplay": "For a detailed description, see the [wiki](https://github.com/ebaauw/homebridge-deconz/wiki/Configuration).",
|
8
8
|
"schema": {
|
@@ -77,7 +77,7 @@
|
|
77
77
|
}
|
78
78
|
}
|
79
79
|
},
|
80
|
-
"
|
80
|
+
"layout": [
|
81
81
|
"name",
|
82
82
|
{
|
83
83
|
"key": "hosts",
|
File without changes
|
@@ -6,19 +6,499 @@ Copyright © 2022 Erik Baauw. All rights reserved.
|
|
6
6
|
-->
|
7
7
|
|
8
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>
|
9
14
|
|
10
15
|
<script>
|
11
|
-
|
12
|
-
|
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) {
|
13
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
|
+
}, {
|
14
320
|
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
+
}
|
18
470
|
|
19
|
-
|
20
|
-
|
21
|
-
|
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()
|
22
502
|
} catch (error) {
|
23
503
|
console.error(error)
|
24
504
|
}
|
package/homebridge-ui/server.js
CHANGED
@@ -5,39 +5,54 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const {
|
9
|
-
|
10
|
-
} = require('@homebridge/plugin-ui-utils')
|
8
|
+
const { UiServer } = require('homebridge-lib')
|
9
|
+
const Deconz = require('../lib/Deconz')
|
11
10
|
|
12
|
-
class
|
11
|
+
class DeconzUiServer extends UiServer {
|
13
12
|
constructor () {
|
14
13
|
super()
|
15
14
|
|
16
|
-
this.onRequest('
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
accessory.context != null &&
|
22
|
-
accessory.context.className === 'Gateway'
|
15
|
+
this.onRequest('discover', async (params) => {
|
16
|
+
if (this.discovery == null) {
|
17
|
+
this.discovery = new Deconz.Discovery({
|
18
|
+
// forceHttp: this.config.forceHttp,
|
19
|
+
// timeout: this.config.timeout
|
23
20
|
})
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
21
|
+
this.discovery
|
22
|
+
.on('error', (error) => {
|
23
|
+
this.log(
|
24
|
+
'%s: request %d: %s %s', error.request.name,
|
25
|
+
error.request.id, error.request.method, error.request.resource
|
26
|
+
)
|
27
|
+
this.warn(
|
28
|
+
'%s: request %d: %s', error.request.name, error.request.id, error
|
29
|
+
)
|
30
|
+
})
|
31
|
+
.on('request', (request) => {
|
32
|
+
this.debug(
|
33
|
+
'%s: request %d: %s %s', request.name,
|
34
|
+
request.id, request.method, request.resource
|
35
|
+
)
|
36
|
+
})
|
37
|
+
.on('response', (response) => {
|
38
|
+
this.debug(
|
39
|
+
'%s: request %d: %d %s', response.request.name,
|
40
|
+
response.request.id, response.statusCode, response.statusMessage
|
41
|
+
)
|
42
|
+
})
|
43
|
+
.on('found', (name, id, address) => {
|
44
|
+
this.debug('%s: found %s at %s', name, id, address)
|
45
|
+
})
|
46
|
+
.on('searching', (host) => {
|
47
|
+
this.debug('upnp: listening on %s', host)
|
48
|
+
})
|
49
|
+
.on('searchDone', () => { this.debug('upnp: search done') })
|
36
50
|
}
|
51
|
+
const configs = await this.discovery.discover()
|
52
|
+
return configs
|
37
53
|
})
|
38
|
-
|
39
54
|
this.ready()
|
40
55
|
}
|
41
56
|
}
|
42
57
|
|
43
|
-
new
|
58
|
+
new DeconzUiServer() // eslint-disable-line no-new
|
package/lib/Deconz/ApiClient.js
CHANGED
@@ -149,7 +149,7 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
149
149
|
maxSockets: _options.maxSockets,
|
150
150
|
path: '/api',
|
151
151
|
timeout: _options.timeout,
|
152
|
-
validStatusCodes: [200, 400, 403
|
152
|
+
validStatusCodes: [200, 400, 403] //, 404]
|
153
153
|
}
|
154
154
|
if (_options.phoscon) {
|
155
155
|
// options.headers = { Accept: 'application/vnd.ddel.v1' }
|
package/lib/Deconz/Discovery.js
CHANGED
@@ -44,7 +44,7 @@ class Discovery extends events.EventEmitter {
|
|
44
44
|
*/
|
45
45
|
async config (host) {
|
46
46
|
const client = new homebridgeLib.HttpClient({
|
47
|
-
host
|
47
|
+
host,
|
48
48
|
json: true,
|
49
49
|
path: '/api',
|
50
50
|
timeout: this._options.timeout
|
@@ -96,7 +96,7 @@ class Discovery extends events.EventEmitter {
|
|
96
96
|
*/
|
97
97
|
async description (host) {
|
98
98
|
const options = {
|
99
|
-
host
|
99
|
+
host,
|
100
100
|
timeout: this._options.timeout
|
101
101
|
}
|
102
102
|
const client = new homebridgeLib.HttpClient(options)
|