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.
- package/README.md +8 -0
- package/cli/deconz.js +980 -0
- package/config.schema.json +1 -1
- package/lib/Client/ApiError.js +42 -0
- package/lib/{DeconzClient.js → Deconz/ApiClient.js} +82 -158
- package/lib/Deconz/ApiError.js +42 -0
- package/lib/Deconz/ApiResponse.js +54 -0
- package/lib/Deconz/Device.js +100 -0
- package/lib/{DeconzDiscovery.js → Deconz/Discovery.js} +4 -3
- package/lib/Deconz/Resource.js +1206 -0
- package/lib/{DeconzWsClient.js → Deconz/WsClient.js} +59 -44
- package/lib/Deconz/index.js +21 -0
- package/lib/DeconzAccessory/Contact.js +54 -0
- package/lib/DeconzAccessory/Gateway.js +316 -374
- package/lib/DeconzAccessory/Light.js +72 -0
- 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 +216 -0
- package/lib/DeconzPlatform.js +8 -3
- package/lib/DeconzService/AirPressure.js +43 -0
- package/lib/DeconzService/AirQuality.js +20 -10
- package/lib/DeconzService/Alarm.js +16 -9
- package/lib/DeconzService/Battery.js +43 -0
- package/lib/DeconzService/Button.js +12 -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 +13 -5
- package/lib/DeconzService/Flag.js +52 -0
- package/lib/DeconzService/GatewaySettings.js +8 -58
- package/lib/DeconzService/Humidity.js +37 -0
- package/lib/DeconzService/Leak.js +38 -0
- package/lib/DeconzService/Light.js +376 -0
- 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 +139 -0
- package/lib/DeconzService/index.js +94 -0
- package/package.json +7 -4
- package/lib/DeconzAccessory/Device.js +0 -91
- package/lib/DeconzAccessory.js +0 -16
- package/lib/DeconzDevice.js +0 -245
- package/lib/DeconzService/Sensor.js +0 -58
- package/lib/DeconzService.js +0 -43
@@ -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.TemperatureSensor
|
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,139 @@
|
|
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.positionChange) {
|
67
|
+
this.addCharacteristicDelegate({
|
68
|
+
key: 'positionChange',
|
69
|
+
Characteristic: this.Characteristics.my.PositionChange
|
70
|
+
}).on('didSet', async (value) => {
|
71
|
+
if (value !== 0) {
|
72
|
+
this.put({ lift_inc: -value })
|
73
|
+
await timeout(this.platform.config.waitTimeReset)
|
74
|
+
this.values.positionChange = 0
|
75
|
+
}
|
76
|
+
})
|
77
|
+
this.values.positionChange = 0
|
78
|
+
}
|
79
|
+
|
80
|
+
this.addCharacteristicDelegates()
|
81
|
+
|
82
|
+
this.update(resource.body, resource.rpath)
|
83
|
+
}
|
84
|
+
|
85
|
+
setPosition () {
|
86
|
+
if (this.timer != null) {
|
87
|
+
clearTimeout(this.timer)
|
88
|
+
delete this.timer
|
89
|
+
}
|
90
|
+
let lift = 100 - this.values.targetPosition // % closed --> % open
|
91
|
+
if (this.venetianBlind) {
|
92
|
+
if (this.values.closeUpwards) {
|
93
|
+
lift *= -1
|
94
|
+
}
|
95
|
+
lift += 100
|
96
|
+
lift /= 2
|
97
|
+
lift = Math.round(lift)
|
98
|
+
this.targetCloseUpwards = this.values.closeUpwards
|
99
|
+
}
|
100
|
+
this.values.positionState =
|
101
|
+
this.values.targetPosition > this.values.currentPosition
|
102
|
+
? this.Characteristics.hap.PositionState.INCREASING
|
103
|
+
: this.Characteristics.hap.PositionState.DECREASING
|
104
|
+
this.put({ lift: lift })
|
105
|
+
this.timer = setTimeout(() => {
|
106
|
+
this.values.positionState =
|
107
|
+
this.Characteristics.hap.PositionState.STOPPED
|
108
|
+
}, 15000)
|
109
|
+
}
|
110
|
+
|
111
|
+
updateState (state, rpath) {
|
112
|
+
if (state.lift != null) {
|
113
|
+
let position = Math.round(state.lift / 5) * 5
|
114
|
+
let closeUpwards
|
115
|
+
if (this.venetianBlind) {
|
116
|
+
if (position < 0) {
|
117
|
+
position *= -1
|
118
|
+
closeUpwards = true
|
119
|
+
} else if (position > 0) {
|
120
|
+
closeUpwards = false
|
121
|
+
}
|
122
|
+
}
|
123
|
+
position = 100 - position // % open -> % closed
|
124
|
+
if (
|
125
|
+
position === this.values.targetPosition &&
|
126
|
+
(closeUpwards == null || closeUpwards === this.targetCloseUpwards)
|
127
|
+
) {
|
128
|
+
this.values.positionState = this.Characteristics.hap.PositionState.STOPPED
|
129
|
+
}
|
130
|
+
this.values.currentPosition = position
|
131
|
+
if (closeUpwards != null) {
|
132
|
+
this.values.closeUpwards = closeUpwards
|
133
|
+
}
|
134
|
+
}
|
135
|
+
super.updateState(state)
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
module.exports = WindowCovering
|
@@ -0,0 +1,94 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/index.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 Deconz = require('../Deconz')
|
10
|
+
|
11
|
+
const { dateToString } = Deconz.ApiClient
|
12
|
+
|
13
|
+
/** Service delegates.
|
14
|
+
* @extends ServiceDelegate
|
15
|
+
*/
|
16
|
+
class DeconzService extends homebridgeLib.ServiceDelegate {
|
17
|
+
static get AirPressure () { return require('./AirPressure') }
|
18
|
+
static get AirQuality () { return require('./AirQuality') }
|
19
|
+
static get Alarm () { return require('./Alarm') }
|
20
|
+
static get Battery () { return require('./Battery') }
|
21
|
+
static get Button () { return require('./Button') }
|
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') }
|
26
|
+
static get DeviceSettings () { return require('./DeviceSettings') }
|
27
|
+
static get Flag () { return require('./Flag') }
|
28
|
+
static get GatewaySettings () { return require('./GatewaySettings') }
|
29
|
+
static get Humidity () { return require('./Humidity') }
|
30
|
+
static get Leak () { return require('./Leak') }
|
31
|
+
static get Light () { return require('./Light') }
|
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
|
+
}
|
88
|
+
if (body.state != null) {
|
89
|
+
this.updateState(body.state, rpath)
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
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.11",
|
8
8
|
"keywords": [
|
9
9
|
"homebridge-plugin",
|
10
10
|
"homekit",
|
@@ -16,15 +16,18 @@
|
|
16
16
|
"dresdenelektronik"
|
17
17
|
],
|
18
18
|
"main": "index.js",
|
19
|
+
"bin": {
|
20
|
+
"deconz": "cli/deconz.js"
|
21
|
+
},
|
19
22
|
"engines": {
|
20
23
|
"deCONZ": "2.13.4",
|
21
|
-
"homebridge": "^1.
|
24
|
+
"homebridge": "^1.4.0",
|
22
25
|
"node": "^16.13.2"
|
23
26
|
},
|
24
27
|
"dependencies": {
|
25
|
-
"homebridge-lib": "~5.
|
28
|
+
"homebridge-lib": "~5.2.2",
|
26
29
|
"semver": "^7.3.5",
|
27
|
-
"ws": "^8.4.
|
30
|
+
"ws": "^8.4.2",
|
28
31
|
"xml2js": "~0.4.23"
|
29
32
|
},
|
30
33
|
"scripts": {
|
@@ -1,91 +0,0 @@
|
|
1
|
-
// homebridge-deconz/lib/DeconzAccessory/Device.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
|
-
/** Delegate class for a device exposed by the gateway.
|
12
|
-
* @extends AccessoryDelegate
|
13
|
-
* @memberof DeconzAccessory
|
14
|
-
*/
|
15
|
-
class Device extends homebridgeLib.AccessoryDelegate {
|
16
|
-
/** Instantiate a gateway delegate.
|
17
|
-
* @param {DeconzAccessory.Gateway} gateway - The gateway delegate.
|
18
|
-
* @param {DeconzAccessory.Gateway.Device} device - The device.
|
19
|
-
*/
|
20
|
-
constructor (gateway, device) {
|
21
|
-
const { body, category } = device.resource
|
22
|
-
super(gateway.platform, {
|
23
|
-
id: device.id,
|
24
|
-
name: body.name,
|
25
|
-
manufacturer: device.zigbee
|
26
|
-
? body.manufacturername
|
27
|
-
: gateway.values.manufacturer,
|
28
|
-
model: device.zigbee ? body.modelid : body.type,
|
29
|
-
firmware: device.Zigbee
|
30
|
-
? body.swversion == null ? '0.0.0' : body.swversion
|
31
|
-
: gateway.values.software,
|
32
|
-
category: category,
|
33
|
-
logLevel: gateway.logLevel
|
34
|
-
})
|
35
|
-
this.gateway = gateway
|
36
|
-
this.id = device.id
|
37
|
-
this.device = device
|
38
|
-
|
39
|
-
this.identify()
|
40
|
-
|
41
|
-
this.service = new DeconzService.Button(this, {
|
42
|
-
name: this.name + ' Button',
|
43
|
-
button: 1,
|
44
|
-
events: DeconzService.Button.SINGLE | DeconzService.Button.LONG
|
45
|
-
})
|
46
|
-
|
47
|
-
this.settingsService = new DeconzService.DeviceSettings(this, {
|
48
|
-
name: this.name + ' Settings',
|
49
|
-
subtype: this.id,
|
50
|
-
resource: this.device.rpaths.join(', '),
|
51
|
-
expose: true,
|
52
|
-
logLevel: gateway.logLevel
|
53
|
-
})
|
54
|
-
|
55
|
-
this
|
56
|
-
.on('polled', (device) => {
|
57
|
-
this.debug('%s: polled', this.device.rpaths.join(', '))
|
58
|
-
this.service.update(1003)
|
59
|
-
})
|
60
|
-
.on('changed', (rpath, body) => {
|
61
|
-
this.debug('%s: changed: %j', rpath, body)
|
62
|
-
this.service.update(1002)
|
63
|
-
})
|
64
|
-
.on('identify', this.identify)
|
65
|
-
|
66
|
-
setImmediate(() => {
|
67
|
-
this.debug('initialised')
|
68
|
-
this.emit('initialised')
|
69
|
-
})
|
70
|
-
}
|
71
|
-
|
72
|
-
/** The primary resource of the device.
|
73
|
-
* @type {DeconzDevice.Resource}
|
74
|
-
*/
|
75
|
-
get resource () { return this.device.resource }
|
76
|
-
|
77
|
-
/** List of resource paths of associated resources in order of prio.
|
78
|
-
* @type {string[]}
|
79
|
-
*/
|
80
|
-
get rpaths () { return this.device.rpaths }
|
81
|
-
|
82
|
-
identify () {
|
83
|
-
this.log(
|
84
|
-
'%s %s v%s (%d resources)', this.values.manufacturer, this.values.model,
|
85
|
-
this.values.firmware, this.rpaths.length
|
86
|
-
)
|
87
|
-
this.debug('%d resources: %s', this.rpaths.length, this.rpaths.join(', '))
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
module.exports = Device
|
package/lib/DeconzAccessory.js
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
// homebridge-deconz/lib/DeconzAccessory.js
|
2
|
-
// Copyright © 2022 Erik Baauw. All rights reserved.
|
3
|
-
//
|
4
|
-
// Homebridge plugin for deCONZ.
|
5
|
-
|
6
|
-
'use strict'
|
7
|
-
|
8
|
-
/** Accessory delegates.
|
9
|
-
* @hideconstructor
|
10
|
-
*/
|
11
|
-
class DeconzAccessory {
|
12
|
-
static get Gateway () { return require('./DeconzAccessory/Gateway') }
|
13
|
-
static get Device () { return require('./DeconzAccessory/Device') }
|
14
|
-
}
|
15
|
-
|
16
|
-
module.exports = DeconzAccessory
|