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,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
|
@@ -0,0 +1,175 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/Thermostat.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 Thermostat extends DeconzService.SensorsResource {
|
14
|
+
constructor (accessory, resource, params = {}) {
|
15
|
+
params.Service = accessory.Services.hap.Thermostat
|
16
|
+
super(accessory, resource, params)
|
17
|
+
|
18
|
+
this.addCharacteristicDelegate({
|
19
|
+
key: 'currentTemperature',
|
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: 'targetTemperature',
|
28
|
+
Characteristic: this.Characteristics.hap.TargetTemperature,
|
29
|
+
unit: '°C',
|
30
|
+
props: { minValue: 5, maxValue: 30, minStep: 0.5 },
|
31
|
+
value: 0
|
32
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
33
|
+
if (fromHomeKit) {
|
34
|
+
await this.put('/config', { heatsetpoint: Math.round(value * 100) })
|
35
|
+
}
|
36
|
+
})
|
37
|
+
|
38
|
+
if (resource.body.state.valve !== undefined) {
|
39
|
+
this.addCharacteristicDelegate({
|
40
|
+
key: 'valvePosition',
|
41
|
+
Characteristic: this.Characteristics.eve.ValvePosition,
|
42
|
+
unit: '%'
|
43
|
+
})
|
44
|
+
}
|
45
|
+
|
46
|
+
this.addCharacteristicDelegate({
|
47
|
+
key: 'currentState',
|
48
|
+
Characteristic: this.Characteristics.hap.CurrentHeatingCoolingState,
|
49
|
+
props: {
|
50
|
+
validValues: [
|
51
|
+
this.Characteristics.hap.CurrentHeatingCoolingState.OFF,
|
52
|
+
this.Characteristics.hap.CurrentHeatingCoolingState.HEAT
|
53
|
+
]
|
54
|
+
}
|
55
|
+
})
|
56
|
+
|
57
|
+
this.addCharacteristicDelegate({
|
58
|
+
key: 'targetState',
|
59
|
+
Characteristic: this.Characteristics.hap.TargetHeatingCoolingState,
|
60
|
+
props: {
|
61
|
+
validValues: [
|
62
|
+
this.Characteristics.hap.TargetHeatingCoolingState.OFF,
|
63
|
+
this.Characteristics.hap.TargetHeatingCoolingState.HEAT
|
64
|
+
]
|
65
|
+
}
|
66
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
67
|
+
if (fromHomeKit) {
|
68
|
+
await this.put('/mode', {
|
69
|
+
mode: value === this.Characteristics.hap.TargetHeatingCoolingState.OFF
|
70
|
+
? 'off'
|
71
|
+
: this.capabilities.heatValue
|
72
|
+
})
|
73
|
+
}
|
74
|
+
})
|
75
|
+
|
76
|
+
this.addCharacteristicDelegate({
|
77
|
+
key: 'offset',
|
78
|
+
Characteristic: this.Characteristics.my.Offset,
|
79
|
+
unit: '°C',
|
80
|
+
value: 0
|
81
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
82
|
+
if (fromHomeKit) {
|
83
|
+
await this.put('/config', { offset: Math.round(value * 100) })
|
84
|
+
}
|
85
|
+
})
|
86
|
+
|
87
|
+
this.addCharacteristicDelegate({
|
88
|
+
key: 'displayUnits',
|
89
|
+
Characteristic: this.Characteristics.hap.TemperatureDisplayUnits,
|
90
|
+
value: this.Characteristics.hap.TemperatureDisplayUnits.CELSIUS
|
91
|
+
})
|
92
|
+
|
93
|
+
this.addCharacteristicDelegate({
|
94
|
+
key: 'programData',
|
95
|
+
Characteristic: this.Characteristics.eve.ProgramData,
|
96
|
+
silent: true,
|
97
|
+
value: Buffer.from('ff04f6', 'hex').toString('base64')
|
98
|
+
})
|
99
|
+
|
100
|
+
this.addCharacteristicDelegate({
|
101
|
+
key: 'programCommand',
|
102
|
+
Characteristic: this.Characteristics.eve.ProgramCommand,
|
103
|
+
silent: true
|
104
|
+
})
|
105
|
+
|
106
|
+
if (resource.body.config.displayflipped !== undefined) {
|
107
|
+
this.addCharacteristicDelegate({
|
108
|
+
key: 'imageMirroring',
|
109
|
+
Characteristic: this.Characteristics.hap.ImageMirroring
|
110
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
111
|
+
if (fromHomeKit) {
|
112
|
+
await this.put('/config', { displayflipped: value })
|
113
|
+
}
|
114
|
+
})
|
115
|
+
}
|
116
|
+
|
117
|
+
if (resource.body.config.locked !== undefined) {
|
118
|
+
this.addCharacteristicDelegate({
|
119
|
+
key: 'lockPhysicalControls',
|
120
|
+
Characteristic: this.Characteristics.hap.LockPhysicalControls
|
121
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
122
|
+
if (fromHomeKit) {
|
123
|
+
await this.put('/config', {
|
124
|
+
locked: value === this.Characteristics.hap.LockPhysicalControls
|
125
|
+
.CONTROL_LOCK_ENABLED
|
126
|
+
})
|
127
|
+
}
|
128
|
+
})
|
129
|
+
}
|
130
|
+
|
131
|
+
super.addCharacteristicDelegates()
|
132
|
+
|
133
|
+
this.update(resource.body, resource.rpath)
|
134
|
+
}
|
135
|
+
|
136
|
+
updateState (state) {
|
137
|
+
if (state.on != null) {
|
138
|
+
this.values.currentState = state.on
|
139
|
+
? this.Characteristics.hap.CurrentHeatingCoolingState.HEAT
|
140
|
+
: this.Characteristics.hap.CurrentHeatingCoolingState.OFF
|
141
|
+
}
|
142
|
+
if (state.temperature != null) {
|
143
|
+
this.values.currentTemperature = Math.round(state.temperature / 10) / 10
|
144
|
+
}
|
145
|
+
if (state.valve != null) {
|
146
|
+
this.values.valvePosition = Math.round(state.valve / 2.55)
|
147
|
+
}
|
148
|
+
super.updateState(state)
|
149
|
+
}
|
150
|
+
|
151
|
+
updateConfig (config) {
|
152
|
+
if (config.displayflipped != null) {
|
153
|
+
this.values.imageMirroring = config.displayflipped
|
154
|
+
}
|
155
|
+
if (config.heatsetpoint != null) {
|
156
|
+
this.values.targetTemperature = Math.round(config.heatsetpoint / 50) / 2
|
157
|
+
}
|
158
|
+
if (config.locked != null) {
|
159
|
+
this.values.lockPhysicalControls = config.locked
|
160
|
+
? this.Characteristics.hap.LockPhysicalControls.CONTROL_LOCK_ENABLED
|
161
|
+
: this.Characteristics.hap.LockPhysicalControls.CONTROL_LOCK_DISABLED
|
162
|
+
}
|
163
|
+
if (config.mode != null) {
|
164
|
+
this.values.targetState = config.mode === 'off'
|
165
|
+
? this.Characteristics.hap.TargetHeatingCoolingState.OFF
|
166
|
+
: this.Characteristics.hap.TargetHeatingCoolingState.HEAT
|
167
|
+
}
|
168
|
+
if (config.offset != null) {
|
169
|
+
this.values.offset = Math.round(config.offset / 10) / 10
|
170
|
+
}
|
171
|
+
super.updateConfig(config)
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
module.exports = Thermostat
|
@@ -0,0 +1,68 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/WarningDevice.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 WarningDevice 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: false
|
19
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
20
|
+
if (fromHomeKit) {
|
21
|
+
if (this.timer != null) {
|
22
|
+
clearTimeout(this.timer)
|
23
|
+
delete this.timer
|
24
|
+
}
|
25
|
+
const onTime = this.values.duration > 0 ? this.values.duration : 1
|
26
|
+
let body = { alert: 'none' }
|
27
|
+
if (value) {
|
28
|
+
if (this.values.mute) {
|
29
|
+
body = { alert: 'blink', ontime: onTime }
|
30
|
+
} else if (this.values.duration === 0) {
|
31
|
+
body = { alert: 'select' }
|
32
|
+
} else {
|
33
|
+
body = { alert: 'lselect', ontime: onTime }
|
34
|
+
}
|
35
|
+
}
|
36
|
+
this.put(body)
|
37
|
+
if (value) {
|
38
|
+
this.timer = setTimeout(() => {
|
39
|
+
this.values.on = false
|
40
|
+
}, onTime * 1000)
|
41
|
+
}
|
42
|
+
}
|
43
|
+
})
|
44
|
+
|
45
|
+
this.addCharacteristicDelegate({
|
46
|
+
key: 'duration',
|
47
|
+
Characteristic: this.Characteristics.hap.SetDuration
|
48
|
+
})
|
49
|
+
|
50
|
+
this.addCharacteristicDelegate({
|
51
|
+
key: 'mute',
|
52
|
+
Characteristic: this.Characteristics.hap.Mute
|
53
|
+
})
|
54
|
+
|
55
|
+
this.addCharacteristicDelegates()
|
56
|
+
|
57
|
+
this.update(resource.body, resource.rpath)
|
58
|
+
}
|
59
|
+
|
60
|
+
updateState (state, rpath) {
|
61
|
+
if (state.on != null) {
|
62
|
+
this.values.on = state.on
|
63
|
+
}
|
64
|
+
super.updateState(state)
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
module.exports = WarningDevice
|
@@ -0,0 +1,162 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/WindowCovering.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 DeconzService = require('../DeconzService')
|
10
|
+
|
11
|
+
const { timeout } = homebridgeLib
|
12
|
+
|
13
|
+
class WindowCovering extends DeconzService.LightsResource {
|
14
|
+
constructor (accessory, resource, params = {}) {
|
15
|
+
params.Service = accessory.Services.hap.WindowCovering
|
16
|
+
super(accessory, resource, params)
|
17
|
+
|
18
|
+
this.addCharacteristicDelegate({
|
19
|
+
key: 'currentPosition',
|
20
|
+
Characteristic: this.Characteristics.hap.CurrentPosition,
|
21
|
+
unit: '%'
|
22
|
+
})
|
23
|
+
|
24
|
+
this.addCharacteristicDelegate({
|
25
|
+
key: 'targetPosition',
|
26
|
+
Characteristic: this.Characteristics.hap.TargetPosition,
|
27
|
+
unit: '%'
|
28
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
29
|
+
if (!fromHomeKit) {
|
30
|
+
return
|
31
|
+
}
|
32
|
+
this.values.targetPosition = Math.round(this.values.targetPosition / 5) * 5
|
33
|
+
await this.setPosition()
|
34
|
+
})
|
35
|
+
|
36
|
+
this.addCharacteristicDelegate({
|
37
|
+
key: 'positionState',
|
38
|
+
Characteristic: this.Characteristics.hap.PositionState,
|
39
|
+
value: this.Characteristics.hap.PositionState.STOPPED
|
40
|
+
}).on('didSet', (value) => {
|
41
|
+
if (value === this.Characteristics.hap.PositionState.STOPPED) {
|
42
|
+
this.values.targetPosition = this.values.currentPosition
|
43
|
+
}
|
44
|
+
})
|
45
|
+
|
46
|
+
this.addCharacteristicDelegate({
|
47
|
+
key: 'holdPosition',
|
48
|
+
Characteristic: this.Characteristics.hap.HoldPosition
|
49
|
+
}).on('didSet', () => {
|
50
|
+
this.put({ stop: true })
|
51
|
+
this.values.positionState = this.Characteristics.hap.PositionState.STOPPED
|
52
|
+
})
|
53
|
+
|
54
|
+
if (this.venetianBlind) {
|
55
|
+
this.addCharacteristicDelegate({
|
56
|
+
key: 'closeUpwards',
|
57
|
+
Characteristic: this.Characteristics.my.CloseUpwards
|
58
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
59
|
+
if (!fromHomeKit) {
|
60
|
+
return
|
61
|
+
}
|
62
|
+
await this.setPosition()
|
63
|
+
})
|
64
|
+
}
|
65
|
+
|
66
|
+
if (resource.capabilities.maxSpeed != null) {
|
67
|
+
this.addCharacteristicDelegate({
|
68
|
+
key: 'motorSpeed',
|
69
|
+
Characteristic: this.Characteristics.my.MotorSpeed,
|
70
|
+
unit: '',
|
71
|
+
props: {
|
72
|
+
unit: '',
|
73
|
+
minValue: 0,
|
74
|
+
maxValue: resource.capabilities.maxSpeed,
|
75
|
+
minStep: 1
|
76
|
+
}
|
77
|
+
}).on('didSet', async (value, fromHomeKit) => {
|
78
|
+
if (!fromHomeKit) {
|
79
|
+
return
|
80
|
+
}
|
81
|
+
await this.put({ speed: value })
|
82
|
+
})
|
83
|
+
}
|
84
|
+
|
85
|
+
if (resource.capabilities.positionChange) {
|
86
|
+
this.addCharacteristicDelegate({
|
87
|
+
key: 'positionChange',
|
88
|
+
Characteristic: this.Characteristics.my.PositionChange
|
89
|
+
}).on('didSet', async (value) => {
|
90
|
+
if (value !== 0) {
|
91
|
+
this.put({ lift_inc: -value })
|
92
|
+
await timeout(this.platform.config.waitTimeReset)
|
93
|
+
this.values.positionChange = 0
|
94
|
+
}
|
95
|
+
})
|
96
|
+
this.values.positionChange = 0
|
97
|
+
}
|
98
|
+
|
99
|
+
this.addCharacteristicDelegates()
|
100
|
+
|
101
|
+
this.update(resource.body, resource.rpath)
|
102
|
+
this.values.targetPosition = this.values.currentPosition
|
103
|
+
}
|
104
|
+
|
105
|
+
async setPosition () {
|
106
|
+
if (this.timer != null) {
|
107
|
+
clearTimeout(this.timer)
|
108
|
+
delete this.timer
|
109
|
+
}
|
110
|
+
let lift = 100 - this.values.targetPosition // % closed --> % open
|
111
|
+
if (this.venetianBlind) {
|
112
|
+
if (this.values.closeUpwards) {
|
113
|
+
lift *= -1
|
114
|
+
}
|
115
|
+
lift += 100
|
116
|
+
lift /= 2
|
117
|
+
lift = Math.round(lift)
|
118
|
+
this.targetCloseUpwards = this.values.closeUpwards
|
119
|
+
}
|
120
|
+
this.values.positionState =
|
121
|
+
this.values.targetPosition > this.values.currentPosition
|
122
|
+
? this.Characteristics.hap.PositionState.INCREASING
|
123
|
+
: this.Characteristics.hap.PositionState.DECREASING
|
124
|
+
await this.put({ lift: lift })
|
125
|
+
this.timer = setTimeout(() => {
|
126
|
+
this.values.positionState =
|
127
|
+
this.Characteristics.hap.PositionState.STOPPED
|
128
|
+
}, 15000)
|
129
|
+
}
|
130
|
+
|
131
|
+
updateState (state) {
|
132
|
+
if (state.lift != null) {
|
133
|
+
let position = Math.round(state.lift / 5) * 5
|
134
|
+
let closeUpwards
|
135
|
+
if (this.venetianBlind) {
|
136
|
+
if (position < 0) {
|
137
|
+
position *= -1
|
138
|
+
closeUpwards = true
|
139
|
+
} else if (position > 0) {
|
140
|
+
closeUpwards = false
|
141
|
+
}
|
142
|
+
}
|
143
|
+
position = 100 - position // % open -> % closed
|
144
|
+
this.values.currentPosition = position
|
145
|
+
if (closeUpwards != null) {
|
146
|
+
this.values.closeUpwards = closeUpwards
|
147
|
+
}
|
148
|
+
if (
|
149
|
+
position === this.values.targetPosition &&
|
150
|
+
(closeUpwards == null || closeUpwards === this.targetCloseUpwards)
|
151
|
+
) {
|
152
|
+
this.values.positionState = this.Characteristics.hap.PositionState.STOPPED
|
153
|
+
}
|
154
|
+
}
|
155
|
+
if (state.speed != null) {
|
156
|
+
this.values.motorSpeed = state.speed
|
157
|
+
}
|
158
|
+
super.updateState(state)
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
module.exports = WindowCovering
|
@@ -5,39 +5,93 @@
|
|
5
5
|
|
6
6
|
'use strict'
|
7
7
|
|
8
|
+
const homebridgeLib = require('homebridge-lib')
|
9
|
+
const Deconz = require('../Deconz')
|
10
|
+
|
11
|
+
const { dateToString } = Deconz.ApiClient
|
12
|
+
|
8
13
|
/** Service delegates.
|
9
|
-
* @
|
14
|
+
* @extends ServiceDelegate
|
10
15
|
*/
|
11
|
-
class DeconzService {
|
16
|
+
class DeconzService extends homebridgeLib.ServiceDelegate {
|
17
|
+
static get AirPressure () { return require('./AirPressure') }
|
12
18
|
static get AirQuality () { return require('./AirQuality') }
|
13
19
|
static get Alarm () { return require('./Alarm') }
|
14
|
-
|
20
|
+
static get Battery () { return require('./Battery') }
|
15
21
|
static get Button () { return require('./Button') }
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
static get CarbonMonoxide () { return require('./CarbonMonoxide') }
|
23
|
+
static get Consumption () { return require('./Consumption') }
|
24
|
+
static get Contact () { return require('./Contact') }
|
25
|
+
static get Daylight () { return require('./Daylight') }
|
19
26
|
static get DeviceSettings () { return require('./DeviceSettings') }
|
20
|
-
|
21
|
-
// static get Fire () { return require('./Fire') }
|
27
|
+
static get Flag () { return require('./Flag') }
|
22
28
|
static get GatewaySettings () { return require('./GatewaySettings') }
|
23
|
-
|
24
|
-
|
29
|
+
static get Humidity () { return require('./Humidity') }
|
30
|
+
static get Leak () { return require('./Leak') }
|
25
31
|
static get Light () { return require('./Light') }
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
static get
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
32
|
+
static get LightsResource () { return require('./LightsResource') }
|
33
|
+
static get LightLevel () { return require('./LightLevel') }
|
34
|
+
static get Motion () { return require('./Motion') }
|
35
|
+
static get Outlet () { return require('./Outlet') }
|
36
|
+
static get Power () { return require('./Power') }
|
37
|
+
static get SensorsResource () { return require('./SensorsResource') }
|
38
|
+
static get Status () { return require('./Status') }
|
39
|
+
static get Smoke () { return require('./Smoke') }
|
40
|
+
static get Switch () { return require('./Switch') }
|
41
|
+
static get Temperature () { return require('./Temperature') }
|
42
|
+
static get Thermostat () { return require('./Thermostat') }
|
43
|
+
static get WarningDevice () { return require('./WarningDevice') }
|
44
|
+
static get WindowCovering () { return require('./WindowCovering') }
|
45
|
+
|
46
|
+
constructor (accessory, resource, params) {
|
47
|
+
super(accessory, {
|
48
|
+
id: resource.id,
|
49
|
+
name: resource.body.name,
|
50
|
+
Service: params.Service,
|
51
|
+
subtype: resource.subtype,
|
52
|
+
primaryService: params.primaryService
|
53
|
+
})
|
54
|
+
this.id = resource.id
|
55
|
+
this.gateway = accessory.gateway
|
56
|
+
this.client = accessory.client
|
57
|
+
this.resource = resource
|
58
|
+
this.rtype = resource.rtype
|
59
|
+
this.rid = resource.rid
|
60
|
+
this.rpath = resource.rpath
|
61
|
+
this.capabilities = resource.capabilities
|
62
|
+
|
63
|
+
this.serviceNameByRpath = {}
|
64
|
+
}
|
65
|
+
|
66
|
+
addResource (resource) {
|
67
|
+
this.serviceNameByRpath[resource.rpath] = resource.serviceName
|
68
|
+
DeconzService[resource.serviceName].addResource(this, resource)
|
69
|
+
}
|
70
|
+
|
71
|
+
update (body, rpath) {
|
72
|
+
if (this.updating) {
|
73
|
+
return
|
74
|
+
}
|
75
|
+
const serviceName = this.serviceNameByRpath[rpath]
|
76
|
+
if (serviceName != null) {
|
77
|
+
if (body.state != null) {
|
78
|
+
DeconzService[serviceName].updateResourceState(this, body.state)
|
79
|
+
}
|
80
|
+
return
|
81
|
+
}
|
82
|
+
if (body.lastseen != null && this.rtype === 'lights') {
|
83
|
+
this.values.lastSeen = dateToString(body.lastseen)
|
84
|
+
}
|
85
|
+
if (body.config != null) {
|
86
|
+
this.updateConfig(body.config)
|
87
|
+
if (this.batteryService != null) {
|
88
|
+
this.batteryService.updateConfig(body.config)
|
89
|
+
}
|
90
|
+
}
|
91
|
+
if (body.state != null) {
|
92
|
+
this.updateState(body.state, rpath)
|
93
|
+
}
|
94
|
+
}
|
41
95
|
}
|
42
96
|
|
43
97
|
module.exports = DeconzService
|
package/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"displayName": "Homebridge deCONZ",
|
5
5
|
"author": "Erik Baauw",
|
6
6
|
"license": "Apache-2.0",
|
7
|
-
"version": "0.0.
|
7
|
+
"version": "0.0.13",
|
8
8
|
"keywords": [
|
9
9
|
"homebridge-plugin",
|
10
10
|
"homekit",
|
@@ -20,14 +20,15 @@
|
|
20
20
|
"deconz": "cli/deconz.js"
|
21
21
|
},
|
22
22
|
"engines": {
|
23
|
-
"deCONZ": "2.
|
23
|
+
"deCONZ": "2.14.1",
|
24
24
|
"homebridge": "^1.4.0",
|
25
|
-
"node": "^16.
|
25
|
+
"node": "^16.14.0"
|
26
26
|
},
|
27
27
|
"dependencies": {
|
28
|
-
"homebridge-
|
28
|
+
"@homebridge/plugin-ui-utils": "~0.0.19",
|
29
|
+
"homebridge-lib": "~5.2.3",
|
29
30
|
"semver": "^7.3.5",
|
30
|
-
"ws": "^8.
|
31
|
+
"ws": "^8.5.0",
|
31
32
|
"xml2js": "~0.4.23"
|
32
33
|
},
|
33
34
|
"scripts": {
|
package/lib/Client/ApiError.js
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
// homebridge-deconz/lib/Deconz/ApiError.js
|
2
|
-
//
|
3
|
-
// Homebridge plug-in for deCONZ.
|
4
|
-
// Copyright © 2018-2022 Erik Baauw. All rights reserved.
|
5
|
-
|
6
|
-
'use strict'
|
7
|
-
|
8
|
-
const homebridgeLib = require('homebridge-lib')
|
9
|
-
|
10
|
-
// API errors that could still cause (part of) the PUT command to be executed.
|
11
|
-
const nonCriticalApiErrorTypes = [
|
12
|
-
6, // parameter not available
|
13
|
-
7, // invalid value for parameter
|
14
|
-
8, // paramater not modifiable
|
15
|
-
201 // paramater not modifiable, device is set to off
|
16
|
-
]
|
17
|
-
|
18
|
-
/** Deconz API error.
|
19
|
-
* @hideconstructor
|
20
|
-
* @extends HttpClient.HttpError
|
21
|
-
* @memberof Deconz
|
22
|
-
*/
|
23
|
-
class ApiError extends homebridgeLib.HttpClient.HttpError {
|
24
|
-
constructor (message, response, type, description) {
|
25
|
-
super(message, response.request, response.statusCode, response.statusMessage)
|
26
|
-
|
27
|
-
/** @member {integer} - The API error type.
|
28
|
-
*/
|
29
|
-
this.type = type
|
30
|
-
|
31
|
-
/** @member {string} - The API error description.
|
32
|
-
*/
|
33
|
-
this.description = description
|
34
|
-
|
35
|
-
/** @member {boolean} - Indication that the request might still succeed
|
36
|
-
* for other attributes.
|
37
|
-
*/
|
38
|
-
this.nonCritical = nonCriticalApiErrorTypes.includes(type)
|
39
|
-
}
|
40
|
-
}
|
41
|
-
|
42
|
-
module.exports = ApiError
|