homebridge-deconz 0.0.6 → 0.0.11

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 (58) hide show
  1. package/README.md +8 -0
  2. package/cli/deconz.js +980 -0
  3. package/config.schema.json +1 -1
  4. package/lib/Client/ApiError.js +42 -0
  5. package/lib/{DeconzClient.js → Deconz/ApiClient.js} +82 -158
  6. package/lib/Deconz/ApiError.js +42 -0
  7. package/lib/Deconz/ApiResponse.js +54 -0
  8. package/lib/Deconz/Device.js +100 -0
  9. package/lib/{DeconzDiscovery.js → Deconz/Discovery.js} +4 -3
  10. package/lib/Deconz/Resource.js +1206 -0
  11. package/lib/{DeconzWsClient.js → Deconz/WsClient.js} +59 -44
  12. package/lib/Deconz/index.js +21 -0
  13. package/lib/DeconzAccessory/Contact.js +54 -0
  14. package/lib/DeconzAccessory/Gateway.js +316 -374
  15. package/lib/DeconzAccessory/Light.js +72 -0
  16. package/lib/DeconzAccessory/Motion.js +51 -0
  17. package/lib/DeconzAccessory/Sensor.js +35 -0
  18. package/lib/DeconzAccessory/Temperature.js +63 -0
  19. package/lib/DeconzAccessory/Thermostat.js +50 -0
  20. package/lib/DeconzAccessory/WarningDevice.js +56 -0
  21. package/lib/DeconzAccessory/WindowCovering.js +47 -0
  22. package/lib/DeconzAccessory/index.js +216 -0
  23. package/lib/DeconzPlatform.js +8 -3
  24. package/lib/DeconzService/AirPressure.js +43 -0
  25. package/lib/DeconzService/AirQuality.js +20 -10
  26. package/lib/DeconzService/Alarm.js +16 -9
  27. package/lib/DeconzService/Battery.js +43 -0
  28. package/lib/DeconzService/Button.js +12 -2
  29. package/lib/DeconzService/CarbonMonoxide.js +38 -0
  30. package/lib/DeconzService/Consumption.js +65 -0
  31. package/lib/DeconzService/Contact.js +60 -0
  32. package/lib/DeconzService/Daylight.js +132 -0
  33. package/lib/DeconzService/DeviceSettings.js +13 -5
  34. package/lib/DeconzService/Flag.js +52 -0
  35. package/lib/DeconzService/GatewaySettings.js +8 -58
  36. package/lib/DeconzService/Humidity.js +37 -0
  37. package/lib/DeconzService/Leak.js +38 -0
  38. package/lib/DeconzService/Light.js +376 -0
  39. package/lib/DeconzService/LightLevel.js +54 -0
  40. package/lib/DeconzService/LightsResource.js +112 -0
  41. package/lib/DeconzService/Motion.js +101 -0
  42. package/lib/DeconzService/Outlet.js +76 -0
  43. package/lib/DeconzService/Power.js +83 -0
  44. package/lib/DeconzService/SensorsResource.js +96 -0
  45. package/lib/DeconzService/Smoke.js +38 -0
  46. package/lib/DeconzService/Status.js +53 -0
  47. package/lib/DeconzService/Switch.js +93 -0
  48. package/lib/DeconzService/Temperature.js +63 -0
  49. package/lib/DeconzService/Thermostat.js +175 -0
  50. package/lib/DeconzService/WarningDevice.js +68 -0
  51. package/lib/DeconzService/WindowCovering.js +139 -0
  52. package/lib/DeconzService/index.js +94 -0
  53. package/package.json +7 -4
  54. package/lib/DeconzAccessory/Device.js +0 -91
  55. package/lib/DeconzAccessory.js +0 -16
  56. package/lib/DeconzDevice.js +0 -245
  57. package/lib/DeconzService/Sensor.js +0 -58
  58. package/lib/DeconzService.js +0 -43
