@homebridge-plugins/homebridge-ewelink 12.3.3

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 (113) hide show
  1. package/CHANGELOG.md +1363 -0
  2. package/LICENSE +21 -0
  3. package/README.md +68 -0
  4. package/config.schema.json +1757 -0
  5. package/eslint.config.js +15 -0
  6. package/lib/connection/api.js +508 -0
  7. package/lib/connection/http.js +304 -0
  8. package/lib/connection/lan.js +318 -0
  9. package/lib/connection/ws.js +414 -0
  10. package/lib/device/curtain.js +324 -0
  11. package/lib/device/diffuser.js +473 -0
  12. package/lib/device/fan.js +349 -0
  13. package/lib/device/group.js +106 -0
  14. package/lib/device/humidifier.js +199 -0
  15. package/lib/device/index.js +61 -0
  16. package/lib/device/light-cct.js +333 -0
  17. package/lib/device/light-dimmer.js +257 -0
  18. package/lib/device/light-rgb-cct.js +809 -0
  19. package/lib/device/light-rgb.js +272 -0
  20. package/lib/device/motor.js +363 -0
  21. package/lib/device/outlet-multi.js +417 -0
  22. package/lib/device/outlet-single-inched.js +409 -0
  23. package/lib/device/outlet-single.js +384 -0
  24. package/lib/device/panel.js +382 -0
  25. package/lib/device/rf-bridge.js +321 -0
  26. package/lib/device/rf-button.js +125 -0
  27. package/lib/device/rf-sensor.js +173 -0
  28. package/lib/device/sensor-ambient.js +311 -0
  29. package/lib/device/sensor-contact.js +140 -0
  30. package/lib/device/sensor-temp-humi.js +182 -0
  31. package/lib/device/simulation/blind.js +253 -0
  32. package/lib/device/simulation/cooler.js +312 -0
  33. package/lib/device/simulation/door.js +253 -0
  34. package/lib/device/simulation/doorbell.js +190 -0
  35. package/lib/device/simulation/garage-eachen.js +235 -0
  36. package/lib/device/simulation/garage-four.js +176 -0
  37. package/lib/device/simulation/garage-od-switch.js +36 -0
  38. package/lib/device/simulation/garage-one.js +395 -0
  39. package/lib/device/simulation/garage-two.js +394 -0
  40. package/lib/device/simulation/gate-one.js +327 -0
  41. package/lib/device/simulation/heater.js +389 -0
  42. package/lib/device/simulation/index.js +75 -0
  43. package/lib/device/simulation/light-fan.js +258 -0
  44. package/lib/device/simulation/lock-eachen.js +163 -0
  45. package/lib/device/simulation/lock-one.js +366 -0
  46. package/lib/device/simulation/p-button.js +223 -0
  47. package/lib/device/simulation/purifier.js +289 -0
  48. package/lib/device/simulation/rf-blind.js +192 -0
  49. package/lib/device/simulation/rf-door.js +180 -0
  50. package/lib/device/simulation/rf-window.js +180 -0
  51. package/lib/device/simulation/sensor-hidden.js +105 -0
  52. package/lib/device/simulation/sensor-leak.js +123 -0
  53. package/lib/device/simulation/sensor-visible.js +231 -0
  54. package/lib/device/simulation/sensor.js +300 -0
  55. package/lib/device/simulation/switch-valve.js +351 -0
  56. package/lib/device/simulation/tap-one.js +283 -0
  57. package/lib/device/simulation/tap-two.js +266 -0
  58. package/lib/device/simulation/th-cooler.js +443 -0
  59. package/lib/device/simulation/th-dehumidifier.js +424 -0
  60. package/lib/device/simulation/th-heater.js +449 -0
  61. package/lib/device/simulation/th-humidifier.js +424 -0
  62. package/lib/device/simulation/th-thermostat.js +611 -0
  63. package/lib/device/simulation/tv.js +252 -0
  64. package/lib/device/simulation/valve-four.js +232 -0
  65. package/lib/device/simulation/valve-one.js +345 -0
  66. package/lib/device/simulation/valve-two.js +340 -0
  67. package/lib/device/simulation/window.js +253 -0
  68. package/lib/device/switch-man.js +106 -0
  69. package/lib/device/switch-mate.js +82 -0
  70. package/lib/device/switch-multi.js +411 -0
  71. package/lib/device/switch-single-inched.js +332 -0
  72. package/lib/device/switch-single.js +307 -0
  73. package/lib/device/template.js +43 -0
  74. package/lib/device/thermostat.js +286 -0
  75. package/lib/device/zigbee/index.js +27 -0
  76. package/lib/device/zigbee/light-cct.js +263 -0
  77. package/lib/device/zigbee/light-dimmer.js +148 -0
  78. package/lib/device/zigbee/light-rgb-cct.js +400 -0
  79. package/lib/device/zigbee/motor.js +301 -0
  80. package/lib/device/zigbee/sensor-ambient.js +177 -0
  81. package/lib/device/zigbee/sensor-contact.js +137 -0
  82. package/lib/device/zigbee/sensor-leak.js +119 -0
  83. package/lib/device/zigbee/sensor-motion.js +119 -0
  84. package/lib/device/zigbee/sensor-occupancy.js +119 -0
  85. package/lib/device/zigbee/sensor-smoke.js +96 -0
  86. package/lib/device/zigbee/switch-stateless.js +104 -0
  87. package/lib/device/zigbee/thermostat.js +323 -0
  88. package/lib/fakegato/LICENSE +21 -0
  89. package/lib/fakegato/fakegato-history.js +813 -0
  90. package/lib/fakegato/fakegato-storage.js +108 -0
  91. package/lib/fakegato/fakegato-timer.js +125 -0
  92. package/lib/fakegato/uuid.js +27 -0
  93. package/lib/homebridge-ui/public/index.html +365 -0
  94. package/lib/homebridge-ui/server.js +46 -0
  95. package/lib/index.js +7 -0
  96. package/lib/node-dns-sd/LICENSE +21 -0
  97. package/lib/node-dns-sd/README.md +613 -0
  98. package/lib/node-dns-sd/lib/dns-sd-classes.json +6 -0
  99. package/lib/node-dns-sd/lib/dns-sd-composer.js +83 -0
  100. package/lib/node-dns-sd/lib/dns-sd-parser.js +344 -0
  101. package/lib/node-dns-sd/lib/dns-sd-types.json +52 -0
  102. package/lib/node-dns-sd/lib/dns-sd.js +580 -0
  103. package/lib/platform.js +2156 -0
  104. package/lib/utils/colour.js +552 -0
  105. package/lib/utils/constants.js +589 -0
  106. package/lib/utils/custom-chars.js +33 -0
  107. package/lib/utils/eve-chars.js +130 -0
  108. package/lib/utils/functions.js +42 -0
  109. package/lib/utils/lang-en.js +160 -0
  110. package/lib/utils/lang-fr.js +163 -0
  111. package/lib/utils/lang-th.js +160 -0
  112. package/lib/utils/lang.js +5 -0
  113. package/package.json +75 -0
