homebridge-deconz 0.0.27 → 0.1.1

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 (39) hide show
  1. package/config.schema.json +0 -7
  2. package/lib/Deconz/Resource.js +27 -4
  3. package/lib/DeconzAccessory/AirPurifier.js +0 -2
  4. package/lib/DeconzAccessory/Gateway.js +298 -149
  5. package/lib/DeconzAccessory/Light.js +27 -37
  6. package/lib/DeconzAccessory/Sensor.js +91 -1
  7. package/lib/DeconzAccessory/Thermostat.js +1 -3
  8. package/lib/DeconzAccessory/WarningDevice.js +0 -8
  9. package/lib/DeconzAccessory/WindowCovering.js +0 -2
  10. package/lib/DeconzAccessory/index.js +123 -13
  11. package/lib/DeconzPlatform.js +12 -20
  12. package/lib/DeconzService/AirPressure.js +1 -1
  13. package/lib/DeconzService/AirPurifier.js +2 -2
  14. package/lib/DeconzService/AirQuality.js +1 -1
  15. package/lib/DeconzService/Alarm.js +1 -1
  16. package/lib/DeconzService/Battery.js +19 -9
  17. package/lib/DeconzService/Button.js +1 -0
  18. package/lib/DeconzService/CarbonMonoxide.js +1 -1
  19. package/lib/DeconzService/Consumption.js +3 -1
  20. package/lib/DeconzService/Contact.js +1 -25
  21. package/lib/DeconzService/Daylight.js +22 -19
  22. package/lib/DeconzService/Flag.js +1 -1
  23. package/lib/DeconzService/Gateway.js +48 -0
  24. package/lib/DeconzService/Humidity.js +1 -1
  25. package/lib/DeconzService/Leak.js +1 -1
  26. package/lib/DeconzService/Light.js +111 -86
  27. package/lib/DeconzService/LightLevel.js +3 -3
  28. package/lib/DeconzService/Motion.js +3 -9
  29. package/lib/DeconzService/Power.js +2 -1
  30. package/lib/DeconzService/Status.js +1 -1
  31. package/lib/DeconzService/Switch.js +1 -1
  32. package/lib/DeconzService/WindowCovering.js +14 -4
  33. package/lib/DeconzService/index.js +11 -12
  34. package/package.json +6 -6
  35. package/lib/DeconzAccessory/Contact.js +0 -53
  36. package/lib/DeconzAccessory/Motion.js +0 -53
  37. package/lib/DeconzAccessory/Temperature.js +0 -61
  38. package/lib/DeconzService/DeviceSettings.js +0 -65
  39. package/lib/DeconzService/GatewaySettings.js +0 -176
@@ -47,55 +47,45 @@ class Light extends DeconzAccessory {
47
47
  }
48
48
  }
49
49
 
