homebridge-deconz 0.0.10 → 0.0.13

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.
Files changed (53) hide show
  1. package/README.md +3 -6
  2. package/cli/deconz.js +12 -0
  3. package/config.schema.json +1 -0
  4. package/homebridge-ui/public/index.html +26 -0
  5. package/homebridge-ui/public/style.css +0 -0
  6. package/homebridge-ui/server.js +43 -0
  7. package/lib/Deconz/ApiClient.js +34 -1
  8. package/lib/Deconz/ApiResponse.js +1 -1
  9. package/lib/Deconz/Device.js +0 -7
  10. package/lib/Deconz/Resource.js +751 -25
  11. package/lib/DeconzAccessory/Contact.js +54 -0
  12. package/lib/DeconzAccessory/Gateway.js +102 -66
  13. package/lib/DeconzAccessory/Light.js +42 -37
  14. package/lib/DeconzAccessory/Motion.js +51 -0
  15. package/lib/DeconzAccessory/Sensor.js +35 -0
  16. package/lib/DeconzAccessory/Temperature.js +63 -0
  17. package/lib/DeconzAccessory/Thermostat.js +50 -0
  18. package/lib/DeconzAccessory/WarningDevice.js +56 -0
  19. package/lib/DeconzAccessory/WindowCovering.js +47 -0
  20. package/lib/DeconzAccessory/index.js +144 -2
  21. package/lib/DeconzPlatform.js +5 -2
  22. package/lib/DeconzService/AirPressure.js +43 -0
  23. package/lib/DeconzService/AirQuality.js +20 -11
  24. package/lib/DeconzService/Alarm.js +13 -9
  25. package/lib/DeconzService/Battery.js +53 -0
  26. package/lib/DeconzService/Button.js +9 -2
  27. package/lib/DeconzService/CarbonMonoxide.js +38 -0
  28. package/lib/DeconzService/Consumption.js +65 -0
  29. package/lib/DeconzService/Contact.js +60 -0
  30. package/lib/DeconzService/Daylight.js +132 -0
  31. package/lib/DeconzService/DeviceSettings.js +11 -0
  32. package/lib/DeconzService/Flag.js +52 -0
  33. package/lib/DeconzService/Humidity.js +37 -0
  34. package/lib/DeconzService/Leak.js +38 -0
  35. package/lib/DeconzService/Light.js +122 -172
  36. package/lib/DeconzService/LightLevel.js +54 -0
  37. package/lib/DeconzService/LightsResource.js +112 -0
  38. package/lib/DeconzService/Motion.js +101 -0
  39. package/lib/DeconzService/Outlet.js +76 -0
  40. package/lib/DeconzService/Power.js +83 -0
  41. package/lib/DeconzService/SensorsResource.js +96 -0
  42. package/lib/DeconzService/Smoke.js +38 -0
  43. package/lib/DeconzService/Status.js +53 -0
  44. package/lib/DeconzService/Switch.js +93 -0
  45. package/lib/DeconzService/Temperature.js +63 -0
  46. package/lib/DeconzService/Thermostat.js +175 -0
  47. package/lib/DeconzService/WarningDevice.js +68 -0
  48. package/lib/DeconzService/WindowCovering.js +162 -0
  49. package/lib/DeconzService/index.js +79 -25
  50. package/package.json +6 -5
  51. package/lib/Client/ApiError.js +0 -42
  52. package/lib/DeconzAccessory/Device.js +0 -69
  53. package/lib/DeconzService/Sensor.js +0 -61
