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.
- package/README.md +3 -6
- package/cli/deconz.js +12 -0
- package/config.schema.json +1 -0
- package/homebridge-ui/public/index.html +26 -0
- package/homebridge-ui/public/style.css +0 -0
- package/homebridge-ui/server.js +43 -0
- package/lib/Deconz/ApiClient.js +34 -1
- package/lib/Deconz/ApiResponse.js +1 -1
- package/lib/Deconz/Device.js +0 -7
- package/lib/Deconz/Resource.js +751 -25
- package/lib/DeconzAccessory/Contact.js +54 -0
- package/lib/DeconzAccessory/Gateway.js +102 -66
- package/lib/DeconzAccessory/Light.js +42 -37
- package/lib/DeconzAccessory/Motion.js +51 -0
- package/lib/DeconzAccessory/Sensor.js +35 -0
- package/lib/DeconzAccessory/Temperature.js +63 -0
- package/lib/DeconzAccessory/Thermostat.js +50 -0
- package/lib/DeconzAccessory/WarningDevice.js +56 -0
- package/lib/DeconzAccessory/WindowCovering.js +47 -0
- package/lib/DeconzAccessory/index.js +144 -2
- package/lib/DeconzPlatform.js +5 -2
- package/lib/DeconzService/AirPressure.js +43 -0
- package/lib/DeconzService/AirQuality.js +20 -11
- package/lib/DeconzService/Alarm.js +13 -9
- package/lib/DeconzService/Battery.js +53 -0
- package/lib/DeconzService/Button.js +9 -2
- package/lib/DeconzService/CarbonMonoxide.js +38 -0
- package/lib/DeconzService/Consumption.js +65 -0
- package/lib/DeconzService/Contact.js +60 -0
- package/lib/DeconzService/Daylight.js +132 -0
- package/lib/DeconzService/DeviceSettings.js +11 -0
- package/lib/DeconzService/Flag.js +52 -0
- package/lib/DeconzService/Humidity.js +37 -0
- package/lib/DeconzService/Leak.js +38 -0
- package/lib/DeconzService/Light.js +122 -172
- package/lib/DeconzService/LightLevel.js +54 -0
- package/lib/DeconzService/LightsResource.js +112 -0
- package/lib/DeconzService/Motion.js +101 -0
- package/lib/DeconzService/Outlet.js +76 -0
- package/lib/DeconzService/Power.js +83 -0
- package/lib/DeconzService/SensorsResource.js +96 -0
- package/lib/DeconzService/Smoke.js +38 -0
- package/lib/DeconzService/Status.js +53 -0
- package/lib/DeconzService/Switch.js +93 -0
- package/lib/DeconzService/Temperature.js +63 -0
- package/lib/DeconzService/Thermostat.js +175 -0
- package/lib/DeconzService/WarningDevice.js +68 -0
- package/lib/DeconzService/WindowCovering.js +162 -0
- package/lib/DeconzService/index.js +79 -25
- package/package.json +6 -5
- package/lib/Client/ApiError.js +0 -42
- package/lib/DeconzAccessory/Device.js +0 -69
- package/lib/DeconzService/Sensor.js +0 -61
@@ -0,0 +1,54 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/Contact.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 DeconzAccessory = require('../DeconzAccessory')
|
10
|
+
|
11
|
+
const { History } = homebridgeLib.ServiceDelegate
|
12
|
+
|
13
|
+
/** Delegate class for a HomeKit accessory corresponding to a contact sensor,
|
14
|
+
* with Eve Door & Window history.
|
15
|
+
* @extends DeconzAccessory
|
16
|
+
* @memberof DeconzAccessory
|
17
|
+
*/
|
18
|
+
class Contact extends DeconzAccessory {
|
19
|
+
/** Instantiate a contact sensor delegate.
|
20
|
+
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
21
|
+
* @param {Deconz.Device} device - The device.
|
22
|
+
*/
|
23
|
+
constructor (gateway, device) {
|
24
|
+
super(gateway, device, gateway.Accessory.Categories.SENSOR)
|
25
|
+
|
26
|
+
this.identify()
|
27
|
+
|
28
|
+
this.service = this.createService(device.resource, { primaryService: true })
|
29
|
+
|
30
|
+
for (const subtype in device.resourceBySubtype) {
|
31
|
+
const resource = device.resourceBySubtype[subtype]
|
32
|
+
if (subtype === device.primary) {
|
33
|
+
continue
|
34
|
+
}
|
35
|
+
this.createService(resource)
|
36
|
+
}
|
37
|
+
|
38
|
+
this.historyService = new History.Contact(
|
39
|
+
this, {},
|
40
|
+
this.service.characteristicDelegate('contact'),
|
41
|
+
this.service.characteristicDelegate('timesOpened'),
|
42
|
+
this.service.characteristicDelegate('lastActivation')
|
43
|
+
)
|
44
|
+
|
45
|
+
this.createSettingsService()
|
46
|
+
|
47
|
+
setImmediate(() => {
|
48
|
+
this.debug('initialised')
|
49
|
+
this.emit('initialised')
|
50
|
+
})
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
module.exports = Contact
|
@@ -8,7 +8,7 @@
|
|
8
8
|
const homebridgeLib = require('homebridge-lib')
|
9
9
|
|
10
10
|
const Deconz = require('../Deconz')
|
11
|
-
const DeconzAccessory = require('
|
11
|
+
const DeconzAccessory = require('../DeconzAccessory')
|
12
12
|
const DeconzService = require('../DeconzService')
|
13
13
|
|
14
14
|
const rtypes = ['lights', 'sensors', 'groups']
|
@@ -20,8 +20,6 @@ const periodicEvents = [
|
|
20
20
|
]
|
21
21
|
|
22
22
|
/** Delegate class for a deCONZ gateway.
|
23
|
-
*
|
24
|
-
* @class
|
25
23
|
* @extends AccessoryDelegate
|
26
24
|
* @memberof DeconzAccessory
|
27
25
|
*/
|
@@ -41,7 +39,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
41
39
|
model: params.config.modelid + ' / ' + params.config.devicename,
|
42
40
|
firmware: '0.0.0',
|
43
41
|
software: params.config.swversion,
|
44
|
-
category: platform.Accessory.Categories.
|
42
|
+
category: platform.Accessory.Categories.BRIDGE
|
45
43
|
})
|
46
44
|
|
47
45
|
this.gateway = this
|
@@ -62,6 +60,9 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
62
60
|
if (this.context.blacklist == null) {
|
63
61
|
this.context.blacklist = {}
|
64
62
|
}
|
63
|
+
if (this.context.fullState != null) {
|
64
|
+
this.analyseFullState(this.context.fullState, { analyseOnly: true })
|
65
|
+
}
|
65
66
|
|
66
67
|
this.addPropertyDelegate({
|
67
68
|
key: 'apiKey',
|
@@ -215,9 +216,6 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
215
216
|
try {
|
216
217
|
this.debug('initialising...')
|
217
218
|
this.initialBeat = beat
|
218
|
-
if (this.context.fullState != null) {
|
219
|
-
this.analyseFullState(this.context.fullState, true)
|
220
|
-
}
|
221
219
|
await this.connect()
|
222
220
|
this.initialised = true
|
223
221
|
this.debug('initialised')
|
@@ -442,6 +440,9 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
442
440
|
}
|
443
441
|
try {
|
444
442
|
try {
|
443
|
+
if (this.context.migration != null) {
|
444
|
+
await this.client.delete(this.context.migration)
|
445
|
+
}
|
445
446
|
await this.client.deleteApiKey()
|
446
447
|
} catch (error) {}
|
447
448
|
this.values.apiKey = null
|
@@ -457,10 +458,12 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
457
458
|
this.exposeErrors = {}
|
458
459
|
this.context.blacklist = {}
|
459
460
|
this.context.fullState = null
|
461
|
+
this.context.migration = null
|
460
462
|
this.service.values.lights = false
|
461
463
|
this.service.values.sensors = false
|
462
464
|
this.service.values.groups = false
|
463
465
|
this.service.values.schedules = false
|
466
|
+
this.service.values.logLevel = 2
|
464
467
|
this.values.rtypes = []
|
465
468
|
} catch (error) { this.error(error) }
|
466
469
|
}
|
@@ -504,12 +507,12 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
504
507
|
if (this.accessoryById[id] == null) {
|
505
508
|
const device = this.deviceById[id]
|
506
509
|
delete this.exposeErrorById[id]
|
507
|
-
const { body
|
510
|
+
const { body } = device.resource
|
508
511
|
this.log('%s: add accessory', body.name)
|
509
512
|
let { serviceName } = device.resource
|
510
513
|
if (DeconzAccessory[serviceName] == null) {
|
511
|
-
this.warn('%s: %s: not yet supported %s type', body.name, body.type, rtype)
|
512
|
-
serviceName = '
|
514
|
+
// this.warn('%s: %s: not yet supported %s type', body.name, body.type, rtype)
|
515
|
+
serviceName = 'Sensor'
|
513
516
|
}
|
514
517
|
const accessory = new DeconzAccessory[serviceName](this, device)
|
515
518
|
this.accessoryById[id] = accessory
|
@@ -593,6 +596,9 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
593
596
|
throw new RangeError(`${id}: unknown device ID`)
|
594
597
|
}
|
595
598
|
if (this.serviceById[id] == null) {
|
599
|
+
if (Object.keys(this.serviceById).length >= 97) {
|
600
|
+
return null
|
601
|
+
}
|
596
602
|
const { resource, rpaths } = this.deviceById[id]
|
597
603
|
const { body } = resource
|
598
604
|
const service = new DeconzService.DeviceSettings(this, {
|
@@ -645,11 +651,14 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
645
651
|
return
|
646
652
|
}
|
647
653
|
this.context.fullState.config = config
|
648
|
-
if (
|
654
|
+
if (
|
655
|
+
this.service.values.lights || this.nDevicesByRtype.lights > 0 ||
|
656
|
+
this.service.values.sensors || this.nDevicesByRtype.sensors > 0
|
657
|
+
) {
|
649
658
|
this.context.fullState.lights = await this.client.get('/lights')
|
650
659
|
this.context.fullState.sensors = await this.client.get('/sensors')
|
651
660
|
}
|
652
|
-
if (this.service.values.groups) {
|
661
|
+
if (this.service.values.groups || this.nDevicesByRtype.groups > 0) {
|
653
662
|
this.context.fullState.groups = await this.client.get('/groups')
|
654
663
|
this.context.fullState.groups[0] = await this.client.get('/groups/0')
|
655
664
|
}
|
@@ -657,7 +666,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
657
666
|
this.context.fullState.schedules = await this.client.get('/schedules')
|
658
667
|
}
|
659
668
|
}
|
660
|
-
this.analyseFullState(this.context.fullState)
|
669
|
+
await this.analyseFullState(this.context.fullState)
|
661
670
|
} catch (error) {
|
662
671
|
this.error(error)
|
663
672
|
} finally {
|
@@ -698,12 +707,12 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
698
707
|
* accessories, corresponding to devices have been blacklisted.
|
699
708
|
* @param {Object} fullState - The gateway full state, as returned by
|
700
709
|
* {@link DeconzAccessory.Gateway#poll poll()}.
|
701
|
-
* @param {
|
702
|
-
*
|
710
|
+
* @param {Object} params - Parameters
|
711
|
+
* @param {boolean} [params.logUnsupportedResources=false] - Issue debug
|
712
|
+
* messsages for unsupported resources.
|
713
|
+
* @param {boolean} [params.analyseOnly=false]
|
703
714
|
*/
|
704
|
-
analyseFullState (fullState,
|
705
|
-
this.update(fullState.config)
|
706
|
-
|
715
|
+
async analyseFullState (fullState, params = {}) {
|
707
716
|
/** Supported devices by device ID.
|
708
717
|
*
|
709
718
|
* Updated by
|
@@ -740,8 +749,10 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
740
749
|
for (const rtype of rtypes) {
|
741
750
|
this.deviceByRidByRtype[rtype] = {}
|
742
751
|
for (const rid in fullState[rtype]) {
|
743
|
-
|
744
|
-
|
752
|
+
try {
|
753
|
+
const body = fullState[rtype][rid]
|
754
|
+
this.analyseResource(rtype, rid, body, params.logUnsupported)
|
755
|
+
} catch (error) { this.error(error) }
|
745
756
|
}
|
746
757
|
}
|
747
758
|
|
@@ -774,64 +785,74 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
774
785
|
this.vdebug('%d %s devices', this.nDevicesByRtype[rtype], rtype)
|
775
786
|
}
|
776
787
|
|
788
|
+
if (params.analyseOnly) {
|
789
|
+
return
|
790
|
+
}
|
791
|
+
|
792
|
+
this.update(fullState.config)
|
793
|
+
|
777
794
|
let changed = false
|
778
795
|
|
779
796
|
this.vdebug('analysing accessories...')
|
780
797
|
for (const id in this.accessoryById) {
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
798
|
+
try {
|
799
|
+
if (
|
800
|
+
this.deviceById[id] == null
|
801
|
+
) {
|
802
|
+
delete this.context.blacklist[id]
|
803
|
+
this.deleteAccessory(id)
|
804
|
+
this.deleteService(id)
|
805
|
+
changed = true
|
806
|
+
} else {
|
807
|
+
/** Emitted when the gateway has been polled.
|
808
|
+
* @event DeconzAccessory.Device#polled
|
809
|
+
* @param {Deconz.Device} device - The updated device.
|
810
|
+
*/
|
811
|
+
this.accessoryById[id].emit('polled', this.deviceById[id])
|
812
|
+
}
|
813
|
+
} catch (error) { this.error(error) }
|
796
814
|
}
|
797
815
|
|
798
816
|
this.vdebug('analysing services...')
|
799
817
|
for (const id in this.serviceById) {
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
818
|
+
try {
|
819
|
+
if (
|
820
|
+
this.deviceById[id] == null ||
|
821
|
+
!this.values.rtypes.includes(this.deviceById[id].resource.rtype)
|
822
|
+
) {
|
823
|
+
delete this.exposeErrorById[id]
|
824
|
+
this.deleteService(id)
|
825
|
+
changed = true
|
826
|
+
}
|
827
|
+
} catch (error) { this.error(error) }
|
809
828
|
}
|
810
829
|
|
811
830
|
for (const rtype of this.values.rtypes) {
|
812
831
|
this.vdebug('analysing %s devices...', rtype)
|
813
832
|
const rids = Object.keys(this.deviceByRidByRtype[rtype]).sort()
|
814
833
|
for (const rid of rids) {
|
815
|
-
|
816
|
-
|
817
|
-
if (this.
|
818
|
-
this.
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
this.
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
this.
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
this.
|
832
|
-
|
834
|
+
try {
|
835
|
+
const { id } = this.deviceByRidByRtype[rtype][rid]
|
836
|
+
if (this.context.blacklist[id] == null) {
|
837
|
+
if (this.accessoryById[id] == null) {
|
838
|
+
this.addAccessory(id)
|
839
|
+
changed = true
|
840
|
+
}
|
841
|
+
if (this.serviceById[id] != null) {
|
842
|
+
this.deleteService(id)
|
843
|
+
changed = true
|
844
|
+
}
|
845
|
+
} else {
|
846
|
+
if (this.serviceById[id] == null) {
|
847
|
+
this.addService(id)
|
848
|
+
changed = true
|
849
|
+
}
|
850
|
+
if (this.accessoryById[id] != null) {
|
851
|
+
this.deleteAccessory(id)
|
852
|
+
changed = true
|
853
|
+
}
|
833
854
|
}
|
834
|
-
}
|
855
|
+
} catch (error) { this.error(error) }
|
835
856
|
}
|
836
857
|
}
|
837
858
|
|
@@ -848,8 +869,23 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
848
869
|
if (changed) {
|
849
870
|
this.nResourcesMonitored = Object.keys(this.accessoryByRpath).length
|
850
871
|
this.identify()
|
851
|
-
this.
|
852
|
-
|
872
|
+
if (this.context.migration == null) {
|
873
|
+
const response = await this.client.post('/resourcelinks', {
|
874
|
+
name: 'homebridge-deconz',
|
875
|
+
description: 'migration',
|
876
|
+
classid: 1,
|
877
|
+
links: Object.keys(this.accessoryByRpath).sort()
|
878
|
+
})
|
879
|
+
this.context.migration = '/resourcelinks/' + response.success.id
|
880
|
+
} else {
|
881
|
+
await this.client.put(this.context.migration, {
|
882
|
+
links: Object.keys(this.accessoryByRpath).sort()
|
883
|
+
})
|
884
|
+
}
|
885
|
+
this.log(
|
886
|
+
'migration: %s: %d resources',
|
887
|
+
this.context.migration, this.nResourcesMonitored
|
888
|
+
)
|
853
889
|
}
|
854
890
|
}
|
855
891
|
|
@@ -862,7 +898,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
|
|
862
898
|
* `groups`, `lights`, or `sensors`.
|
863
899
|
* @param {integer} rid - The resource ID of the resource.
|
864
900
|
* @param {object} body - The body of the resource.
|
865
|
-
* @param {boolean}
|
901
|
+
* @param {boolean} logUnsupported - Issue a debug message for
|
866
902
|
* unsupported resources.
|
867
903
|
*/
|
868
904
|
analyseResource (rtype, rid, body, logUnsupported) {
|
@@ -1,16 +1,17 @@
|
|
1
|
-
// homebridge-deconz/lib/DeconzAccessory/
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/Light.js
|
2
2
|
// Copyright © 2022 Erik Baauw. All rights reserved.
|
3
3
|
//
|
4
4
|
// Homebridge plugin for deCONZ.
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
-
const
|
9
|
-
const
|
8
|
+
const homebridgeLib = require('homebridge-lib')
|
9
|
+
const DeconzAccessory = require('../DeconzAccessory')
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
const { History } = homebridgeLib.ServiceDelegate
|
12
|
+
|
13
|
+
/** Delegate class for a HomeKit accessory, corresponding to a light device
|
14
|
+
* or groups resource.
|
14
15
|
* @extends DeconzAccessory
|
15
16
|
* @memberof DeconzAccessory
|
16
17
|
*/
|
@@ -19,49 +20,53 @@ class Light extends DeconzAccessory {
|
|
19
20
|
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
20
21
|
* @param {Deconz.Device} device - The device.
|
21
22
|
*/
|
22
|
-
constructor (gateway, device) {
|
23
|
-
super(gateway, device)
|
23
|
+
constructor (gateway, device, settings = {}) {
|
24
|
+
super(gateway, device, gateway.Accessory.Categories.LIGHTBULB)
|
24
25
|
|
25
26
|
this.identify()
|
26
27
|
|
27
|
-
this.
|
28
|
+
this.addPropertyDelegate({
|
29
|
+
key: 'serviceName',
|
30
|
+
value: device.resource.capabilities.bri ? 'Light' : 'Outlet'
|
31
|
+
})
|
28
32
|
|
29
|
-
this.
|
30
|
-
|
31
|
-
|
32
|
-
resource: this.device.rpaths.join(', '),
|
33
|
-
expose: true,
|
34
|
-
logLevel: gateway.logLevel
|
33
|
+
this.service = this.createService(device.resource, {
|
34
|
+
primaryService: true,
|
35
|
+
serviceName: this.values.serviceName
|
35
36
|
})
|
36
|
-
this.manageLogLevel(this.settingsService.characteristicDelegate('logLevel'))
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
.
|
38
|
+
for (const subtype in device.resourceBySubtype) {
|
39
|
+
const resource = device.resourceBySubtype[subtype]
|
40
|
+
if (subtype === device.primary) {
|
41
|
+
continue
|
42
|
+
}
|
43
|
+
if (resource.rtype === 'lights') {
|
44
|
+
this.createService(resource, { serviceName: this.values.serviceName })
|
45
|
+
} else {
|
46
|
+
this.createService(resource)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
if (this.serviceByServiceName.Consumption != null) {
|
51
|
+
this.historyService = new History.Consumption(
|
52
|
+
this, {},
|
53
|
+
this.serviceByServiceName.Consumption.characteristicDelegate('totalConsumption'),
|
54
|
+
this.serviceByServiceName.Consumption.characteristicDelegate('currentConsumption')
|
55
|
+
)
|
56
|
+
} else if (this.serviceByServiceName.Power != null) {
|
57
|
+
this.historyService = new History.Power(
|
58
|
+
this, {},
|
59
|
+
this.serviceByServiceName.Power.characteristicDelegate('currentConsumption')
|
60
|
+
)
|
61
|
+
}
|
62
|
+
|
63
|
+
this.createSettingsService()
|
52
64
|
|
53
65
|
setImmediate(() => {
|
54
66
|
this.debug('initialised')
|
55
67
|
this.emit('initialised')
|
56
68
|
})
|
57
69
|
}
|
58
|
-
|
59
|
-
async identify () {
|
60
|
-
super.identify()
|
61
|
-
if (this.service != null) {
|
62
|
-
await this.service.identify()
|
63
|
-
}
|
64
|
-
}
|
65
70
|
}
|
66
71
|
|
67
72
|
module.exports = Light
|
@@ -0,0 +1,51 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/Motion.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 DeconzAccessory = require('../DeconzAccessory')
|
10
|
+
|
11
|
+
const { History } = homebridgeLib.ServiceDelegate
|
12
|
+
|
13
|
+
class Motion extends DeconzAccessory {
|
14
|
+
/** Instantiate a delegate for an accessory corresponding to a device.
|
15
|
+
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
16
|
+
* @param {Deconz.Device} device - The device.
|
17
|
+
*/
|
18
|
+
constructor (gateway, device) {
|
19
|
+
super(gateway, device, gateway.Accessory.Categories.SENSOR)
|
20
|
+
|
21
|
+
this.identify()
|
22
|
+
|
23
|
+
this.service = this.createService(device.resource, { primaryService: true })
|
24
|
+
|
25
|
+
for (const subtype in device.resourceBySubtype) {
|
26
|
+
const resource = device.resourceBySubtype[subtype]
|
27
|
+
if (subtype === device.primary) {
|
28
|
+
continue
|
29
|
+
}
|
30
|
+
this.createService(resource)
|
31
|
+
}
|
32
|
+
|
33
|
+
this.historyService = new History.Motion(
|
34
|
+
this, {},
|
35
|
+
this.service.characteristicDelegate('motion'),
|
36
|
+
this.service.characteristicDelegate('lastActivation'),
|
37
|
+
this.serviceByServiceName.Temperature == null
|
38
|
+
? null
|
39
|
+
: this.serviceByServiceName.Temperature.characteristicDelegate('temperature')
|
40
|
+
)
|
41
|
+
|
42
|
+
this.createSettingsService()
|
43
|
+
|
44
|
+
setImmediate(() => {
|
45
|
+
this.debug('initialised')
|
46
|
+
this.emit('initialised')
|
47
|
+
})
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
module.exports = Motion
|
@@ -0,0 +1,35 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/Sensor.js
|
2
|
+
// Copyright © 2022 Erik Baauw. All rights reserved.
|
3
|
+
//
|
4
|
+
// Homebridge plugin for deCONZ.
|
5
|
+
|
6
|
+
'use strict'
|
7
|
+
|
8
|
+
const DeconzAccessory = require('../DeconzAccessory')
|
9
|
+
|
10
|
+
class Sensor extends DeconzAccessory {
|
11
|
+
constructor (gateway, device) {
|
12
|
+
super(gateway, device, gateway.Accessory.Categories.SENSOR)
|
13
|
+
|
14
|
+
this.identify()
|
15
|
+
|
16
|
+
this.service = this.createService(device.resource, { primaryService: true })
|
17
|
+
|
18
|
+
for (const subtype in device.resourceBySubtype) {
|
19
|
+
const resource = device.resourceBySubtype[subtype]
|
20
|
+
if (subtype === device.primary) {
|
21
|
+
continue
|
22
|
+
}
|
23
|
+
this.createService(resource)
|
24
|
+
}
|
25
|
+
|
26
|
+
this.createSettingsService()
|
27
|
+
|
28
|
+
setImmediate(() => {
|
29
|
+
this.debug('initialised')
|
30
|
+
this.emit('initialised')
|
31
|
+
})
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
module.exports = Sensor
|
@@ -0,0 +1,63 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/Temperature.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 DeconzAccessory = require('../DeconzAccessory')
|
10
|
+
|
11
|
+
const { History } = homebridgeLib.ServiceDelegate
|
12
|
+
|
13
|
+
class Temperature extends DeconzAccessory {
|
14
|
+
/** Instantiate a delegate for an accessory corresponding to a device.
|
15
|
+
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
16
|
+
* @param {Deconz.Device} device - The device.
|
17
|
+
*/
|
18
|
+
constructor (gateway, device, settings = {}) {
|
19
|
+
super(gateway, device, gateway.Accessory.Categories.SENSOR)
|
20
|
+
this.identify()
|
21
|
+
|
22
|
+
this.service = this.createService(device.resource, { primaryService: true })
|
23
|
+
|
24
|
+
for (const subtype in device.resourceBySubtype) {
|
25
|
+
const resource = device.resourceBySubtype[subtype]
|
26
|
+
if (subtype === device.primary) {
|
27
|
+
continue
|
28
|
+
}
|
29
|
+
this.createService(resource)
|
30
|
+
}
|
31
|
+
|
32
|
+
if (this.serviceByServiceName.AirQuality == null) {
|
33
|
+
this.historyService = new History.Weather(
|
34
|
+
this, {},
|
35
|
+
this.service.characteristicDelegate('temperature'),
|
36
|
+
this.serviceByServiceName.Humidity == null
|
37
|
+
? null
|
38
|
+
: this.serviceByServiceName.Humidity.characteristicDelegate('humidity'),
|
39
|
+
this.serviceByServiceName.AirPressure == null
|
40
|
+
? null
|
41
|
+
: this.serviceByServiceName.AirPressure.characteristicDelegate('airPressure')
|
42
|
+
)
|
43
|
+
} else {
|
44
|
+
this.historyService = new History.Room(
|
45
|
+
this, {},
|
46
|
+
this.service.characteristicDelegate('temperature'),
|
47
|
+
this.serviceByServiceName.Humidity == null
|
48
|
+
? null
|
49
|
+
: this.serviceByServiceName.Humidity.characteristicDelegate('humidity'),
|
50
|
+
this.serviceByServiceName.AirQuality.characteristicDelegate('vocDensity')
|
51
|
+
)
|
52
|
+
}
|
53
|
+
|
54
|
+
this.createSettingsService()
|
55
|
+
|
56
|
+
setImmediate(() => {
|
57
|
+
this.debug('initialised')
|
58
|
+
this.emit('initialised')
|
59
|
+
})
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
module.exports = Temperature
|
@@ -0,0 +1,50 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/Thermostat.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 DeconzAccessory = require('../DeconzAccessory')
|
10
|
+
|
11
|
+
const { History } = homebridgeLib.ServiceDelegate
|
12
|
+
|
13
|
+
class Thermostat extends DeconzAccessory {
|
14
|
+
/** Instantiate a delegate for an accessory corresponding to a device.
|
15
|
+
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
16
|
+
* @param {Deconz.Device} device - The device.
|
17
|
+
*/
|
18
|
+
constructor (gateway, device, settings = {}) {
|
19
|
+
super(gateway, device, gateway.Accessory.Categories.THERMOSTAT)
|
20
|
+
this.identify()
|
21
|
+
|
22
|
+
this.service = this.createService(device.resource, { primaryService: true })
|
23
|
+
|
24
|
+
for (const subtype in device.resourceBySubtype) {
|
25
|
+
const resource = device.resourceBySubtype[subtype]
|
26
|
+
if (subtype === device.primary) {
|
27
|
+
continue
|
28
|
+
}
|
29
|
+
this.createService(resource)
|
30
|
+
}
|
31
|
+
|
32
|
+
if (device.resource.body.state.valve !== undefined) {
|
33
|
+
this.historyService = new History.Thermo(
|
34
|
+
this, {},
|
35
|
+
this.service.characteristicDelegate('currentTemperature'),
|
36
|
+
this.service.characteristicDelegate('targetTemperature'),
|
37
|
+
this.service.characteristicDelegate('valvePosition')
|
38
|
+
)
|
39
|
+
}
|
40
|
+
|
41
|
+
this.createSettingsService()
|
42
|
+
|
43
|
+
setImmediate(() => {
|
44
|
+
this.debug('initialised')
|
45
|
+
this.emit('initialised')
|
46
|
+
})
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
module.exports = Thermostat
|