homebridge-deconz 0.0.9 → 0.0.12

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 (54) hide show
  1. package/README.md +3 -6
  2. package/cli/deconz.js +12 -0
  3. package/config.schema.json +2 -1
  4. package/homebridge-ui/public/index.html +26 -0
  5. package/homebridge-ui/public/style.css +0 -0
  6. package/homebridge-ui/server.js +43 -0
  7. package/lib/Deconz/ApiClient.js +34 -1
  8. package/lib/Deconz/ApiResponse.js +1 -1
  9. package/lib/Deconz/Device.js +0 -7
  10. package/lib/Deconz/Resource.js +752 -27
  11. package/lib/DeconzAccessory/Contact.js +54 -0
  12. package/lib/DeconzAccessory/Gateway.js +102 -66
  13. package/lib/DeconzAccessory/Light.js +42 -35
  14. package/lib/DeconzAccessory/Motion.js +51 -0
  15. package/lib/DeconzAccessory/Sensor.js +35 -0
  16. package/lib/DeconzAccessory/Temperature.js +63 -0
  17. package/lib/DeconzAccessory/Thermostat.js +50 -0
  18. package/lib/DeconzAccessory/WarningDevice.js +56 -0
  19. package/lib/DeconzAccessory/WindowCovering.js +47 -0
  20. package/lib/DeconzAccessory/index.js +145 -4
  21. package/lib/DeconzPlatform.js +6 -3
  22. package/lib/DeconzService/AirPressure.js +43 -0
  23. package/lib/DeconzService/AirQuality.js +20 -11
  24. package/lib/DeconzService/Alarm.js +13 -9
  25. package/lib/DeconzService/Battery.js +53 -0
  26. package/lib/DeconzService/Button.js +9 -2
  27. package/lib/DeconzService/CarbonMonoxide.js +38 -0
  28. package/lib/DeconzService/Consumption.js +65 -0
  29. package/lib/DeconzService/Contact.js +60 -0
  30. package/lib/DeconzService/Daylight.js +132 -0
  31. package/lib/DeconzService/DeviceSettings.js +12 -4
  32. package/lib/DeconzService/Flag.js +52 -0
  33. package/lib/DeconzService/GatewaySettings.js +1 -4
  34. package/lib/DeconzService/Humidity.js +37 -0
  35. package/lib/DeconzService/Leak.js +38 -0
  36. package/lib/DeconzService/Light.js +289 -280
  37. package/lib/DeconzService/LightLevel.js +54 -0
  38. package/lib/DeconzService/LightsResource.js +112 -0
  39. package/lib/DeconzService/Motion.js +101 -0
  40. package/lib/DeconzService/Outlet.js +76 -0
  41. package/lib/DeconzService/Power.js +83 -0
  42. package/lib/DeconzService/SensorsResource.js +96 -0
  43. package/lib/DeconzService/Smoke.js +38 -0
  44. package/lib/DeconzService/Status.js +53 -0
  45. package/lib/DeconzService/Switch.js +93 -0
  46. package/lib/DeconzService/Temperature.js +63 -0
  47. package/lib/DeconzService/Thermostat.js +175 -0
  48. package/lib/DeconzService/WarningDevice.js +68 -0
  49. package/lib/DeconzService/WindowCovering.js +139 -0
  50. package/lib/DeconzService/index.js +79 -25
  51. package/package.json +6 -5
  52. package/lib/Client/ApiError.js +0 -42
  53. package/lib/DeconzAccessory/Device.js +0 -69
  54. 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.Bridge
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',
@@ -139,6 +140,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
139
140
  primaryService: true,
140
141
  host: params.host
141
142
  })
143
+ this.manageLogLevel(this.service.characteristicDelegate('logLevel'))
142
144
 
