homebridge-deconz 1.2.12 → 1.3.1

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/ui.js CHANGED
@@ -344,58 +344,10 @@ class Main extends CommandLineTool {
344
344
  const client = new HttpClient({
345
345
  host,
346
346
  json: true,
347
+ logger: this,
347
348
  name: host,
348
349
  timeout: this.clargs.options.timeout
349
350
  })
350
- client
351
- .on('error', (error) => {
352
- if (error.request.id !== this.requestId) {
353
- if (error.request.body == null) {
354
- this.log(
355
- '%s: request %d: %s %s', error.request.name, error.request.id,
356
- error.request.method, error.request.resource
357
- )
358
- } else {
359
- this.log(
360
- '%s: request %d: %s %s %s', error.request.name, error.request.id,
361
- error.request.method, error.request.resource, error.request.body
362
- )
363
- }
364
- this.requestId = error.request.id
365
- }
366
- this.error('%s: request %d: %s', error.request.name, error.request.id, error)
367
- })
368
- .on('request', (request) => {
369
- if (request.body == null) {
370
- this.debug(
371
- '%s: request %d: %s %s', request.name, request.id,
372
- request.method, request.resource
373
- )
374
- this.vdebug(
375
- '%s: request %d: %s %s', request.name, request.id,
376
- request.method, request.url
377
- )
378
- } else {
379
- this.debug(
380
- '%s: request %d: %s %s %s', request.name, request.id,
381
- request.method, request.resource, request.body
382
- )
383
- this.vdebug(
384
- '%s: request %d: %s %s %s', request.name, request.id,
385
- request.method, request.url, request.body
386
- )
387
- }
388
- })
389
- .on('response', (response) => {
390
- this.vdebug(
391
- '%s: request %d: response: %j', response.request.name, response.request.id,
392
- response.body
393
- )
394
- this.debug(
395
- '%s: request %d: %d %s', response.request.name, response.request.id,
396
- response.statusCode, response.statusMessage
397
- )
398
- })
399
351
  const response = await client.get('/ping')
400
352
  if (response.body !== 'pong') {
401
353
  throw new Error(`${host}: cannot ping`)
@@ -14,10 +14,6 @@
14
14
  "required": true,
15
15
  "default": "deCONZ"
16
16
  },
17
- "forceHttp": {
18
- "description": "Use plain http instead of https.",
19
- "type": "boolean"
20
- },
21
17
  "hosts": {
22
18
  "title": "Gateways",
23
19
  "type": "array",
@@ -94,7 +90,6 @@
94
90
  "title": "Advanced Settings",
95
91
  "description": "Don't change these, unless you understand what you're doing.",
96
92
  "items": [
97
- "forceHttp",
98
93
  "noResponse",
99
94
  "parallelRequests",
100
95
  "stealth",
@@ -82,10 +82,6 @@ Copyright © 2022-2026 Erik Baauw. All rights reserved.
82
82
  default: 'deCONZ',
83
83
  type: 'string'
84
84
  },
85
- forceHttp: {
86
- description: "Use plain http instead of https.",
87
- type: "boolean"
88
- },
89
85
  noResponse: {
90
86
  description: "Report unreachable lights as <i>No Response</i> in HomeKit.",
91
87
  type: "boolean"
@@ -147,7 +143,6 @@ Copyright © 2022-2026 Erik Baauw. All rights reserved.
147
143
  title: "Advanced Settings",
148
144
  description: "Don't change these, unless you understand what you're doing.",
149
145
  items: [
150
- "forceHttp",
151
146
  "parallelRequests",
152
147
  "stealth",
153
148
  "timeout",
@@ -13,7 +13,6 @@ class DeconzUiServer extends UiServer {
13
13
  this.onRequest('discover', async (params) => {
14
14
  if (this.discovery == null) {
15
15
  this.discovery = new Discovery({
16
- // forceHttp: this.config.forceHttp,
17
16
  // timeout: this.config.timeout
18
17
  })
19
18
  this.discovery
@@ -344,7 +344,7 @@ class Resource {
344
344
  case 'Battery': return 'Battery'
345
345
  case 'CarbonMonoxide': return 'CarbonMonoxide'
346
346
  case 'Consumption': return 'Consumption'
347
- // case 'DoorLock': return null
347
+ case 'DoorLock': return 'DoorLock'
348
348
  case 'Daylight': return 'Daylight'
349
349
  case 'DaylightOffset': return ''
350
350
  case 'Fire': return 'Smoke'
@@ -1159,22 +1159,6 @@ class Resource {
1159
1159
  break
1160
1160
  case 'icasa':
1161
1161
  switch (this.model) {
1162
- case 'ICZB-KPD12':
1163
- case 'ICZB-KPD14S':
1164
- case 'ICZB-KPD18S':
1165
- buttons.push([1, 'Off', SINGLE | LONG])
1166
- buttons.push([2, 'On', SINGLE | LONG])
1167
- if (this.model !== 'ICZB-KPD12') {
1168
- buttons.push([3, 'S1', SINGLE])
1169
- buttons.push([4, 'S2', SINGLE])
1170
- if (this.model === 'ICZB-KPD18S') {
1171
- buttons.push([5, 'S3', SINGLE])
1172
- buttons.push([6, 'S4', SINGLE])
1173
- buttons.push([7, 'S5', SINGLE])
1174
- buttons.push([8, 'S6', SINGLE])
1175
- }
1176
- }
1177
- break
1178
1162
  case 'ICZB-RM11S':
1179
1163
  buttons.push([1, '1 Off', SINGLE | LONG])
1180
1164
  buttons.push([2, '1 On', SINGLE | LONG])
@@ -21,8 +21,6 @@ import { DeconzService } from '../DeconzService/index.js'
21
21
  import '../DeconzService/Button.js'
22
22
  import '../DeconzService/Gateway.js'
23
23
 
24
- const { HttpError } = ApiClient
25
-
26
24
  const migration = {
27
25
  name: 'homebridge-deconz',
28
26
  description: 'migration',
@@ -78,12 +76,6 @@ class Gateway extends AccessoryDelegate {
78
76
  if (this.context.settingsById == null) {
79
77
  this.context.settingsById = {}
80
78
  }
81
- // if (this.context.fullState != null) {
82
- // this.analyseFullState(this.context.fullState, {
83
- // analyseOnly: true,
84
- // logUnsupported: true
85
- // })
86
- // }
87
79
 
88
80
  this.addPropertyDelegate({
89
81
  key: 'apiKey',
@@ -127,6 +119,11 @@ class Gateway extends AccessoryDelegate {
127
119
  this.pollNext = true
128
120
  })
129
121
 
122
+ this.addPropertyDelegate({
123
+ key: 'fingerprint',
124
+ silent: true
125
+ })
126
+
130
127
  this.addPropertyDelegate({
131
128
  key: 'heartrate',
132
129
  value: 30,
@@ -137,16 +134,15 @@ class Gateway extends AccessoryDelegate {
137
134
  key: 'host',
138
135
  value: params.host,
139
136
  silent: true
140
- }).on('didSet', (value) => {
141
- if (this.client != null) {
142
- this.client.host = value
143
- }
144
- if (this.wsClient != null) {
145
- this.wsClient.host = this.values.host.split(':')[0] +
146
- ':' + this.values.wsPort
147
- }
148
137
  })
149
138
 
139
+ this.addPropertyDelegate({
140
+ key: 'https',
141
+ value: params.config.https,
142
+ silent: true
143
+ })
144
+ this.values.https = params.config.https
145
+
150
146
  this.addPropertyDelegate({
151
147
  key: 'periodicEvents',
152
148
  value: false,
@@ -196,16 +192,32 @@ class Gateway extends AccessoryDelegate {
196
192
  }
197
193
  })
198
194
 
195
+ this.addPropertyDelegate({
196
+ key: 'url',
197
+ silent: true
198
+ }).on('didSet', async (value) => {
199
+ if (value != null) {
200
+ this.log('gateway %s at %s', this.id, value)
201
+ try {
202
+ await this.createClient()
203
+ this.values.wsPort = null
204
+ } catch (error) { this.warn(error) }
205
+ }
206
+ })
207
+ this.values.url = null
208
+
199
209
  this.addPropertyDelegate({
200
210
  key: 'wsPort',
201
- value: 443,
211
+ value: null,
202
212
  silent: true
203
- }).on('didSet', (value) => {
204
- if (this.wsClient != null) {
205
- this.wsClient.host = this.values.host.split(':')[0] +
206
- ':' + this.values.wsPort
213
+ }).on('didSet', async (value) => {
214
+ if (value != null) {
215
+ try {
216
+ await this.createWsClient()
217
+ } catch (error) { this.warn(error) }
207
218
  }
208
219
  })
220
+ this.values.wsPort = null
209
221
 
210
222
  this.log(
211
223
  '%s %s gateway v%s', this.values.manufacturer, this.values.model,
@@ -256,14 +268,13 @@ class Gateway extends AccessoryDelegate {
256
268
  */
257
269
  this.scheduleServicesByRid = {}
258
270
 
259
- this.createClient()
260
- this.createWsClient()
261
271
  this.heartbeatEnabled = true
262
272
  this
263
273
  .on('identify', this.identify)
264
- .once('heartbeat', (beat) => { this.initialBeat = beat })
274
+ .once('heartbeat', async (beat) => {
275
+ this.initialBeat = beat
276
+ })
265
277
  .on('heartbeat', this.heartbeat)
266
- .on('shutdown', this.shutdown)
267
278
  }
268
279
 
269
280
  get transitionTime () { return this.service.values.transitionTime }
@@ -330,13 +341,11 @@ class Gateway extends AccessoryDelegate {
330
341
  */
331
342
  async found (host, config) {
332
343
  try {
333
- this.values.host = host
334
344
  this.context.config = config
345
+ this.values.host = host
346
+ this.values.https = config.https
335
347
  this.values.software = config.swversion
336
- if (!this.initialised) {
337
- this.debug('initialising...')
338
- await this.connect()
339
- }
348
+ this.values.url = 'http' + (config.https ? 's' : '') + '://' + host
340
349
  } catch (error) {
341
350
  this.error(error)
342
351
  }
@@ -344,7 +353,7 @@ class Gateway extends AccessoryDelegate {
344
353
 
345
354
  async shutdown () {
346
355
  this.service.values.statusActive = false
347
- return this.wsClient.close()
356
+ return this.wsClient?.close()
348
357
  }
349
358
 
350
359
  /** Called every second.
@@ -372,7 +381,9 @@ class Gateway extends AccessoryDelegate {
372
381
  this.values.firmware = parseInt(config.fwversion.slice(6, 8)) + '.' +
373
382
  parseInt(config.fwversion.slice(2, 4), 16) + '.' +
374
383
  parseInt(config.fwversion.slice(4, 6), 16)
375
- this.values.wsPort = config.websocketport
384
+ this.values.wsPort = this.values.https
385
+ ? config.websocketport_wss ?? config.websocketport
386
+ : config.websocketport
376
387
  this.service.update(config)
377
388
  if (this.checkApiKeys) {
378
389
  const myEntry = config.whitelist[this.values.apiKey]
@@ -390,70 +401,47 @@ class Gateway extends AccessoryDelegate {
390
401
 
391
402
  /** Create {@link DeconzAccessory.Gateway#client}.
392
403
  */
393
- createClient () {
404
+ async createClient () {
405
+ this.client?.removeAllListeners()
394
406
  /** REST API client for the gateway.
395
407
  * @type {DeconzClient}
396
408
  */
397
409
  this.client = new ApiClient({
398
410
  apiKey: this.values.apiKey,
399
411
  config: this.context.config,
412
+ fingerprint: this.values.fingerprint,
400
413
  host: this.values.host,
414
+ https: this.values.https,
415
+ logger: this,
401
416
  maxSockets: this.platform.config.parallelRequests,
402
417
  timeout: this.platform.config.timeout,
403
418
  waitTimePut: this.platform.config.waitTimePut,
404
419
  waitTimePutGroup: this.platform.config.waitTimePutGroup,
405
420
  waitTimeResend: this.platform.config.waitTimeResend
406
421
  })
407
- this.client
408
- .on('error', (error) => {
409
- if (error instanceof HttpError) {
410
- if (error.request.id !== this.requestId) {
411
- this.log(
412
- 'request %d: %s %s%s', error.request.id,
413
- error.request.method, error.request.resource,
414
- error.request.body == null ? '' : ' ' + error.request.body
415
- )
416
- this.requestId = error.request.id
417
- }
418
- this.warn('request %s: %s', error.request.id, error)
419
- return
420
- }
421
- this.warn(error)
422
- })
423
- .on('request', (request) => {
424
- this.debug(
425
- 'request %d: %s %s%s', request.id,
426
- request.method, request.resource,
427
- request.body == null ? '' : ' ' + request.body
428
- )
429
- this.vdebug(
430
- 'request %s: %s %s%s', request.id,
431
- request.method, request.url,
432
- request.body == null ? '' : ' ' + request.body
433
- )
434
- })
435
- .on('response', (response) => {
436
- this.vdebug(
437
- 'request %d: response: %j', response.request.id,
438
- response.body
439
- )
440
- this.debug(
441
- 'request %s: %d %s', response.request.id,
442
- response.statusCode, response.statusMessage
443
- )
444
- })
422
+ return this.connect()
445
423
  }
446
424
 
447
425
  /** Create {@link DeconzAccessory.Gateway#wsclient}.
448
426
  */
449
- createWsClient () {
427
+ async createWsClient () {
428
+ this.wsRestart = true
429
+ await this.wsClient?.close()
430
+ this.wsClient?.removeAllListeners()
431
+ const wss = this.values.https && this.context.fullState?.config.websocketport_wss != null
432
+ const port = wss
433
+ ? this.context.fullState?.config.websocketport_wss
434
+ : this.context.fullState?.config.websocketport
435
+ const options = {
436
+ wss,
437
+ fingerprint: this.values.fingerprint,
438
+ host: this.values.host.split(':')[0] + ':' + port,
439
+ retryTime: 0
440
+ }
450
441
  /** Client for gateway web socket notifications.
451
442
  * @type {DeconzWsClient}
452
443
  */
453
- this.wsClient = new WsClient({
454
- host: this.values.host.split(':')[0] + ':' + this.values.wsPort,
455
- retryTime: 15
456
- })
444
+ this.wsClient = new WsClient(options)
457
445
  this.wsClient
458
446
  .on('error', (error) => {
459
447
  this.warn('websocket communication error: %s', error)
@@ -490,14 +478,13 @@ class Gateway extends AccessoryDelegate {
490
478
  this.pollFullState = true
491
479
  })
492
480
  .on('closed', (url, retryTime) => {
493
- if (retryTime > 0) {
494
- this.log(
495
- 'websocket connection to %s closed - retry in %ds', url, retryTime
496
- )
497
- } else {
498
- this.log('websocket connection to %s closed', url)
481
+ this.log('websocket connection to %s closed', url)
482
+ if (!this.wsRestart) {
483
+ this.values.wsPort = null
499
484
  }
500
485
  })
486
+ this.wsClient.listen()
487
+ this.wsRestart = false
501
488
  }
502
489
 
503
490
  /** Connect to the gateway.
@@ -515,8 +502,8 @@ class Gateway extends AccessoryDelegate {
515
502
  if (this.values.apiKey == null) {
516
503
  this.values.apiKey =
517
504
  await this.client.getApiKey('homebridge-deconz')
505
+ this.values.fingerprint = this.client.fingerprint
518
506
  }
519
- this.wsClient.listen()
520
507
  this.service.values.restart = false
521
508
  this.service.values.statusActive = true
522
509
  this.checkApiKeys = true
@@ -989,6 +976,9 @@ class Gateway extends AccessoryDelegate {
989
976
  this.vdebug('%spolling...', this.pollNext ? 'priority ' : '')
990
977
  if (this.context.fullState == null || this.pollFullState) {
991
978
  const fullState = await this.client.get('/')
979
+ if (this.values.https && (this.values.fingerprint == null || this.values.fingerprint === '')) {
980
+ this.values.fingerprint = this.client.fingerprint
981
+ }
992
982
  try {
993
983
  fullState.groups[0] = await this.client.get('/groups/0')
994
984
  } catch (error) {}
@@ -1025,6 +1015,9 @@ class Gateway extends AccessoryDelegate {
1025
1015
  this.warn('deCONZ not ready')
1026
1016
  return
1027
1017
  }
1018
+ if (this.values.https && (this.values.fingerprint == null || this.values.fingerprint === '')) {
1019
+ this.values.fingerprint = this.client.fingerprint
1020
+ }
1028
1021
  this.context.fullState.config = config
1029
1022
  this.context.fullState.lights = await this.client.get('/lights')
1030
1023
  this.context.fullState.sensors = await this.client.get('/sensors')
@@ -1338,25 +1331,26 @@ class Gateway extends AccessoryDelegate {
1338
1331
  const resource = new Deconz.Resource(this, rtype, rid, body)
1339
1332
  const { id, serviceName } = resource
1340
1333
  // FIX_ME: check introspect against whitelist
1341
- if (logUnsupported && resource.body.type === 'ZHASwitch') {
1334
+ if (resource.body.type === 'ZHASwitch') {
1342
1335
  if (!resource.capabilities._introspect) {
1343
- this.warn(
1336
+ warn(
1344
1337
  '%s: /sensors/%d: %s by %s: no introspect',
1345
1338
  id, rid, resource.model, resource.manufacturer
1346
1339
  )
1347
1340
  }
1348
- } else if (resource.capabilities._buttons != null) {
1341
+ }
1342
+ if (resource.capabilities._buttons != null) {
1349
1343
  if (
1350
1344
  JSON.stringify(resource.capabilities._buttons) !==
1351
1345
  JSON.stringify(resource.capabilities.buttons) ||
1352
1346
  resource.capabilities._namespace !== resource.capabilities.namespace
1353
1347
  ) {
1354
- this.debug(
1348
+ debug(
1355
1349
  '%s: /sensors/%d: %s by %s: whitelist vs introspect mismatch: %j',
1356
1350
  id, rid, resource.model, resource.manufacturer, resource.capabilities
1357
1351
  )
1358
1352
  } else {
1359
- this.warn(
1353
+ warn(
1360
1354
  '%s: /sensors/%d: %s by %s: whitelist matches introspect',
1361
1355
  id, rid, resource.model, resource.manufacturer
1362
1356
  )
@@ -158,11 +158,25 @@ class DeconzAccessory extends AccessoryDelegate {
158
158
  } else if (params.serviceName === 'Battery') {
159
159
  service = this.servicesByServiceName.Battery?.[0]
160
160
  } else if (params.serviceName === 'Consumption') {
161
+ if (this.servicesByServiceName.Consumption?.[0] != null) {
162
+ this.warn(
163
+ '%s: ignoring additional ZHAConsumption resource - consider splitting the accessory',
164
+ resource.rpath
165
+ )
166
+ return
167
+ }
161
168
  service = this.servicesByServiceName.Power?.[0]
162
169
  if (service != null) {
163
170
  service.addResource(resource)
164
171
  }
165
172
  } else if (params.serviceName === 'Power') {
173
+ if (this.servicesByServiceName.Power?.[0] != null) {
174
+ this.warn(
175
+ '%s: ignoring additional ZHAPower resource - consider splitting the accessory',
176
+ resource.rpath
177
+ )
178
+ return
179
+ }
166
180
  service = this.servicesByServiceName.Consumption?.[0]
167
181
  if (service != null) {
168
182
  service.addResource(resource)
@@ -6,7 +6,6 @@
6
6
  import { once } from 'node:events'
7
7
 
8
8
  import { timeout } from 'homebridge-lib'
9
- import { HttpClient } from 'homebridge-lib/HttpClient'
10
9
  import { OptionParser } from 'homebridge-lib/OptionParser'
11
10
  import { Platform } from 'homebridge-lib/Platform'
12
11
 
@@ -29,7 +28,6 @@ class DeconzPlatform extends Platform {
29
28
 
30
29
  parseConfigJson (configJson) {
31
30
  this.config = {
32
- forceHttp: false,
33
31
  hosts: [],
34
32
  noResponse: false,
35
33
  parallelRequests: 10,
@@ -48,7 +46,6 @@ class DeconzPlatform extends Platform {
48
46
  })
49
47
  .stringKey('name')
50
48
  .stringKey('platform')
51
- .boolKey('forceHttp')
52
49
  .stringKey('host')
53
50
  .arrayKey('hosts')
54
51
  .boolKey('noResponse')
@@ -69,42 +66,9 @@ class DeconzPlatform extends Platform {
69
66
  this.config.hosts.push(this.config.host)
70
67
  }
71
68
  this.discovery = new Discovery({
72
- forceHttp: this.config.forceHttp,
69
+ logger: this,
73
70
  timeout: this.config.timeout
74
71
  })
75
- this.discovery
76
- .on('error', (error) => {
77
- if (error instanceof HttpClient.HttpError) {
78
- this.log(
79
- '%s: request %d: %s %s', error.request.name,
80
- error.request.id, error.request.method, error.request.resource
81
- )
82
- this.warn(
83
- '%s: request %d: %s', error.request.name, error.request.id, error
84
- )
85
- return
86
- }
87
- this.warn(error)
88
- })
89
- .on('request', (request) => {
90
- this.debug(
91
- '%s: request %d: %s %s', request.name,
92
- request.id, request.method, request.resource
93
- )
94
- })
95
- .on('response', (response) => {
96
- this.debug(
97
- '%s: request %d: %d %s', response.request.name,
98
- response.request.id, response.statusCode, response.statusMessage
99
- )
100
- })
101
- .on('found', (name, id, address) => {
102
- this.debug('%s: found %s at %s', name, id, address)
103
- })
104
- .on('searching', (host) => {
105
- this.debug('upnp: listening on %s', host)
106
- })
107
- .on('searchDone', () => { this.debug('upnp: search done') })
108
72
  } catch (error) {
109
73
  this.error(error)
110
74
  }
@@ -114,9 +78,11 @@ class DeconzPlatform extends Platform {
114
78
  const id = config.bridgeid
115
79
  if (this.gatewayMap[id] == null) {
116
80
  this.gatewayMap[id] = new DeconzAccessory.Gateway(this, { config, host })
81
+ await this.gatewayMap[id].found(host, config)
82
+ await once(this.gatewayMap[id], 'initialised')
83
+ } else {
84
+ await this.gatewayMap[id].found(host, config)
117
85
  }
118
- await this.gatewayMap[id].found(host, config)
119
- await once(this.gatewayMap[id], 'initialised')
120
86
  this.emit('found')
121
87
  }
122
88
 
@@ -224,7 +190,9 @@ class DeconzPlatform extends Platform {
224
190
  const configs = await this.discovery.discover()
225
191
  const jobs = []
226
192
  for (const host in configs) {
227
- jobs.push(this.foundGateway(host, configs[host]))
193
+ if (this.config.hosts.length === 0 || this.gatewayMap[configs[host].bridgeid] != null) {
194
+ jobs.push(this.foundGateway(host, configs[host]))
195
+ }
228
196
  }
229
197
  for (const job of jobs) {
230
198
  try {
@@ -19,7 +19,7 @@ class Contact extends DeconzService.SensorsResource {
19
19
  Characteristic: this.Characteristics.hap.ContactSensorState
20
20
  })
21
21
 
22
- // With _Status Tapered_ Eve thinks the _Door Sensor_ is an Eve Windows Guard
22
+ // With _Status Tampered_ Eve thinks the _Door Sensor_ is an Eve Windows Guard
23
23
  // (instead of an Eve Door & Window) and won't display it.
24
24
  this.addCharacteristicDelegates({ noTampered: true })
25
25
 
@@ -0,0 +1,56 @@
1
+ // homebridge-deconz/lib/DeconzService/DoorLock.js
2
+ // Copyright © 2022-2026 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ import { DeconzService } from '../DeconzService/index.js'
7
+ import '../DeconzService/SensorsResource.js'
8
+
9
+ /**
10
+ * @memberof DeconzService
11
+ */
12
+ class DoorLock extends DeconzService.SensorsResource {
13
+ constructor (accessory, resource, params = {}) {
14
+ params.Service = accessory.Services.hap.LockMechanism
15
+ super(accessory, resource, params)
16
+
17
+ this.addCharacteristicDelegate({
18
+ key: 'currentState',
19
+ Characteristic: this.Characteristics.hap.LockCurrentState
20
+ })
21
+ this.addCharacteristicDelegate({
22
+ key: 'targetState',
23
+ Characteristic: this.Characteristics.hap.LockTargetState
24
+ }).on('didSet', async (value, fromHomeKit) => {
25
+ if (fromHomeKit) {
26
+ await this.put('/config', {
27
+ lock: value === this.Characteristics.hap.LockTargetState.SECURED
28
+ })
29
+ this.locking = new Date()
30
+ }
31
+ })
32
+ this.addCharacteristicDelegates()
33
+
34
+ this.update(resource.body, resource.rpath)
35
+ }
36
+
37
+ updateState (state) {
38
+ if (state.lockstate != null) {
39
+ this.values.currentState = state.lockestate === 'locked'
40
+ ? this.Characteristics.hap.LockCurrentState.SECURED
41
+ : this.Characteristics.hap.LockCurrentState.UNSECURED
42
+ }
43
+ super.updateState(state)
44
+ }
45
+
46
+ updateConfig (config) {
47
+ if (config.lock != null && new Date() - this.locking >= 5000) {
48
+ this.values.targetLockState = config.lock
49
+ ? this.Characteristics.hap.LockTargetState.SECURED
50
+ : this.Characteristics.hap.LockTargetState.UNSECURED
51
+ }
52
+ super.updateConfig(config)
53
+ }
54
+ }
55
+
56
+ DeconzService.DoorLock = DoorLock
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "ebaauw"
8
8
  ],
9
9
  "license": "Apache-2.0",
10
- "version": "1.2.12",
10
+ "version": "1.3.1",
11
11
  "keywords": [
12
12
  "homebridge-plugin",
13
13
  "homekit",
@@ -27,12 +27,12 @@
27
27
  },
28
28
  "engines": {
29
29
  "deCONZ": "2.32.5",
30
- "homebridge": "^1.11.2||^2.0.0-beta",
31
- "node": "^24||^22||^20"
30
+ "homebridge": "^2.0.1",
31
+ "node": "^24||^22"
32
32
  },
33
33
  "dependencies": {
34
- "hb-deconz-tools": "~2.0.22",
35
- "homebridge-lib": "~7.3.1"
34
+ "hb-deconz-tools": "~3.0.3",
35
+ "homebridge-lib": "~8.1.0"
36
36
  },
37
37
  "scripts": {
38
38
  "prepare": "standard && rm -rf out && jsdoc -c jsdoc.json",