@@ -0,0 +1,132 @@
1
+ // homebridge-deconz/lib/DeconzService/Daylight.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+ const Deconz = require('../Deconz')
10
+
11
+ const { dateToString, lightLevelToLux } = Deconz.ApiClient
12
+
13
+ const daylightEvents = {
14
+ 100: { name: 'Solar Midnight', period: 'Night' },
15
+ 110: { name: 'Astronomical Dawn', period: 'Astronomical Twilight' },
16
+ 120: { name: 'Nautical Dawn', period: 'Nautical Twilight' },
17
+ 130: { name: 'Dawn', period: 'Twilight' },
18
+ 140: { name: 'Sunrise', period: 'Sunrise' },
19
+ 150: { name: 'End Sunrise', period: 'Golden Hour' },
20
+ 160: { name: 'End Golden Hour', period: 'Day' },
21
+ 170: { name: 'Solar Noon', period: 'Day' },
22
+ 180: { name: 'Start Golden Hour', period: 'Golden Hour' },
23
+ 190: { name: 'Start Sunset', period: 'Sunset' },
24
+ 200: { name: 'Sunset', period: 'Twilight' },
25
+ 210: { name: 'Dusk', period: 'Nautical Twilight' },
26
+ 220: { name: 'Nautical Dusk', period: 'Astronomical Twilight' },
27
+ 230: { name: 'Astronomical Dusk', period: 'Night' }
28
+ }
29
+
30
+ const daylightPeriods = {
31
+ Night: { lightlevel: 0, daylight: false, dark: true },
32
+ 'Astronomical Twilight': { lightlevel: 100, daylight: false, dark: true },
33
+ 'Nautical Twilight': { lightlevel: 1000, daylight: false, dark: true },
34
+ Twilight: { lightlevel: 10000, daylight: false, dark: false },
35
+ Sunrise: { lightlevel: 15000, daylight: true, dark: false },
36
+ Sunset: { lightlevel: 20000, daylight: true, dark: false },
37
+ 'Golden Hour': { lightlevel: 40000, daylight: true, dark: false },
38
+ Day: { lightlevel: 65535, daylight: true, dark: false }
39
+ }
40
+
41
+ /**
42
+ * @memberof DeconzService
43
+ */
44
+ class Daylight extends DeconzService.SensorsResource {
45
+ constructor (accessory, resource, params = {}) {
46
+ params.Service = accessory.Services.hap.LightSensor
47
+ super(accessory, resource, params)
48
+
49
+ this.addCharacteristicDelegate({
50
+ key: 'lightlevel',
51
+ Characteristic: this.Characteristics.hap.CurrentAmbientLightLevel,
52
+ unit: ' lux'
53
+ })
54
+
55
+ this.addCharacteristicDelegate({
56
+ key: 'dark',
57
+ Characteristic: this.Characteristics.my.Dark
58
+ })
59
+
60
+ this.addCharacteristicDelegate({
61
+ key: 'daylight',
62
+ Characteristic: this.Characteristics.my.Daylight
63
+ })
64
+
65
+ this.addCharacteristicDelegate({
66
+ key: 'status',
67
+ Characteristic: this.Characteristics.my.Status,
68
+ props: {
69
+ minValue: 100,
70
+ maxValue: 230,
71
+ perms: [
72
+ this.Characteristic.Perms.READ,
73
+ this.Characteristic.Perms.NOTIFY]
74
+ },
75
+ value: resource.body.state.status
76
+ })
77
+
78
+ this.addCharacteristicDelegate({
79
+ key: 'lastEvent',
80
+ Characteristic: this.Characteristics.my.LastEvent
81
+ })
82
+
83
+ this.addCharacteristicDelegate({
84
+ key: 'period',
85
+ Characteristic: this.Characteristics.my.Period
86
+ })
87
+
88
+ this.addCharacteristicDelegates()
89
+
90
+ this.addCharacteristicDelegate({
91
+ key: 'sunrise',
92
+ Characteristic: this.Characteristics.my.Sunrise
93
+ })
94
+
95
+ this.addCharacteristicDelegate({
96
+ key: 'sunset',
97
+ Characteristic: this.Characteristics.my.Sunset
98
+ })
99
+
100
+ if (!resource.body.config.configured) {
101
+ this.warn('%s: %s not configured', resource.rpath, resource.body.type)
102
+ }
103
+
104
+ this.update(resource.body)
105
+ }
106
+
107
+ updateState (state) {
108
+ if (state.status != null) {
109
+ this.values.status = state.status
110
+ const { name, period } = daylightEvents[state.status]
111
+ this.values.lastEvent = name
112
+ this.values.period = period
113
+ const { lightlevel } = daylightPeriods[period]
114
+ this.values.lightlevel = lightLevelToLux(lightlevel)
115
+ }
116
+ if (state.dark != null) {
117
+ this.values.dark = state.dark
118
+ }
119
+ if (state.daylight != null) {
120
+ this.values.daylight = state.daylight
121
+ }
122
+ if (state.sunrise != null) {
123
+ this.values.sunrise = dateToString(state.sunrise)
124
+ }
125
+ if (state.sunset != null) {
126
+ this.values.sunset = dateToString(state.sunset)
127
+ }
128
+ super.updateState(state)
129
+ }
130
+ }
131
+
132
+ module.exports = Daylight
@@ -16,6 +16,8 @@ class DeviceSettings extends homebridgeLib.ServiceDelegate {
16
16
  params.Service = accessory.Services.my.DeconzDevice
17
17
  super(accessory, params)
18
18
 
19
+ this.debug('settings: %j', params)
20
+
19
21
  this.addCharacteristicDelegate({
20
22
  key: 'expose',
21
23
  Characteristic: this.Characteristics.my.Expose,
@@ -25,6 +27,15 @@ class DeviceSettings extends homebridgeLib.ServiceDelegate {
25
27
  accessory.gateway.exposeDevice(params.subtype, value)
26
28
  })
27
29
 
30
+ if (params.hasRepeat != null) {
31
+ this.addCharacteristicDelegate({
32
+ key: 'repeat',
33
+ Characteristic: this.Characteristics.my.Repeat,
34
+ props: { minValue: 0, maxValue: 1, minStep: 1 },
35
+ value: 0
36
+ })
37
+ }
38
+
28
39
  if (params.logLevel != null) {
29
40
  this.addCharacteristicDelegate({
30
41
  key: 'logLevel',
@@ -0,0 +1,52 @@
1
+ // homebridge-deconz/lib/DeconzService/Flag.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Flag extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.hap.Switch
16
+ super(accessory, resource, params)
17
+
18
+ if (resource.capabilities.readonly) {
19
+ this.addCharacteristicDelegate({
20
+ key: 'on',
21
+ Characteristic: this.Characteristics.hap.On,
22
+ props: {
23
+ perms: [
24
+ this.Characteristic.Perms.READ, this.Characteristic.Perms.NOTIFY
25
+ ]
26
+ }
27
+ })
28
+ } else {
29
+ this.addCharacteristicDelegate({
30
+ key: 'on',
31
+ Characteristic: this.Characteristics.hap.On
32
+ }).on('didSet', async (value, fromHomeKit) => {
33
+ if (fromHomeKit) {
34
+ await this.put('/state', { flag: value })
35
+ }
36
+ })
37
+ }
38
+
39
+ this.addCharacteristicDelegates()
40
+
41
+ this.update(resource.body)
42
+ }
43
+
44
+ updateState (state) {
45
+ if (state.flag != null) {
46
+ this.values.on = state.flag
47
+ }
48
+ super.updateState(state)
49
+ }
50
+ }
51
+
52
+ module.exports = Flag
@@ -0,0 +1,37 @@
1
+ // homebridge-deconz/lib/DeconzService/Humidity.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Humidity extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.hap.HumiditySensor
16
+ super(accessory, resource, params)
17
+
18
+ this.addCharacteristicDelegate({
19
+ key: 'humidity',
20
+ Characteristic: this.Characteristics.hap.CurrentRelativeHumidity,
21
+ unit: '%'
22
+ })
23
+
24
+ this.addCharacteristicDelegates()
25
+
26
+ this.update(resource.body)
27
+ }
28
+
29
+ updateState (state) {
30
+ if (state.humidity != null) {
31
+ this.values.humidity = Math.round(state.humidity / 10) / 10
32
+ }
33
+ super.updateState(state)
34
+ }
35
+ }
36
+
37
+ module.exports = Humidity
@@ -0,0 +1,38 @@
1
+ // homebridge-deconz/lib/DeconzService/Leak.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Leak extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.hap.LeakSensor
16
+ super(accessory, resource, params)
17
+
18
+ this.addCharacteristicDelegate({
19
+ key: 'leak',
20
+ Characteristic: this.Characteristics.hap.LeakDetected
21
+ })
22
+
23
+ super.addCharacteristicDelegates()
24
+
25
+ this.update(resource.body)
26
+ }
27
+
28
+ updateState (state) {
29
+ if (state.water != null || state.test != null) {
30
+ this.values.leak = state.water || state.test
31
+ ? this.Characteristics.hap.LeakDetected.LEAK_DETECTED
32
+ : this.Characteristics.hap.LeakDetected.LEAK_NOT_DETECTED
33
+ }
34
+ super.updateState(state)
35
+ }
36
+ }
37
+
38
+ module.exports = Leak
@@ -1,4 +1,4 @@
1
- // homebridge-deconz/lib/DeconzService/Sensor.js
1
+ // homebridge-deconz/lib/DeconzService/Light.js
2
2
  // Copyright © 2022 Erik Baauw. All rights reserved.