143
145
  /** The service delegate for the Stateless Programmable Switch service.
144
146
  * @type {DeconzService.Button}
@@ -214,9 +216,6 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
214
216
  try {
215
217
  this.debug('initialising...')
216
218
  this.initialBeat = beat
217
- if (this.context.fullState != null) {
218
- this.analyseFullState(this.context.fullState, true)
219
- }
220
219
  await this.connect()
221
220
  this.initialised = true
222
221
  this.debug('initialised')
@@ -441,6 +440,9 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
441
440
  }
442
441
  try {
443
442
  try {
443
+ if (this.context.migration != null) {
444
+ await this.client.delete(this.context.migration)
445
+ }
444
446
  await this.client.deleteApiKey()
445
447
  } catch (error) {}
446
448
  this.values.apiKey = null
@@ -456,10 +458,12 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
456
458
  this.exposeErrors = {}
457
459
  this.context.blacklist = {}
458
460
  this.context.fullState = null
461
+ this.context.migration = null
459
462
  this.service.values.lights = false
460
463
  this.service.values.sensors = false
461
464
  this.service.values.groups = false
462
465
  this.service.values.schedules = false
466
+ this.service.values.logLevel = 2
463
467
  this.values.rtypes = []
464
468
  } catch (error) { this.error(error) }
465
469
  }
@@ -503,12 +507,12 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
503
507
  if (this.accessoryById[id] == null) {
504
508
  const device = this.deviceById[id]
505
509
  delete this.exposeErrorById[id]
506
- const { body, rtype } = device.resource
510
+ const { body } = device.resource
507
511
  this.log('%s: add accessory', body.name)
508
512
  let { serviceName } = device.resource
509
513
  if (DeconzAccessory[serviceName] == null) {
510
- this.warn('%s: %s: not yet supported %s type', body.name, body.type, rtype)
511
- serviceName = 'Device'
514
+ // this.warn('%s: %s: not yet supported %s type', body.name, body.type, rtype)
515
+ serviceName = 'Sensor'
512
516
  }
513
517
  const accessory = new DeconzAccessory[serviceName](this, device)
514
518
  this.accessoryById[id] = accessory
@@ -592,6 +596,9 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
592
596
  throw new RangeError(`${id}: unknown device ID`)
593
597
  }
594
598
  if (this.serviceById[id] == null) {
599
+ if (Object.keys(this.serviceById).length >= 97) {
600
+ return null
601
+ }
595
602
  const { resource, rpaths } = this.deviceById[id]
596
603
  const { body } = resource
597
604
  const service = new DeconzService.DeviceSettings(this, {
@@ -644,11 +651,14 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
644
651
  return
645
652
  }
646
653
  this.context.fullState.config = config
647
- if (this.service.values.lights || this.service.values.sensors) {
654
+ if (
655
+ this.service.values.lights || this.nDevicesByRtype.lights > 0 ||
656
+ this.service.values.sensors || this.nDevicesByRtype.sensors > 0
657
+ ) {
648
658
  this.context.fullState.lights = await this.client.get('/lights')
649
659
  this.context.fullState.sensors = await this.client.get('/sensors')
650
660
  }
651
- if (this.service.values.groups) {
661
+ if (this.service.values.groups || this.nDevicesByRtype.groups > 0) {
652
662
  this.context.fullState.groups = await this.client.get('/groups')
653
663
  this.context.fullState.groups[0] = await this.client.get('/groups/0')
654
664
  }
@@ -656,7 +666,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
656
666
  this.context.fullState.schedules = await this.client.get('/schedules')
657
667
  }
658
668
  }
659
- this.analyseFullState(this.context.fullState)
669
+ await this.analyseFullState(this.context.fullState)
660
670
  } catch (error) {
661
671
  this.error(error)
662
672
  } finally {
@@ -697,12 +707,12 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
697
707
  * accessories, corresponding to devices have been blacklisted.
698
708
  * @param {Object} fullState - The gateway full state, as returned by
699
709
  * {@link DeconzAccessory.Gateway#poll poll()}.
700
- * @param {boolean} [logUnsupportedResources=false] - Issue debug messsages
701
- * for unsupported resources.
710
+ * @param {Object} params - Parameters
711
+ * @param {boolean} [params.logUnsupportedResources=false] - Issue debug
712
+ * messsages for unsupported resources.
713
+ * @param {boolean} [params.analyseOnly=false]
702
714
  */
703
- analyseFullState (fullState, logUnsupported = false) {
704
- this.update(fullState.config)
705
-
715
+ async analyseFullState (fullState, params = {}) {
706
716
  /** Supported devices by device ID.
707
717
  *
708
718
  * Updated by
@@ -739,8 +749,10 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
739
749
  for (const rtype of rtypes) {
740
750
  this.deviceByRidByRtype[rtype] = {}
741
751
  for (const rid in fullState[rtype]) {
742
- const body = fullState[rtype][rid]
743
- this.analyseResource(rtype, rid, body, logUnsupported)
752
+ try {
753
+ const body = fullState[rtype][rid]
754
+ this.analyseResource(rtype, rid, body, params.logUnsupported)
755
+ } catch (error) { this.error(error) }
744
756
  }
745
757
  }
746
758
 
@@ -773,64 +785,74 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
773
785
  this.vdebug('%d %s devices', this.nDevicesByRtype[rtype], rtype)
774
786
  }
775
787
 
788
+ if (params.analyseOnly) {
789
+ return
790
+ }
791
+
792
+ this.update(fullState.config)
793
+
776
794
  let changed = false
777
795
 
778
796
  this.vdebug('analysing accessories...')
779
797
  for (const id in this.accessoryById) {
780
- if (
781
- this.deviceById[id] == null ||
782
- !this.values.rtypes.includes(this.deviceById[id].resource.rtype)
783
- ) {
784
- delete this.context.blacklist[id]
785
- this.deleteAccessory(id)
786
- this.deleteService(id)
787
- changed = true
788
- } else {
789
- /** Emitted when the gateway has been polled.
790
- * @event DeconzAccessory.Device#polled
791
- * @param {Deconz.Device} device - The updated device.
792
- */
793
- this.accessoryById[id].emit('polled', this.deviceById[id])
794
- }
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) }
795
814
  }
