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.
Files changed (53) hide show
  1. package/README.md +3 -6
  2. package/cli/deconz.js +12 -0
  3. package/config.schema.json +1 -0
  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 +751 -25
  11. package/lib/DeconzAccessory/Contact.js +54 -0
  12. package/lib/DeconzAccessory/Gateway.js +102 -66
  13. package/lib/DeconzAccessory/Light.js +42 -37
  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 +144 -2
  21. package/lib/DeconzPlatform.js +5 -2
  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 +11 -0
  32. package/lib/DeconzService/Flag.js +52 -0
  33. package/lib/DeconzService/Humidity.js +37 -0
  34. package/lib/DeconzService/Leak.js +38 -0
  35. package/lib/DeconzService/Light.js +122 -172
  36. package/lib/DeconzService/LightLevel.js +54 -0
  37. package/lib/DeconzService/LightsResource.js +112 -0
  38. package/lib/DeconzService/Motion.js +101 -0
  39. package/lib/DeconzService/Outlet.js +76 -0
  40. package/lib/DeconzService/Power.js +83 -0
  41. package/lib/DeconzService/SensorsResource.js +96 -0
  42. package/lib/DeconzService/Smoke.js +38 -0
  43. package/lib/DeconzService/Status.js +53 -0
  44. package/lib/DeconzService/Switch.js +93 -0
  45. package/lib/DeconzService/Temperature.js +63 -0
  46. package/lib/DeconzService/Thermostat.js +175 -0
  47. package/lib/DeconzService/WarningDevice.js +68 -0
  48. package/lib/DeconzService/WindowCovering.js +162 -0
  49. package/lib/DeconzService/index.js +79 -25
  50. package/package.json +6 -5
  51. package/lib/Client/ApiError.js +0 -42
  52. package/lib/DeconzAccessory/Device.js +0 -69
  53. 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',
@@ -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, rtype } = device.resource
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 = 'Device'
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 (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
+ ) {
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 {boolean} [logUnsupportedResources=false] - Issue debug messsages
702
- * 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]
703
714
  */
704
- analyseFullState (fullState, logUnsupported = false) {
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
- const body = fullState[rtype][rid]
744
- 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) }
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
- if (
782
- this.deviceById[id] == null ||
783
- !this.values.rtypes.includes(this.deviceById[id].resource.rtype)
784
- ) {
785
- delete this.context.blacklist[id]
786
- this.deleteAccessory(id)
787
- this.deleteService(id)
788
- changed = true
789
- } else {
790
- /** Emitted when the gateway has been polled.
791
- * @event DeconzAccessory.Device#polled
792
- * @param {Deconz.Device} device - The updated device.
793
- */
794
- this.accessoryById[id].emit('polled', this.deviceById[id])
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
- if (
801
- this.deviceById[id] == null ||
802
- !this.values.rtypes.includes(this.deviceById[id].resource.rtype)
803
- ) {
804
- delete this.context.blacklist[id]
805
- delete this.exposeErrorById[id]
806
- this.deleteService(id)
807
- changed = true
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
- const { id } = this.deviceByRidByRtype[rtype][rid]
816
- if (this.context.blacklist[id] == null) {
817
- if (this.accessoryById[id] == null) {
818
- this.addAccessory(id)
819
- changed = true
820
- }
821
- if (this.serviceById[id] != null) {
822
- this.deleteService(id)
823
- changed = true
824
- }
825
- } else {
826
- if (this.serviceById[id] == null) {
827
- this.addService(id)
828
- changed = true
829
- }
830
- if (this.accessoryById[id] != null) {
831
- this.deleteAccessory(id)
832
- 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
+ }
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.vdebug('updating resourcelink...')
852
- // 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.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} logUnsupportedResources - Issue a debug message for
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/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,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.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
- this.manageLogLevel(this.settingsService.characteristicDelegate('logLevel'))
37
37
 
38
- this
39
- .on('polled', (device) => {
40
- this.debug(
41
- '%s: polled: %j', device.rpaths.join(', '), device.resource.body
42
- )
43
- this.service.update(device.resource.body)
44
- })
45
- .on('changed', (rpath, body) => {
46
- if (rpath === device.resource.rpath) {
47
- this.debug('%s: changed: %j', rpath, body)
48
- this.service.update(body)
49
- }
50
- })
51
- .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()
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