homebridge-deconz 0.1.4 → 0.1.7
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 +47 -43
- package/cli/ui.js +419 -0
- package/jsdoc.json +1 -0
- package/lib/Deconz/ApiClient.js +23 -23
- package/lib/Deconz/ApiError.js +2 -2
- package/lib/Deconz/ApiResponse.js +2 -2
- package/lib/Deconz/Discovery.js +6 -6
- package/lib/Deconz/Resource.js +4 -4
- package/lib/Deconz/WsClient.js +4 -4
- package/lib/DeconzAccessory/Gateway.js +26 -63
- package/lib/DeconzAccessory/Light.js +2 -4
- package/lib/DeconzAccessory/Sensor.js +6 -7
- package/lib/DeconzAccessory/Thermostat.js +2 -4
- package/lib/DeconzAccessory/WarningDevice.js +0 -3
- package/lib/DeconzAccessory/index.js +2 -3
- package/lib/DeconzPlatform.js +5 -5
- package/lib/DeconzService/Battery.js +2 -2
- package/lib/DeconzService/Button.js +2 -2
- package/lib/DeconzService/Gateway.js +2 -2
- package/lib/DeconzService/Light.js +6 -7
- package/lib/DeconzService/LightsResource.js +1 -2
- package/lib/DeconzService/WindowCovering.js +1 -3
- package/lib/DeconzService/index.js +2 -2
- package/package.json +5 -5
- package/cli/ui.sh +0 -83
package/jsdoc.json
CHANGED
package/lib/Deconz/ApiClient.js
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
'use strict'
|
7
7
|
|
8
8
|
const events = require('events')
|
9
|
-
const
|
9
|
+
const { HttpClient, OptionParser, timeout } = require('homebridge-lib')
|
10
10
|
const os = require('os')
|
11
11
|
|
12
12
|
const Deconz = require('../Deconz')
|
@@ -42,7 +42,7 @@ function numberOfZigbeeMessages (body = {}) {
|
|
42
42
|
* @extends HttpClient
|
43
43
|
* @memberof Deconz
|
44
44
|
*/
|
45
|
-
class ApiClient extends
|
45
|
+
class ApiClient extends HttpClient {
|
46
46
|
/** Events reported through `buttonevent`.
|
47
47
|
* @type {Object<string, integer>}
|
48
48
|
*/
|
@@ -85,11 +85,11 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
85
85
|
return v ? Math.round(Math.pow(10, (v - 1) / 10000) * 10) / 10 : 0.0001
|
86
86
|
}
|
87
87
|
|
88
|
-
/** Create a new instance of a Deconz.
|
88
|
+
/** Create a new instance of a Deconz.ApiClient.
|
89
89
|
*
|
90
90
|
* The caller is expected to verify that the given host is a reachable
|
91
91
|
* deCONZ gateway, by calling
|
92
|
-
* {@link
|
92
|
+
* {@link Deconz.Discovery#config Deconz.Discovery#config()} and passing the
|
93
93
|
* response as `params.config`.<br>
|
94
94
|
* The caller is expected to persist the API key, passing it as
|
95
95
|
* `params.apiKey`.
|
@@ -127,7 +127,7 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
127
127
|
waitTimePutGroup: 1000,
|
128
128
|
waitTimeResend: 300
|
129
129
|
}
|
130
|
-
const optionParser = new
|
130
|
+
const optionParser = new OptionParser(_options)
|
131
131
|
optionParser
|
132
132
|
.objectKey('config', true)
|
133
133
|
.stringKey('host', true)
|
@@ -196,7 +196,7 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
196
196
|
* This might be a resource as exposed by the API, e.g. `/lights/1/state`,
|
197
197
|
* or an attribute returned by the API, e.g. `/lights/1/state/on`.
|
198
198
|
* @return {*} response - The JSON response body converted to JavaScript.
|
199
|
-
* @throws {
|
199
|
+
* @throws {Deconz.ApiError} In case of error.
|
200
200
|
*/
|
201
201
|
async get (resource) {
|
202
202
|
if (typeof resource !== 'string' || resource[0] !== '/') {
|
@@ -261,8 +261,8 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
261
261
|
* delaying the request when needed.
|
262
262
|
* @param {string} resource - The resource.
|
263
263
|
* @param {*} body - The body, which will be converted to JSON.
|
264
|
-
* @return {
|
265
|
-
* @throws {
|
264
|
+
* @return {Deconz.ApiResponse} response - The response.
|
265
|
+
* @throws {Deconz.ApiError} In case of error, except for non-critical API errors.
|
266
266
|
*/
|
267
267
|
async put (resource, body) {
|
268
268
|
if (this.waitForIt) {
|
@@ -291,8 +291,8 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
291
291
|
*
|
292
292
|
* @param {string} resource - The resource.
|
293
293
|
* @param {*} body - The body, which will be converted to JSON.
|
294
|
-
* @return {
|
295
|
-
* @throws {
|
294
|
+
* @return {Deconz.ApiResponse} response - The response.
|
295
|
+
* @throws {Deconz.ApiError} In case of error.
|
296
296
|
*/
|
297
297
|
async post (resource, body) {
|
298
298
|
return this.request('POST', resource, body)
|
@@ -301,8 +301,8 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
301
301
|
/** Issue a DELETE request of `/api/`_API_key_`/`_resource_.
|
302
302
|
* @param {string} resource - The resource.
|
303
303
|
* @param {*} body - The body, which will be converted to JSON.
|
304
|
-
* @return {
|
305
|
-
* @throws {
|
304
|
+
* @return {Deconz.ApiResponse} response - The response.
|
305
|
+
* @throws {Deconz.ApiError} In case of error.
|
306
306
|
*/
|
307
307
|
async delete (resource, body) {
|
308
308
|
return this.request('DELETE', resource, body)
|
@@ -318,7 +318,7 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
318
318
|
* the client is running on the same host as the gateway.
|
319
319
|
* @return {string} apiKey - The newly created API key.
|
320
320
|
* @throws {HttpError} In case of HTTP error.
|
321
|
-
* @throws {
|
321
|
+
* @throws {Deconz.ApiError} In case of API error.
|
322
322
|
*/
|
323
323
|
async getApiKey (application) {
|
324
324
|
if (typeof application !== 'string' || application === '') {
|
@@ -339,7 +339,7 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
339
339
|
|
340
340
|
/** Delete the API key and clear {@link Deconz.ApiClient#apiKey apiKey}.
|
341
341
|
* @throws {HttpError} In case of HTTP error.
|
342
|
-
* @throws {
|
342
|
+
* @throws {Deconz.ApiError} In case of API error.
|
343
343
|
*/
|
344
344
|
async deleteApiKey () {
|
345
345
|
try {
|
@@ -353,9 +353,9 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
353
353
|
* Calls {@link Deconz.ApiClient#put put()} to issue a PUT request to
|
354
354
|
* `/api/`_API_key_`/config`.
|
355
355
|
*
|
356
|
-
* @return {
|
356
|
+
* @return {Deconz.ApiResponse} response - The response.
|
357
357
|
* @throws {HttpError} In case of HTTP error.
|
358
|
-
* @throws {
|
358
|
+
* @throws {Deconz.ApiError} In case of API error.
|
359
359
|
*/
|
360
360
|
async unlock () {
|
361
361
|
return this.put('/config', { unlock: 60 })
|
@@ -368,9 +368,9 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
368
368
|
*
|
369
369
|
* To see the newly paired devices, issue a GET request of
|
370
370
|
* `/api/`_API_key_`/lights/new` and/or `/api/`_API_key_`/sensor/new`
|
371
|
-
* @return {
|
371
|
+
* @return {Deconz.ApiResponse} response - The response.
|
372
372
|
* @throws {HttpError} In case of HTTP error.
|
373
|
-
* @throws {
|
373
|
+
* @throws {Deconz.ApiError} In case of API error.
|
374
374
|
*/
|
375
375
|
async search () {
|
376
376
|
return this.put('/config', { permitjoin: 120 })
|
@@ -381,9 +381,9 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
381
381
|
* Calls {@link Deconz.ApiClient#post post()} to issue a POST request to
|
382
382
|
* `/api/`_API_key_`/config/restartapp`, to restart the deCONZ gateway.
|
383
383
|
*
|
384
|
-
* @return {
|
384
|
+
* @return {Deconz.ApiResponse} response - The response.
|
385
385
|
* @throws {HttpError} In case of HTTP error.
|
386
|
-
* @throws {
|
386
|
+
* @throws {Deconz.ApiError} In case of API error.
|
387
387
|
*/
|
388
388
|
async restart () {
|
389
389
|
return this.post('/config/restartapp')
|
@@ -401,9 +401,9 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
401
401
|
* @param {string} method - The method for the request.
|
402
402
|
* @param {!string} resource - The resource for the request.
|
403
403
|
* @param {?*} body - The body for the request.
|
404
|
-
* @return {
|
404
|
+
* @return {Deconz.ApiResponse} response - The response.
|
405
405
|
* @throws {HttpError} In case of HTTP error.
|
406
|
-
* @throws {
|
406
|
+
* @throws {Deconz.ApiError} In case of API error.
|
407
407
|
*/
|
408
408
|
async request (method, resource, body = null, retry = 0) {
|
409
409
|
try {
|
@@ -430,7 +430,7 @@ class ApiClient extends homebridgeLib.HttpClient {
|
|
430
430
|
if (error.request != null && this._options.waitTimeResend > 0 && retry < 5) {
|
431
431
|
error.message += ' - retry in ' + this._options.waitTimeResend + 'ms'
|
432
432
|
this.emit('error', error)
|
433
|
-
await
|
433
|
+
await timeout(this._options.waitTimeResend)
|
434
434
|
return this.request(method, resource, body, retry + 1)
|
435
435
|
}
|
436
436
|
}
|
package/lib/Deconz/ApiError.js
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
8
|
+
const { HttpClient } = require('homebridge-lib')
|
9
9
|
|
10
10
|
// API errors that could still cause (part of) the PUT command to be executed.
|
11
11
|
const nonCriticalApiErrorTypes = [
|
@@ -20,7 +20,7 @@ const nonCriticalApiErrorTypes = [
|
|
20
20
|
* @extends HttpClient.HttpError
|
21
21
|
* @memberof Deconz
|
22
22
|
*/
|
23
|
-
class ApiError extends
|
23
|
+
class ApiError extends HttpClient.HttpError {
|
24
24
|
constructor (e, response) {
|
25
25
|
super(
|
26
26
|
`${e.address}: api error ${e.type}: ${e.description}`,
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
8
|
+
const { HttpClient } = require('homebridge-lib')
|
9
9
|
|
10
10
|
const Deconz = require('../Deconz')
|
11
11
|
|
@@ -14,7 +14,7 @@ const Deconz = require('../Deconz')
|
|
14
14
|
* @extends HttpClient.HttpResponse
|
15
15
|
* @memberof Deconz
|
16
16
|
*/
|
17
|
-
class ApiResponse extends
|
17
|
+
class ApiResponse extends HttpClient.HttpResponse {
|
18
18
|
constructor (response) {
|
19
19
|
super(
|
20
20
|
response.request, response.statusCode, response.statusMessage,
|
package/lib/Deconz/Discovery.js
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
'use strict'
|
7
7
|
|
8
8
|
const events = require('events')
|
9
|
-
const
|
9
|
+
const { HttpClient, OptionParser, UpnpClient } = require('homebridge-lib')
|
10
10
|
const xml2js = require('xml2js')
|
11
11
|
|
12
12
|
/** Class for discovery of deCONZ gateways.
|
@@ -28,7 +28,7 @@ class Discovery extends events.EventEmitter {
|
|
28
28
|
forceHttp: false,
|
29
29
|
timeout: 5
|
30
30
|
}
|
31
|
-
const optionParser = new
|
31
|
+
const optionParser = new OptionParser(this._options)
|
32
32
|
optionParser.boolKey('forceHttp')
|
33
33
|
optionParser.intKey('timeout', 1, 60)
|
34
34
|
optionParser.parse(params)
|
@@ -43,7 +43,7 @@ class Discovery extends events.EventEmitter {
|
|
43
43
|
* @throws {HttpError} In case of error.
|
44
44
|
*/
|
45
45
|
async config (host) {
|
46
|
-
const client = new
|
46
|
+
const client = new HttpClient({
|
47
47
|
host,
|
48
48
|
json: true,
|
49
49
|
path: '/api',
|
@@ -102,7 +102,7 @@ class Discovery extends events.EventEmitter {
|
|
102
102
|
host,
|
103
103
|
timeout: this._options.timeout
|
104
104
|
}
|
105
|
-
const client = new
|
105
|
+
const client = new HttpClient(options)
|
106
106
|
client
|
107
107
|
.on('error', (error) => { this.emit('error', error) })
|
108
108
|
.on('request', (request) => { this.emit('request', request) })
|
@@ -167,7 +167,7 @@ class Discovery extends events.EventEmitter {
|
|
167
167
|
}
|
168
168
|
|
169
169
|
async _upnp () {
|
170
|
-
const upnpClient = new
|
170
|
+
const upnpClient = new UpnpClient({
|
171
171
|
filter: (message) => {
|
172
172
|
return /^[0-9A-F]{16}$/.test(message['gwid.phoscon.de'])
|
173
173
|
},
|
@@ -213,7 +213,7 @@ class Discovery extends events.EventEmitter {
|
|
213
213
|
async _nupnp (options) {
|
214
214
|
options.json = true
|
215
215
|
options.timeout = this._options.timeout
|
216
|
-
const client = new
|
216
|
+
const client = new HttpClient(options)
|
217
217
|
client
|
218
218
|
.on('error', (error) => { this.emit('error', error) })
|
219
219
|
.on('request', (request) => { this.emit('request', request) })
|
package/lib/Deconz/Resource.js
CHANGED
@@ -5,13 +5,13 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
8
|
+
const { Colour, OptionParser } = require('homebridge-lib')
|
9
9
|
const Deconz = require('../Deconz')
|
10
10
|
const DeconzAccessory = require('../DeconzAccessory')
|
11
11
|
const DeconzService = require('../DeconzService')
|
12
12
|
|
13
|
-
const { toInstance, toInt, toObject, toString } =
|
14
|
-
const { defaultGamut } =
|
13
|
+
const { toInstance, toInt, toObject, toString } = OptionParser
|
14
|
+
const { defaultGamut } = Colour
|
15
15
|
const { buttonEvent } = Deconz.ApiClient
|
16
16
|
const { SINGLE, DOUBLE, LONG } = DeconzService.Button
|
17
17
|
const rtypes = ['lights', 'sensors', 'groups']
|
@@ -23,7 +23,7 @@ const sensorsPrios = [
|
|
23
23
|
'Temperature',
|
24
24
|
'LightLevel',
|
25
25
|
'Motion',
|
26
|
-
'
|
26
|
+
'Contact',
|
27
27
|
'AirPurifier',
|
28
28
|
'Thermostat'
|
29
29
|
]
|
package/lib/Deconz/WsClient.js
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
'use strict'
|
7
7
|
|
8
8
|
const events = require('events')
|
9
|
-
const
|
9
|
+
const { OptionParser, timeout } = require('homebridge-lib')
|
10
10
|
const WebSocket = require('ws')
|
11
11
|
|
12
12
|
/** Client for web socket notifications by a deCONZ gateway.
|
@@ -37,7 +37,7 @@ class WsClient extends events.EventEmitter {
|
|
37
37
|
port: 443,
|
38
38
|
retryTime: 15
|
39
39
|
}
|
40
|
-
const optionParser = new
|
40
|
+
const optionParser = new OptionParser(this.config)
|
41
41
|
optionParser
|
42
42
|
.hostKey()
|
43
43
|
.intKey('retryTime', 0, 120)
|
@@ -50,7 +50,7 @@ class WsClient extends events.EventEmitter {
|
|
50
50
|
*/
|
51
51
|
get host () { return this.config.hostname + ':' + this.config.port }
|
52
52
|
set host (host) {
|
53
|
-
const { hostname, port } =
|
53
|
+
const { hostname, port } = OptionParser.toHost('host', host)
|
54
54
|
this.config.hostname = hostname
|
55
55
|
this.config.port = port
|
56
56
|
}
|
@@ -185,7 +185,7 @@ class WsClient extends events.EventEmitter {
|
|
185
185
|
*/
|
186
186
|
this.emit('closed', url, retryTime)
|
187
187
|
if (retryTime > 0) {
|
188
|
-
await
|
188
|
+
await timeout(retryTime * 1000)
|
189
189
|
return this.listen()
|
190
190
|
}
|
191
191
|
})
|
@@ -5,7 +5,9 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
8
|
+
const {
|
9
|
+
AccessoryDelegate, HttpClient, OptionParser, timeout
|
10
|
+
} = require('homebridge-lib')
|
9
11
|
|
10
12
|
const Deconz = require('../Deconz')
|
11
13
|
const DeconzAccessory = require('../DeconzAccessory')
|
@@ -23,7 +25,7 @@ const periodicEvents = [
|
|
23
25
|
* @extends AccessoryDelegate
|
24
26
|
* @memberof DeconzAccessory
|
25
27
|
*/
|
26
|
-
class Gateway extends
|
28
|
+
class Gateway extends AccessoryDelegate {
|
27
29
|
/** Instantiate a gateway delegate.
|
28
30
|
* @param {DeconzPlatform} platform - The platform plugin.
|
29
31
|
* @param {Object} params - Parameters.
|
@@ -74,14 +76,6 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
74
76
|
this.client.apiKey = value
|
75
77
|
})
|
76
78
|
|
77
|
-
this.addPropertyDelegate({
|
78
|
-
key: 'autoExpose',
|
79
|
-
value: { groups: false, lights: true, schedules: false, sensors: true },
|
80
|
-
silent: true
|
81
|
-
}).on('didSet', async () => {
|
82
|
-
this.pollNext = true
|
83
|
-
})
|
84
|
-
|
85
79
|
this.addPropertyDelegate({
|
86
80
|
key: 'brightnessAdjustment',
|
87
81
|
value: 1,
|
@@ -153,7 +147,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
153
147
|
if (value) {
|
154
148
|
try {
|
155
149
|
await this.client.search()
|
156
|
-
await
|
150
|
+
await timeout(120000)
|
157
151
|
this.values.search = false
|
158
152
|
return
|
159
153
|
} catch (error) { this.warn(error) }
|
@@ -168,7 +162,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
168
162
|
if (value) {
|
169
163
|
try {
|
170
164
|
await this.client.unlock()
|
171
|
-
await
|
165
|
+
await timeout(60000)
|
172
166
|
this.values.unlock = false
|
173
167
|
return
|
174
168
|
} catch (error) { this.warn(error) }
|
@@ -247,7 +241,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
247
241
|
return
|
248
242
|
}
|
249
243
|
this.resetting = true
|
250
|
-
await
|
244
|
+
await timeout(this.platform.config.waitTimeUpdate)
|
251
245
|
this.service.values.transitionTime = this.defaultTransitionTime
|
252
246
|
this.resetting = false
|
253
247
|
}
|
@@ -378,7 +372,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
378
372
|
})
|
379
373
|
this.client
|
380
374
|
.on('error', (error) => {
|
381
|
-
if (error instanceof
|
375
|
+
if (error instanceof HttpClient.HttpError) {
|
382
376
|
if (error.request.id !== this.requestId) {
|
383
377
|
this.log(
|
384
378
|
'request %d: %s %s%s', error.request.id,
|
@@ -453,15 +447,13 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
453
447
|
})
|
454
448
|
.on('added', (rtype, rid, body) => {
|
455
449
|
this.vdebug('/%s/%d: added: %j', rtype, rid, body)
|
456
|
-
|
457
|
-
|
458
|
-
}
|
450
|
+
this.pollNext = true
|
451
|
+
this.pollFullState = true
|
459
452
|
})
|
460
453
|
.on('deleted', (rtype, rid) => {
|
461
454
|
this.vdebug('/%s/%d: deleted', rtype, rid)
|
462
|
-
|
463
|
-
|
464
|
-
}
|
455
|
+
this.pollNext = true
|
456
|
+
this.pollFullState = true
|
465
457
|
})
|
466
458
|
.on('closed', (url, retryTime) => {
|
467
459
|
if (retryTime > 0) {
|
@@ -504,7 +496,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
504
496
|
error instanceof Deconz.ApiError && error.type === 101 && retry < 8
|
505
497
|
) {
|
506
498
|
this.log('unlock gateway to obtain API key - retrying in 15s')
|
507
|
-
await
|
499
|
+
await timeout(15000)
|
508
500
|
return this.connect(retry + 1)
|
509
501
|
}
|
510
502
|
this.error(error)
|
@@ -542,9 +534,6 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
542
534
|
this.context.fullState = null
|
543
535
|
this.context.migration = null
|
544
536
|
this.values.logLevel = 2
|
545
|
-
this.values.autoExpose = {
|
546
|
-
groups: false, lights: true, schedules: false, sensors: true
|
547
|
-
}
|
548
537
|
} catch (error) { this.error(error) }
|
549
538
|
}
|
550
539
|
|
@@ -719,7 +708,6 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
719
708
|
model: this.values.model,
|
720
709
|
name: this.name,
|
721
710
|
settings: {
|
722
|
-
autoExpose: this.values.autoExpose,
|
723
711
|
brightnessAdjustment: this.values.brightnessAdjustment * 100,
|
724
712
|
expose: this.values.expose,
|
725
713
|
heartrate: this.values.heartrate,
|
@@ -770,12 +758,11 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
770
758
|
}
|
771
759
|
if (path[0] === 'settings') {
|
772
760
|
const settings = {}
|
773
|
-
const optionParser = new
|
761
|
+
const optionParser = new OptionParser(settings, true)
|
774
762
|
optionParser
|
775
763
|
.on('userInputError', (error) => {
|
776
764
|
this.warn(error)
|
777
765
|
})
|
778
|
-
.objectKey('autoExpose')
|
779
766
|
.intKey('brightnessAdjustment', 10, 100)
|
780
767
|
.boolKey('expose')
|
781
768
|
.intKey('heartrate', 1, 60)
|
@@ -789,27 +776,6 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
789
776
|
const responseBody = {}
|
790
777
|
for (const key in settings) {
|
791
778
|
switch (key) {
|
792
|
-
case 'autoExpose':
|
793
|
-
for (const rtype in settings[key]) {
|
794
|
-
if (this.values[key][rtype] == null) {
|
795
|
-
this.warn('ui error: %s.%s: invalid key', key, rtype)
|
796
|
-
continue
|
797
|
-
}
|
798
|
-
try {
|
799
|
-
settings[key][rtype] = homebridgeLib.OptionParser.toBool(
|
800
|
-
key + '.' + rtype, settings[key][rtype], true
|
801
|
-
)
|
802
|
-
} catch (error) {
|
803
|
-
this.warn(error)
|
804
|
-
continue
|
805
|
-
}
|
806
|
-
this.values[key][rtype] = settings[key][rtype]
|
807
|
-
if (responseBody[key] == null) {
|
808
|
-
responseBody[key] = {}
|
809
|
-
}
|
810
|
-
responseBody[key][rtype] = this.values[key][rtype]
|
811
|
-
}
|
812
|
-
break
|
813
779
|
case 'brightnessAdjustment':
|
814
780
|
this.values[key] = settings[key] / 100
|
815
781
|
responseBody[key] = this.values[key]
|
@@ -831,6 +797,9 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
831
797
|
return { status: 200, body: responseBody }
|
832
798
|
}
|
833
799
|
if (path[0] === 'accessories') {
|
800
|
+
if (path.length < 3) {
|
801
|
+
return { status: 405 } // Method Not Allowed
|
802
|
+
}
|
834
803
|
if (path.length === 3 && path[2] === 'settings') {
|
835
804
|
const id = path[1]
|
836
805
|
if (this.accessoryById[id] == null) {
|
@@ -838,9 +807,11 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
838
807
|
}
|
839
808
|
return this.accessoryById[id].onUiPut(body)
|
840
809
|
}
|
841
|
-
return { status: 405 } // Method Not Allowed
|
842
810
|
}
|
843
811
|
if (path[0] === 'devices') {
|
812
|
+
if (path.length < 3) {
|
813
|
+
return { status: 405 } // Method Not Allowed
|
814
|
+
}
|
844
815
|
if (path.length === 3 && path[2] === 'settings') {
|
845
816
|
const id = path[1]
|
846
817
|
if (this.deviceById[id] == null) {
|
@@ -852,7 +823,6 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
852
823
|
}
|
853
824
|
return { status: 200 }
|
854
825
|
}
|
855
|
-
return { status: 405 } // Method Not Allowed
|
856
826
|
}
|
857
827
|
return { status: 403 } // Forbidden
|
858
828
|
}
|
@@ -885,18 +855,13 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
885
855
|
return
|
886
856
|
}
|
887
857
|
this.context.fullState.config = config
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
) {
|
892
|
-
this.context.fullState.lights = await this.client.get('/lights')
|
893
|
-
this.context.fullState.sensors = await this.client.get('/sensors')
|
894
|
-
}
|
895
|
-
if (this.values.autoExpose.groups || this.nDevicesByRtype.groups > 0) {
|
858
|
+
this.context.fullState.lights = await this.client.get('/lights')
|
859
|
+
this.context.fullState.sensors = await this.client.get('/sensors')
|
860
|
+
if (this.nDevicesByRtype.groups > 0) {
|
896
861
|
this.context.fullState.groups = await this.client.get('/groups')
|
897
862
|
this.context.fullState.groups[0] = await this.client.get('/groups/0')
|
898
863
|
}
|
899
|
-
if (this.
|
864
|
+
if (this.nDevicesByRtype.schedules) {
|
900
865
|
this.context.fullState.schedules = await this.client.get('/schedules')
|
901
866
|
}
|
902
867
|
}
|
@@ -1057,11 +1022,9 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
1057
1022
|
const rids = Object.keys(this.deviceByRidByRtype[rtype]).sort()
|
1058
1023
|
for (const rid of rids) {
|
1059
1024
|
try {
|
1060
|
-
const { id } = this.deviceByRidByRtype[rtype][rid]
|
1025
|
+
const { id, zigbee } = this.deviceByRidByRtype[rtype][rid]
|
1061
1026
|
if (this.context.settingsById[id] == null) {
|
1062
|
-
this.context.settingsById[id] = {
|
1063
|
-
expose: this.values.autoExpose[rtype]
|
1064
|
-
}
|
1027
|
+
this.context.settingsById[id] = { expose: zigbee }
|
1065
1028
|
}
|
1066
1029
|
if (this.context.settingsById[id].expose) {
|
1067
1030
|
if (this.accessoryById[id] == null) {
|
@@ -5,11 +5,9 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
8
|
+
const { ServiceDelegate } = require('homebridge-lib')
|
9
9
|
const DeconzAccessory = require('../DeconzAccessory')
|
10
10
|
|
11
|
-
const { History } = homebridgeLib.ServiceDelegate
|
12
|
-
|
13
11
|
/** Delegate class for a HomeKit accessory, corresponding to a light device
|
14
12
|
* or groups resource.
|
15
13
|
* @extends DeconzAccessory
|
@@ -86,7 +84,7 @@ class Light extends DeconzAccessory {
|
|
86
84
|
unit: ' kWh'
|
87
85
|
})
|
88
86
|
}
|
89
|
-
this.historyService = new History(this, params)
|
87
|
+
this.historyService = new ServiceDelegate.History(this, params)
|
90
88
|
|
91
89
|
setImmediate(() => {
|
92
90
|
this.debug('initialised')
|
@@ -5,11 +5,9 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
8
|
+
const { ServiceDelegate } = require('homebridge-lib')
|
9
9
|
const DeconzAccessory = require('../DeconzAccessory')
|
10
10
|
|
11
|
-
const { History } = homebridgeLib.ServiceDelegate
|
12
|
-
|
13
11
|
class Sensor extends DeconzAccessory {
|
14
12
|
constructor (gateway, device) {
|
15
13
|
super(gateway, device, gateway.Accessory.Categories.SENSOR)
|
@@ -30,7 +28,7 @@ class Sensor extends DeconzAccessory {
|
|
30
28
|
case 'Daylight':
|
31
29
|
case 'LightLevel':
|
32
30
|
// Create dummy motion sensor service.
|
33
|
-
this.motionService = new
|
31
|
+
this.motionService = new ServiceDelegate(this, {
|
34
32
|
name: this.name + ' Motion',
|
35
33
|
Service: this.Services.hap.MotionSensor,
|
36
34
|
hidden: true
|
@@ -56,14 +54,15 @@ class Sensor extends DeconzAccessory {
|
|
56
54
|
if (this.serviceByServiceName.Contact != null) {
|
57
55
|
const service = this.serviceByServiceName.Contact
|
58
56
|
params.contactDelegate = service.characteristicDelegate('contact')
|
59
|
-
params.lastContactDelegate =
|
57
|
+
params.lastContactDelegate = service.addCharacteristicDelegate({
|
60
58
|
key: 'lastActivation',
|
61
59
|
Characteristic: this.Characteristics.eve.LastActivation,
|
62
60
|
silent: true
|
63
61
|
})
|
64
|
-
params.timesOpenedDelegate =
|
62
|
+
params.timesOpenedDelegate = service.addCharacteristicDelegate({
|
65
63
|
key: 'timesOpened',
|
66
64
|
Characteristic: this.Characteristics.eve.TimesOpened,
|
65
|
+
value: 0,
|
67
66
|
silent: true
|
68
67
|
})
|
69
68
|
}
|
@@ -112,7 +111,7 @@ class Sensor extends DeconzAccessory {
|
|
112
111
|
})
|
113
112
|
}
|
114
113
|
if (Object.keys(params).length > 0) {
|
115
|
-
this.historyService = new History(this, params)
|
114
|
+
this.historyService = new ServiceDelegate.History(this, params)
|
116
115
|
}
|
117
116
|
|
118
117
|
setImmediate(() => {
|
@@ -5,11 +5,9 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
8
|
+
const { ServiceDelegate } = require('homebridge-lib')
|
9
9
|
const DeconzAccessory = require('../DeconzAccessory')
|
10
10
|
|
11
|
-
const { History } = homebridgeLib.ServiceDelegate
|
12
|
-
|
13
11
|
class Thermostat extends DeconzAccessory {
|
14
12
|
/** Instantiate a delegate for an accessory corresponding to a device.
|
15
13
|
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
@@ -30,7 +28,7 @@ class Thermostat extends DeconzAccessory {
|
|
30
28
|
}
|
31
29
|
|
32
30
|
if (device.resource.body.state.valve !== undefined) {
|
33
|
-
this.historyService = new History(this, {
|
31
|
+
this.historyService = new ServiceDelegate.History(this, {
|
34
32
|
temperatureDelegate: this.service.characteristicDelegate('currentTemperature'),
|
35
33
|
targetTemperatureDelegate: this.service.characteristicDelegate('targetTemperature'),
|
36
34
|
valvePositionDelegate: this.service.characteristicDelegate('valvePosition')
|
@@ -5,11 +5,8 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
// const homebridgeLib = require('homebridge-lib')
|
9
8
|
const DeconzAccessory = require('../DeconzAccessory')
|
10
9
|
|
11
|
-
// const { History } = homebridgeLib.ServiceDelegate
|
12
|
-
|
13
10
|
/** Delegate class for a HomeKit accessory, corresponding to a light device
|
14
11
|
* or groups resource.
|
15
12
|
* @extends DeconzAccessory
|
@@ -5,8 +5,7 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
9
|
-
const { OptionParser } = homebridgeLib
|
8
|
+
const { AccessoryDelegate, OptionParser } = require('homebridge-lib')
|
10
9
|
const Deconz = require('../Deconz')
|
11
10
|
const DeconzService = require('../DeconzService')
|
12
11
|
|
@@ -17,7 +16,7 @@ const { SINGLE, DOUBLE, LONG } = DeconzService.Button
|
|
17
16
|
* corresponding to a Zigbee or virtual device on a deCONZ gateway.
|
18
17
|
* @extends AccessoryDelegate
|
19
18
|
*/
|
20
|
-
class DeconzAccessory extends
|
19
|
+
class DeconzAccessory extends AccessoryDelegate {
|
21
20
|
static get Light () { return require('./Light') }
|
22
21
|
static get Gateway () { return require('./Gateway') }
|
23
22
|
static get Sensor () { return require('./Sensor') }
|