@@ -0,0 +1,809 @@
1
+ import {
2
+ hs2rgb,
3
+ k2rgb,
4
+ m2hs,
5
+ rgb2hs,
6
+ } from '../utils/colour.js'
7
+ import platformConsts from '../utils/constants.js'
8
+ import { generateRandomString, hasProperty, sleep } from '../utils/functions.js'
9
+
10
+ export default class {
11
+ constructor(platform, accessory) {
12
+ // Set up variables from the platform
13
+ this.cusChar = platform.cusChar
14
+ this.hapChar = platform.api.hap.Characteristic
15
+ this.hapErr = platform.api.hap.HapStatusError
16
+ this.hapServ = platform.api.hap.Service
17
+ this.lang = platform.lang
18
+ this.log = platform.log
19
+ this.platform = platform
20
+
21
+ // Set up variables from the accessory
22
+ this.name = accessory.displayName
23
+ this.accessory = accessory
24
+
25
+ // Initially set the online flag as true (to be then updated as false if necessary)
26
+ this.isOnline = true
27
+
28
+ // Set up custom variables for this device type
29
+ const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
30
+ this.alShift = deviceConf.adaptiveLightingShift || platformConsts.defaultValues.adaptiveLightingShift
31
+ this.brightStep = deviceConf.brightnessStep
32
+ ? Math.min(deviceConf.brightnessStep, 100)
33
+ : platformConsts.defaultValues.brightnessStep
34
+ this.offlineAsOff = deviceConf.offlineAsOff
35
+
36
+ // Set the correct logging variables for this accessory
37
+ switch (deviceConf.overrideLogging) {
38
+ case 'standard':
39
+ this.enableLogging = true
40
+ this.enableDebugLogging = false
41
+ break
42
+ case 'debug':
43
+ this.enableLogging = true
44
+ this.enableDebugLogging = true
45
+ break
46
+ case 'disable':
47
+ this.enableLogging = false
48
+ this.enableDebugLogging = false
49
+ break
50
+ default:
51
+ this.enableLogging = !platform.config.disableDeviceLogging
52
+ this.enableDebugLogging = platform.config.debug
53
+ break
54
+ }
55
+
56
+ // If the accessory has a outlet service then remove it (remedies bug int in v5)
57
+ if (this.accessory.getService(this.hapServ.Switch)) {
58
+ this.accessory.removeService(this.accessory.getService(this.hapServ.Switch))
59
+ }
60
+
61
+ // Add the lightbulb service if it doesn't already exist
62
+ this.service = this.accessory.getService(this.hapServ.Lightbulb)
63
+ || this.accessory.addService(this.hapServ.Lightbulb)
64
+
65
+ // If adaptive lighting has just been disabled then remove and re-add service to hide AL icon
66
+ if (this.alShift === -1 && this.accessory.context.adaptiveLighting) {
67
+ this.accessory.removeService(this.service)
68
+ this.service = this.accessory.addService(this.hapServ.Lightbulb)
69
+ this.accessory.context.adaptiveLighting = false
70
+ }
71
+
72
+ // Add the set handler to the lightbulb on/off characteristic
73
+ this.service
74
+ .getCharacteristic(this.hapChar.On)
75
+ .onSet(async value => this.internalStateUpdate(value))
76
+
77
+ // Add the set handler to the lightbulb brightness characteristic
78
+ this.service
79
+ .getCharacteristic(this.hapChar.Brightness)
80
+ .setProps({ minStep: this.brightStep })
81
+ .onSet(async value => this.internalBrightnessUpdate(value))
82
+
83
+ // Add the set handler to the lightbulb hue characteristic
84
+ this.service
85
+ .getCharacteristic(this.hapChar.Hue)
86
+ .onSet(async value => this.internalColourUpdate(value))
87
+ this.cacheSat = this.service.getCharacteristic(this.hapChar.Saturation).value
88
+
89
+ // Add the set handler to the lightbulb colour temperature characteristic
90
+ this.service
91
+ .getCharacteristic(this.hapChar.ColorTemperature)
92
+ .onSet(async value => this.internalCTUpdate(value))
93
+
94
+ // This is needed as sometimes we need to send the brightness with a cct update
95
+ this.cacheBright = this.service.getCharacteristic(this.hapChar.Brightness).value
96
+
97
+ // If the device is the L2 then add the FestiveScene custom characteristic
98
+ if (this.accessory.context.eweUIID === 137) {
99
+ if (!this.service.testCharacteristic(this.cusChar.FestiveScene)) {
100
+ this.service.addCharacteristic(this.cusChar.FestiveScene)
101
+ }
102
+ this.service.getCharacteristic(this.cusChar.FestiveScene).onSet(async (value) => {
103
+ await this.internalSceneUpdate(16, value)
104
+ })
105
+ }
106
+
107
+ // Set up the adaptive lighting controller if not disabled by user
108
+ if (this.alShift !== -1) {
109
+ this.accessory.alController = new platform.api.hap.AdaptiveLightingController(this.service, {
110
+ customTemperatureAdjustment: this.alShift,
111
+ })
112
+ this.accessory.configureController(this.accessory.alController)
113
+ }
114
+
115
+ /*
116
+ Modes for the L2 light
117
+ 0 - rgb
118
+ 1 - rgb (we use this for colour, not sure what the diff is to 0
119
+ 2 - cct mode
120
+ 3 - some black/white mode
121
+ 4 - music mode:
122
+ { "mode": 4, "rhythmMode": 0, "rhythmSensitive": 0 } -> Classic
123
+ { "mode": 4, "rhythmMode": 1, "rhythmSensitive": 0 } -> Soft
124
+ { "mode": 4, "rhythmMode": 2, "rhythmSensitive": 0 } -> Dynamic
125
+ { "mode": 4, "rhythmMode": 3, "rhythmSensitive": 0 } -> Disco
126
+ 5 - DIY scene
127
+ 6 - Vibrant
128
+ 7 - Reading
129
+ 8 - Leisure
130
+ 9 - Sunrise
131
+ 10 - Sunshine
132
+ 11 - Radiant
133
+ 12 - Dream
134
+ 13 - Candle
135
+ 14 - Night
136
+ 15 - Sunny
137
+ 16 - Festive
138
+ 17 - Vivid
139
+ 18 - Work
140
+ 19 - Ocean
141
+ 20 - Creek
142
+ 21 - Gentle
143
+ 22 - Passive
144
+ 23 - Joy
145
+ 24 - Rainbow
146
+ 25 - Moonlight
147
+ 26 - Sunset
148
+ */
149
+
150
+ // Add the get handlers only if the user hasn't disabled the disableNoResponse setting
151
+ if (!platform.config.disableNoResponse) {
152
+ this.service.getCharacteristic(this.hapChar.On).onGet(() => {
153
+ if (!this.isOnline) {
154
+ throw new this.hapErr(-70402)
155
+ }
156
+ return this.service.getCharacteristic(this.hapChar.On).value
157
+ })
158
+ this.service.getCharacteristic(this.hapChar.Brightness).onGet(() => {
159
+ if (!this.isOnline) {
160
+ throw new this.hapErr(-70402)
161
+ }
162
+ return this.service.getCharacteristic(this.hapChar.Brightness).value
163
+ })
164
+ this.service.getCharacteristic(this.hapChar.Hue).onGet(() => {
165
+ if (!this.isOnline) {
166
+ throw new this.hapErr(-70402)
167
+ }
168
+ return this.service.getCharacteristic(this.hapChar.Hue).value
169
+ })
170
+ this.service.getCharacteristic(this.hapChar.ColorTemperature).onGet(() => {
171
+ if (!this.isOnline) {
172
+ throw new this.hapErr(-70402)
173
+ }
174
+ return this.service.getCharacteristic(this.hapChar.ColorTemperature).value
175
+ })
176
+ }
177
+
178
+ // Output the customised options to the log
179
+ const normalLogging = this.enableLogging ? 'standard' : 'disable'
180
+ const opts = JSON.stringify({
181
+ adaptiveLightingShift: this.alShift,
182
+ brightnessStep: this.brightStep,
183
+ logging: this.enableDebugLogging ? 'debug' : normalLogging,
184
+ offlineAsOff: !!this.offlineAsOff,
185
+ })
186
+ this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
187
+ }
188
+
189
+ async internalStateUpdate(value) {
190
+ try {
191
+ const newValue = value ? 'on' : 'off'
192
+ if (this.cacheState === newValue) {
193
+ return
194
+ }
195
+ const timerKey = generateRandomString(5)
196
+ this.updateTimeout = timerKey
197
+ setTimeout(() => {
198
+ if (this.updateTimeout === timerKey) {
199
+ this.updateTimeout = false
200
+ }
201
+ }, 5000)
202
+ const params = { switch: newValue }
203
+ await this.platform.sendDeviceUpdate(this.accessory, params)
204
+ this.cacheState = newValue
205
+ if (this.enableLogging) {
206
+ this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
207
+ }
208
+ if (this.accessory.context.eweUIID === 137 && this.cacheState === 'off') {
209
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, false)
210
+ }
211
+ } catch (err) {
212
+ this.platform.deviceUpdateError(this.accessory, err, true)
213
+ setTimeout(() => {
214
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
215
+ }, 2000)
216
+ throw new this.hapErr(-70402)
217
+ }
218
+ }
219
+
220
+ async internalBrightnessUpdate(value) {
221
+ try {
222
+ if (this.cacheBright === value) {
223
+ return
224
+ }
225
+ const updateKey = generateRandomString(5)
226
+ this.updateKeyBright = updateKey
227
+ await sleep(500)
228
+ if (updateKey !== this.updateKeyBright) {
229
+ return
230
+ }
231
+ let params
232
+ this.updateTimeout = updateKey
233
+ setTimeout(() => {
234
+ if (this.updateTimeout === updateKey) {
235
+ this.updateTimeout = false
236
+ }
237
+ }, 5000)
238
+ switch (this.accessory.context.eweUIID) {
239
+ case 33:
240
+ case 59:
241
+ // L1
242
+ params = {
243
+ mode: 1,
244
+ bright: value,
245
+ }
246
+ break
247
+ case 104:
248
+ // B02-B-A60, B05-B-A60, GTLC104
249
+ if (this.cacheMode === 'white') {
250
+ params = {
251
+ white: {
252
+ br: value,
253
+ ct: this.cacheCT,
254
+ },
255
+ }
256
+ } else {
257
+ params = {
258
+ color: {
259
+ br: value,
260
+ r: this.cacheR,
261
+ g: this.cacheG,
262
+ b: this.cacheB,
263
+ },
264
+ }
265
+ }
266
+ break
267
+ case 135:
268
+ case 136:
269
+ if (this.cacheMode === 'white') {
270
+ params = {
271
+ ltype: 'white',
272
+ white: {
273
+ br: value,
274
+ ct: this.cacheCT,
275
+ },
276
+ }
277
+ } else {
278
+ params = {
279
+ ltype: 'color',
280
+ color: {
281
+ br: value,
282
+ r: this.cacheR,
283
+ g: this.cacheG,
284
+ b: this.cacheB,
285
+ },
286
+ }
287
+ }
288
+ break
289
+ case 137:
290
+ case 173:
291
+ params = {
292
+ bright: value,
293
+ }
294
+ break
295
+ default:
296
+ return
297
+ }
298
+ await this.platform.sendDeviceUpdate(this.accessory, params)
299
+ this.cacheBright = value
300
+ if (this.enableLogging) {
301
+ this.log('[%s] %s [%s%].', this.name, this.lang.curBright, this.cacheBright)
302
+ }
303
+ } catch (err) {
304
+ this.platform.deviceUpdateError(this.accessory, err, true)
305
+ setTimeout(() => {
306
+ this.service.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
307
+ }, 2000)
308
+ throw new this.hapErr(-70402)
309
+ }
310
+ }
311
+
312
+ async internalColourUpdate(value) {
313
+ try {
314
+ if (this.cacheHue === value) {
315
+ return
316
+ }
317
+ const updateKey = generateRandomString(5)
318
+ this.updateKey = updateKey
319
+ await sleep(400)
320
+ if (updateKey !== this.updateKey) {
321
+ return
322
+ }
323
+ this.updateTimeout = updateKey
324
+ setTimeout(() => {
325
+ if (this.updateTimeout === updateKey) {
326
+ this.updateTimeout = false
327
+ }
328
+ }, 5000)
329
+ this.service.updateCharacteristic(this.hapChar.ColorTemperature, 140)
330
+ let params
331
+ const sat = this.service.getCharacteristic(this.hapChar.Saturation).value
332
+ const rgb = hs2rgb(value, sat)
333
+ switch (this.accessory.context.eweUIID) {
334
+ case 33:
335
+ case 59:
336
+ case 137:
337
+ case 173:
338
+ // L1/L2
339
+ params = {
340
+ mode: 1,
341
+ colorR: rgb[0],
342
+ colorG: rgb[1],
343
+ colorB: rgb[2],
344
+ }
345
+ break
346
+ case 104:
347
+ // B02-B-A60, B05-B-A60, GTLC104
348
+ params = {
349
+ ltype: this.cacheMode === 'color' ? undefined : 'color',
350
+ color: {
351
+ br: this.cacheBright,
352
+ r: rgb[0],
353
+ g: rgb[1],
354
+ b: rgb[2],
355
+ },
356
+ }
357
+ break
358
+ case 135:
359
+ case 136:
360
+ params = {
361
+ ltype: 'color',
362
+ color: {
363
+ br: this.cacheBright,
364
+ r: rgb[0],
365
+ g: rgb[1],
366
+ b: rgb[2],
367
+ },
368
+ }
369
+ break
370
+ default:
371
+ return
372
+ }
373
+ await this.platform.sendDeviceUpdate(this.accessory, params)
374
+ this.cacheHue = value;
375
+ [this.cacheR, this.cacheG, this.cacheB] = rgb
376
+ this.cacheMired = 0
377
+ this.cacheCT = 0
378
+ if ([104, 135, 136].includes(this.accessory.context.eweUIID)) {
379
+ this.cacheMode = 'color'
380
+ }
381
+ if (this.enableLogging) {
382
+ this.log(
383
+ '[%s] %s [rgb %s].',
384
+ this.name,
385
+ this.lang.curColour,
386
+ `${this.cacheR} ${this.cacheG} ${this.cacheB}`,
387
+ )
388
+ }
389
+ if (this.accessory.context.eweUIID === 137) {
390
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, false)
391
+ }
392
+ } catch (err) {
393
+ this.platform.deviceUpdateError(this.accessory, err, true)
394
+ setTimeout(() => {
395
+ this.service.updateCharacteristic(this.hapChar.Hue, this.cacheHue)
396
+ }, 2000)
397
+ throw new this.hapErr(-70402)
398
+ }
399
+ }
400
+
401
+ async internalCTUpdate(value) {
402
+ try {
403
+ if (this.cacheMired === value) {
404
+ return
405
+ }
406
+ if (
407
+ this.accessory.alController
408
+ && this.accessory.alController.isAdaptiveLightingActive()
409
+ && (this.cacheState !== 'on' || !this.isOnline)
410
+ ) {
411
+ return
412
+ }
413
+ const updateKey = generateRandomString(5)
414
+ this.updateKey = updateKey
415
+ await sleep(400)
416
+ if (updateKey !== this.updateKey) {
417
+ return
418
+ }
419
+ this.updateTimeout = updateKey
420
+ setTimeout(() => {
421
+ if (this.updateTimeout === updateKey) {
422
+ this.updateTimeout = false
423
+ }
424
+ }, 5000)
425
+ const hs = m2hs(value)
426
+ this.service.updateCharacteristic(this.hapChar.Hue, hs[0])
427
+ this.service.updateCharacteristic(this.hapChar.Saturation, hs[1])
428
+ const mToK = Math.max(Math.min(Math.round(1000000 / value), 6500), 2700)
429
+ let scaledCT
430
+ let params
431
+ let newRGB
432
+ switch (this.accessory.context.eweUIID) {
433
+ case 33:
434
+ case 59: {
435
+ // L1
436
+ scaledCT = Math.round(((mToK - 2700) / 3800) * 100)
437
+ newRGB = k2rgb(mToK)
438
+ params = {
439
+ mode: 1,
440
+ colorR: newRGB[0],
441
+ colorG: newRGB[1],
442
+ colorB: newRGB[2],
443
+ }
444
+ break
445
+ }
446
+ case 104:
447
+ // B02-B-A60, B05-B-A60, GTLC104
448
+ scaledCT = Math.round(((mToK - 2700) / 3800) * 255)
449
+ params = {
450
+ ltype: this.cacheMode === 'white' ? undefined : 'white',
451
+ white: {
452
+ br: this.cacheBright,
453
+ ct: scaledCT,
454
+ },
455
+ }
456
+ break
457
+ case 135:
458
+ case 136:
459
+ scaledCT = Math.round(((mToK - 2700) / 3800) * 100)
460
+ params = {
461
+ ltype: 'white',
462
+ white: {
463
+ br: this.cacheBright,
464
+ ct: scaledCT,
465
+ },
466
+ }
467
+ break
468
+ case 137:
469
+ case 173: {
470
+ // L2
471
+ scaledCT = 100 - Math.round(((mToK - 2700) / 3800) * 100)
472
+ newRGB = k2rgb(mToK)
473
+ params = {
474
+ mode: 2,
475
+ colorTemp: scaledCT,
476
+ }
477
+ break
478
+ }
479
+ default:
480
+ return
481
+ }
482
+ await this.platform.sendDeviceUpdate(this.accessory, params)
483
+ this.cacheMired = value;
484
+ [this.cacheHue] = hs
485
+ this.cacheCT = scaledCT
486
+ this.cacheHue = 0
487
+ switch (this.accessory.context.eweUIID) {
488
+ case 33:
489
+ case 59:
490
+ case 137:
491
+ case 173: {
492
+ // L1
493
+ [this.cacheR, this.cacheG, this.cacheB] = newRGB
494
+ break
495
+ }
496
+ case 104:
497
+ case 135:
498
+ case 136:
499
+ this.cacheMode = 'white'
500
+ break
501
+ default:
502
+ return
503
+ }
504
+ if (this.enableLogging) {
505
+ if (this.accessory.alController && this.accessory.alController.isAdaptiveLightingActive()) {
506
+ this.log('[%s] %s [%sK] %s.', this.name, this.lang.curColour, mToK, this.lang.viaAL)
507
+ } else {
508
+ this.log('[%s] %s [%sK].', this.name, this.lang.curColour, mToK)
509
+ }
510
+ }
511
+ if (this.accessory.context.eweUIID === 137) {
512
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, false)
513
+ }
514
+ } catch (err) {
515
+ this.platform.deviceUpdateError(this.accessory, err, true)
516
+ setTimeout(() => {
517
+ this.service.updateCharacteristic(this.hapChar.ColorTemperature, this.cacheMired)
518
+ }, 2000)
519
+ throw new this.hapErr(-70402)
520
+ }
521
+ }
522
+
523
+ async internalSceneUpdate(scene, value) {
524
+ try {
525
+ if (!value) {
526
+ return
527
+ }
528
+ const timerKey = generateRandomString(5)
529
+ this.updateTimeout = timerKey
530
+ setTimeout(() => {
531
+ if (this.updateTimeout === timerKey) {
532
+ this.updateTimeout = false
533
+ }
534
+ }, 5000)
535
+ const params = { mode: scene }
536
+ if (this.cacheState === 'off') {
537
+ params.switch = 'on'
538
+ this.cacheState = 'on'
539
+ }
540
+ await this.platform.sendDeviceUpdate(this.accessory, params)
541
+ this.service.updateCharacteristic(this.hapChar.On, true)
542
+ this.accessory.alController.disableAdaptiveLighting()
543
+ if (this.enableLogging) {
544
+ this.log('[%s] %s [%s].', this.name, this.lang.curScene, 'festive')
545
+ }
546
+ } catch (err) {
547
+ this.platform.deviceUpdateError(this.accessory, err, true)
548
+ setTimeout(() => {
549
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, false)
550
+ }, 2000)
551
+ throw new this.hapErr(-70402)
552
+ }
553
+ }
554
+
555
+ async externalUpdate(params) {
556
+ try {
557
+ if (this.updateTimeout) {
558
+ return
559
+ }
560
+ if (params.switch && params.switch !== this.cacheState) {
561
+ this.cacheState = params.switch
562
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
563
+ if (params.updateSource && this.enableLogging) {
564
+ this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
565
+ }
566
+ if (this.accessory.context.eweUIID === 137 && this.cacheState === 'off') {
567
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, false)
568
+ }
569
+ }
570
+ let hs
571
+ switch (this.accessory.context.eweUIID) {
572
+ case 33:
573
+ case 59:
574
+ case 137:
575
+ case 173:
576
+ // L1/L2
577
+ if (hasProperty(params, 'bright')) {
578
+ if (params.bright !== this.cacheBright) {
579
+ this.cacheBright = params.bright
580
+ this.service.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
581
+ if (params.updateSource && this.enableLogging) {
582
+ this.log('[%s] %s [%s%].', this.name, this.lang.curBright, this.cacheBright)
583
+ }
584
+ }
585
+ }
586
+ if (hasProperty(params, 'colorR')) {
587
+ if (this.accessory.context.eweUIID === 137) {
588
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, false)
589
+ }
590
+ if (
591
+ params.colorR !== this.cacheR
592
+ || params.colorG !== this.cacheB
593
+ || params.colorB !== this.cacheB
594
+ ) {
595
+ const rgbDiff = Math.abs(params.colorR - this.cacheR)
596
+ + Math.abs(params.colorG - this.cacheG)
597
+ + Math.abs(params.colorG - this.cacheB)
598
+ this.cacheR = params.colorR
599
+ this.cacheG = params.colorG
600
+ this.cacheB = params.colorB
601
+ hs = rgb2hs(this.cacheR, this.cacheG, this.cacheB);
602
+ [this.cacheHue] = hs
603
+ this.cacheMired = 140
604
+ this.service.updateCharacteristic(this.hapChar.Hue, this.cacheHue)
605
+ this.service.updateCharacteristic(this.hapChar.Saturation, hs[1])
606
+ if (params.updateSource) {
607
+ if (this.enableLogging) {
608
+ this.log(
609
+ '[%s] %s [rgb %s].',
610
+ this.name,
611
+ this.lang.curColour,
612
+ `${this.cacheR} ${this.cacheG} ${this.cacheB}`,
613
+ )
614
+ }
615
+ if (
616
+ this.accessory.alController
617
+ && this.accessory.alController.isAdaptiveLightingActive()
618
+ && rgbDiff > 50
619
+ ) {
620
+ this.accessory.alController.disableAdaptiveLighting()
621
+ if (this.enableLogging) {
622
+ this.log('[%s] %s.', this.name, this.lang.disabledAL)
623
+ }
624
+ }
625
+ }
626
+ }
627
+ }
628
+ if (hasProperty(params, 'colorTemp')) {
629
+ if (this.accessory.context.eweUIID === 137) {
630
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, false)
631
+ }
632
+ if (params.colorTemp !== this.cacheCTRaw && params.mode === 2) {
633
+ this.cacheCTRaw = params.colorTemp
634
+ const ctDiff = Math.abs(params.colorTemp - this.cacheCTRaw)
635
+ this.cacheCT = 100 - params.colorTemp
636
+ const ctToK = Math.round((this.cacheCT / 100) * 3800 + 2700)
637
+ this.cacheMired = Math.max(Math.min(Math.round(1000000 / ctToK), 500), 140)
638
+ hs = m2hs(this.cacheMired);
639
+ [this.cacheHue] = hs
640
+ this.service.updateCharacteristic(this.hapChar.Hue, this.cacheHue)
641
+ this.service.updateCharacteristic(this.hapChar.Saturation, hs[1])
642
+ this.service.updateCharacteristic(this.hapChar.ColorTemperature, this.cacheMired)
643
+ if (params.updateSource) {
644
+ if (this.enableLogging) {
645
+ this.log('[%s] %s [%sK].', this.name, this.lang.curColour, ctToK)
646
+ }
647
+ if (
648
+ this.accessory.alController
649
+ && this.accessory.alController.isAdaptiveLightingActive()
650
+ && ctDiff > 20
651
+ ) {
652
+ // Look for a variation greater than twenty
653
+ this.accessory.alController.disableAdaptiveLighting()
654
+ if (this.enableLogging) {
655
+ this.log('[%s] %s.', this.name, this.lang.disabledAL)
656
+ }
657
+ }
658
+ }
659
+ }
660
+ }
661
+ if (this.accessory.context.eweUIID === 137 && params.mode === 16) {
662
+ // Festive scene enabled
663
+ this.accessory.alController.disableAdaptiveLighting()
664
+ this.service.updateCharacteristic(this.cusChar.FestiveScene, true)
665
+ if (this.enableLogging) {
666
+ this.log('[%s] %s [%s].', this.name, this.lang.curScene, 'festive')
667
+ }
668
+ }
669
+ break
670
+ case 104:
671
+ case 135:
672
+ case 136:
673
+ // B02-B-A60, B05-B-A60, GTLC104
674
+ if (params.ltype === 'color' && params.color) {
675
+ if (hasProperty(params.color, 'br')) {
676
+ if (params.color.br !== this.cacheBright) {
677
+ this.cacheBright = params.color.br
678
+ this.service.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
679
+ if (params.updateSource && this.enableLogging) {
680
+ this.log('[%s] %s [%s%].', this.name, this.lang.curBright, this.cacheBright)
681
+ }
682
+ }
683
+ }
684
+ if (hasProperty(params.color, 'r')) {
685
+ if (
686
+ params.color.r !== this.cacheR
687
+ || params.color.g !== this.cacheG
688
+ || params.color.b !== this.cacheB
689
+ || this.cacheMode !== 'color'
690
+ ) {
691
+ this.cacheMode = 'color'
692
+ this.cacheR = params.color.r
693
+ this.cacheG = params.color.g
694
+ this.cacheB = params.color.b
695
+ this.cacheMired = 140
696
+ hs = rgb2hs(this.cacheR, this.cacheG, this.cacheB);
697
+ [this.cacheHue] = hs
698
+ this.service.updateCharacteristic(this.hapChar.ColorTemperature, 140)
699
+ this.service.updateCharacteristic(this.hapChar.Hue, this.cacheHue)
700
+ this.service.updateCharacteristic(this.hapChar.Saturation, 100)
701
+ if (params.updateSource && this.enableLogging) {
702
+ this.log(
703
+ '[%s] %s [rgb %s].',
704
+ this.name,
705
+ this.lang.curColour,
706
+ `${this.cacheR} ${this.cacheG} ${this.cacheB}`,
707
+ )
708
+ }
709
+ }
710
+ }
711
+ if (
712
+ params.updateSource
713
+ && this.accessory.alController
714
+ && this.accessory.alController.isAdaptiveLightingActive()
715
+ ) {
716
+ this.accessory.alController.disableAdaptiveLighting()
717
+ if (this.enableLogging) {
718
+ this.log('[%s] %s.', this.name, this.lang.disabledAL)
719
+ }
720
+ }
721
+ }
722
+ if (params.ltype === 'white' && params.white) {
723
+ if (hasProperty(params.white, 'br')) {
724
+ if (params.white.br !== this.cacheBright || this.cacheMode !== 'white') {
725
+ this.cacheBright = params.white.br
726
+ this.service.updateCharacteristic(this.hapChar.Brightness, this.cacheBright)
727
+ if (params.updateSource && this.enableLogging) {
728
+ this.log('[%s] %s [%s%].', this.name, this.lang.curBright, this.cacheBright)
729
+ }
730
+ }
731
+ }
732
+ if (hasProperty(params.white, 'ct') && params.white.ct !== this.cacheCT) {
733
+ this.cacheMode = 'white'
734
+ const ctDiff = Math.abs(params.white.ct - this.cacheCT)
735
+ this.cacheCT = params.white.ct
736
+
737
+ let ctToK
738
+ switch (this.accessory.context.eweUIID) {
739
+ case 135:
740
+ case 136:
741
+ ctToK = Math.round((this.cacheCT / 100) * 3800 + 2700)
742
+ break
743
+ default:
744
+ ctToK = Math.round((this.cacheCT / 255) * 3800 + 2700)
745
+ break
746
+ }
747
+ this.cacheMired = Math.max(Math.min(Math.round(1000000 / ctToK), 500), 140)
748
+ hs = m2hs(this.cacheMired);
749
+ [this.cacheHue] = hs
750
+ this.service.updateCharacteristic(this.hapChar.Hue, this.cacheHue)
751
+ this.service.updateCharacteristic(this.hapChar.Saturation, hs[1])
752
+ this.service.updateCharacteristic(this.hapChar.ColorTemperature, this.cacheMired)
753
+ if (params.updateSource) {
754
+ if (this.enableLogging) {
755
+ this.log('[%s] %s [%sK].', this.name, this.lang.curColour, ctToK)
756
+ }
757
+ if (
758
+ this.accessory.alController
759
+ && this.accessory.alController.isAdaptiveLightingActive()
760
+ && ctDiff > 20
761
+ ) {
762
+ // Look for a variation greater than twenty
763
+ this.accessory.alController.disableAdaptiveLighting()
764
+ if (this.enableLogging) {
765
+ this.log('[%s] %s.', this.name, this.lang.disabledAL)
766
+ }
767
+ }
768
+ }
769
+ }
770
+ }
771
+ break
772
+ default:
773
+ }
774
+ } catch (err) {
775
+ this.platform.deviceUpdateError(this.accessory, err, false)
776
+ }
777
+ }
778
+
779
+ markStatus(isOnline) {
780
+ this.isOnline = isOnline
781
+
782
+ // Show as off if offlineAsOff is enabled
783
+ if (this.offlineAsOff && !isOnline && this.cacheState !== 'off') {
784
+ this.service.updateCharacteristic(this.hapChar.On, false)
785
+ this.cacheState = 'off'
786
+ if (this.enableLogging) {
787
+ this.log('[%s] %s [%s - offline]', this.name, this.lang.curState, this.cacheState)
788
+ }
789
+ }
790
+ }
791
+
792
+ currentState() {
793
+ const toReturn = {}
794
+ toReturn.services = ['light']
795
+ toReturn.light = {
796
+ state: this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off',
797
+ brightness: this.service.getCharacteristic(this.hapChar.Brightness).value,
798
+ colourmode: this.cacheMode === 'white' ? 'colourtemperature' : 'hue',
799
+ hue: this.service.getCharacteristic(this.hapChar.Hue).value,
800
+ saturation: this.service.getCharacteristic(this.hapChar.Saturation).value,
801
+ colourtemperature: this.service.getCharacteristic(this.hapChar.ColorTemperature).value,
802
+ adaptivelighting:
803
+ this.accessory.alController && this.accessory.alController.isAdaptiveLightingActive()
804
+ ? 'on'
805
+ : 'off',
806
+ }
807
+ return toReturn
808
+ }
809
+ }