50
- if (this.serviceByServiceName.Consumption != null) {
51
- // Current Consumption to be computed by history if not exposed by device
52
- const currentConsumption =
53
- this.service.values.currentConsumption === undefined
54
- ? this.service.addCharacteristicDelegate({
55
- key: 'currentConsumption',
56
- Characteristic: this.Characteristics.eve.CurrentConsumption,
57
- unit: ' W'
58
- })
59
- : null
60
- this.service.addCharacteristicDelegate({
61
- key: 'lockPhysicalControls',
62
- Characteristic: this.Characteristics.hap.LockPhysicalControls
63
- })
64
- this.historyService = new History.Consumption(this, {
65
- consumptionDelegate: this.service.characteristicDelegate('totalConsumption'),
66
- powerDelegate: currentConsumption,
67
- onDelegate: this.service.characteristicDelegate('on')
68
- })
69
- } else if (this.serviceByServiceName.Power != null) {
70
- // Total Consumption to be computed by history
71
- const TotalConsumption = this.service.addCharacteristicDelegate({
72
- key: 'totalConsumption',
73
- Characteristic: this.Characteristics.eve.TotalConsumption,
74
- unit: ' kWh',
75
- value: 0
76
- })
50
+ const params = {}
51
+ if (this.values.serviceName === 'Outlet') {
77
52
  this.service.addCharacteristicDelegate({
78
53
  key: 'lockPhysicalControls',
79
54
  Characteristic: this.Characteristics.hap.LockPhysicalControls
80
55
  })
81
- this.historyService = new History.Power(this, {
82
- powerDelegate: this.service.characteristicDelegate('currentConsumption'),
83
- consumptionDelegate: TotalConsumption,
84
- onDelegate: this.service.characteristicDelegate('on')
56
+ params.onDelegate = this.service.characteristicDelegate('on')
57
+ params.lastOnDelegate = this.service.addCharacteristicDelegate({
58
+ key: 'lastActivation',
59
+ Characteristic: this.Characteristics.eve.LastActivation,
60
+ silent: true
85
61
  })
86
62
  } else {
87
- const lastActivation = this.service.addCharacteristicDelegate({
63
+ params.lightOnDelegate = this.service.characteristicDelegate('on')
64
+ params.lastLightOnDelegate = this.service.addCharacteristicDelegate({
88
65
  key: 'lastActivation',
89
66
  Characteristic: this.Characteristics.eve.LastActivation,
90
67
  silent: true
91
68
  })
92
- this.historyService = new History.Light(this, {
93
- onDelegate: this.service.characteristicDelegate('on'),
94
- lastActivationDelegate: lastActivation
69
+ }
70
+ if (this.serviceByServiceName.Consumption != null) {
71
+ params.consumptionDelegate = this.service.characteristicDelegate('totalConsumption')
72
+ if (this.service.values.currentConsumption === undefined) {
73
+ // Current Consumption to be computed by history if not exposed by device
74
+ params.computedPowerDelegate = this.service.addCharacteristicDelegate({
75
+ key: 'currentConsumption',
76
+ Characteristic: this.Characteristics.eve.CurrentConsumption,
77
+ unit: ' W'
78
+ })
79
+ }
80
+ } else if (this.serviceByServiceName.Power != null) {
81
+ // Total Consumption to be computed by history
82
+ params.computedConsumptionDelegate = this.service.addCharacteristicDelegate({
83
+ key: 'totalConsumption',
84
+ Characteristic: this.Characteristics.eve.TotalConsumption,
85
+ unit: ' kWh'
95
86
  })
96
87
  }
97
-
98
- this.createSettingsService()
88
+ this.historyService = new History(this, params)
99
89
 
100
90
  setImmediate(() => {
101
91
  this.debug('initialised')
@@ -5,8 +5,11 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ const homebridgeLib = require('homebridge-lib')
8
9
  const DeconzAccessory = require('../DeconzAccessory')
9
10
 
11
+ const { History } = homebridgeLib.ServiceDelegate
12
+
10
13
  class Sensor extends DeconzAccessory {
11
14
  constructor (gateway, device) {
12
15
  super(gateway, device, gateway.Accessory.Categories.SENSOR)
@@ -23,7 +26,94 @@ class Sensor extends DeconzAccessory {
23
26
  this.createService(resource)
24
27
  }
25
28
 
26
- this.createSettingsService()
29
+ switch (device.resource.serviceName) {
30
+ case 'Daylight':
31
+ case 'LightLevel':
32
+ // Create dummy motion sensor service.
33
+ this.motionService = new homebridgeLib.ServiceDelegate(this, {
34
+ name: this.name + ' Motion',
35
+ Service: this.Services.hap.MotionSensor,
36
+ hidden: true
37
+ })
38
+ this.motionService.addCharacteristicDelegate({
39
+ key: 'motion',
40
+ Characteristic: this.Characteristics.hap.MotionDetected,
41
+ props: {
42
+ perms: [
43
+ this.Characteristic.Perms.PAIRED_READ,
44
+ this.Characteristic.Perms.NOTIFY,
45
+ this.Characteristic.Perms.HIDDEN
46
+ ]
47
+ },
48
+ value: 0
49
+ })
50
+ break
51
+ default:
52
+ break
53
+ }
54
+
55
+ const params = {}
56
+ if (this.serviceByServiceName.Contact != null) {
57
+ const service = this.serviceByServiceName.Contact
58
+ params.contactDelegate = service.characteristicDelegate('contact')
59
+ params.lastContactDelegate = this.service.addCharacteristicDelegate({
60
+ key: 'lastActivation',
61
+ Characteristic: this.Characteristics.eve.LastActivation,
62
+ silent: true
63
+ })
64
+ params.timesOpenedDelegate = this.service.addCharacteristicDelegate({
65
+ key: 'timesOpened',
66
+ Characteristic: this.Characteristics.eve.TimesOpened,
67
+ silent: true
68
+ })
69
+ }
70
+ if (this.serviceByServiceName.Motion != null) {
71
+ const service = this.serviceByServiceName.Motion
72
+ params.motionDelegate = service.characteristicDelegate('motion')
73
+ params.lastMotionDelegate = this.service.addCharacteristicDelegate({
74
+ key: 'lastActivation',
75
+ Characteristic: this.Characteristics.eve.LastActivation,
76
+ silent: true
77
+ })
78
+ }
79
+ if (this.serviceByServiceName.LightLevel != null) {
80
+ const service = this.serviceByServiceName.LightLevel
81
+ params.lightLevelDelegate = service.characteristicDelegate('lightLevel')
82
+ }
83
+ if (this.serviceByServiceName.Daylight != null) {
84
+ const service = this.serviceByServiceName.Daylight
85
+ params.lightLevelDelegate = service.characteristicDelegate('lightLevel')
86
+ }
87
+ if (this.serviceByServiceName.Temperature != null) {
88
+ const service = this.serviceByServiceName.Temperature
89
+ params.temperatureDelegate = service.characteristicDelegate('temperature')
90
+ }
91
+ if (this.serviceByServiceName.Humidity != null) {
92
+ const service = this.serviceByServiceName.Humidity
93
+ params.humidityDelegate = service.characteristicDelegate('humidity')
94
+ }
95
+ if (this.serviceByServiceName.AirPressure != null) {
96
+ const service = this.serviceByServiceName.AirPressure
97
+ params.airPressureDelegate = service.characteristicDelegate('airPressure')
98
+ }
99
+ if (this.serviceByServiceName.AirQuality != null) {
100
+ const service = this.serviceByServiceName.AirQuality
101
+ if (service.characteristicDelegate('vocDensity') != null) {
102
+ params.vocDensityDelegate = service.characteristicDelegate('vocDensity')
103
+ }
104
+ }
105
+ if (this.serviceByServiceName.Flag != null) {
106
+ const service = this.serviceByServiceName.Flag
107
+ params.switchOnDelegate = service.characteristicDelegate('on')
108
+ params.lastSwitchOnDelegate = this.service.addCharacteristicDelegate({
109
+ key: 'lastActivation',
110
+ Characteristic: this.Characteristics.eve.LastActivation,
111
+ silent: true
112
+ })
113
+ }
114
+ if (Object.keys(params).length > 0) {
115
+ this.historyService = new History(this, params)
116
+ }
27
117
 
28
118
  setImmediate(() => {
29
119
  this.debug('initialised')
@@ -30,15 +30,13 @@ class Thermostat extends DeconzAccessory {
30
30
  }
31
31
 
32
32
  if (device.resource.body.state.valve !== undefined) {
33
- this.historyService = new History.Thermo(this, {
33
+ this.historyService = new History(this, {
34
34
  temperatureDelegate: this.service.characteristicDelegate('currentTemperature'),
35
35
  targetTemperatureDelegate: this.service.characteristicDelegate('targetTemperature'),
36
36
  valvePositionDelegate: this.service.characteristicDelegate('valvePosition')
37
37
  })
38
38
  }
39
39
 
40
- this.createSettingsService()
41
-
42
40
  setImmediate(() => {
43
41
  this.debug('initialised')
44
42
  this.emit('initialised')
@@ -35,14 +35,6 @@ class WarningDevice extends DeconzAccessory {
35
35
  this.createService(resource)
36
36
  }
37
37
 
38
- // if (this.serviceByServiceName.Temperature != null) {
39
- // this.historyService = new History.Weather(this, {
40
- // temperatureDelegate: this.serviceByServiceName.Temperature.characteristicDelegate('temperature')
41
- // })
42
- // }
43
-
44
- this.createSettingsService()
45
-
46
38
  setImmediate(() => {
47
39
  this.debug('initialised')
48
40
  this.emit('initialised')
@@ -35,8 +35,6 @@ class WindowCovering extends DeconzAccessory {
35
35
  this.createService(resource)
36
36
  }
37
37
 
38
- this.createSettingsService()
39
-
40
38
  setImmediate(() => {
41
39
  this.debug('initialised')
42
40
  this.emit('initialised')
@@ -6,6 +6,7 @@
6
6
  'use strict'
7
7
 
8
8
  const homebridgeLib = require('homebridge-lib')
9
+ const { OptionParser } = homebridgeLib
9
10
  const Deconz = require('../Deconz')
10
11
  const DeconzService = require('../DeconzService')
11
12
 
@@ -17,12 +18,9 @@ const { SINGLE, DOUBLE, LONG } = DeconzService.Button
17
18
  * @extends AccessoryDelegate
18
19
  */
19
20
  class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
20
- static get Contact () { return require('./Contact') }
21
21
  static get Light () { return require('./Light') }
22
22
  static get Gateway () { return require('./Gateway') }
23
- static get Motion () { return require('./Motion') }
24
23
  static get Sensor () { return require('./Sensor') }
25
- static get Temperature () { return require('./Temperature') }
26
24
  static get WarningDevice () { return require('./WarningDevice') }
27
25
  static get WindowCovering () { return require('./WindowCovering') }
28
26
 
@@ -41,6 +39,7 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
41
39
  firmware: device.resource.firmware,
42
40
  category
43
41
  })
42
+ this.values.logLevel = gateway.logLevel
44
43
 
45
44
  this.context.gid = gateway.id
46
45
 
@@ -203,16 +202,127 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
203
202
  return service
204
203
  }
205
204
 
206
- createSettingsService (params = {}) {
207
- this.settingsService = new DeconzService.DeviceSettings(this, {
208
- name: this.name + ' Settings',
209
- subtype: this.id,
210
- resource: this.device.rpaths.join(', '),
211
- expose: true,
212
- logLevel: this.gateway.logLevel,
213
- hasRepeat: this.service.hasRepeat
214
- })
215
- this.manageLogLevel(this.settingsService.characteristicDelegate('logLevel'))
205
+ settings = {
206
+ anyOn: { service: 'Lightbulb', type: 'bool' },
207
+ buttonRepeat: { service: 'Button', type: 'boolMap' },
208
+ effects: { service: 'Light', type: 'boolMap' },
209
+ expose: { type: 'bool' },
210
+ logLevel: { type: 'int', min: 0, max: 3 },
211
+ lowBatteryThreshold: { service: 'Battery', type: 'int', min: 10, max: 100, factor: 100 },
212
+ offset: { service: 'Temperature', type: 'number', min: -5, max: 5 },
213
+ splitLight: { service: 'Light' }
214
+ }
215
+
216
+ onUiGet (details = false) {
217
+ const resource = this.device.resourceBySubtype[this.device.primary]
218
+ const body = {
219
+ id: details ? this.id : undefined,
220
+ manufacturer: this.values.manufacturer,
221
+ model: this.values.model,
222
+ name: this.name,
223
+ resources: this.device.rpaths,
224
+ settings: details
225
+ ? {
226
+ anyOn: this.device.resource.rtype === 'groups'
227
+ ? this.values.anyOn
228
+ : undefined,
229
+ buttonRepeat: undefined, // map per button
230
+ expose: true,
231
+ exposeEffects: this.service.values.exposeEffects,
232
+ exposeScenes: this.service.values.exposeScenes,
233
+ multiClip: undefined,
234
+ multiLight: undefined,
235
+ logLevel: this.logLevel,
236
+ lowBatteryThreshold: this.serviceByServiceName.Battery == null
237
+ ? undefined
238
+ : this.serviceByServiceName.Battery.values.lowBatteryThreshold,
239
+ // offset: this.serviceByServiceName.Temperature == null
240
+ // ? undefined
241
+ // : this.serviceByServiceName.Temperature.values.offset,
242
+ serviceName: this.values.serviceName,
243
+ splitLight: undefined,
244
+ venetianBlind: this.service.values.venetianBlind,
245
+ wallSwitch: undefined
246
+ }
247
+ : undefined,
248
+ type: resource.rtype,
249
+ zigbee: this.device.zigbee
250
+ }
251
+ return { status: 200, body }
252
+ }
253
+
254
+ onUiPut (body) {
255
+ let reExpose = false
256
+ const responseBody = {}
257
+ for (const key in body) {
258
+ try {
259
+ let value
260
+ switch (key) {
261
+ case 'expose':
262
+ value = OptionParser.toBool(key, body[key])
263
+ if (value) {
264
+ reExpose = true
265
+ } else {
266
+ this.gateway.exposeDevice(this.id, value)
267
+ }
268
+ responseBody[key] = value
269
+ continue
270
+ // Settings for the primary service.
271
+ case 'anyOn':
272
+ case 'exposeEffects':
273
+ case 'exposeScenes':
274
+ case 'venetianBlind':
275
+ if (this.service.values[key] != null) {
276
+ value = OptionParser.toBool(key, body[key])
277
+ this.service.values[key] = value
278
+ reExpose = true
279
+ responseBody[key] = value
280
+ continue
281
+ }
282
+ break
283
+ case 'logLevel':
284
+ value = OptionParser.toInt(key, body[key], 0, 1)
285
+ this.values[key] = value
286
+ responseBody[key] = value
287
+ continue
288
+ case 'lowBatteryThreshold':
289
+ if (this.serviceByServiceName.Battery != null) {
290
+ value = OptionParser.toInt(key, body[key], 10, 100)
291
+ this.serviceByServiceName.Battery.values[key] = value
292
+ responseBody[key] = value
293
+ continue
294
+ }
295
+ break
296
+ // case 'offset': // TODO: doesn't work because of fromHomeKit
297
+ // if (this.serviceByServiceName.Temperature != null) {
298
+ // const value = OptionParser.toNumber(key, body[key], -5, 5)
299
+ // this.serviceByServiceName.Temperature.values[key] = value
300
+ // responseBody[key] = value
301
+ // continue
302
+ // }
303
+ // break
304
+ case 'serviceName':
305
+ if (this.values.serviceName != null) {
306
+ value = OptionParser.toString(key, body[key])
307
+ if (DeconzService[value] == null) {
308
+ throw new Error(`${value}: illegal serviceName`)
309
+ }
310
+ this.values.serviceName = value
311
+ reExpose = true
312
+ responseBody[key] = value
313
+ continue
314
+ }
315
+ break
316
+ default:
317
+ break
318
+ }
319
+ this.warn('ui error: %s: invalid key', key)
320
+ } catch (error) { this.warn('ui error: %s', error) }
321
+ }
322
+ if (reExpose) {
323
+ this.gateway.reExposeAccessory(this.id)
324
+ }
325
+ return { status: 200, body: responseBody }
216
326
  }
217
327
  }
218
328
 
@@ -45,7 +45,6 @@ class DeconzPlatform extends homebridgeLib.Platform {
45
45
  })
46
46
  .stringKey('name')
47
47
  .stringKey('platform')
48
- .intKey('brightnessAdjustment', 10, 100)
49
48
  .boolKey('forceHttp')
50
49
  .stringKey('host')
51
50
  .arrayKey('hosts')
@@ -63,7 +62,6 @@ class DeconzPlatform extends homebridgeLib.Platform {
63
62
 
64
63
  try {
65
64
  optionParser.parse(configJson)
66
- this.config.brightnessAdjustment /= 100
67
65
  if (this.config.host != null) {
68
66
  this.config.hosts.push(this.config.host)
69
67
  }
@@ -181,42 +179,36 @@ class DeconzPlatform extends homebridgeLib.Platform {
181
179
  }
182
180
 
183
181
  async onUiRequest (method, url, body) {
184
- const a = url.split('/').slice(1)
185
- if (a.length < 1) {
182
+ const path = url.split('/').slice(1)
183
+ if (path.length < 1) {
186
184
  return { status: 403 } // Forbidden
187
185
  }
188
- if (a[0] === 'gateways') {
189
- if (a.length === 1) {
186
+ if (path[0] === 'gateways') {
187
+ if (path.length === 1) {
190
188
  if (method === 'GET') {
191
189
  // const gatewayByHost = await this.discovery.discover()
192
- const gatewayByHost = {}
193
- for (const id in this.gatewayMap) {
190
+ const body = {}
191
+ for (const id of Object.keys(this.gatewayMap).sort()) {
194
192
  const gateway = this.gatewayMap[id]
195
- gatewayByHost[gateway.context.host] = {
193
+ body[gateway.values.host] = {
196
194
  config: gateway.context.config,
197
- host: gateway.context.host,
195
+ host: gateway.values.host,
198
196
  id
199
197
  }
200
198
  }
201
- return {
202
- status: 200,
203
- body: Object.keys(gatewayByHost).sort().map((host) => {
204
- return gatewayByHost[host]
205
- })
206
- }
199
+ return { status: 200, body }
207
200
  }
208
201
  return { status: 405 } // Method Not Allowed
209
202
  }
210
- const gateway = this.gatewayMap[a[1]]
211
- const path = a.slice(2)
203
+ const gateway = this.gatewayMap[path[1]]
212
204
  if (gateway == null) {
213
205
  return { status: 404 } // Not Found
214
206
  }
215
207
  if (method === 'GET') {
216
- return gateway.onUiGet(path)
208
+ return gateway.onUiGet(path.slice(2))
217
209
  }
218
210
  if (method === 'PUT') {
219
- return gateway.onUiPut(path, body)
211
+ return gateway.onUiPut(path.slice(2), body)
220
212
  }
221
213
  return { status: 405 } // Method Not Allowed
222
214
  }
@@ -35,7 +35,7 @@ class AirPressure extends DeconzService.SensorsResource {
35
35
 
36
36
  this.addCharacteristicDelegates()
37
37
 
38
- this.update(resource.body)
38
+ this.update(resource.body, resource.rpath)
39
39
  }
40
40
 
41
41
  updateState (state) {
@@ -37,7 +37,7 @@ class FilterMaintenance extends DeconzService.SensorsResource {
37
37
  this.values.filterLifeTime = resource.body.config.filterlifetime
38
38
  }
39
39
 
40
- this.update(resource.body)
40
+ this.update(resource.body, resource.rpath)
41
41
  }
42
42
 
43
43
  updateState (state) {
@@ -137,7 +137,7 @@ class AirPurifier extends DeconzService.SensorsResource {
137
137
 
138
138
  super.addCharacteristicDelegates()
139
139
 
140
- this.update(resource.body)
140
+ this.update(resource.body, resource.rpath)
141
141
  }
142
142
 
143
143
  modeValue (
@@ -42,7 +42,7 @@ class AirQuality extends DeconzService.SensorsResource {
42
42
  super.addCharacteristicDelegates()
43
43
  }
44
44
 
45
- this.update(resource.body)
45
+ this.update(resource.body, resource.rpath)
46
46
  }
47
47
 
48
48
  airQualityValue (value) {
@@ -22,7 +22,7 @@ class Alarm extends DeconzService.SensorsResource {
22
22
 
23
23
  super.addCharacteristicDelegates(params)
24
24
 
25
- this.update(resource.body)
25
+ this.update(resource.body, resource.rpath)
26
26
  }
27
27
 
28
28
  updateState (state) {
@@ -5,10 +5,9 @@
5
5
 
6
6
  'use strict'
7
7
 
8
+ const Deconz = require('../Deconz')
8
9
  const homebridgeLib = require('homebridge-lib')
9
- // const Deconz = require('../Deconz')
10
-
11
- // const { dateToString } = Deconz.ApiClient
10
+ const { dateToString } = Deconz.ApiClient
12
11
 
13
12
  /**
14
13
  * @memberof DeconzService
@@ -19,9 +18,19 @@ class Battery extends homebridgeLib.ServiceDelegate.Battery {
19
18
  name: accessory.name + ' Battery',
20
19
  exposeConfiguredName: true
21
20
  })
21
+
22
+ if (resource.body.state.battery != null) {
23
+ this.addCharacteristicDelegate({
24
+ key: 'lastUpdated',
25
+ Characteristic: this.Characteristics.my.LastUpdated,
26
+ silent: true
27
+ })
28
+ }
29
+
30
+ this.update(resource.body, resource.rpath)
22
31
  }
23
32
 
24
- update (body) {
33
+ update (body, rpath) {
25
34
  if (this.updating) {
26
35
  return
27
36
  }
@@ -36,11 +45,12 @@ class Battery extends homebridgeLib.ServiceDelegate.Battery {
36
45
  updateState (state) {
37
46
  if (state.battery != null) {
38
47
  this.values.batteryLevel = state.battery
39
- }
40
- if (state.charging != null) {
41
- this.values.chargingState = state.charging
42
- ? this.Characteristics.hap.ChargingState.CHARGING
43
- : this.Characteristics.hap.ChargingState.NOT_CHARGING
48
+ if (state.charging != null) {
49
+ this.values.chargingState = state.charging
50
+ ? this.Characteristics.hap.ChargingState.CHARGING
51
+ : this.Characteristics.hap.ChargingState.NOT_CHARGING
52
+ }
53
+ this.values.lastUpdated = dateToString(state.lastupdated)
44
54
  }
45
55
  }
46
56
 
@@ -107,6 +107,7 @@ class Button extends homebridgeLib.ServiceDelegate {
107
107
  constructor (deconzAccessory, params = {}) {
108
108
  params.Service = deconzAccessory.Services.hap.StatelessProgrammableSwitch
109
109
  params.subtype = params.button
110
+ params.exposeConfiguredName = true
110
111
  super(deconzAccessory, params)
111
112
  this.button = params.button
112
113
 
@@ -22,7 +22,7 @@ class CarbonMonoxide extends DeconzService.SensorsResource {
22
22
 
23
23
  super.addCharacteristicDelegates(params)
24
24
 
25
- this.update(resource.body)
25
+ this.update(resource.body, resource.rpath)
26
26
  }
27
27
 
28
28
  updateState (state) {
@@ -39,6 +39,8 @@ class Consumption extends DeconzService.SensorsResource {
39
39
  silent: true
40
40
  })
41
41
  }
42
+
43
+ service.update(resource.body, resource.rpath)
42
44
  }
43
45
 
44
46
  static updateResourceState (service, state) {
@@ -61,7 +63,7 @@ class Consumption extends DeconzService.SensorsResource {
61
63
 
62
64
  super.addCharacteristicDelegates({ noLastUpdated: true })
63
65
 
64
- this.update(resource.body)
66
+ this.update(resource.body, resource.rpath)
65
67
  }
66
68
 
67
69
  updateState (state) {
@@ -20,33 +20,9 @@ class Contact extends DeconzService.SensorsResource {
20
20
  Characteristic: this.Characteristics.hap.ContactSensorState
21
21
  })
22
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
23
  this.addCharacteristicDelegates({ noTampered: true })
48
24
 
49
- this.update(resource.body)
25
+ this.update(resource.body, resource.rpath)
50
26
  }
51
27
 
52
28
  updateState (state) {