796
815
 
797
816
  this.vdebug('analysing services...')
798
817
  for (const id in this.serviceById) {
799
- if (
800
- this.deviceById[id] == null ||
801
- !this.values.rtypes.includes(this.deviceById[id].resource.rtype)
802
- ) {
803
- delete this.context.blacklist[id]
804
- delete this.exposeErrorById[id]
805
- this.deleteService(id)
806
- changed = true
807
- }
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) }
808
828
  }
809
829
 
810
830
  for (const rtype of this.values.rtypes) {
811
831
  this.vdebug('analysing %s devices...', rtype)
812
832
  const rids = Object.keys(this.deviceByRidByRtype[rtype]).sort()
813
833
  for (const rid of rids) {
814
- const { id } = this.deviceByRidByRtype[rtype][rid]
815
- if (this.context.blacklist[id] == null) {
816
- if (this.accessoryById[id] == null) {
817
- this.addAccessory(id)
818
- changed = true
819
- }
820
- if (this.serviceById[id] != null) {
821
- this.deleteService(id)
822
- changed = true
823
- }
824
- } else {
825
- if (this.serviceById[id] == null) {
826
- this.addService(id)
827
- changed = true
828
- }
829
- if (this.accessoryById[id] != null) {
830
- this.deleteAccessory(id)
831
- changed = true
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
+ }
832
854
  }
833
- }
855
+ } catch (error) { this.error(error) }
834
856
  }
835
857
  }
836
858
 
@@ -847,8 +869,22 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
847
869
  if (changed) {
848
870
  this.nResourcesMonitored = Object.keys(this.accessoryByRpath).length
849
871
  this.identify()
850
- this.vdebug('updating resourcelink...')
851
- // TOOD create resourcelink for Homebridge Hue migration
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.resourceByRpath).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.resourceByRpath).sort()
883
+ })
884
+ }
885
+ this.log(
886
+ 'migration: %s: %d resources', this.context.migration, this.nResources
887
+ )
852
888
  }
853
889
  }
854
890
 
@@ -861,7 +897,7 @@ class Gateway extends homebridgeLib.AccessoryDelegate {
861
897
  * `groups`, `lights`, or `sensors`.
862
898
  * @param {integer} rid - The resource ID of the resource.
863
899
  * @param {object} body - The body of the resource.
864
- * @param {boolean} logUnsupportedResources - Issue a debug message for
900
+ * @param {boolean} logUnsupported - Issue a debug message for
865
901
  * unsupported resources.
866
902
  */
867
903
  analyseResource (rtype, rid, body, logUnsupported) {
@@ -1,16 +1,17 @@
1
- // homebridge-deconz/lib/DeconzAccessory/Device.js
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 DeconzAccessory = require('.')
9
- const DeconzService = require('../DeconzService')
8
+ const homebridgeLib = require('homebridge-lib')
9
+ const DeconzAccessory = require('../DeconzAccessory')
10
10
 
11
- /** Delegate class for a HomeKit accessory,
12
- * corresponding to a Zigbee or virtual device on a deCONZ gateway,
13
- * that is not yet supported.
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,47 +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.service = new DeconzService.Light(this, device.resource)
28
+ this.addPropertyDelegate({
29
+ key: 'serviceName',
30
+ value: device.resource.capabilities.bri ? 'Light' : 'Outlet'
31
+ })
28
32
 
29
- this.settingsService = new DeconzService.DeviceSettings(this, {
30
- name: this.name + ' Settings',
31
- subtype: this.id,
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
37
 
37
- this
38
- .on('polled', (device) => {
39
- this.debug('%s: polled: %j', device.resource.rpath, device.resource.body)
40
- this.service.update(device.resource.body)
41
- this.service.checkAdaptiveLighting()
42
- })
43
- .on('changed', (rpath, body) => {
44
- if (rpath === device.resource.rpath) {
45
- this.debug('%s: changed: %j', rpath, body)
46
- this.service.update(body)
47
- }
48
- })
49
- .on('identify', this.identify)
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()
50
64
 
51
65
  setImmediate(() => {
52
66
  this.debug('initialised')
53
67
  this.emit('initialised')
54
68
  })
55
69
  }
56
-
57
- async identify () {
58
- super.identify()
59
- if (this.service != null) {
60
- await this.service.identify()
61
- }
62
- }
63
70
  }
64
71
 
65
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