homebridge-deconz 0.0.6 → 0.0.11

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 (58) hide show
  1. package/README.md +8 -0
  2. package/cli/deconz.js +980 -0
  3. package/config.schema.json +1 -1
  4. package/lib/Client/ApiError.js +42 -0
  5. package/lib/{DeconzClient.js → Deconz/ApiClient.js} +82 -158
  6. package/lib/Deconz/ApiError.js +42 -0
  7. package/lib/Deconz/ApiResponse.js +54 -0
  8. package/lib/Deconz/Device.js +100 -0
  9. package/lib/{DeconzDiscovery.js → Deconz/Discovery.js} +4 -3
  10. package/lib/Deconz/Resource.js +1206 -0
  11. package/lib/{DeconzWsClient.js → Deconz/WsClient.js} +59 -44
  12. package/lib/Deconz/index.js +21 -0
  13. package/lib/DeconzAccessory/Contact.js +54 -0
  14. package/lib/DeconzAccessory/Gateway.js +316 -374
  15. package/lib/DeconzAccessory/Light.js +72 -0
  16. package/lib/DeconzAccessory/Motion.js +51 -0
  17. package/lib/DeconzAccessory/Sensor.js +35 -0
  18. package/lib/DeconzAccessory/Temperature.js +63 -0
  19. package/lib/DeconzAccessory/Thermostat.js +50 -0
  20. package/lib/DeconzAccessory/WarningDevice.js +56 -0
  21. package/lib/DeconzAccessory/WindowCovering.js +47 -0
  22. package/lib/DeconzAccessory/index.js +216 -0
  23. package/lib/DeconzPlatform.js +8 -3
  24. package/lib/DeconzService/AirPressure.js +43 -0
  25. package/lib/DeconzService/AirQuality.js +20 -10
  26. package/lib/DeconzService/Alarm.js +16 -9
  27. package/lib/DeconzService/Battery.js +43 -0
  28. package/lib/DeconzService/Button.js +12 -2
  29. package/lib/DeconzService/CarbonMonoxide.js +38 -0
  30. package/lib/DeconzService/Consumption.js +65 -0
  31. package/lib/DeconzService/Contact.js +60 -0
  32. package/lib/DeconzService/Daylight.js +132 -0
  33. package/lib/DeconzService/DeviceSettings.js +13 -5
  34. package/lib/DeconzService/Flag.js +52 -0
  35. package/lib/DeconzService/GatewaySettings.js +8 -58
  36. package/lib/DeconzService/Humidity.js +37 -0
  37. package/lib/DeconzService/Leak.js +38 -0
  38. package/lib/DeconzService/Light.js +376 -0
  39. package/lib/DeconzService/LightLevel.js +54 -0
  40. package/lib/DeconzService/LightsResource.js +112 -0
  41. package/lib/DeconzService/Motion.js +101 -0
  42. package/lib/DeconzService/Outlet.js +76 -0
  43. package/lib/DeconzService/Power.js +83 -0
  44. package/lib/DeconzService/SensorsResource.js +96 -0
  45. package/lib/DeconzService/Smoke.js +38 -0
  46. package/lib/DeconzService/Status.js +53 -0
  47. package/lib/DeconzService/Switch.js +93 -0
  48. package/lib/DeconzService/Temperature.js +63 -0
  49. package/lib/DeconzService/Thermostat.js +175 -0
  50. package/lib/DeconzService/WarningDevice.js +68 -0
  51. package/lib/DeconzService/WindowCovering.js +139 -0
  52. package/lib/DeconzService/index.js +94 -0
  53. package/package.json +7 -4
  54. package/lib/DeconzAccessory/Device.js +0 -91
  55. package/lib/DeconzAccessory.js +0 -16
  56. package/lib/DeconzDevice.js +0 -245
  57. package/lib/DeconzService/Sensor.js +0 -58
  58. package/lib/DeconzService.js +0 -43