@@ -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
@@ -0,0 +1,376 @@
1
+ // homebridge-deconz/lib/DeconzService/Light.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const homebridgeLib = require('homebridge-lib')
9
+ const DeconzService = require('../DeconzService')
10
+
11
+ const { timeout } = homebridgeLib
12
+ const { xyToHsv, hsvToXy, ctToXy } = homebridgeLib.Colour
13
+
14
+ class Light extends DeconzService.LightsResource {
15
+ constructor (accessory, resource, params = {}) {
16
+ params.Service = accessory.Services.hap.Lightbulb
17
+ super(accessory, resource, params)
18
+
19
+ this.addCharacteristicDelegate({
20
+ key: 'on',
21
+ Characteristic: this.Characteristics.hap.On,
22
+ value: this.capabilities.on
23
+ ? this.resource.body.state.on
24
+ : this.resource.body.state.all_on
25
+ }).on('didSet', (value, fromHomeKit) => {
26
+ if (fromHomeKit) {
27
+ this.put({ on: value })
28
+ this.updateAdaptiveLighting()
29
+ }
30
+ })
31
+
32
+ if (!this.capabilities.on) {
33
+ this.addCharacteristicDelegate({
34
+ key: 'anyOn',
35
+ Characteristic: this.Characteristics.my.AnyOn,
36
+ value: this.resource.body.state.any_on
37
+ }).on('didSet', (value, fromHomeKit) => {
38
+ if (fromHomeKit) {
39
+ this.put({ on: value })
40
+ this.updateAdaptiveLighting()
41
+ }
42
+ })
43
+ }
44
+
45
+ if (this.capabilities.bri) {
46
+ this.brightnessDelegate = this.addCharacteristicDelegate({
47
+ key: 'brightness',
48
+ Characteristic: this.Characteristics.hap.Brightness,
49
+ unit: '%',
50
+ value: Math.round(this.resource.body.state.bri / 2.54)
51
+ }).on('didSet', (value, fromHomeKit) => {
52
+ if (fromHomeKit) {
53
+ const bri = Math.round(value * 2.54)
54
+ this.put({ bri: bri })
55
+ this.updateAdaptiveLighting()
56
+ }
57
+ })
58
+
59
+ this.addCharacteristicDelegate({
60
+ key: 'brightnessChange',
61
+ Characteristic: this.Characteristics.my.BrightnessChange,
62
+ value: 0
63
+ }).on('didSet', async (value) => {
64
+ this.put({ bri_inc: Math.round(value * 254.0 / 100.0) })
65
+ await timeout(this.platform.config.waitTimeReset)
66
+ this.values.brightnessChange = 0
67
+ })
68
+ this.values.brightnessChange = 0
69
+ }
70
+
71
+ if (this.capabilities.ct || this.capabilities.xy || this.capabilities.hs) {
72
+ this.addCharacteristicDelegate({
73
+ key: 'colormode',
74
+ value: this.resource.body.state.colormode,
75
+ silent: true
76
+ }).on('didSet', (value) => {
77
+ this.resource.body.colormode = value
78
+ if (value !== 'ct') {
79
+ this.checkAdaptiveLighting()
80
+ }
81
+ })
82
+ }
83
+
84
+ if (this.capabilities.ct) {
85
+ this.colorTemperatureDelegate = this.addCharacteristicDelegate({
86
+ key: 'colorTemperature',
87
+ Characteristic: this.Characteristics.hap.ColorTemperature,
88
+ unit: ' mired',
89
+ props: {
90
+ minValue: this.capabilities.ctMin,
91
+ maxValue: this.capabilities.ctMax
92
+ },
93
+ value: this.resource.body.state.ct
94
+ }).on('didSet', (value, fromHomeKit) => {
95
+ this.checkAdaptiveLighting()
96
+ const ct = Math.max(
97
+ this.capabilities.ctMin, Math.min(value, this.capabilities.ctMax)
98
+ )
99
+ if (fromHomeKit) {
100
+ this.put({ ct: ct })
101
+ this.values.colormode = 'ct'
102
+ }
103
+ if (this.capabilities.xy && this.values.colormode === 'ct') {
104
+ const { h, s } = xyToHsv(ctToXy(ct), this.capabilities.gamut)
105
+ this.values.hue = h
106
+ this.values.saturation = s
107
+ }
108
+ })
109
+ }
110
+
111
+ if (this.capabilities.xy) {
112
+ this.addCharacteristicDelegate({
113
+ key: 'hue',
114
+ Characteristic: this.Characteristics.hap.Hue,
115
+ unit: '°'
116
+ }).on('didSet', (value, fromHomeKit) => {
117
+ if (fromHomeKit) {
118
+ const xy = hsvToXy(
119
+ value, this.values.saturation, this.capabilities.gamut
120
+ )
121
+ this.put({ xy: xy })
122
+ this.values.colormode = 'xy'
123
+ }
124
+ })
125
+ this.addCharacteristicDelegate({
126
+ key: 'saturation',
127
+ Characteristic: this.Characteristics.hap.Saturation,
128
+ unit: '%'
129
+ }).on('didSet', (value, fromHomeKit) => {
130
+ if (fromHomeKit) {
131
+ const xy = hsvToXy(this.values.hue, value, this.capabilities.gamut)
132
+ this.put({ xy: xy })
133
+ this.values.colormode = 'xy'
134
+ }
135
+ })
136
+ } else if (this.capabilities.hs) {
137
+ this.addCharacteristicDelegate({
138
+ key: 'hue',
139
+ Characteristic: this.Characteristics.hap.Hue,
140
+ unit: '°'
141
+ }).on('didSet', (value, fromHomeKit) => {
142
+ if (fromHomeKit) {
143
+ const hue = Math.round(this.hk.hue * 65535.0 / 360.0)
144
+ this.put({ hue: hue })
145
+ this.values.colormode = 'hs'
146
+ }
147
+ })
148
+ this.addCharacteristicDelegate({
149
+ key: 'saturation',
150
+ Characteristic: this.Characteristics.hap.Saturation,
151
+ unit: '%'
152
+ }).on('didSet', (value, fromHomeKit) => {
153
+ if (fromHomeKit) {
154
+ const sat = Math.round(this.hk.sat * 254.0 / 100.0)
155
+ this.put({ sat: sat })
156
+ this.values.colormode = 'hs'
157
+ }
158
+ })
159
+ }
160
+
161
+ if (this.capabilities.colorLoop) {
162
+ this.addCharacteristicDelegate({
163
+ key: 'colorLoop',
164
+ Characteristic: this.Characteristics.my.ColorLoop
165
+ }).on('didSet', (value, fromHomeKit) => {
166
+ if (fromHomeKit) {
167
+ const effect = value ? 'colorloop' : 'none'
168
+ const state = { effect: effect }
169
+ if (value) {
170
+ state.colorloopspeed = this.values.colorLoopSpeed
171
+ }
172
+ this.put(state)
173
+ this.values.colormode = 'hs'
174
+ }
175
+ })
176
+ this.addCharacteristicDelegate({
177
+ key: 'colorLoopSpeed',
178
+ Characteristic: this.Characteristics.my.ColorLoopSpeed,
179
+ unit: 's',
180
+ value: 25
181
+ }).on('didSet', (value, fromHomeKit) => {
182
+ if (fromHomeKit) {
183
+ const effect = 'colorloop'
184
+ this.put({ effect: effect, colorloopspeed: value })
185
+ this.values.colormode = 'hs'
186
+ }
187
+ })
188
+ }
189
+
190
+ this.addCharacteristicDelegates()
191
+
192
+ if (this.capabilities.bri && this.capabilities.ct && !this.capabilities.hs) {
193
+ this.addCharacteristicDelegate({
194
+ key: 'supportedTransitionConfiguration',
195
+ Characteristic: this.Characteristics.hap
196
+ .SupportedCharacteristicValueTransitionConfiguration,
197
+ silent: true
198
+ })
199
+ this.addCharacteristicDelegate({
200
+ key: 'transitionControl',
201
+ Characteristic: this.Characteristics.hap
202
+ .CharacteristicValueTransitionControl,
203
+ silent: true,
204
+ getter: async () => {
205
+ this.initAdaptiveLighting()
206
+ return this.adaptiveLighting.generateControl()
207
+ },
208
+ setter: async (value) => {
209
+ this.initAdaptiveLighting()
210
+ const control = this.adaptiveLighting.parseControl(value)
211
+ this.context.transitionControl = value
212
+ const response = this.adaptiveLighting.generateControlResponse()
213
+ const parsedResponse = this.adaptiveLighting.parseControl(response)
214
+ this.vdebug(
215
+ 'Adaptive Lighting: control update: %j => %j',
216
+ control, parsedResponse
217
+ )
218
+ this.values.activeTransitionCount = parsedResponse === '' ? 0 : 1
219
+ return response
220
+ }
221
+ })
222
+ this.addCharacteristicDelegate({
223
+ key: 'activeTransitionCount',
224
+ Characteristic: this.Characteristics.hap
225
+ .CharacteristicValueActiveTransitionCount,
226
+ silent: true,
227
+ value: 0
228
+ }).on('didSet', (value) => {
229
+ this.log('Adaptive Lighting: %sabled', value > 0 ? 'en' : 'dis')
230
+ if (value) {
231
+ this.updateAdaptiveLighting()
232
+ }
233
+ })
234
+ if (this.values.supportedTransitionConfiguration != null) {
235
+ this.initAdaptiveLighting()
236
+ }
237
+ }
238
+
239
+ this.settings = {
240
+ brightnessAdjustment: 1,
241
+ resetTimeout: this.platform.config.resetTimeout,
242
+ waitTimeUpdate: this.platform.config.waitTimeUpdate,
243
+ wallSwitch: false
244
+ }
245
+ }
246
+
247
+ updateState (state) {
248
+ let updateAdaptiveLighting = false
249
+ for (const key in state) {
250
+ const value = state[key]
251
+ this.resource.body.state[key] = value
252
+ switch (key) {
253
+ case 'all_on':
254
+ this.values.on = value
255
+ updateAdaptiveLighting = true
256
+ break
257
+ case 'any_on':
258
+ this.values.anyOn = value
259
+ updateAdaptiveLighting = true
260
+ break
261
+ case 'bri':
262
+ if (!this.recentlyUpdated) {
263
+ this.values.brightness = Math.round(value / 2.54)
264
+ updateAdaptiveLighting = true
265
+ }
266
+ break
267
+ case 'colormode':
268
+ this.values.colormode = value
269
+ break
270
+ case 'ct':
271
+ if (!this.recentlyUpdated && this.values.colormode === 'ct') {
272
+ this.values.colorTemperature = value
273
+ }
274
+ break
275
+ case 'effect':
276
+ this.values.colorLoop = value === 'colorloop'
277
+ break
278
+ case 'hue':
279
+ if (!this.capabilities.xy) {
280
+ this.values.hue = value
281
+ }
282
+ break
283
+ case 'on':
284
+ this.values.on = value
285
+ break
286
+ case 'sat':
287
+ if (!this.capabilities.xy) {
288
+ this.values.hue = value
289
+ }
290
+ break
291
+ case 'xy':
292
+ if (
293
+ !this.recentlyUpdated &&
294
+ (this.values.colormode !== 'ct' || this.capabilities.computesXy)
295
+ ) {
296
+ const { h, s } = xyToHsv(value, this.capabilities.gamut)
297
+ this.values.hue = h
298
+ this.values.saturation = s
299
+ }
300
+ break
301
+ default:
302
+ break
303
+ }
304
+ }
305
+ if (updateAdaptiveLighting) {
306
+ this.updateAdaptiveLighting()
307
+ }
308
+ super.updateState(state)
309
+ }
310
+
311
+ initAdaptiveLighting () {
312
+ if (this.adaptiveLighting == null) {
313
+ this.adaptiveLighting = new homebridgeLib.AdaptiveLighting(
314
+ this.brightnessDelegate, this.colorTemperatureDelegate
315
+ )
316
+ this.values.supportedTransitionConfiguration =
317
+ this.adaptiveLighting.generateConfiguration()
318
+ if (this.values.activeTransitionCount > 0) {
319
+ const control = this.adaptiveLighting.parseControl(
320
+ this.context.transitionControl
321
+ )
322
+ this.vdebug('Adaptive Lighting: restore control: %j', control)
323
+ this.adaptiveLighting.parseControl(this.context.transitionControl)
324
+ }
325
+ this.log(
326
+ 'Adaptive Lighting: %sabled',
327
+ this.values.activeTransitionCount > 0 ? 'en' : 'dis'
328
+ )
329
+ }
330
+ }
331
+
332
+ async updateAdaptiveLighting () {
333
+ if (
334
+ this.adaptiveLighting == null || // not supported
335
+ this.values.activeTransitionCount === 0 || // disabled
336
+ !this.values.on // light is off
337
+ ) {
338
+ return
339
+ }
340
+ const ct = this.adaptiveLighting.getCt(
341
+ this.values.brightness * this.settings.brightnessAdjustment
342
+ )
343
+ if (ct == null) {
344
+ this.warn('assertion failed')
345
+ return
346
+ }
347
+ this.debug(
348
+ '/%s/%d: adaptive lighting: {"state":{"ct": %d}}',
349
+ this.rtype, this.rid, ct
350
+ )
351
+ if (this.values.colormode === 'ct' && ct === this.values.colorTemperature) {
352
+ return
353
+ }
354
+ this.put({ ct: ct })
355
+ this.fromAdaptiveLighting = true
356
+ this.values.colormode = 'ct'
357
+ if (ct !== this.values.colorTemperature) {
358
+ this.values.colorTemperature = ct
359
+ } else if (this.capabilities.xy) { // colormode changed
360
+ const { h, s } = xyToHsv(ctToXy(ct), this.capabilities.gamut)
361
+ this.values.hue = h
362
+ this.values.saturation = s
363
+ }
364
+ this.fromAdaptiveLighting = false
365
+ }
366
+
367
+ checkAdaptiveLighting (key, value) {
368
+ if (this.fromAdaptiveLighting) {
369
+ return
370
+ }
371
+ this.adaptiveLighting.deactivate()
372
+ this.values.activeTransitionCount = 0
373
+ }
374
+ }
375
+
376
+ module.exports = Light
@@ -0,0 +1,54 @@
1
+ // homebridge-deconz/lib/DeconzService/LightLevel.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 { lightLevelToLux } = Deconz.ApiClient
12
+
13
+ /**
14
+ * @memberof DeconzService
15
+ */
16
+ class LightLevel extends DeconzService.SensorsResource {
17
+ constructor (accessory, resource, params = {}) {
18
+ params.Service = accessory.Services.hap.LightSensor
19
+ super(accessory, resource, params)
20
+
21
+ this.addCharacteristicDelegate({
22
+ key: 'lightlevel',
23
+ Characteristic: this.Characteristics.hap.CurrentAmbientLightLevel,
24
+ unit: ' lux'
25
+ })
26
+
27
+ this.addCharacteristicDelegate({
28
+ key: 'dark',
29
+ Characteristic: this.Characteristics.my.Dark
30
+ })
31
+
32
+ this.addCharacteristicDelegate({
33
+ key: 'daylight',
34
+ Characteristic: this.Characteristics.my.Daylight
35
+ })
36
+
37
+ this.addCharacteristicDelegates()
38
+ }
39
+
40
+ updateState (state) {
41
+ if (state.lightlevel != null) {
42
+ this.values.lightlevel = lightLevelToLux(state.lightlevel)
43
+ }
44
+ if (state.dark != null) {
45
+ this.values.dark = state.dark
46
+ }
47
+ if (state.daylight != null) {
48
+ this.values.daylight = state.daylight
49
+ }
50
+ super.updateState(state)
51
+ }
52
+ }
53
+
54
+ module.exports = LightLevel
@@ -0,0 +1,112 @@
1
+ // homebridge-deconz/lib/DeconzService/LightsResource.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const homebridgeLib = require('homebridge-lib')
9
+ const Deconz = require('../Deconz')
10
+ const DeconzService = require('../DeconzService')
11
+
12
+ const { HttpError } = Deconz.ApiClient
13
+ const { timeout } = homebridgeLib
14
+
15
+ class LightsResource extends DeconzService {
16
+ constructor (accessory, resource, params) {
17
+ super(accessory, resource, params)
18
+ this.rpath += resource.rtype === 'groups' ? '/action' : '/state'
19
+
20
+ this.targetState = {}
21
+ this.deferrals = []
22
+ }
23
+
24
+ addCharacteristicDelegates (params = {}) {
25
+ this.addCharacteristicDelegate({
26
+ key: 'lastSeen',
27
+ Characteristic: this.Characteristics.my.LastSeen,
28
+ silent: true
29
+ })
30
+
31
+ this.addCharacteristicDelegate({
32
+ key: 'statusFault',
33
+ Characteristic: this.Characteristics.hap.StatusFault
34
+ })
35
+ }
36
+
37
+ updateState (state) {
38
+ if (state.reachable != null) {
39
+ this.values.statusFault = state.reachable
40
+ ? this.Characteristics.hap.StatusFault.NO_FAULT
41
+ : this.Characteristics.hap.StatusFault.GENERAL_FAULT
42
+ }
43
+ }
44
+
45
+ async identify () {
46
+ if (this.capabilities.alert) {
47
+ if (this.capabilities.breathe) {
48
+ await this.client.put(this.rpath, { alert: 'breathe' })
49
+ await timeout(1500)
50
+ await this.client.put(this.rpath, { alert: 'stop' })
51
+ }
52
+ await this.put(this.rpath, { alert: 'select' })
53
+ }
54
+ }
55
+
56
+ // Collect changes into a combined request.
57
+ put (state) {
58
+ for (const key in state) {
59
+ this.resource.body.state[key] = state[key]
60
+ this.targetState[key] = state[key]
61
+ }
62
+ this._put()
63
+ }
64
+
65
+ // Send the request (for the combined changes) to the gateway.
66
+ async _put () {
67
+ try {
68
+ if (this.updating) {
69
+ return
70
+ }
71
+ this.updating = true
72
+ if (this.platform.config.waitTimeUpdate > 0) {
73
+ await timeout(this.platform.config.waitTimeUpdate)
74
+ }
75
+ const targetState = this.targetState
76
+ this.targetState = {}
77
+ this.updating = false
78
+ if (
79
+ this.gateway.transitionTime !== this.gateway.defaultTransitionTime &&
80
+ targetState.transitiontime === undefined
81
+ ) {
82
+ targetState.transitiontime = this.gateway.transitionTime * 10
83
+ this.gateway.resetTransitionTime()
84
+ }
85
+ if (this.capabilities.noTransition) {
86
+ if (
87
+ (
88
+ targetState.on != null || targetState.bri != null ||
89
+ targetState.bri_inc != null
90
+ ) && (
91
+ targetState.xy != null || targetState.ct != null ||
92
+ targetState.hue != null || targetState.sat != null ||
93
+ targetState.effect != null
94
+ )
95
+ ) {
96
+ targetState.transitiontime = 0
97
+ }
98
+ }
99
+ this.debug('PUT %s %j', this.rpath, targetState)
100
+ await this.client.put(this.rpath, targetState)
101
+ this.recentlyUpdated = true
102
+ await timeout(500)
103
+ this.recentlyUpdated = false
104
+ } catch (error) {
105
+ if (!(error instanceof HttpError)) {
106
+ this.warn(error)
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ module.exports = LightsResource