3
3
  //
4
4
  // Homebridge plugin for deCONZ.
@@ -6,34 +6,15 @@
6
6
  'use strict'
7
7
 
8
8
  const homebridgeLib = require('homebridge-lib')
9
- const Deconz = require('../Deconz')
9
+ const DeconzService = require('../DeconzService')
10
10
 
11
- const { dateToString } = Deconz.ApiClient
12
11
  const { timeout } = homebridgeLib
13
12
  const { xyToHsv, hsvToXy, ctToXy } = homebridgeLib.Colour
14
13
 
15
- class Light extends homebridgeLib.ServiceDelegate {
16
- constructor (accessory, resource) {
17
- super(accessory, {
18
- id: resource.id,
19
- name: resource.body.name,
20
- subtype: resource.subtype,
21
- Service: accessory.Services.hap.Lightbulb
22
- })
23
- this.id = resource.id
24
- this.gateway = accessory.gateway
25
- this.client = accessory.client
26
- this.resource = resource
27
- this.rtype = resource.rtype
28
- this.rid = resource.rid
29
- this.rpath = resource.rpath +
30
- (resource.rtype === 'groups' ? '/action' : '/state')
31
- this.capabilities = resource.capabilities
32
-
33
- this.debug('%s: capabilities: %j', this.resource.rpath, this.capabilities)
34
-
35
- this.targetState = {}
36
- this.deferrals = []
14
+ class Light extends DeconzService.LightsResource {
15
+ constructor (accessory, resource, params = {}) {
16
+ params.Service = accessory.Services.hap.Lightbulb
17
+ super(accessory, resource, params)
37
18
 
38
19
  this.addCharacteristicDelegate({
39
20
  key: 'on',
@@ -66,10 +47,10 @@ class Light extends homebridgeLib.ServiceDelegate {
66
47
  key: 'brightness',
67
48
  Characteristic: this.Characteristics.hap.Brightness,
68
49
  unit: '%',
69
- value: this.resource.body.state.bri
50
+ value: Math.round(this.resource.body.state.bri / 2.54)
70
51
  }).on('didSet', (value, fromHomeKit) => {
71
52
  if (fromHomeKit) {
72
- const bri = Math.round(value * 254.0 / 100.0)
53
+ const bri = Math.round(value * 2.54)
73
54
  this.put({ bri: bri })
74
55
  this.updateAdaptiveLighting()
75
56
  }
@@ -206,23 +187,18 @@ class Light extends homebridgeLib.ServiceDelegate {
206
187
  })
207
188
  }
208
189
 
209
- this.addCharacteristicDelegate({
210
- key: 'lastSeen',
211
- Characteristic: this.Characteristics.my.LastSeen,
212
- silent: true
213
- })
214
-
215
- this.addCharacteristicDelegate({
216
- key: 'statusFault',
217
- Characteristic: this.Characteristics.hap.StatusFault
218
- })
190
+ this.addCharacteristicDelegates()
219
191
 
220
192
  if (this.capabilities.bri && this.capabilities.ct && !this.capabilities.hs) {
221
193
  this.addCharacteristicDelegate({
222
194
  key: 'supportedTransitionConfiguration',
223
195
  Characteristic: this.Characteristics.hap
224
196
  .SupportedCharacteristicValueTransitionConfiguration,
225
- silent: true
197
+ silent: true,
198
+ getter: async () => {
199
+ this.initAdaptiveLighting()
200
+ return this.adaptiveLighting.generateConfiguration()
201
+ }
226
202
  })
227
203
  this.addCharacteristicDelegate({
228
204
  key: 'transitionControl',
@@ -230,11 +206,9 @@ class Light extends homebridgeLib.ServiceDelegate {
230
206
  .CharacteristicValueTransitionControl,
231
207
  silent: true,
232
208
  getter: async () => {
233
- this.initAdaptiveLighting()
234
209
  return this.adaptiveLighting.generateControl()
235
210
  },
236
211
  setter: async (value) => {
237
- this.initAdaptiveLighting()
238
212
  const control = this.adaptiveLighting.parseControl(value)
239
213
  this.context.transitionControl = value
240
214
  const response = this.adaptiveLighting.generateControlResponse()
@@ -259,9 +233,107 @@ class Light extends homebridgeLib.ServiceDelegate {
259
233
  this.updateAdaptiveLighting()
260
234
  }
261
235
  })
262
- if (this.values.supportedTransitionConfiguration != null) {
263
- this.initAdaptiveLighting()
236
+ }
237
+
238
+ if (this.resource.rtype === 'groups') {
239
+ this.sceneServices = []
240
+ for (const scene of this.resource.body.scenes) {
241
+ const service = new homebridgeLib.ServiceDelegate(accessory, {
242
+ name: this.resource.body.name + ' ' + scene.name,
243
+ Service: this.Services.hap.Switch,
244
+ subtype: this.subtype + '-S' + scene.id
245
+ })
246
+ service.addCharacteristicDelegate({
247
+ key: 'on',
248
+ Characteristic: this.Characteristics.hap.On,
249
+ value: false
250
+ }).on('didSet', async (value, fromHomeKit) => {
251
+ this.checkAdaptiveLighting()
252
+ if (fromHomeKit && value) {
253
+ try {
254
+ const path = this.resource.rpath + '/scenes/' + scene.id + '/recall'
255
+ this.debug('PUT %s', path)
256
+ await this.client.put(path)
257
+ } catch (error) { this.error(error) }
258
+ await timeout(this.platform.config.waitTimeReset)
259
+ service.values.on = false
260
+ }
261
+ })
262
+ this.sceneServices.push(service)
263
+ }
264
+ }
265
+
266
+ if (this.capabilities.effects != null) {
267
+ this.effectServices = []
268
+ this.addCharacteristicDelegate({
269
+ key: 'effect',
270
+ value: -1,
271
+ silent: true
272
+ }).on('didSet', (value) => {
273
+ for (const i in this.capabilities.effects) {
274
+ this.effectServices[i].values.on = value === i
275
+ }
276
+ })
277
+ for (const i in this.capabilities.effects) {
278
+ const effect = this.capabilities.effects[i]
279
+ const service = new homebridgeLib.ServiceDelegate(accessory, {
280
+ name: this.resource.body.name + ' ' + effect,
281
+ Service: this.Services.hap.Switch,
282
+ subtype: this.subtype + '-E' + i
283
+ })
284
+ service.addCharacteristicDelegate({
285
+ key: 'on',
286
+ Characteristic: this.Characteristics.hap.On
287
+ }).on('didSet', (value, fromHomeKit) => {
288
+ if (fromHomeKit) {
289
+ this.checkAdaptiveLighting()
290
+ this.values.effect = value ? i : -1
291
+ const newEffect = value
292
+ ? effect.toLowerCase()
293
+ : 'none'
294
+ this.put({ effect: newEffect })
295
+ }
296
+ })
297
+ this.effectServices.push(service)
264
298
  }
299
+ // if (this.capabilities.effectSpeed) {
300
+ // this.addCharacteristicDelegate({
301
+ // key: 'effectSpeed',
302
+ // Characteristic: this.Characteristics.my.EffectSpeed,
303
+ // value: 50
304
+ // }).on('didSet', (value) => {
305
+ // this.setEffectSpeed(value)
306
+ // })
307
+ // this.hk.effectColours = []
308
+ // for (let i = 0; i <= 5; i++) {
309
+ // const service = new this.Service.Lightbulb(
310
+ // this.name + ' Effect Color ' + (i + 1), this.subtype + '-C' + i
311
+ // )
312
+ // service.addCharacteristicDelegate({
313
+ // key: 'on',
314
+ // Characteristic: this.Characteristics.hap.On,
315
+ // value: true
316
+ // }).on('didSet', (value) => {
317
+ // this.setEffectOn(i, value)
318
+ // })
319
+ // service.addCharacteristicDelegate({
320
+ // key: 'hue',
321
+ // Characteristic: this.Characteristics.hap.Hue,
322
+ // value: i * 60
323
+ // }).on('didSet', (value) => {
324
+ // this.setEffectHue(i, value)
325
+ // })
326
+ // service.addCharacteristicDelegate({
327
+ // key: 'saturation',
328
+ // Characteristic: this.Characteristics.hap.Saturation,
329
+ // value: 100
330
+ // }).on('didSet', (value) => {
331
+ // this.setEffectSat(i, value)
332
+ // })
333
+ // this.effectServices.push(service)
334
+ // }
335
+ // }
336
+ // this.checkEffect(this.obj.state.effect)
265
337
  }
266
338
 
267
339
  this.settings = {
@@ -272,50 +344,6 @@ class Light extends homebridgeLib.ServiceDelegate {
272
344
  }
273
345
  }
274
346
 
275
- update (body) {
276
- if (this.updating) {
277
- return
278
- }
279
- for (const key in body) {
280
- const value = body[key]
281
- switch (key) {
282
- case 'action':
283
- // Copied to `state` by `Resource` during polling.
284
- break
285
- case 'state':
286
- this.updateState(value)
287
- break
288
- case 'lastannounced':
289
- // this.values.lastBoot = dateToString(value)
290
- break
291
- case 'lastseen':
292
- this.resource.body.lastseen = value
293
- this.values.lastSeen = dateToString(value)
294
- break
295
- case 'colorcapabilities':
296
- case 'ctmax':
297
- case 'ctmin':
298
- case 'devicemembership':
299
- case 'etag':
300
- case 'id':
301
- case 'lights':
302
- case 'hascolor':
303
- case 'manufacturername':
304
- case 'modelid':
305
- case 'name':
306
- case 'powerup':
307
- case 'scenes':
308
- case 'swversion':
309
- case 'type':
310
- case 'uniqueid':
311
- break
312
- default:
313
- this.warn('%s: unknown %s attribute', key, this.rtype)
314
- break
315
- }
316
- }
317
- }
318
-
319
347
  updateState (state) {
320
348
  let updateAdaptiveLighting = false
321
349
  for (const key in state) {
@@ -330,11 +358,9 @@ class Light extends homebridgeLib.ServiceDelegate {
330
358
  this.values.anyOn = value
331
359
  updateAdaptiveLighting = true
332
360
  break
333
- case 'alert':
334
- break
335
361
  case 'bri':
336
362
  if (!this.recentlyUpdated) {
337
- this.values.brightness = Math.round(value * 100.0 / 254.0)
363
+ this.values.brightness = Math.round(value / 2.54)
338
364
  updateAdaptiveLighting = true
339
365
  }
340
366
  break
@@ -347,6 +373,11 @@ class Light extends homebridgeLib.ServiceDelegate {
347
373
  }
348
374
  break
349
375
  case 'effect':
376
+ this.values.colorLoop = value === 'colorloop'
377
+ if (this.capabilities.effects != null) {
378
+ const effectName = value[0].toUpperCase() + value.slice(1)
379
+ this.values.effect = '' + this.capabilities.effects.indexOf(effectName)
380
+ }
350
381
  break
351
382
  case 'hue':
352
383
  if (!this.capabilities.xy) {
@@ -356,18 +387,11 @@ class Light extends homebridgeLib.ServiceDelegate {
356
387
  case 'on':
357
388
  this.values.on = value
358
389
  break
359
- case 'reachable':
360
- this.values.statusFault = value
361
- ? this.Characteristics.hap.StatusFault.NO_FAULT
362
- : this.Characteristics.hap.StatusFault.GENERAL_FAULT
363
- break
364
390
  case 'sat':
365
391
  if (!this.capabilities.xy) {
366
392
  this.values.hue = value
367
393
  }
368
394
  break
369
- case 'scene':
370
- break
371
395
  case 'xy':
372
396
  if (
373
397
  !this.recentlyUpdated &&
@@ -379,30 +403,13 @@ class Light extends homebridgeLib.ServiceDelegate {
379
403
  }
380
404
  break
381
405
  default:
382
- this.warn('state.%s: unknown %s attribute', key, this.rtype)
383
406
  break
384
407
  }
385
408
  }
386
409
  if (updateAdaptiveLighting) {
387
410
  this.updateAdaptiveLighting()
388
411
  }
389
- }
390
-
391
- async identify () {
392
- try {
393
- if (this.capabilities.alert) {
394
- if (this.capabilities.breathe) {
395
- await this.client.put({ alert: 'breathe' })
396
- await timeout(1500)
397
- return this.client.put({ alert: 'stop' })
398
- }
399
- return this.put({ alert: 'select' })
400
- }
401
- } catch (error) {
402
- if (!(error instanceof Deconz.ApiClient.HttpError)) {
403
- this.warn(error)
404
- }
405
- }
412
+ super.updateState(state)
406
413
  }
407
414
 
408
415
  initAdaptiveLighting () {
@@ -410,8 +417,6 @@ class Light extends homebridgeLib.ServiceDelegate {
410
417
  this.adaptiveLighting = new homebridgeLib.AdaptiveLighting(
411
418
  this.brightnessDelegate, this.colorTemperatureDelegate
412
419
  )
413
- this.values.supportedTransitionConfiguration =
414
- this.adaptiveLighting.generateConfiguration()
415
420
  if (this.values.activeTransitionCount > 0) {
416
421
  const control = this.adaptiveLighting.parseControl(
417
422
  this.context.transitionControl
@@ -462,67 +467,12 @@ class Light extends homebridgeLib.ServiceDelegate {
462
467
  }
463
468
 
464
469
  checkAdaptiveLighting (key, value) {
465
- if (this.fromAdaptiveLighting) {
470
+ if (this.adaptiveLighting == null || this.fromAdaptiveLighting) {
466
471
  return
467
472
  }
468
473
  this.adaptiveLighting.deactivate()
469
474
  this.values.activeTransitionCount = 0
470
475
  }
471
-
472
- // Collect changes into a combined request.
473
- put (state) {
474
- for (const key in state) {
475
- this.resource.body.state[key] = state[key]
476
- this.targetState[key] = state[key]
477
- }
478
- this._put()
479
- }
480
-
481
- // Send the request (for the combined changes) to the gateway.
482
- async _put () {
483
- try {
484
- if (this.updating) {
485
- return
486
- }
487
- this.updating = true
488
- if (this.settings.waitTimeUpdate > 0) {
489
- await timeout(this.settings.waitTimeUpdate)
490
- }
491
- const targetState = this.targetState
492
- this.targetState = {}
493
- this.updating = false
494
- if (
495
- this.gateway.transitionTime !== this.gateway.defaultTransitionTime &&
496
- targetState.transitiontime === undefined
497
- ) {
498
- targetState.transitiontime = this.gateway.transitionTime * 10
499
- this.gateway.resetTransitionTime()
500
- }
501
- if (this.capabilities.noTransition) {
502
- if (
503
- (
504
- targetState.on != null || targetState.bri != null ||
505
- targetState.bri_inc != null
506
- ) && (
507
- targetState.xy != null || targetState.ct != null ||
508
- targetState.hue != null || targetState.sat != null ||
509
- targetState.effect != null
510
- )
511
- ) {
512
- targetState.transitiontime = 0
513
- }
514
- }
515
- this.debug('PUT %s %j', this.rpath, targetState)
516
- await this.client.put(this.rpath, targetState)
517
- this.recentlyUpdated = true
518
- await timeout(500)
519
- this.recentlyUpdated = false
520
- } catch (error) {
521
- if (!(error instanceof Deconz.ApiClient.HttpError)) {
522
- this.warn(error)
523
- }
524
- }
525
- }
526
476
  }
527
477
 
528
478
  module.exports = Light