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,56 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/WarningDevice.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 light device
|
14
|
+
* or groups resource.
|
15
|
+
* @extends DeconzAccessory
|
16
|
+
* @memberof DeconzAccessory
|
17
|
+
*/
|
18
|
+
class WarningDevice extends DeconzAccessory {
|
19
|
+
/** Instantiate a delegate for an accessory corresponding to a device.
|
20
|
+
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
21
|
+
* @param {Deconz.Device} device - The device.
|
22
|
+
*/
|
23
|
+
constructor (gateway, device, settings = {}) {
|
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
|
+
if (this.serviceByServiceName.Temperature != null) {
|
39
|
+
this.historyService = new History.Weather(
|
40
|
+
this, {},
|
41
|
+
this.serviceByServiceName.Temperature.characteristicDelegate('temperature'),
|
42
|
+
null,
|
43
|
+
null
|
44
|
+
)
|
45
|
+
}
|
46
|
+
|
47
|
+
this.createSettingsService()
|
48
|
+
|
49
|
+
setImmediate(() => {
|
50
|
+
this.debug('initialised')
|
51
|
+
this.emit('initialised')
|
52
|
+
})
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
module.exports = WarningDevice
|
@@ -0,0 +1,47 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzAccessory/WindowCovering.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
|
+
/** Delegate class for a HomeKit accessory, corresponding to a light device
|
11
|
+
* or groups resource.
|
12
|
+
* @extends DeconzAccessory
|
13
|
+
* @memberof DeconzAccessory
|
14
|
+
*/
|
15
|
+
class WindowCovering extends DeconzAccessory {
|
16
|
+
/** Instantiate a delegate for an accessory corresponding to a device.
|
17
|
+
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
18
|
+
* @param {Deconz.Device} device - The device.
|
19
|
+
*/
|
20
|
+
constructor (gateway, device, settings = {}) {
|
21
|
+
super(gateway, device, gateway.Accessory.Categories.WINDOW_COVERING)
|
22
|
+
|
23
|
+
this.identify()
|
24
|
+
|
25
|
+
this.service = this.createService(device.resource, {
|
26
|
+
primaryService: true,
|
27
|
+
serviceName: this.values.serviceName
|
28
|
+
})
|
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.createSettingsService()
|
39
|
+
|
40
|
+
setImmediate(() => {
|
41
|
+
this.debug('initialised')
|
42
|
+
this.emit('initialised')
|
43
|
+
})
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
module.exports = WindowCovering
|
@@ -6,14 +6,25 @@
|
|
6
6
|
'use strict'
|
7
7
|
|
8
8
|
const homebridgeLib = require('homebridge-lib')
|
9
|
+
const Deconz = require('../Deconz')
|
10
|
+
const DeconzService = require('../DeconzService')
|
11
|
+
|
12
|
+
const { HttpError } = Deconz.ApiClient
|
13
|
+
const { SINGLE, DOUBLE, LONG } = DeconzService.Button
|
9
14
|
|
10
15
|
/** Abstract superclass for a delegate of a HomeKit accessory,
|
11
16
|
* corresponding to a Zigbee or virtual device on a deCONZ gateway.
|
17
|
+
* @extends AccessoryDelegate
|
12
18
|
*/
|
13
19
|
class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
|
14
|
-
static get
|
20
|
+
static get Contact () { return require('./Contact') }
|
15
21
|
static get Light () { return require('./Light') }
|
16
22
|
static get Gateway () { return require('./Gateway') }
|
23
|
+
static get Motion () { return require('./Motion') }
|
24
|
+
static get Sensor () { return require('./Sensor') }
|
25
|
+
static get Temperature () { return require('./Temperature') }
|
26
|
+
static get WarningDevice () { return require('./WarningDevice') }
|
27
|
+
static get WindowCovering () { return require('./WindowCovering') }
|
17
28
|
|
18
29
|
/** Instantiate a delegate for an accessory corresponding to a device.
|
19
30
|
* @param {DeconzAccessory.Gateway} gateway - The gateway.
|
@@ -31,6 +42,12 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
|
|
31
42
|
category: category
|
32
43
|
})
|
33
44
|
|
45
|
+
this.context.gid = gateway.id
|
46
|
+
|
47
|
+
this.serviceByRpath = {}
|
48
|
+
this.serviceBySubtype = {}
|
49
|
+
this.serviceByServiceName = {}
|
50
|
+
|
34
51
|
/** The gateway.
|
35
52
|
* @type {DeconzAccessory.Gateway}
|
36
53
|
*/
|
@@ -52,6 +69,35 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
|
|
52
69
|
* @type {Deconz.ApiClient}
|
53
70
|
*/
|
54
71
|
this.client = gateway.client
|
72
|
+
|
73
|
+
this
|
74
|
+
.on('polled', (device) => {
|
75
|
+
this.values.firmware = device.resource.firmware
|
76
|
+
for (const subtype in this.serviceBySubtype) {
|
77
|
+
try {
|
78
|
+
const service = this.serviceBySubtype[subtype]
|
79
|
+
const resource = device.resourceBySubtype[subtype]
|
80
|
+
this.debug('%s: polled: %j', resource.rpath, resource.body)
|
81
|
+
service.update(resource.body, resource.rpath)
|
82
|
+
} catch (error) { this.error(error) }
|
83
|
+
}
|
84
|
+
})
|
85
|
+
.on('changed', (rpath, body) => {
|
86
|
+
this.debug('%s: changed: %j', rpath, body)
|
87
|
+
const service = this.serviceByRpath[rpath]
|
88
|
+
if (service != null) {
|
89
|
+
service.update(body, rpath)
|
90
|
+
}
|
91
|
+
})
|
92
|
+
.on('identify', async () => {
|
93
|
+
try {
|
94
|
+
await this.identify()
|
95
|
+
} catch (error) {
|
96
|
+
if (!(error instanceof HttpError)) {
|
97
|
+
this.warn(error)
|
98
|
+
}
|
99
|
+
}
|
100
|
+
})
|
55
101
|
}
|
56
102
|
|
57
103
|
/** The primary resource of the device.
|
@@ -64,12 +110,108 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
|
|
64
110
|
*/
|
65
111
|
get rpaths () { return this.device.rpaths }
|
66
112
|
|
67
|
-
identify () {
|
113
|
+
async identify () {
|
68
114
|
this.log(
|
69
115
|
'%s %s v%s (%d resources)', this.values.manufacturer, this.values.model,
|
70
116
|
this.values.firmware, this.rpaths.length
|
71
117
|
)
|
72
118
|
this.debug('%d resources: %s', this.rpaths.length, this.rpaths.join(', '))
|
119
|
+
if (this.service != null) {
|
120
|
+
await this.service.identify()
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
createService (resource, params = {}) {
|
125
|
+
if (resource == null) {
|
126
|
+
return
|
127
|
+
}
|
128
|
+
if (params.serviceName == null) {
|
129
|
+
params.serviceName = resource.serviceName
|
130
|
+
}
|
131
|
+
if (DeconzService[params.serviceName] == null) {
|
132
|
+
this.warn(
|
133
|
+
'%s: %s: not yet supported %s type',
|
134
|
+
resource.rpath, resource.body.type, resource.rtype
|
135
|
+
)
|
136
|
+
return
|
137
|
+
}
|
138
|
+
this.debug(
|
139
|
+
'%s: capabilities: %j', resource.rpath, resource.capabilities
|
140
|
+
)
|
141
|
+
this.debug('%s: params: %j', resource.rpath, params)
|
142
|
+
|
143
|
+
let service
|
144
|
+
if (params.serviceName === 'Battery') {
|
145
|
+
service = this.serviceByServiceName.Battery
|
146
|
+
} else if (params.serviceName === 'Consumption') {
|
147
|
+
service = this.serviceByServiceName.Light ||
|
148
|
+
this.serviceByServiceName.Power
|
149
|
+
if (service != null) {
|
150
|
+
service.addResource(resource)
|
151
|
+
}
|
152
|
+
} else if (params.serviceName === 'Power') {
|
153
|
+
service = this.serviceByServiceName.Light ||
|
154
|
+
this.serviceByServiceName.Consumption
|
155
|
+
if (service != null) {
|
156
|
+
service.addResource(resource)
|
157
|
+
}
|
158
|
+
this.consumptionService = service
|
159
|
+
} else if (params.serviceName === 'Switch') {
|
160
|
+
// Default button
|
161
|
+
if (resource.capabilities.buttons == null) {
|
162
|
+
this.warn(
|
163
|
+
'%s: unknown %s: %j', resource.rpath, resource.body.type,
|
164
|
+
resource.body
|
165
|
+
)
|
166
|
+
resource.capabilities.buttons = {
|
167
|
+
1: {
|
168
|
+
label: 'Unknown Button',
|
169
|
+
events: SINGLE | DOUBLE | LONG
|
170
|
+
}
|
171
|
+
}
|
172
|
+
resource.capabilities.namespace =
|
173
|
+
this.Characteristics.hap.ServiceLabelNamespace.ARABIC_NUMERALS
|
174
|
+
}
|
175
|
+
service = this.serviceByServiceName.Switch
|
176
|
+
if (service == null) {
|
177
|
+
service = new DeconzService.Switch(this, resource, {
|
178
|
+
primaryService: params.primaryService
|
179
|
+
})
|
180
|
+
}
|
181
|
+
service.createButtonServices(resource, params)
|
182
|
+
}
|
183
|
+
if (service == null) {
|
184
|
+
service = new DeconzService[params.serviceName](this, resource, {
|
185
|
+
primaryService: params.primaryService
|
186
|
+
})
|
187
|
+
}
|
188
|
+
this.serviceBySubtype[resource.subtype] = service
|
189
|
+
this.serviceByRpath[resource.rpath] = service
|
190
|
+
if (this.serviceByServiceName[resource.serviceName] == null) {
|
191
|
+
this.serviceByServiceName[resource.serviceName] = service
|
192
|
+
}
|
193
|
+
if (
|
194
|
+
resource.body.config != null &&
|
195
|
+
resource.body.config.battery !== undefined
|
196
|
+
) {
|
197
|
+
if (this.serviceByServiceName.Battery == null) {
|
198
|
+
this.serviceByServiceName.Battery = new DeconzService.Battery(this, resource)
|
199
|
+
}
|
200
|
+
service.batteryService = this.serviceByServiceName.Battery
|
201
|
+
}
|
202
|
+
return service
|
203
|
+
}
|
204
|
+
|
205
|
+
createSettingsService (params = {}) {
|
206
|
+
this.settingsService = new DeconzService.DeviceSettings(this, {
|
207
|
+
name: this.name + ' Settings',
|
208
|
+
subtype: this.id,
|
209
|
+
resource: this.device.rpaths.join(', '),
|
210
|
+
expose: true,
|
211
|
+
logLevel: this.gateway.logLevel,
|
212
|
+
hasRepeat: this.service.hasRepeat
|
213
|
+
})
|
214
|
+
this.manageLogLevel(this.settingsService.characteristicDelegate('logLevel'))
|
73
215
|
}
|
74
216
|
}
|
75
217
|
|
package/lib/DeconzPlatform.js
CHANGED
@@ -21,8 +21,6 @@ class DeconzPlatform extends homebridgeLib.Platform {
|
|
21
21
|
.on('accessoryRestored', this.accessoryRestored)
|
22
22
|
.once('heartbeat', this.init)
|
23
23
|
.on('heartbeat', this.heartbeat)
|
24
|
-
|
25
|
-
this.warn('This plugin is work in progress')
|
26
24
|
}
|
27
25
|
|
28
26
|
parseConfigJson (configJson) {
|
@@ -190,6 +188,11 @@ class DeconzPlatform extends homebridgeLib.Platform {
|
|
190
188
|
) {
|
191
189
|
this.gatewayMap[id] = new DeconzAccessory.Gateway(this, context)
|
192
190
|
}
|
191
|
+
} else {
|
192
|
+
const gateway = this.gatewayMap[context.gid]
|
193
|
+
if (gateway != null) {
|
194
|
+
gateway.addAccessory(id)
|
195
|
+
}
|
193
196
|
}
|
194
197
|
} catch (error) { this.error(error) }
|
195
198
|
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/AirPressure.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 AirPressure extends DeconzService.SensorsResource {
|
14
|
+
constructor (accessory, resource, params = {}) {
|
15
|
+
params.Service = accessory.Services.eve.AirPressureSensor
|
16
|
+
super(accessory, resource, params)
|
17
|
+
|
18
|
+
this.addCharacteristicDelegate({
|
19
|
+
key: 'airPressure',
|
20
|
+
Characteristic: this.Characteristics.eve.AirPressure,
|
21
|
+
unit: ' hPa'
|
22
|
+
})
|
23
|
+
|
24
|
+
this.addCharacteristicDelegate({
|
25
|
+
key: 'elevation',
|
26
|
+
Characteristic: this.Characteristics.eve.Elevation,
|
27
|
+
value: 0
|
28
|
+
})
|
29
|
+
|
30
|
+
this.addCharacteristicDelegates()
|
31
|
+
|
32
|
+
this.update(resource.body)
|
33
|
+
}
|
34
|
+
|
35
|
+
updateState (state) {
|
36
|
+
if (state.pressure != null) {
|
37
|
+
this.values.airPressure = Math.round(state.pressure * 10) / 10
|
38
|
+
}
|
39
|
+
super.updateState(state)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
module.exports = AirPressure
|
@@ -10,21 +10,26 @@ const DeconzService = require('../DeconzService')
|
|
10
10
|
/**
|
11
11
|
* @memberof DeconzService
|
12
12
|
*/
|
13
|
-
class AirQuality extends DeconzService.
|
14
|
-
constructor (
|
15
|
-
params.Service =
|
16
|
-
super(
|
13
|
+
class AirQuality extends DeconzService.SensorsResource {
|
14
|
+
constructor (accessory, resource, params = {}) {
|
15
|
+
params.Service = accessory.Services.hap.AirQualitySensor
|
16
|
+
super(accessory, resource, params)
|
17
17
|
|
18
18
|
this.addCharacteristicDelegate({
|
19
19
|
key: 'airQuality',
|
20
20
|
Characteristic: this.Characteristics.hap.AirQuality
|
21
21
|
})
|
22
|
+
|
22
23
|
this.addCharacteristicDelegate({
|
23
24
|
key: 'vocDensity',
|
24
|
-
Characteristic: this.Characteristics.hap.VOCDensity
|
25
|
+
Characteristic: this.Characteristics.hap.VOCDensity,
|
26
|
+
unit: ' µg/m³',
|
27
|
+
props: { minValue: 0, maxValue: 65535, minStep: 1 }
|
25
28
|
})
|
26
|
-
|
27
|
-
|
29
|
+
|
30
|
+
super.addCharacteristicDelegates()
|
31
|
+
|
32
|
+
this.update(resource.body)
|
28
33
|
}
|
29
34
|
|
30
35
|
airQualityValue (value) {
|
@@ -44,10 +49,14 @@ class AirQuality extends DeconzService.Sensor {
|
|
44
49
|
}
|
45
50
|
}
|
46
51
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
52
|
+
updateState (state) {
|
53
|
+
if (state.airquality != null) {
|
54
|
+
this.values.airQuality = this.airQualityValue(state.airquality)
|
55
|
+
}
|
56
|
+
if (state.airqualityppb != null) {
|
57
|
+
this.values.vocDensity = Math.round(state.airqualityppb * 4.57)
|
58
|
+
}
|
59
|
+
super.updateState(state)
|
51
60
|
}
|
52
61
|
}
|
53
62
|
|
@@ -10,22 +10,26 @@ const DeconzService = require('../DeconzService')
|
|
10
10
|
/**
|
11
11
|
* @memberof DeconzService
|
12
12
|
*/
|
13
|
-
class Alarm extends DeconzService.
|
14
|
-
constructor (
|
15
|
-
params.Service =
|
16
|
-
super(
|
13
|
+
class Alarm extends DeconzService.SensorsResource {
|
14
|
+
constructor (accessory, resource, params = {}) {
|
15
|
+
params.Service = accessory.Services.my.Resource
|
16
|
+
super(accessory, resource, params)
|
17
17
|
|
18
18
|
this.addCharacteristicDelegate({
|
19
19
|
key: 'alarm',
|
20
|
-
Characteristic: this.Characteristics.
|
20
|
+
Characteristic: this.Characteristics.my.Alarm
|
21
21
|
})
|
22
|
+
|
22
23
|
super.addCharacteristicDelegates(params)
|
23
|
-
|
24
|
+
|
25
|
+
this.update(resource.body)
|
24
26
|
}
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
updateState (state) {
|
29
|
+
if (state.alarm != null || state.test != null) {
|
30
|
+
this.values.alarm = state.alarm || state.test
|
31
|
+
}
|
32
|
+
super.updateState(state)
|
29
33
|
}
|
30
34
|
}
|
31
35
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/Battery.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
|
+
/**
|
14
|
+
* @memberof DeconzService
|
15
|
+
*/
|
16
|
+
class Battery extends homebridgeLib.ServiceDelegate.Battery {
|
17
|
+
constructor (accessory, resource, params = {}) {
|
18
|
+
super(accessory, {
|
19
|
+
name: accessory.name + ' Battery'
|
20
|
+
})
|
21
|
+
}
|
22
|
+
|
23
|
+
update (body) {
|
24
|
+
if (this.updating) {
|
25
|
+
return
|
26
|
+
}
|
27
|
+
if (body.config != null) {
|
28
|
+
this.updateConfig(body.config)
|
29
|
+
}
|
30
|
+
if (body.state != null) {
|
31
|
+
this.updateState(body.state)
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
updateState (state) {
|
36
|
+
if (state.battery != null) {
|
37
|
+
this.values.batteryLevel = state.battery
|
38
|
+
}
|
39
|
+
if (state.charging != null) {
|
40
|
+
this.values.chargingState = state.charging
|
41
|
+
? this.Characteristics.hap.ChargingState.CHARGING
|
42
|
+
: this.Characteristics.hap.ChargingState.NOT_CHARGING
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
updateConfig (config) {
|
47
|
+
if (config.battery != null) {
|
48
|
+
this.values.batteryLevel = config.battery
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
module.exports = Battery
|
@@ -115,6 +115,12 @@ class Button extends homebridgeLib.ServiceDelegate {
|
|
115
115
|
Characteristic: this.Characteristics.hap.ProgrammableSwitchEvent,
|
116
116
|
props: this.props(params.events)
|
117
117
|
})
|
118
|
+
|
119
|
+
this.addCharacteristicDelegate({
|
120
|
+
key: 'index',
|
121
|
+
Characteristic: this.Characteristics.hap.ServiceLabelIndex,
|
122
|
+
value: params.button
|
123
|
+
})
|
118
124
|
}
|
119
125
|
|
120
126
|
homeKitValue (value, oldValue = 0, repeat = false) {
|
@@ -132,11 +138,12 @@ class Button extends homebridgeLib.ServiceDelegate {
|
|
132
138
|
case deconzEvent.SHORT_RELEASE:
|
133
139
|
return homeKitEvent.SINGLE_PRESS
|
134
140
|
case deconzEvent.HOLD:
|
135
|
-
case deconzEvent.LONG_RELEASE:
|
136
141
|
if (repeat) {
|
137
142
|
return homeKitEvent.SINGLE_PRESS
|
138
143
|
}
|
139
|
-
|
144
|
+
// falls through
|
145
|
+
case deconzEvent.LONG_RELEASE:
|
146
|
+
if (repeat || (button === oldButton && oldEvent === deconzEvent.HOLD)) {
|
140
147
|
// Already issued action on previous Hold.
|
141
148
|
return null
|
142
149
|
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/CarbonMonoxide.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 CarbonMonoxide extends DeconzService.SensorsResource {
|
14
|
+
constructor (accessory, resource, params = {}) {
|
15
|
+
params.Service = accessory.Services.hap.CarbonMonoxideSensor
|
16
|
+
super(accessory, resource, params)
|
17
|
+
|
18
|
+
this.addCharacteristicDelegate({
|
19
|
+
key: 'carbonmonoxide',
|
20
|
+
Characteristic: this.Characteristics.hap.CarbonMonoxideDetected
|
21
|
+
})
|
22
|
+
|
23
|
+
super.addCharacteristicDelegates(params)
|
24
|
+
|
25
|
+
this.update(resource.body)
|
26
|
+
}
|
27
|
+
|
28
|
+
updateState (state) {
|
29
|
+
if (state.carbonmonoxide != null || state.test != null) {
|
30
|
+
this.values.carbonmonoxide = state.carbonmonoxide || state.test
|
31
|
+
? this.Characteristics.hap.CarbonMonoxideDetected.CO_LEVELS_ABNORMAL
|
32
|
+
: this.Characteristics.hap.CarbonMonoxideDetected.CO_LEVELS_NORMAL
|
33
|
+
}
|
34
|
+
super.updateState(state)
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
module.exports = CarbonMonoxide
|
@@ -0,0 +1,65 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/Consumption.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 Consumption extends DeconzService.SensorsResource {
|
17
|
+
static addResource (service, resource) {
|
18
|
+
service.addCharacteristicDelegate({
|
19
|
+
key: 'totalConsumption',
|
20
|
+
Characteristic: service.Characteristics.eve.TotalConsumption,
|
21
|
+
unit: ' kWh'
|
22
|
+
})
|
23
|
+
|
24
|
+
if (
|
25
|
+
resource.body.state.power !== undefined &&
|
26
|
+
service.values.currentConsumption === undefined
|
27
|
+
) {
|
28
|
+
service.addCharacteristicDelegate({
|
29
|
+
key: 'currentConsumption',
|
30
|
+
Characteristic: service.Characteristics.eve.CurrentConsumption,
|
31
|
+
unit: ' W'
|
32
|
+
})
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
static updateResourceState (service, state) {
|
37
|
+
if (state.consumption != null) {
|
38
|
+
service.values.totalConsumption = state.consumption / 1000
|
39
|
+
}
|
40
|
+
if (state.power != null) {
|
41
|
+
service.values.currentConsumption = state.power
|
42
|
+
}
|
43
|
+
if (state.lastupdated != null) {
|
44
|
+
service.values.lastUpdated = dateToString(state.lastupdated)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
constructor (accessory, resource, params = {}) {
|
49
|
+
params.Service = accessory.Services.my.Resource
|
50
|
+
super(accessory, resource, params)
|
51
|
+
|
52
|
+
Consumption.addResource(this, resource)
|
53
|
+
|
54
|
+
super.addCharacteristicDelegates()
|
55
|
+
|
56
|
+
this.update(resource.body)
|
57
|
+
}
|
58
|
+
|
59
|
+
updateState (state) {
|
60
|
+
Consumption.updateResourceState(this.service, state)
|
61
|
+
super.updateState(state)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
module.exports = Consumption
|
@@ -0,0 +1,60 @@
|
|
1
|
+
// homebridge-deconz/lib/DeconzService/Contact.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 Contact extends DeconzService.SensorsResource {
|
14
|
+
constructor (accessory, resource, params = {}) {
|
15
|
+
params.Service = accessory.Services.hap.ContactSensor
|
16
|
+
super(accessory, resource, params)
|
17
|
+
|
18
|
+
this.addCharacteristicDelegate({
|
19
|
+
key: 'contact',
|
20
|
+
Characteristic: this.Characteristics.hap.ContactSensorState
|
21
|
+
})
|
22
|
+
|
23
|
+
this.addCharacteristicDelegate({
|
24
|
+
key: 'timesOpened',
|
25
|
+
Characteristic: this.Characteristics.eve.TimesOpened,
|
26
|
+
value: 0
|
27
|
+
})
|
28
|
+
|
29
|
+
this.addCharacteristicDelegate({
|
30
|
+
key: 'openDuration',
|
31
|
+
Characteristic: this.Characteristics.eve.OpenDuration,
|
32
|
+
value: 0
|
33
|
+
})
|
34
|
+
|
35
|
+
this.addCharacteristicDelegate({
|
36
|
+
key: 'closedDuration',
|
37
|
+
Characteristic: this.Characteristics.eve.ClosedDuration,
|
38
|
+
value: 0
|
39
|
+
})
|
40
|
+
|
41
|
+
this.addCharacteristicDelegate({
|
42
|
+
key: 'lastActivation',
|
43
|
+
Characteristic: this.Characteristics.eve.LastActivation,
|
44
|
+
silent: true
|
45
|
+
})
|
46
|
+
|
47
|
+
this.addCharacteristicDelegates({ noTampered: true })
|
48
|
+
}
|
49
|
+
|
50
|
+
updateState (state) {
|
51
|
+
if (state.open != null) {
|
52
|
+
this.values.contact = state.open
|
53
|
+
? this.Characteristics.hap.ContactSensorState.CONTACT_NOT_DETECTED
|
54
|
+
: this.Characteristics.hap.ContactSensorState.CONTACT_DETECTED
|
55
|
+
}
|
56
|
+
super.updateState(state)
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
module.exports = Contact
|