homebridge-deconz 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Deconz/Resource.js +7 -138
- package/lib/DeconzAccessory/Light.js +8 -8
- package/lib/DeconzAccessory/index.js +6 -1
- package/lib/DeconzService/AirQuality.js +60 -29
- package/lib/DeconzService/Consumption.js +5 -5
- package/lib/DeconzService/Light.js +72 -71
- package/lib/DeconzService/Power.js +6 -5
- package/package.json +4 -4
package/lib/Deconz/Resource.js
CHANGED
@@ -30,51 +30,6 @@ const sensorsPrios = [
|
|
30
30
|
|
31
31
|
// =============================================================================
|
32
32
|
|
33
|
-
// See: http://www.developers.meethue.com/documentation/supported-lights
|
34
|
-
|
35
|
-
const hueGamutType = { // Color gamut per light model.
|
36
|
-
A: { // Color Lights
|
37
|
-
r: [0.7040, 0.2960],
|
38
|
-
g: [0.2151, 0.7106],
|
39
|
-
b: [0.1380, 0.0800]
|
40
|
-
},
|
41
|
-
B: { // Extended Color Lights
|
42
|
-
r: [0.6750, 0.3220],
|
43
|
-
g: [0.4090, 0.5180],
|
44
|
-
b: [0.1670, 0.0400]
|
45
|
-
},
|
46
|
-
C: { // next gen Extended Color Lights
|
47
|
-
r: [0.6920, 0.3080],
|
48
|
-
g: [0.1700, 0.7000],
|
49
|
-
b: [0.1530, 0.0480]
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
const hueGamutTypeByModel = {
|
54
|
-
LCT001: 'B', // Hue bulb A19
|
55
|
-
LCT002: 'B', // Hue Spot BR30
|
56
|
-
LCT003: 'B', // Hue Spot GU10
|
57
|
-
LCT007: 'B', // Hue bulb A19
|
58
|
-
LCT010: 'C', // Hue bulb A19
|
59
|
-
LCT011: 'C', // Hue BR30
|
60
|
-
LCT012: 'C', // Hue Color Candle
|
61
|
-
LCT014: 'C', // Hue bulb A19
|
62
|
-
LCT015: 'C', // Hue bulb A19
|
63
|
-
LCT016: 'C', // Hue bulb A19
|
64
|
-
LLC005: 'A', // Living Colors Gen3 Bloom, Aura
|
65
|
-
LLC006: 'A', // Living Colors Gen3 Iris
|
66
|
-
LLC007: 'A', // Living Colors Gen3 Bloom, Aura
|
67
|
-
LLC010: 'A', // Hue Living Colors Iris
|
68
|
-
LLC011: 'A', // Hue Living Colors Bloom
|
69
|
-
LLC012: 'A', // Hue Living Colors Bloom
|
70
|
-
LLC013: 'A', // Disney Living Colors
|
71
|
-
LLC014: 'A', // Living Colors Gen3 Bloom, Aura
|
72
|
-
LLC020: 'C', // Hue Go
|
73
|
-
LLM001: 'B', // Color Light Module
|
74
|
-
LST001: 'A', // Hue LightStrips
|
75
|
-
LST002: 'C' // Hue LightStrips Plus
|
76
|
-
}
|
77
|
-
|
78
33
|
const hueTapMap = {
|
79
34
|
34: 1002, // press 1
|
80
35
|
16: 2002, // press 2
|
@@ -240,9 +195,7 @@ class Resource {
|
|
240
195
|
this.capabilities.ctMin = cap.color.ct.min
|
241
196
|
}
|
242
197
|
if (cap.color.effects != null && cap.color.effects.length > 2) {
|
243
|
-
this.capabilities.effects = cap.color.effects.slice(2)
|
244
|
-
return effect[0].toUpperCase() + effect.slice(1)
|
245
|
-
})
|
198
|
+
this.capabilities.effects = cap.color.effects.slice(2)
|
246
199
|
}
|
247
200
|
if (cap.color.xy != null) {
|
248
201
|
this.capabilities.gamut = {
|
@@ -386,34 +339,7 @@ class Resource {
|
|
386
339
|
*/
|
387
340
|
patchLight (gateway) {
|
388
341
|
switch (this.manufacturer) {
|
389
|
-
case 'Busch-Jaeger':
|
390
|
-
// See: https://www.busch-jaeger.de/en/products/product-solutions/dimmer/busch-radio-controlled-dimmer-zigbee-light-link/
|
391
|
-
if (
|
392
|
-
this.model === 'RM01' && // 6715 U-500 with 6736-84.
|
393
|
-
this.capabilities.bri && this.body.type === 'On/Off light' // Issue #241
|
394
|
-
) {
|
395
|
-
gateway.vdebug(
|
396
|
-
'%s: ignoring state.bri for %s', this.rpath, this.body.type
|
397
|
-
)
|
398
|
-
this.capabilities.bri = false
|
399
|
-
}
|
400
|
-
break
|
401
|
-
case 'dresden elektronik':
|
402
|
-
// See: https://www.dresden-elektronik.de/funktechnik/solutions/wireless-light-control/wireless-ballasts/?L=1
|
403
|
-
this.capabilities.computesXy = true
|
404
|
-
break
|
405
|
-
case 'FeiBit':
|
406
|
-
if (this.model === 'FNB56-SKT1EHG1.2') { // issue #361
|
407
|
-
this.body.type = 'On/Off plug-in unit'
|
408
|
-
}
|
409
|
-
break
|
410
342
|
case 'GLEDOPTO':
|
411
|
-
// See: https://www.led-trading.de/zigbee-kompatibel-controller-led-lichtsteuerung
|
412
|
-
this.capabilities.gamut = {
|
413
|
-
r: [0.7006, 0.2993],
|
414
|
-
g: [0.1387, 0.8148],
|
415
|
-
b: [0.1510, 0.0227]
|
416
|
-
}
|
417
343
|
if (this.model === 'GLEDOPTO') { // Issue #244
|
418
344
|
if (
|
419
345
|
this.endpoint === '0A' &&
|
@@ -444,37 +370,6 @@ class Resource {
|
|
444
370
|
gateway.vdebug('%s: set model to %j', this.rpath, this.model)
|
445
371
|
}
|
446
372
|
break
|
447
|
-
case 'IKEA of Sweden':
|
448
|
-
// See: http://www.ikea.com/us/en/catalog/categories/departments/lighting/smart_lighting/
|
449
|
-
this.capabilities.gamut = defaultGamut // Issue #956
|
450
|
-
this.capabilities.noTransition = true
|
451
|
-
if (this.model === 'TRADFRI bulb E27 CWS 806lm') {
|
452
|
-
this.capabilities.computesXy = true
|
453
|
-
this.capabilities.gamut = {
|
454
|
-
r: [0.68, 0.31],
|
455
|
-
g: [0.11, 0.82],
|
456
|
-
b: [0.13, 0.04]
|
457
|
-
}
|
458
|
-
}
|
459
|
-
break
|
460
|
-
case 'innr':
|
461
|
-
// See: https://shop.innrlighting.com/en/shop
|
462
|
-
this.capabilities.gamut = { // Issue #152
|
463
|
-
r: [0.8817, 0.1033],
|
464
|
-
g: [0.2204, 0.7758],
|
465
|
-
b: [0.0551, 0.1940]
|
466
|
-
}
|
467
|
-
if (this.model === 'SP 120') { // smart plug
|
468
|
-
this.capabilities.bri = false
|
469
|
-
}
|
470
|
-
break
|
471
|
-
case 'LEDVANCE':
|
472
|
-
this.capabilities.gamut = {
|
473
|
-
r: [0.6972, 0.3027],
|
474
|
-
g: [0.1737, 0.6991],
|
475
|
-
b: [0.1227, 0.0959]
|
476
|
-
}
|
477
|
-
break
|
478
373
|
case 'LIDL Livarno Lux':
|
479
374
|
this.capabilities.ctMax = 454 // 2200 K
|
480
375
|
this.capabilities.ctMin = 153 // 6500 K
|
@@ -489,36 +384,6 @@ class Resource {
|
|
489
384
|
]
|
490
385
|
}
|
491
386
|
break
|
492
|
-
case 'MLI': // Issue #439
|
493
|
-
this.capabilities.gamut = {
|
494
|
-
r: [0.68, 0.31],
|
495
|
-
g: [0.11, 0.82],
|
496
|
-
b: [0.13, 0.04]
|
497
|
-
}
|
498
|
-
if (this.capabilities.colorLoop) {
|
499
|
-
this.capabilities.effects = [
|
500
|
-
'Sunset', 'Party', 'Worklight', 'Campfire', 'Romance', 'Nightlight'
|
501
|
-
]
|
502
|
-
}
|
503
|
-
break
|
504
|
-
case 'OSRAM':
|
505
|
-
this.capabilities.gamut = {
|
506
|
-
r: [0.6850, 0.3149],
|
507
|
-
g: [0.1780, 0.7253],
|
508
|
-
b: [0.1241, 0.0578]
|
509
|
-
}
|
510
|
-
break
|
511
|
-
case 'Philips':
|
512
|
-
case 'Signify Netherlands B.V.':
|
513
|
-
// See: http://www.developers.meethue.com/documentation/supported-lights
|
514
|
-
this.manufacturer = 'Signify Netherlands B.V.'
|
515
|
-
this.capabilities.breathe = true
|
516
|
-
this.capabilities.computesXy = true
|
517
|
-
if (this.body.capabilities == null) {
|
518
|
-
const gamut = hueGamutTypeByModel[this.model] || 'C'
|
519
|
-
this.capabilities.gamut = hueGamutType[gamut]
|
520
|
-
}
|
521
|
-
break
|
522
387
|
default:
|
523
388
|
break
|
524
389
|
}
|
@@ -784,12 +649,16 @@ class Resource {
|
|
784
649
|
}
|
785
650
|
}
|
786
651
|
break
|
787
|
-
case 'lumi.sensor_86sw1': // Xiaomi wall switch (single button)
|
788
652
|
case 'lumi.ctrl_ln1.aq1':
|
653
|
+
case 'lumi.sensor_86sw1': // Xiaomi wall switch (single button).
|
654
|
+
case 'lumi.switch.l1aeu1': // Xiaomi Aqara H1, see #1149.
|
655
|
+
case 'lumi.switch.n1aeu1': // Xiaomi Aqara H1, see #1149.
|
789
656
|
buttons.push([1, 'Button', SINGLE | DOUBLE])
|
790
657
|
break
|
791
|
-
case 'lumi.sensor_86sw2': // Xiaomi wall switch (two buttons)
|
792
658
|
case 'lumi.ctrl_ln2.aq1':
|
659
|
+
case 'lumi.sensor_86sw2': // Xiaomi wall switch (two buttons).
|
660
|
+
case 'lumi.switch.l2aeu1': // Xiaomi Aqara H2, see #1149.
|
661
|
+
case 'lumi.switch.n2aeu1': // Xiaomi Aqara H2, see #1149.
|
793
662
|
buttons.push([1, 'Left', SINGLE | DOUBLE])
|
794
663
|
buttons.push([2, 'Right', SINGLE | DOUBLE])
|
795
664
|
buttons.push([3, 'Both', SINGLE | DOUBLE])
|
@@ -66,19 +66,19 @@ class Light extends DeconzAccessory {
|
|
66
66
|
})
|
67
67
|
}
|
68
68
|
if (this.serviceByServiceName.Consumption != null) {
|
69
|
-
params.
|
70
|
-
if (this.service.values.
|
71
|
-
//
|
72
|
-
params.
|
73
|
-
key: '
|
74
|
-
Characteristic: this.Characteristics.eve.
|
69
|
+
params.totalConsumptionDelegate = this.service.characteristicDelegate('totalConsumption')
|
70
|
+
if (this.service.values.consumption === undefined) {
|
71
|
+
// Power to be computed by history if not exposed by device
|
72
|
+
params.computedConsumptionDelegate = this.service.addCharacteristicDelegate({
|
73
|
+
key: 'consumption',
|
74
|
+
Characteristic: this.Characteristics.eve.Consumption,
|
75
75
|
unit: ' W'
|
76
76
|
})
|
77
77
|
}
|
78
78
|
} else if (this.serviceByServiceName.Power != null) {
|
79
|
-
params.
|
79
|
+
params.consumptionDelegate = this.service.characteristicDelegate('consumption')
|
80
80
|
// Total Consumption to be computed by history
|
81
|
-
params.
|
81
|
+
params.computedTotalConsumptionDelegate = this.service.addCharacteristicDelegate({
|
82
82
|
key: 'totalConsumption',
|
83
83
|
Characteristic: this.Characteristics.eve.TotalConsumption,
|
84
84
|
unit: ' kWh'
|
@@ -139,7 +139,12 @@ class DeconzAccessory extends AccessoryDelegate {
|
|
139
139
|
this.debug('%s: params: %j', resource.rpath, params)
|
140
140
|
|
141
141
|
let service
|
142
|
-
if (params.serviceName === '
|
142
|
+
if (params.serviceName === 'AirQuality') {
|
143
|
+
service = this.serviceByServiceName.AirQuality
|
144
|
+
if (service != null) {
|
145
|
+
service.addResource(resource)
|
146
|
+
}
|
147
|
+
} else if (params.serviceName === 'Battery') {
|
143
148
|
service = this.serviceByServiceName.Battery
|
144
149
|
} else if (params.serviceName === 'Consumption') {
|
145
150
|
service = this.serviceByServiceName.Outlet ||
|
@@ -5,73 +5,104 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
+
const Deconz = require('../Deconz')
|
8
9
|
const DeconzService = require('../DeconzService')
|
9
10
|
|
11
|
+
const { dateToString } = Deconz.ApiClient
|
12
|
+
|
10
13
|
/**
|
11
14
|
* @memberof DeconzService
|
12
15
|
*/
|
13
16
|
class AirQuality extends DeconzService.SensorsResource {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
})
|
17
|
+
static addResource (service, resource) {
|
18
|
+
if (service.values.airQuality === undefined) {
|
19
|
+
service.addCharacteristicDelegate({
|
20
|
+
key: 'airQuality',
|
21
|
+
Characteristic: service.Characteristics.hap.AirQuality
|
22
|
+
})
|
23
|
+
}
|
22
24
|
|
23
25
|
if (resource.body.state.airqualityppb !== undefined) {
|
24
|
-
|
26
|
+
service.addCharacteristicDelegate({
|
25
27
|
key: 'vocDensity',
|
26
|
-
Characteristic:
|
28
|
+
Characteristic: service.Characteristics.hap.VOCDensity,
|
27
29
|
unit: ' µg/m³',
|
28
30
|
props: { minValue: 0, maxValue: 65535, minStep: 1 }
|
29
31
|
})
|
30
32
|
}
|
31
33
|
|
32
34
|
if (resource.body.state.pm2_5 !== undefined) {
|
33
|
-
|
34
|
-
key: '
|
35
|
-
Characteristic:
|
35
|
+
service.addCharacteristicDelegate({
|
36
|
+
key: 'pm25Density',
|
37
|
+
Characteristic: service.Characteristics.hap.PM2_5Density,
|
36
38
|
unit: ' µg/m³',
|
37
39
|
props: { minValue: 0, maxValue: 65535, minStep: 1 }
|
38
40
|
})
|
39
41
|
}
|
40
42
|
|
41
|
-
if (
|
42
|
-
|
43
|
+
if (service.values.lastUpdated === undefined) {
|
44
|
+
service.addCharacteristicDelegate({
|
45
|
+
key: 'lastUpdated',
|
46
|
+
Characteristic: service.Characteristics.my.LastUpdated,
|
47
|
+
silent: true
|
48
|
+
})
|
43
49
|
}
|
44
50
|
|
45
|
-
|
51
|
+
AirQuality.updateResourceState(service, resource.body.state)
|
46
52
|
}
|
47
53
|
|
48
|
-
airQualityValue (value) {
|
54
|
+
static airQualityValue (service, value) {
|
49
55
|
switch (value) {
|
50
56
|
case 'excellent':
|
51
|
-
return
|
57
|
+
return service.Characteristics.hap.AirQuality.EXCELLENT
|
52
58
|
case 'good':
|
53
|
-
return
|
59
|
+
return service.Characteristics.hap.AirQuality.GOOD
|
54
60
|
case 'moderate':
|
55
|
-
return
|
61
|
+
return service.Characteristics.hap.AirQuality.FAIR
|
56
62
|
case 'poor':
|
57
|
-
return
|
63
|
+
return service.Characteristics.hap.AirQuality.INFERIOR
|
58
64
|
case 'unhealthy':
|
59
|
-
return
|
65
|
+
return service.Characteristics.hap.AirQuality.POOR
|
60
66
|
default:
|
61
|
-
return
|
67
|
+
return service.Characteristics.hap.AirQuality.UNKNOWN
|
62
68
|
}
|
63
69
|
}
|
64
70
|
|
65
|
-
|
66
|
-
if (state.airquality != null) {
|
67
|
-
this.values.airQuality = this.airQualityValue(state.airquality)
|
68
|
-
}
|
71
|
+
static updateResourceState (service, state) {
|
69
72
|
if (state.airqualityppb != null) {
|
70
|
-
|
73
|
+
service.values.vocDensity = Math.round(state.airqualityppb * 4.57)
|
74
|
+
if (state.airquality != null) {
|
75
|
+
service.values.airQuality = AirQuality.airQualityValue(
|
76
|
+
service, state.airquality
|
77
|
+
)
|
78
|
+
}
|
71
79
|
}
|
72
80
|
if (state.pm2_5 != null) {
|
73
|
-
|
81
|
+
service.values.pm25Density = state.pm2_5
|
82
|
+
if (state.airquality != null && service.values.vocDensity === undefined) {
|
83
|
+
service.values.airQuality = AirQuality.airQualityValue(
|
84
|
+
service, state.airquality
|
85
|
+
)
|
86
|
+
}
|
87
|
+
}
|
88
|
+
if (state.lastupdated != null) {
|
89
|
+
service.values.lastUpdated = dateToString(state.lastupdated)
|
74
90
|
}
|
91
|
+
}
|
92
|
+
|
93
|
+
constructor (accessory, resource, params = {}) {
|
94
|
+
params.Service = accessory.Services.hap.AirQualitySensor
|
95
|
+
super(accessory, resource, params)
|
96
|
+
|
97
|
+
AirQuality.addResource(this, resource)
|
98
|
+
|
99
|
+
super.addCharacteristicDelegates({ noLastUpdated: true })
|
100
|
+
|
101
|
+
this.update(resource.body, resource.rpath)
|
102
|
+
}
|
103
|
+
|
104
|
+
updateState (state) {
|
105
|
+
AirQuality.updateResourceState(this, state)
|
75
106
|
super.updateState(state)
|
76
107
|
}
|
77
108
|
}
|
@@ -23,11 +23,11 @@ class Consumption extends DeconzService.SensorsResource {
|
|
23
23
|
|
24
24
|
if (
|
25
25
|
resource.body.state.power !== undefined &&
|
26
|
-
service.values.
|
26
|
+
service.values.consumption === undefined
|
27
27
|
) {
|
28
28
|
service.addCharacteristicDelegate({
|
29
|
-
key: '
|
30
|
-
Characteristic: service.Characteristics.eve.
|
29
|
+
key: 'consumption',
|
30
|
+
Characteristic: service.Characteristics.eve.Consumption,
|
31
31
|
unit: ' W'
|
32
32
|
})
|
33
33
|
}
|
@@ -40,7 +40,7 @@ class Consumption extends DeconzService.SensorsResource {
|
|
40
40
|
})
|
41
41
|
}
|
42
42
|
|
43
|
-
|
43
|
+
Consumption.updateResourceState(service, resource.body.state)
|
44
44
|
}
|
45
45
|
|
46
46
|
static updateResourceState (service, state) {
|
@@ -48,7 +48,7 @@ class Consumption extends DeconzService.SensorsResource {
|
|
48
48
|
service.values.totalConsumption = state.consumption / 1000
|
49
49
|
}
|
50
50
|
if (state.power != null) {
|
51
|
-
service.values.
|
51
|
+
service.values.consumption = state.power
|
52
52
|
}
|
53
53
|
if (state.lastupdated != null) {
|
54
54
|
service.values.lastUpdated = dateToString(state.lastupdated)
|
@@ -8,14 +8,31 @@
|
|
8
8
|
const { AdaptiveLighting, Colour, ServiceDelegate, timeout } = require('homebridge-lib')
|
9
9
|
const DeconzService = require('../DeconzService')
|
10
10
|
|
11
|
-
const { xyToHsv, hsvToXy, ctToXy } = Colour
|
12
|
-
const { History } = ServiceDelegate
|
11
|
+
const { defaultGamut, xyToHsv, hsvToXy, ctToXy } = Colour
|
13
12
|
|
14
13
|
class Light extends DeconzService.LightsResource {
|
15
14
|
constructor (accessory, resource, params = {}) {
|
16
15
|
params.Service = accessory.Services.hap.Lightbulb
|
17
16
|
super(accessory, resource, params)
|
18
17
|
|
18
|
+
this.capabilities = {
|
19
|
+
on: this.resource.body.state.on !== undefined,
|
20
|
+
bri: this.resource.body.state.bri !== undefined,
|
21
|
+
ct: this.resource.body.state.ct !== undefined,
|
22
|
+
hs: this.resource.body.state.xy === undefined &&
|
23
|
+
this.resource.body.state.hue !== undefined,
|
24
|
+
xy: this.resource.body.state.xy !== undefined
|
25
|
+
}
|
26
|
+
if (this.resource.body?.capabilities?.color?.effects != null) {
|
27
|
+
const effects = this.resource.body.capabilities.color.effects
|
28
|
+
if (effects.length > 1 && effects[1] === 'colorloop') {
|
29
|
+
this.capabilities.colorLoop = true
|
30
|
+
this.capabilities.effects = effects.length > 2
|
31
|
+
} else if (effects.length > 1) {
|
32
|
+
this.capabilities.effects = effects.length > 1
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
19
36
|
this.addCharacteristicDelegate({
|
20
37
|
key: 'on',
|
21
38
|
Characteristic: this.Characteristics.hap.On,
|
@@ -81,11 +98,7 @@ class Light extends DeconzService.LightsResource {
|
|
81
98
|
})
|
82
99
|
}
|
83
100
|
|
84
|
-
if (
|
85
|
-
this.resource.body.config != null &&
|
86
|
-
this.resource.body.config.color != null &&
|
87
|
-
this.resource.body.config.color.execute_if_off != null
|
88
|
-
) {
|
101
|
+
if (this.resource.body?.config?.color?.execute_if_off != null) {
|
89
102
|
this.addCharacteristicDelegate({
|
90
103
|
key: 'colorExecuteIfOff',
|
91
104
|
value: this.resource.body.config.color.execute_if_off
|
@@ -93,19 +106,25 @@ class Light extends DeconzService.LightsResource {
|
|
93
106
|
}
|
94
107
|
|
95
108
|
if (this.capabilities.ct) {
|
109
|
+
if (
|
110
|
+
this.resource.body?.capabilities?.color?.ct?.min == null ||
|
111
|
+
this.resource.body?.capabilities?.color?.ct?.max == null
|
112
|
+
) {
|
113
|
+
this.warn('using default ct range')
|
114
|
+
}
|
115
|
+
const ctMin = this.resource.body?.capabilities?.color?.ct?.min ?? 153
|
116
|
+
const ctMax = this.resource.body?.capabilities?.color?.ct?.max ?? 500
|
96
117
|
this.colorTemperatureDelegate = this.addCharacteristicDelegate({
|
97
118
|
key: 'colorTemperature',
|
98
119
|
Characteristic: this.Characteristics.hap.ColorTemperature,
|
99
120
|
unit: ' mired',
|
100
121
|
props: {
|
101
|
-
minValue:
|
102
|
-
maxValue:
|
122
|
+
minValue: ctMin,
|
123
|
+
maxValue: ctMax
|
103
124
|
},
|
104
125
|
value: this.resource.body.state.ct
|
105
126
|
}).on('didSet', (value, fromHomeKit) => {
|
106
|
-
const ct = Math.max(
|
107
|
-
this.capabilities.ctMin, Math.min(value, this.capabilities.ctMax)
|
108
|
-
)
|
127
|
+
const ct = Math.max(ctMin, Math.min(value, ctMax))
|
109
128
|
if (fromHomeKit) {
|
110
129
|
this.checkAdaptiveLighting()
|
111
130
|
this.put({ ct })
|
@@ -120,6 +139,21 @@ class Light extends DeconzService.LightsResource {
|
|
120
139
|
}
|
121
140
|
|
122
141
|
if (this.capabilities.xy) {
|
142
|
+
if (
|
143
|
+
this.resource.body?.capabilities?.color?.xy?.blue == null ||
|
144
|
+
this.resource.body?.capabilities?.color?.xy?.green == null ||
|
145
|
+
this.resource.body?.capabilities?.color?.xy?.red == null
|
146
|
+
) {
|
147
|
+
this.warn('using default xy gamut')
|
148
|
+
this.capabilities.gamut = defaultGamut
|
149
|
+
} else {
|
150
|
+
this.capabilities.gamut = {
|
151
|
+
r: this.resource.body.capabilities.color.xy.red,
|
152
|
+
g: this.resource.body.capabilities.color.xy.green,
|
153
|
+
b: this.resource.body.capabilities.color.xy.blue
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
123
157
|
this.addCharacteristicDelegate({
|
124
158
|
key: 'hue',
|
125
159
|
Characteristic: this.Characteristics.hap.Hue,
|
@@ -261,13 +295,7 @@ class Light extends DeconzService.LightsResource {
|
|
261
295
|
}
|
262
296
|
|
263
297
|
if (this.capabilities.effects != null) {
|
264
|
-
this.
|
265
|
-
key: 'exposeEffects',
|
266
|
-
value: true
|
267
|
-
})
|
268
|
-
if (this.values.exposeEffects) {
|
269
|
-
this.exposeEffects()
|
270
|
-
}
|
298
|
+
this.exposeEffects()
|
271
299
|
}
|
272
300
|
|
273
301
|
if (this.resource.rtype === 'lights') {
|
@@ -279,57 +307,29 @@ class Light extends DeconzService.LightsResource {
|
|
279
307
|
}
|
280
308
|
|
281
309
|
exposeEffects () {
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
value: -1,
|
310
|
+
const effectString = this.addCharacteristicDelegate({
|
311
|
+
key: 'effectString',
|
312
|
+
value: 'none',
|
286
313
|
silent: true
|
287
|
-
}).on('didSet', (value) => {
|
288
|
-
for (const i in this.capabilities.effects) {
|
289
|
-
this.effectServices[i].values.on = value === i
|
290
|
-
}
|
291
314
|
})
|
292
|
-
for (const id in this.capabilities.effects) {
|
293
|
-
const effect = this.capabilities.effects[id]
|
294
|
-
const
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
this.accessoryDelegate.historyService.lastActivationValue(History.now())
|
305
|
-
if (fromHomeKit) {
|
306
|
-
this.checkAdaptiveLighting()
|
307
|
-
this.values.effect = value ? id : -1
|
308
|
-
const newEffect = value
|
309
|
-
? effect.toLowerCase()
|
310
|
-
: 'none'
|
311
|
-
this.put({ effect: newEffect })
|
312
|
-
}
|
313
|
-
})
|
314
|
-
service.addCharacteristicDelegate({
|
315
|
-
key: 'index',
|
316
|
-
Characteristic: this.Characteristics.hap.ServiceLabelIndex,
|
317
|
-
value: Number(id) + 1
|
318
|
-
})
|
319
|
-
service.addCharacteristicDelegate({
|
320
|
-
key: 'lastActivation',
|
321
|
-
Characteristic: this.Characteristics.eve.LastActivation,
|
322
|
-
silent: true
|
323
|
-
})
|
324
|
-
this.effectServices[id] = service
|
325
|
-
|
326
|
-
this.characteristicDelegate('configuredName')
|
327
|
-
.on('didSet', (value) => {
|
328
|
-
for (const id in this.capabilities.effects) {
|
329
|
-
this.effectServices[id].values.configuredName = value +
|
330
|
-
' ' + this.capabilities.effects[id]
|
315
|
+
for (const id in this.resource.body.capabilities.color.effects) {
|
316
|
+
const effect = this.resource.body.capabilities.color.effects[id]
|
317
|
+
const characteristicName = effect[0].toUpperCase() + effect.slice(1) + 'Effect'
|
318
|
+
if (this.Characteristics.my[characteristicName] != null) {
|
319
|
+
this.addCharacteristicDelegate({
|
320
|
+
key: effect,
|
321
|
+
Characteristic: this.Characteristics.my[characteristicName]
|
322
|
+
}).on('didSet', (value, fromHomeKit) => {
|
323
|
+
if (fromHomeKit) {
|
324
|
+
this.checkAdaptiveLighting()
|
325
|
+
this.put({ effect: value ? effect : 'none' })
|
326
|
+
this.values.effectString = value ? effect : 'none'
|
331
327
|
}
|
332
328
|
})
|
329
|
+
effectString.on('didSet', (value) => {
|
330
|
+
this.values[effect] = value === effect
|
331
|
+
})
|
332
|
+
}
|
333
333
|
}
|
334
334
|
// if (this.capabilities.effectSpeed) {
|
335
335
|
// this.addCharacteristicDelegate({
|
@@ -403,9 +403,8 @@ class Light extends DeconzService.LightsResource {
|
|
403
403
|
break
|
404
404
|
case 'effect':
|
405
405
|
this.values.colorLoop = value === 'colorloop'
|
406
|
-
if (this.capabilities.effects
|
407
|
-
|
408
|
-
this.values.effect = '' + this.capabilities.effects.indexOf(effectName)
|
406
|
+
if (this.capabilities.effects) {
|
407
|
+
this.values.effectString = value
|
409
408
|
}
|
410
409
|
break
|
411
410
|
case 'hue':
|
@@ -430,8 +429,10 @@ class Light extends DeconzService.LightsResource {
|
|
430
429
|
break
|
431
430
|
case 'xy':
|
432
431
|
if (
|
433
|
-
!this.recentlyUpdated &&
|
434
|
-
|
432
|
+
!this.recentlyUpdated && (
|
433
|
+
this.values.colormode !== 'ct' ||
|
434
|
+
this.resource.body?.capabilities?.color?.ct?.computesXy
|
435
|
+
)
|
435
436
|
) {
|
436
437
|
const { h, s } = xyToHsv(value, this.capabilities.gamut)
|
437
438
|
this.values.hue = h
|
@@ -15,10 +15,10 @@ const { dateToString } = Deconz.ApiClient
|
|
15
15
|
*/
|
16
16
|
class Power extends DeconzService.SensorsResource {
|
17
17
|
static addResource (service, resource) {
|
18
|
-
if (service.values.
|
18
|
+
if (service.values.consumption === undefined) {
|
19
19
|
service.addCharacteristicDelegate({
|
20
|
-
key: '
|
21
|
-
Characteristic: service.Characteristics.eve.
|
20
|
+
key: 'consumption',
|
21
|
+
Characteristic: service.Characteristics.eve.Consumption,
|
22
22
|
unit: ' W'
|
23
23
|
})
|
24
24
|
}
|
@@ -46,12 +46,13 @@ class Power extends DeconzService.SensorsResource {
|
|
46
46
|
silent: true
|
47
47
|
})
|
48
48
|
}
|
49
|
-
|
49
|
+
|
50
|
+
Power.updateResourceState(service, resource.body.state)
|
50
51
|
}
|
51
52
|
|
52
53
|
static updateResourceState (service, state) {
|
53
54
|
if (state.power != null) {
|
54
|
-
service.values.
|
55
|
+
service.values.consumption = state.power
|
55
56
|
}
|
56
57
|
if (state.current != null) {
|
57
58
|
service.values.electricCurrent = state.current / 1000
|
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.
|
7
|
+
"version": "0.1.10",
|
8
8
|
"keywords": [
|
9
9
|
"homebridge-plugin",
|
10
10
|
"homekit",
|
@@ -21,12 +21,12 @@
|
|
21
21
|
"ui": "cli/ui.js"
|
22
22
|
},
|
23
23
|
"engines": {
|
24
|
-
"deCONZ": "2.
|
24
|
+
"deCONZ": "2.20.1",
|
25
25
|
"homebridge": "^1.6.0",
|
26
|
-
"node": "^18.
|
26
|
+
"node": "^18.15.0"
|
27
27
|
},
|
28
28
|
"dependencies": {
|
29
|
-
"homebridge-lib": "~6.3.
|
29
|
+
"homebridge-lib": "~6.3.12",
|
30
30
|
"ws": "^8.12.1",
|
31
31
|
"xml2js": "~0.4.23"
|
32
32
|
},
|