@@ -0,0 +1,101 @@
1
+ // homebridge-deconz/lib/DeconzService/Motion.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Motion extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.hap.MotionSensor
16
+ super(accessory, resource, params)
17
+
18
+ this.durationKey = resource.body.config.delay !== null ? 'delay' : 'duration'
19
+ this.sensitivitymax = resource.body.config.sensitivitymax
20
+
21
+ this.addCharacteristicDelegate({
22
+ key: 'motion',
23
+ Characteristic: this.Characteristics.hap.MotionDetected,
24
+ value: 0
25
+ })
26
+
27
+ this.addCharacteristicDelegate({
28
+ key: 'sensitivity',
29
+ Characteristic: this.Characteristics.eve.Sensitivity,
30
+ value: this.Characteristics.hap.TemperatureDisplayUnits.CELSIUS
31
+ }).on('didSet', async (value, fromHomeKit) => {
32
+ if (fromHomeKit) {
33
+ const sensitivity = value === this.Characteristics.eve.Sensitivity.HIGH
34
+ ? this.sensitivitymax
35
+ : value === this.Characteristics.eve.Sensitivity.LOW
36
+ ? 0
37
+ : Math.round(this.sensitivitymax / 2)
38
+ await this.put('/config', { sensitivity: sensitivity })
39
+ }
40
+ })
41
+
42
+ this.addCharacteristicDelegate({
43
+ key: 'duration',
44
+ Characteristic: this.Characteristics.eve.Duration,
45
+ unit: 's'
46
+ }).on('didSet', async (value, fromHomeKit) => {
47
+ if (fromHomeKit) {
48
+ const config = {}
49
+ config[this.durationKey] =
50
+ value === this.Characteristics.eve.Duration.VALID_VALUES[0] ? 0 : value
51
+ await this.put('/config', config)
52
+ }
53
+ })
54
+
55
+ this.addCharacteristicDelegate({
56
+ key: 'lastActivation',
57
+ Characteristic: this.Characteristics.eve.LastActivation,
58
+ silent: true
59
+ })
60
+
61
+ this.addCharacteristicDelegates()
62
+
63
+ this.update(resource.body)
64
+ }
65
+
66
+ updateState (state) {
67
+ if (state.presence != null) {
68
+ this.values.motion = state.presence
69
+ }
70
+ if (state.vibration != null) {
71
+ this.values.motion = state.vibration
72
+ }
73
+ if (state.tampered != null) {
74
+ this.values.tampered = state.tampered
75
+ }
76
+ super.updateState(state)
77
+ }
78
+
79
+ updateConfig (config) {
80
+ if (config[this.durationKey] != null) {
81
+ let duration
82
+ for (const value of this.Characteristics.eve.Duration.VALID_VALUES) {
83
+ duration = value
84
+ if (config[this.durationKey] <= value) {
85
+ break
86
+ }
87
+ }
88
+ this.values.duration = duration
89
+ }
90
+ if (config.sensitivity != null) {
91
+ this.values.sensitivity = config.sensitivity === this.sensitivitymax
92
+ ? this.Characteristics.eve.Sensitivity.HIGH
93
+ : config.sensitivity === 0
94
+ ? this.Characteristics.eve.Sensitivity.LOW
95
+ : this.Characteristics.eve.Sensitivity.MEDIUM
96
+ }
97
+ super.updateConfig(config)
98
+ }
99
+ }
100
+
101
+ module.exports = Motion
@@ -0,0 +1,76 @@
1
+ // homebridge-deconz/lib/DeconzService/Outlet.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ class Outlet extends DeconzService.LightsResource {
11
+ constructor (accessory, resource, params = {}) {
12
+ params.Service = accessory.Services.hap.Outlet
13
+ super(accessory, resource, params)
14
+
15
+ this.addCharacteristicDelegate({
16
+ key: 'on',
17
+ Characteristic: this.Characteristics.hap.On,
18
+ value: this.capabilities.on
19
+ ? this.resource.body.state.on
20
+ : this.resource.body.state.all_on
21
+ }).on('didSet', (value, fromHomeKit) => {
22
+ if (fromHomeKit) {
23
+ this.put({ on: value })
24
+ }
25
+ })
26
+
27
+ if (!this.capabilities.on) {
28
+ this.addCharacteristicDelegate({
29
+ key: 'anyOn',
30
+ Characteristic: this.Characteristics.my.AnyOn,
31
+ value: this.resource.body.state.any_on
32
+ }).on('didSet', (value, fromHomeKit) => {
33
+ if (fromHomeKit) {
34
+ this.put({ on: value })
35
+ }
36
+ })
37
+ }
38
+
39
+ this.addCharacteristicDelegate({
40
+ key: 'outletInUse',
41
+ Characteristic: this.Characteristics.hap.OutletInUse,
42
+ value: 1
43
+ })
44
+
45
+ this.addCharacteristicDelegates()
46
+
47
+ this.settings = {
48
+ resetTimeout: this.platform.config.resetTimeout,
49
+ waitTimeUpdate: this.platform.config.waitTimeUpdate,
50
+ wallSwitch: false
51
+ }
52
+ }
53
+
54
+ updateState (state, rpath) {
55
+ for (const key in state) {
56
+ const value = state[key]
57
+ this.resource.body.state[key] = value
58
+ switch (key) {
59
+ case 'all_on':
60
+ this.values.on = value
61
+ break
62
+ case 'any_on':
63
+ this.values.anyOn = value
64
+ break
65
+ case 'on':
66
+ this.values.on = value
67
+ break
68
+ default:
69
+ break
70
+ }
71
+ }
72
+ super.updateState(state)
73
+ }
74
+ }
75
+
76
+ module.exports = Outlet
@@ -0,0 +1,83 @@
1
+ // homebridge-deconz/lib/DeconzService/Power.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const Deconz = require('../Deconz')
9
+ const DeconzService = require('../DeconzService')
10
+
11
+ const { dateToString } = Deconz.ApiClient
12
+
13
+ /**
14
+ * @memberof DeconzService
15
+ */
16
+ class Power extends DeconzService.SensorsResource {
17
+ static addResource (service, resource) {
18
+ if (service.values.currentConsumption === undefined) {
19
+ service.addCharacteristicDelegate({
20
+ key: 'currentConsumption',
21
+ Characteristic: service.Characteristics.eve.CurrentConsumption,
22
+ unit: ' W'
23
+ })
24
+ }
25
+
26
+ if (resource.body.state.current !== undefined) {
27
+ service.addCharacteristicDelegate({
28
+ key: 'electricCurrent',
29
+ Characteristic: service.Characteristics.eve.ElectricCurrent,
30
+ unit: ' A'
31
+ })
32
+ }
33
+
34
+ if (resource.body.state.voltage !== undefined) {
35
+ service.addCharacteristicDelegate({
36
+ key: 'voltage',
37
+ Characteristic: service.Characteristics.eve.Voltage,
38
+ unit: ' V'
39
+ })
40
+ }
41
+
42
+ if (service.values.lastUpdated === undefined) {
43
+ service.addCharacteristicDelegate({
44
+ key: 'lastUpdated',
45
+ Characteristic: service.Characteristics.my.LastUpdated,
46
+ silent: true
47
+ })
48
+ }
49
+ }
50
+
51
+ static updateResourceState (service, state) {
52
+ if (state.power != null) {
53
+ service.values.currentConsumption = state.power
54
+ }
55
+ if (state.current != null) {
56
+ service.values.electricCurrent = state.current / 1000
57
+ }
58
+ if (state.voltage != null) {
59
+ service.values.voltage = state.voltage
60
+ }
61
+ if (state.lastupdated != null) {
62
+ service.values.lastUpdated = dateToString(state.lastupdated)
63
+ }
64
+ }
65
+
66
+ constructor (accessory, resource, params = {}) {
67
+ params.Service = accessory.Services.my.Resource
68
+ super(accessory, resource, params)
69
+
70
+ Power.addResource(this, resource)
71
+
72
+ super.addCharacteristicDelegates()
73
+
74
+ this.update(resource.body)
75
+ }
76
+
77
+ updateState (state) {
78
+ Power.updateResourceState(this.service, state)
79
+ super.updateState(state)
80
+ }
81
+ }
82
+
83
+ module.exports = Power
@@ -0,0 +1,96 @@
1
+ // homebridge-deconz/lib/DeconzService/SensorsResource.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const Deconz = require('../Deconz')
9
+ const DeconzService = require('../DeconzService')
10
+
11
+ const { dateToString, HttpError } = Deconz.ApiClient
12
+
13
+ /**
14
+ * @memberof DeconzService
15
+ */
16
+ class SensorsResource extends DeconzService {
17
+ // constructor (accessory, resource, params) {
18
+ // super(accessory, resource, params)
19
+ // }
20
+
21
+ addCharacteristicDelegates (params = {}) {
22
+ if (!params.noLastUpdated) {
23
+ this.addCharacteristicDelegate({
24
+ key: 'lastUpdated',
25
+ Characteristic: this.Characteristics.my.LastUpdated,
26
+ silent: true
27
+ })
28
+ }
29
+
30
+ this.addCharacteristicDelegate({
31
+ key: 'enabled',
32
+ Characteristic: this.Characteristics.my.Enabled
33
+ }).on('didSet', (value) => {
34
+ this.values.statusActive = value
35
+ })
36
+
37
+ this.addCharacteristicDelegate({
38
+ key: 'statusActive',
39
+ Characteristic: this.Characteristics.hap.StatusActive
40
+ })
41
+
42
+ if (this.resource.body.config.reachable !== undefined) {
43
+ this.addCharacteristicDelegate({
44
+ key: 'statusFault',
45
+ Characteristic: this.Characteristics.hap.StatusFault
46
+ })
47
+ }
48
+
49
+ if (this.resource.body.state.tampered !== undefined && !params.noTampered) {
50
+ this.addCharacteristicDelegate({
51
+ key: 'tampered',
52
+ Characteristic: this.Characteristics.hap.StatusTampered
53
+ })
54
+ }
55
+ }
56
+
57
+ async identify () {
58
+ if (this.resource.body.config.alert) {
59
+ return this.put('/config', { alert: 'select' })
60
+ }
61
+ }
62
+
63
+ updateState (state) {
64
+ if (state.lastupdated != null) {
65
+ this.values.lastUpdated = dateToString(state.lastupdated)
66
+ }
67
+ if (state.tampered != null) {
68
+ this.values.tampered = state.tampered
69
+ ? this.Characteristics.hap.StatusTampered.TAMPERED
70
+ : this.Characteristics.hap.StatusTampered.NOT_TAMPERED
71
+ }
72
+ }
73
+
74
+ updateConfig (config) {
75
+ if (config.on != null) {
76
+ this.values.enabled = !!config.on
77
+ }
78
+ if (config.reachable != null) {
79
+ this.values.statusFault = config.reachable
80
+ ? this.Characteristics.hap.StatusFault.NO_FAULT
81
+ : this.Characteristics.hap.StatusFault.GENERAL_FAULT
82
+ }
83
+ }
84
+
85
+ async put (resource, body) {
86
+ try {
87
+ await this.client.put(this.rpath + resource, body)
88
+ } catch (error) {
89
+ if (!(error instanceof HttpError)) {
90
+ this.warn(error)
91
+ }
92
+ }
93
+ }
94
+ }
95
+
96
+ module.exports = SensorsResource
@@ -0,0 +1,38 @@
1
+ // homebridge-deconz/lib/DeconzService/Smoke.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Smoke extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.hap.SmokeSensor
16
+ super(accessory, resource, params)
17
+
18
+ this.addCharacteristicDelegate({
19
+ key: 'fire',
20
+ Characteristic: this.Characteristics.hap.SmokeDetected
21
+ })
22
+
23
+ super.addCharacteristicDelegates(params)
24
+
25
+ this.update(resource.body, resource.rpath)
26
+ }
27
+
28
+ updateState (state) {
29
+ if (state.fire != null || state.test != null) {
30
+ this.values.fire = state.fire || state.test
31
+ ? this.Characteristics.hap.SmokeDetected.SMOKE_DETECTED
32
+ : this.Characteristics.hap.SmokeDetected.SMOKE_NOT_DETECTED
33
+ }
34
+ super.updateState(state)
35
+ }
36
+ }
37
+
38
+ module.exports = Smoke
@@ -0,0 +1,53 @@
1
+ // homebridge-deconz/lib/DeconzService/Status.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Status extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.my.Status
16
+ super(accessory, resource, params)
17
+
18
+ if (resource.capabilities.readonly) {
19
+ this.addCharacteristicDelegate({
20
+ key: 'status',
21
+ Characteristic: this.Characteristics.my.Status,
22
+ props: {
23
+ perms: [
24
+ this.Characteristic.Perms.READ, this.Characteristic.Perms.NOTIFY
25
+ ]
26
+ }
27
+ })
28
+ } else {
29
+ this.addCharacteristicDelegate({
30
+ key: 'status',
31
+ Characteristic: this.Characteristics.my.Status,
32
+ props: resource.capabilities.props
33
+ }).on('didSet', async (value, fromHomeKit) => {
34
+ if (fromHomeKit) {
35
+ await this.put('/state', { status: value })
36
+ }
37
+ })
38
+ }
39
+
40
+ this.addCharacteristicDelegates()
41
+
42
+ this.update(resource.body)
43
+ }
44
+
45
+ updateState (state) {
46
+ if (state.status != null) {
47
+ this.values.status = state.status
48
+ }
49
+ super.updateState(state)
50
+ }
51
+ }
52
+
53
+ module.exports = Status
@@ -0,0 +1,93 @@
1
+ // homebridge-deconz/lib/DeconzService/Switch.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Switch extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.hap.ServiceLabel
16
+ super(accessory, resource, params)
17
+
18
+ this.addCharacteristicDelegate({
19
+ key: 'namespace',
20
+ Characteristic: this.Characteristics.hap.ServiceLabelNamespace,
21
+ value: resource.capabilities.namespace
22
+ })
23
+
24
+ this.addCharacteristicDelegates({ noLastUpdated: true })
25
+
26
+ this.buttonResources = {}
27
+ this.buttonServices = {}
28
+ this.hasRepeat = false
29
+ }
30
+
31
+ createButtonServices (resource) {
32
+ this.buttonResources[resource.rpath] = {
33
+ buttonEvent: resource.body.state.buttonevent,
34
+ lastUpdated: '',
35
+ toButtonEvent: resource.capabilities.toButtonEvent
36
+ }
37
+ for (const i in resource.capabilities.buttons) {
38
+ const { label, events, hasRepeat } = resource.capabilities.buttons[i]
39
+ if (hasRepeat) {
40
+ this.hasRepeat = hasRepeat
41
+ }
42
+ this.buttonServices[i] = new DeconzService.Button(this.accessoryDelegate, {
43
+ name: this.name + ' ' + label,
44
+ button: Number(i),
45
+ events: events,
46
+ hasRepeat: hasRepeat
47
+ })
48
+ }
49
+ }
50
+
51
+ updateState (state, rpath) {
52
+ const buttonResource = this.buttonResources[rpath]
53
+ if (buttonResource.lastUpdated === '') {
54
+ buttonResource.lastUpdated = state.lastupdated
55
+ } else if (
56
+ state.lastupdated != null &&
57
+ state.lastupdated !== buttonResource.lastUpdated
58
+ ) {
59
+ buttonResource.lastUpdated = state.lastupdated
60
+ const oldValue = buttonResource.buttonEvent
61
+ if (state.buttonevent != null) {
62
+ buttonResource.buttonEvent = buttonResource.toButtonEvent == null
63
+ ? state.buttonevent
64
+ : buttonResource.toButtonEvent(state.buttonevent)
65
+ }
66
+ // TODO handle repeat
67
+ this.updateButtonEvent(
68
+ buttonResource.buttonEvent, oldValue,
69
+ this.accessoryDelegate.settingsService.values.repeat
70
+ )
71
+ }
72
+ super.updateState(state)
73
+ }
74
+
75
+ updateConfig (config) {
76
+ // TODO handle change in devicemode
77
+ super.updateConfig(config)
78
+ }
79
+
80
+ updateButtonEvent (value, oldValue, repeat) {
81
+ const i = Math.floor(value / 1000)
82
+ if (this.buttonServices[i] != null) {
83
+ this.buttonServices[i].update(value, oldValue, repeat)
84
+ }
85
+ }
86
+
87
+ async identify () {
88
+ this.debug('hasRepeat: %j', this.hasRepeat)
89
+ return super.identify()
90
+ }
91
+ }
92
+
93
+ module.exports = Switch
@@ -0,0 +1,63 @@
1
+ // homebridge-deconz/lib/DeconzService/Temperature.js
2
+ // Copyright © 2022 Erik Baauw. All rights reserved.
3
+ //
4
+ // Homebridge plugin for deCONZ.
5
+
6
+ 'use strict'
7
+
8
+ const DeconzService = require('../DeconzService')
9
+
10
+ /**
11
+ * @memberof DeconzService
12
+ */
13
+ class Temperature extends DeconzService.SensorsResource {
14
+ constructor (accessory, resource, params = {}) {
15
+ params.Service = accessory.Services.hap.TemperatureSensor
16
+ super(accessory, resource, params)
17
+
18
+ this.addCharacteristicDelegate({
19
+ key: 'temperature',
20
+ Characteristic: this.Characteristics.hap.CurrentTemperature,
21
+ unit: '°C',
22
+ props: { minValue: -40, maxValue: 100, minStep: 0.1 },
23
+ value: 0
24
+ })
25
+
26
+ this.addCharacteristicDelegate({
27
+ key: 'offset',
28
+ Characteristic: this.Characteristics.my.Offset,
29
+ unit: '°C',
30
+ value: 0
31
+ }).on('didSet', async (value, fromHomeKit) => {
32
+ if (fromHomeKit) {
33
+ await this.put('/config', { offset: Math.round(value * 100) })
34
+ }
35
+ })
36
+
37
+ this.addCharacteristicDelegate({
38
+ key: 'displayUnits',
39
+ Characteristic: this.Characteristics.hap.TemperatureDisplayUnits,
40
+ value: this.Characteristics.hap.TemperatureDisplayUnits.CELSIUS
41
+ })
42
+
43
+ this.addCharacteristicDelegates()
44
+
45
+ this.update(resource.body, resource.rpath)
46
+ }
47
+
48
+ updateState (state) {
49
+ if (state.temperature != null) {
50
+ this.values.temperature = Math.round(state.temperature / 10) / 10
51
+ }
52
+ super.updateState(state)
53
+ }
54
+
55
+ updateConfig (config) {
56
+ if (config.offset != null) {
57
+ this.values.offset = Math.round(config.offset / 10) / 10
58
+ }
59
+ super.updateConfig(config)
60
+ }
61
+ }
62
+
63
+ module.exports = Temperature