homebridge-deconz 0.1.16 → 0.1.18

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.
@@ -6,7 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  const { UiServer } = require('homebridge-lib')
9
- const Deconz = require('../lib/Deconz')
9
+ const { Discovery } = require('hb-deconz-tools')
10
10
 
11
11
  class DeconzUiServer extends UiServer {
12
12
  constructor () {
@@ -14,7 +14,7 @@ class DeconzUiServer extends UiServer {
14
14
 
15
15
  this.onRequest('discover', async (params) => {
16
16
  if (this.discovery == null) {
17
- this.discovery = new Deconz.Discovery({
17
+ this.discovery = new Discovery({
18
18
  // forceHttp: this.config.forceHttp,
19
19
  // timeout: this.config.timeout
20
20
  })
@@ -6,15 +6,21 @@
6
6
  'use strict'
7
7
 
8
8
  const { OptionParser } = require('homebridge-lib')
9
- const Deconz = require('../Deconz')
9
+ const { ApiClient } = require('hb-deconz-tools')
10
10
  const DeconzAccessory = require('../DeconzAccessory')
11
11
  const DeconzService = require('../DeconzService')
12
12
 
13
13
  const { toInstance, toInt, toObject, toString } = OptionParser
14
- const { buttonEvent } = Deconz.ApiClient
14
+ const { buttonEvent } = ApiClient
15
15
  const { SINGLE, DOUBLE, LONG } = DeconzService.Button
16
16
  const rtypes = ['lights', 'sensors', 'groups']
17
17
 
18
+ const patterns = {
19
+ uniqueid: /^([0-9a-f]{1,2}(?:[:-]?(?:[0-9a-f]{1,2})){7})-([0-9a-z]{2})(?:-([0-9a-z]{4}))?$/i,
20
+ clipId: /^(S[0-9]{1,3})-([0-9a-z]{2})-([0-9a-z]{4})$/i,
21
+ swversion: /^([0-9]+)(?:\.([0-9]+)(?:\.([0-9]+)(?:_([0-9]{4}))?)?)?$/
22
+ }
23
+
18
24
  // From low to high.
19
25
  const sensorsPrios = [
20
26
  'Power',
@@ -24,7 +30,8 @@ const sensorsPrios = [
24
30
  'Motion',
25
31
  'Contact',
26
32
  'AirPurifier',
27
- 'Thermostat'
33
+ 'Thermostat',
34
+ 'Flag'
28
35
  ]
29
36
 
30
37
  // =============================================================================
@@ -51,14 +58,43 @@ class Resource {
51
58
  */
52
59
  static parseUniqueid (uniqueid) {
53
60
  toString('uniqueid', uniqueid, true)
54
- const a = uniqueid.replace(/:/g, '').toUpperCase().split('-')
61
+ const a = patterns.uniqueid.exec(uniqueid.replace(/:/g, '').toUpperCase())
62
+ return {
63
+ mac: a?.[1],
64
+ endpoint: a?.[2],
65
+ cluster: a?.[3]
66
+ }
67
+ }
68
+
69
+ /** Parse the `uniqueid` in the resource body of a resource for a CLIP sensor.
70
+ * @param {string} uniqueid - The `uniqueid`.
71
+ * @return {object} The MultiCLIP `id`, `endpoint`, and `cluster`.
72
+ */
73
+ static parseClipId (uniqueid) {
74
+ toString('uniqueid', uniqueid, true)
75
+ const a = patterns.clipId.exec(uniqueid.replace(/:/g, '').toUpperCase())
55
76
  return {
56
- mac: a?.[0],
57
- endpoint: a?.[1],
58
- cluster: a?.[2]
77
+ id: a?.[1],
78
+ endpoint: a?.[2],
79
+ cluster: a?.[3]
59
80
  }
60
81
  }
61
82
 
83
+ /** Parse the `swversion` in the resource body of a resource for a Zigbee device.
84
+ * @param {string} swversion - The `swversion`.
85
+ * @return {string} The normalised version in semver format.
86
+ */
87
+ static parseSwversion (swversion) {
88
+ if (swversion == null) {
89
+ return '0.0.0'
90
+ }
91
+ const a = patterns.swversion.exec(swversion)
92
+ if (a?.[1] === '0' && a?.[2] === '0' && a?.[3] === '0' && a?.[4] != null) {
93
+ return '0.0.' + Number(a[4]).toString()
94
+ }
95
+ return swversion
96
+ }
97
+
62
98
  /** Create a new instance of a delegate of a resource.
63
99
  *
64
100
  * @param {DeconzAccessory.Gateway} gateway - The gateway.
@@ -90,6 +126,8 @@ class Resource {
90
126
  toString('body.name', body.name, true)
91
127
  toString('body.type', body.type, true)
92
128
 
129
+ let realDevice = false
130
+
93
131
  if (
94
132
  this.rtype === 'lights' ||
95
133
  (this.rtype === 'sensors' && this.body.type.startsWith('Z'))
@@ -129,16 +167,30 @@ class Resource {
129
167
  * @type {boolean}
130
168
  */
131
169
  this.zigbee = true
170
+
171
+ realDevice = true
132
172
  } else if (this.rtype === 'sensors') {
133
173
  const { mac, endpoint, cluster } = Resource.parseUniqueid(body.uniqueid)
134
174
  if (mac != null && endpoint != null && cluster != null) {
175
+ // uniqueid for proxy device has proper mac, endpoint, cluster
135
176
  this.id = mac
136
- this.subtype = endpoint + (cluster == null ? '' : '-' + cluster)
177
+ this.subtype = endpoint + '-' + cluster
137
178
  this.endpoint = endpoint
138
179
  this.cluster = cluster
180
+ realDevice = true
139
181
  } else {
140
- this.subtype = rtype[0].toUpperCase() + rid
141
- this.id = gateway.id + '-' + this.subtype
182
+ const { id, endpoint, cluster } = Resource.parseClipId(body.uniqueid)
183
+ if (id != null && endpoint != null && cluster != null) {
184
+ // uniqueid for MultiCLIP has proper id, endpoint, cluster
185
+ this.id = gateway.id + '-' + id
186
+ this.subtype = endpoint + '-' + cluster
187
+ this.endpoint = endpoint
188
+ this.cluster = cluster
189
+ } else {
190
+ // ignore uniqueid for regular CLIP
191
+ this.subtype = rtype[0].toUpperCase() + rid
192
+ this.id = gateway.id + '-' + this.subtype
193
+ }
142
194
  }
143
195
  this.zigbee = false
144
196
  } else {
@@ -154,7 +206,7 @@ class Resource {
154
206
  * For virtual devices, this is the _Manufacturer_ for the gateway.
155
207
  * @type {string}
156
208
  */
157
- this.manufacturer = this.endpoint != null
209
+ this.manufacturer = realDevice
158
210
  ? body.manufacturername.replace(/\//g, '')
159
211
  : gateway.values.manufacturer
160
212
 
@@ -165,7 +217,7 @@ class Resource {
165
217
  * For virtual devices, this is the `type` in the resource body.
166
218
  * @type {string}
167
219
  */
168
- this.model = this.endpoint != null ? body.modelid : body.type
220
+ this.model = realDevice ? body.modelid : body.type
169
221
 
170
222
  /** The associated HomeKit _Firmware Version_.
171
223
  *
@@ -173,8 +225,8 @@ class Resource {
173
225
  * resource body.
174
226
  * For virtual devices, this is the _Firmware Version_ for the gateway.
175
227
  */
176
- this.firmware = this.endpoint != null
177
- ? body.swversion == null ? '0.0.0' : body.swversion
228
+ this.firmware = realDevice
229
+ ? Resource.parseSwversion(body.swversion)
178
230
  : gateway.values.software
179
231
 
180
232
  /** The name of the {@link DeconzService} subclass of the delegate of the
@@ -237,6 +289,7 @@ class Resource {
237
289
  case 'On/Off light': return 'Light'
238
290
  case 'On/Off output': return 'Outlet'
239
291
  case 'On/Off plug-in unit': return 'Outlet'
292
+ case 'On/Off switch': return 'Switch'
240
293
  case 'Smart plug': return 'Outlet'
241
294
  case 'Configuration tool': return ''
242
295
  case 'Range extender': return ''
@@ -9,13 +9,8 @@
9
9
  * @hideconstructor
10
10
  */
11
11
  class Deconz {
12
- static get ApiClient () { return require('./ApiClient') }
13
- static get ApiError () { return require('./ApiError') }
14
- static get ApiResponse () { return require('./ApiResponse') }
15
12
  static get Device () { return require('./Device') }
16
- static get Discovery () { return require('./Discovery') }
17
13
  static get Resource () { return require('./Resource') }
18
- static get WsClient () { return require('./WsClient') }
19
14
  }
20
15
 
21
16
  module.exports = Deconz
@@ -8,7 +8,7 @@
8
8
  const {
9
9
  AccessoryDelegate, HttpClient, OptionParser, timeout
10
10
  } = require('homebridge-lib')
11
-
11
+ const { ApiClient, ApiError, WsClient } = require('hb-deconz-tools')
12
12
  const Deconz = require('../Deconz')
13
13
  const DeconzAccessory = require('../DeconzAccessory')
14
14
  const DeconzService = require('../DeconzService')
@@ -103,6 +103,14 @@ class Gateway extends AccessoryDelegate {
103
103
  } catch (error) { this.error(error) }
104
104
  })
105
105
 
106
+ this.addPropertyDelegate({
107
+ key: 'exposeSchedules',
108
+ value: false,
109
+ silent: true
110
+ }).on('didSet', async (value) => {
111
+ this.pollNext = true
112
+ })
113
+
106
114
  this.addPropertyDelegate({
107
115
  key: 'heartrate',
108
116
  value: 30,
@@ -149,6 +157,7 @@ class Gateway extends AccessoryDelegate {
149
157
  value: false,
150
158
  silent: true
151
159
  }).on('didSet', async (value) => {
160
+ this.service.values.search = value
152
161
  if (value) {
153
162
  try {
154
163
  await this.client.search()
@@ -229,6 +238,11 @@ class Gateway extends AccessoryDelegate {
229
238
  DeconzService.Button.LONG
230
239
  })
231
240
 
241
+ /** The service delegates for the Schedule services.
242
+ * @type {Object<string, DeconzService.Schedule>}
243
+ */
244
+ this.scheduleServicesByRid = {}
245
+
232
246
  this.createClient()
233
247
  this.createWsClient()
234
248
  this.heartbeatEnabled = true
@@ -342,7 +356,9 @@ class Gateway extends AccessoryDelegate {
342
356
 
343
357
  update (config) {
344
358
  this.values.software = config.swversion
345
- this.values.firmware = config.fwversion
359
+ this.values.firmware = parseInt(config.fwversion.slice(6, 8)) + '.' +
360
+ parseInt(config.fwversion.slice(2, 4), 16) + '.' +
361
+ parseInt(config.fwversion.slice(4, 6), 16)
346
362
  this.values.wsPort = config.websocketport
347
363
  this.service.update(config)
348
364
  if (this.checkApiKeys) {
@@ -365,7 +381,7 @@ class Gateway extends AccessoryDelegate {
365
381
  /** REST API client for the gateway.
366
382
  * @type {DeconzClient}
367
383
  */
368
- this.client = new Deconz.ApiClient({
384
+ this.client = new ApiClient({
369
385
  apiKey: this.values.apiKey,
370
386
  config: this.context.config,
371
387
  host: this.values.host,
@@ -421,7 +437,7 @@ class Gateway extends AccessoryDelegate {
421
437
  /** Client for gateway web socket notifications.
422
438
  * @type {DeconzWsClient}
423
439
  */
424
- this.wsClient = new Deconz.WsClient({
440
+ this.wsClient = new WsClient({
425
441
  host: this.values.host.split(':')[0] + ':' + this.values.wsPort,
426
442
  retryTime: 15
427
443
  })
@@ -498,7 +514,7 @@ class Gateway extends AccessoryDelegate {
498
514
  this.pollFullState = true
499
515
  } catch (error) {
500
516
  if (
501
- error instanceof Deconz.ApiError && error.type === 101 && retry < 8
517
+ error instanceof ApiError && error.type === 101 && retry < 8
502
518
  ) {
503
519
  this.log('unlock gateway to obtain API key - retrying in 15s')
504
520
  await timeout(15000)
@@ -772,6 +788,7 @@ class Gateway extends AccessoryDelegate {
772
788
  : {
773
789
  brightnessAdjustment: this.values.brightnessAdjustment * 100,
774
790
  expose: this.values.expose,
791
+ exposeSchedules: this.values.exposeSchedules,
775
792
  heartrate: this.values.heartrate,
776
793
  logLevel: this.values.logLevel,
777
794
  periodicEvents: this.values.periodicEvents,
@@ -830,6 +847,7 @@ class Gateway extends AccessoryDelegate {
830
847
  if (this.values.apiKey != null) {
831
848
  optionParser
832
849
  .intKey('brightnessAdjustment', 10, 100)
850
+ .boolKey('exposeSchedules')
833
851
  .intKey('heartrate', 1, 60)
834
852
  .boolKey('periodicEvents')
835
853
  .boolKey('restart')
@@ -846,6 +864,7 @@ class Gateway extends AccessoryDelegate {
846
864
  responseBody[key] = this.values[key]
847
865
  break
848
866
  case 'expose':
867
+ case 'exposeSchedules':
849
868
  case 'heartrate':
850
869
  case 'logLevel':
851
870
  case 'periodicEvents':
@@ -919,7 +938,7 @@ class Gateway extends AccessoryDelegate {
919
938
  await this.wsClient.close()
920
939
  return
921
940
  }
922
- if (config.fwversion === '0x00000000') {
941
+ if (config.bridgeid === '0000000000000000' || config.fwversion === '0x00000000') {
923
942
  this.warn('deCONZ not ready')
924
943
  return
925
944
  }
@@ -930,7 +949,7 @@ class Gateway extends AccessoryDelegate {
930
949
  this.context.fullState.groups = await this.client.get('/groups')
931
950
  this.context.fullState.groups[0] = await this.client.get('/groups/0')
932
951
  }
933
- if (this.nDevicesByRtype.schedules) {
952
+ if (this.values.exposeSchedules) {
934
953
  this.context.fullState.schedules = await this.client.get('/schedules')
935
954
  }
936
955
  }
@@ -1114,6 +1133,24 @@ class Gateway extends AccessoryDelegate {
1114
1133
  )
1115
1134
  }
1116
1135
 
1136
+ this.vdebug('analysing schedules...')
1137
+ if (this.values.exposeSchedules) {
1138
+ for (const rid in fullState.schedules) {
1139
+ if (this.scheduleServicesByRid[rid] == null) {
1140
+ this.scheduleServicesByRid[rid] = new DeconzService.Schedule(
1141
+ this, rid, fullState.schedules[rid]
1142
+ )
1143
+ }
1144
+ this.scheduleServicesByRid[rid].update(fullState.schedules[rid])
1145
+ }
1146
+ }
1147
+ for (const rid in this.scheduleServicesByRid) {
1148
+ if (!this.values.exposeSchedules || fullState.schedules[rid] == null) {
1149
+ this.scheduleServicesByRid[rid].destroy()
1150
+ delete this.scheduleServicesByRid[rid]
1151
+ }
1152
+ }
1153
+
1117
1154
  if (changed) {
1118
1155
  await this.updateMigration()
1119
1156
  this.identify()
@@ -6,10 +6,10 @@
6
6
  'use strict'
7
7
 
8
8
  const { AccessoryDelegate, OptionParser } = require('homebridge-lib')
9
- const Deconz = require('../Deconz')
9
+ const { ApiClient } = require('hb-deconz-tools')
10
10
  const DeconzService = require('../DeconzService')
11
11
 
12
- const { HttpError } = Deconz.ApiClient
12
+ const { HttpError } = ApiClient
13
13
  const { SINGLE, DOUBLE, LONG } = DeconzService.Button
14
14
 
15
15
  /** Abstract superclass for a delegate of a HomeKit accessory,
@@ -65,7 +65,7 @@ class DeconzAccessory extends AccessoryDelegate {
65
65
  this.device = device
66
66
 
67
67
  /** The API client instance for the gateway.
68
- * @type {Deconz.ApiClient}
68
+ * @type {ApiClient}
69
69
  */
70
70
  this.client = gateway.client
71
71
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  const events = require('events')
9
9
  const { HttpClient, OptionParser, Platform, timeout } = require('homebridge-lib')
10
- const Deconz = require('./Deconz')
10
+ const { Discovery } = require('hb-deconz-tools')
11
11
  const DeconzAccessory = require('./DeconzAccessory')
12
12
 
13
13
  class DeconzPlatform extends Platform {
@@ -65,7 +65,7 @@ class DeconzPlatform extends Platform {
65
65
  if (this.config.host != null) {
66
66
  this.config.hosts.push(this.config.host)
67
67
  }
68
- this.discovery = new Deconz.Discovery({
68
+ this.discovery = new Discovery({
69
69
  forceHttp: this.config.forceHttp,
70
70
  timeout: this.config.timeout
71
71
  })
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const Deconz = require('../Deconz')
8
+ const { ApiClient } = require('hb-deconz-tools')
9
9
  const DeconzService = require('../DeconzService')
10
10
 
11
- const { dateToString } = Deconz.ApiClient
11
+ const { dateToString } = ApiClient
12
12
 
13
13
  /**
14
14
  * @memberof DeconzService
@@ -5,9 +5,9 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const Deconz = require('../Deconz')
8
+ const { ApiClient } = require('hb-deconz-tools')
9
9
  const { ServiceDelegate } = require('homebridge-lib')
10
- const { dateToString } = Deconz.ApiClient
10
+ const { dateToString } = ApiClient
11
11
 
12
12
  /**
13
13
  * @memberof DeconzService
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const Deconz = require('../Deconz')
8
+ const { ApiClient } = require('hb-deconz-tools')
9
9
  const DeconzService = require('../DeconzService')
10
10
 
11
- const { dateToString } = Deconz.ApiClient
11
+ const { dateToString } = ApiClient
12
12
 
13
13
  /**
14
14
  * @memberof DeconzService
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ const { ApiClient } = require('hb-deconz-tools')
8
9
  const DeconzService = require('../DeconzService')
9
- const Deconz = require('../Deconz')
10
10
 
11
- const { dateToString } = Deconz.ApiClient
11
+ const { dateToString } = ApiClient
12
12
 
13
13
  const daylightEvents = {
14
14
  100: { name: 'Solar Midnight', period: 'Night' },
@@ -31,6 +31,16 @@ class Gateway extends ServiceDelegate {
31
31
  silent: true
32
32
  })
33
33
 
34
+ this.addCharacteristicDelegate({
35
+ key: 'search',
36
+ Characteristic: this.Characteristics.my.Search,
37
+ value: false
38
+ }).on('didSet', (value, fromHomeKit) => {
39
+ if (fromHomeKit) {
40
+ this.gateway.values.search = value
41
+ }
42
+ })
43
+
34
44
  this.addCharacteristicDelegate({
35
45
  key: 'transitionTime',
36
46
  Characteristic: this.Characteristics.my.TransitionTime,
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ const { ApiClient } = require('hb-deconz-tools')
8
9
  const DeconzService = require('../DeconzService')
9
- const Deconz = require('../Deconz')
10
10
 
11
- const { lightLevelToLux } = Deconz.ApiClient
11
+ const { lightLevelToLux } = ApiClient
12
12
 
13
13
  /**
14
14
  * @memberof DeconzService
@@ -6,10 +6,10 @@
6
6
  'use strict'
7
7
 
8
8
  const { timeout } = require('homebridge-lib')
9
- const Deconz = require('../Deconz')
9
+ const { ApiClient } = require('hb-deconz-tools')
10
10
  const DeconzService = require('../DeconzService')
11
11
 
12
- const { HttpError } = Deconz.ApiClient
12
+ const { HttpError } = ApiClient
13
13
 
14
14
  class LightsResource extends DeconzService {
15
15
  constructor (accessory, resource, params) {
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const Deconz = require('../Deconz')
9
8
  const DeconzService = require('../DeconzService')
9
+ const { ApiClient } = require('hb-deconz-tools')
10
10
 
11
- const { dateToString } = Deconz.ApiClient
11
+ const { dateToString } = ApiClient
12
12
 
13
13
  /**
14
14
  * @memberof DeconzService
@@ -0,0 +1,69 @@
1
+ // homebridge-deconz/lib/DeconzService/Schedule.js
2
+ // Copyright© 2022-2023 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const { ApiClient } = require('hb-deconz-tools')
9
+ const { ServiceDelegate } = require('homebridge-lib')
10
+
11
+ const { HttpError } = ApiClient
12
+
13
+ /**
14
+ * @memberof DeconzService
15
+ */
16
+ class Schedule extends ServiceDelegate {
17
+ constructor (accessory, rid, body) {
18
+ super(accessory, {
19
+ id: accessory.gateway.id + '-T' + rid,
20
+ name: body.name,
21
+ Service: accessory.Services.my.Resource,
22
+ subtype: 'T' + rid,
23
+ exposeConfiguredName: true
24
+ })
25
+ this.id = accessory.gateway.id + '-T' + rid
26
+ this.gateway = accessory.gateway
27
+ this.accessory = accessory
28
+ this.client = accessory.client
29
+ this.rtype = 'schedules'
30
+ this.rid = rid
31
+ this.rpath = '/' + this.rtype + '/' + this.rid
32
+
33
+ this.addCharacteristicDelegate({
34
+ key: 'enabled',
35
+ Characteristic: this.Characteristics.my.Enabled
36
+ }).on('didSet', async (value, fromHomeKit) => {
37
+ await this.put({ status: value ? 'enabled' : 'disabled' })
38
+ this.values.statusActive = value
39
+ })
40
+
41
+ this.addCharacteristicDelegate({
42
+ key: 'statusActive',
43
+ Characteristic: this.Characteristics.hap.StatusActive
44
+ })
45
+
46
+ // this.addCharacteristicDelegate({
47
+ // key: 'index',
48
+ // Characteristic: this.Characteristics.hap.ServiceLabelIndex,
49
+ // value: rid
50
+ // })
51
+ }
52
+
53
+ update (body) {
54
+ this.values.enabled = body.status === 'enabled'
55
+ this.values.statusActive = this.values.enabled
56
+ }
57
+
58
+ async put (body) {
59
+ try {
60
+ await this.client.put(this.rpath, body)
61
+ } catch (error) {
62
+ if (!(error instanceof HttpError)) {
63
+ this.warn(error)
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ module.exports = Schedule
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const Deconz = require('../Deconz')
8
+ const { ApiClient } = require('hb-deconz-tools')
9
9
  const DeconzService = require('../DeconzService')
10
10
 
11
- const { dateToString, HttpError } = Deconz.ApiClient
11
+ const { dateToString, HttpError } = ApiClient
12
12
 
13
13
  /**
14
14
  * @memberof DeconzService
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ const { ApiClient } = require('hb-deconz-tools')
8
9
  const { ServiceDelegate } = require('homebridge-lib')
9
- const Deconz = require('../Deconz')
10
10
 
11
- const { dateToString } = Deconz.ApiClient
11
+ const { dateToString } = ApiClient
12
12
 
13
13
  /** Service delegates.
14
14
  * @extends ServiceDelegate
@@ -35,6 +35,7 @@ class DeconzService extends ServiceDelegate {
35
35
  static get Motion () { return require('./Motion') }
36
36
  static get Outlet () { return require('./Outlet') }
37
37
  static get Power () { return require('./Power') }
38
+ static get Schedule () { return require('./Schedule') }
38
39
  static get SensorsResource () { return require('./SensorsResource') }
39
40
  static get Status () { return require('./Status') }
40
41
  static get Smoke () { return require('./Smoke') }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "displayName": "Homebridge deCONZ",
5
5
  "author": "Erik Baauw",
6
6
  "license": "Apache-2.0",
7
- "version": "0.1.16",
7
+ "version": "0.1.18",
8
8
  "keywords": [
9
9
  "homebridge-plugin",
10
10
  "homekit",
@@ -26,6 +26,7 @@
26
26
  "node": "^18.16.0"
27
27
  },
28
28
  "dependencies": {
29
+ "hb-deconz-tools": "~1.0.2",
29
30
  "homebridge-lib": "~6.3.17",
30
31
  "ws": "^8.13.0",
31
32
  "xml2js": "~0.5.0"