homebridge-deconz 0.0.18 → 0.0.22

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 CHANGED
@@ -82,3 +82,6 @@ Allow ample time after exposing or removing accessories for HomeKit to sync the
82
82
  Homebridge deCONZ includes the `deconz` command-line utility, to discover,
83
83
  monitor, and interact with a deCONZ gateway.
84
84
  See the [`deconz` Tutorial](https://github.com/ebaauw/homebridge-deconz/wiki/%60deconz%60-Tutorial) in the Wiki for more info.
85
+
86
+ ### Troubleshooting
87
+ - As mentioned above, Homebridge deCONZ is still under development. Sometimes, cached accessories from an older version might confuse a newer version, causing all sorts of weird errors. In this case, best un-expose the offending accessory, wait for HomeKit to remove it, and re-expose the accessory. Note that this will cause HomeKit to see a new accessory, and lose any associations with HomeKit rooms, groups, scenes, and automations.
@@ -14,6 +14,13 @@
14
14
  "required": true,
15
15
  "default": "deCONZ"
16
16
  },
17
+ "brightnessAdjustment": {
18
+ "description": "Adjustment factor for brightness for adaptive lighting. Default: 100.",
19
+ "type": "integer",
20
+ "placeholder": 100,
21
+ "minimum": 10,
22
+ "maximum": 100
23
+ },
17
24
  "forceHttp": {
18
25
  "description": "Use plain http instead of https.",
19
26
  "type": "boolean"
@@ -94,6 +101,7 @@
94
101
  "title": "Advanced Settings",
95
102
  "description": "Don't change these, unless you understand what you're doing.",
96
103
  "items": [
104
+ "brightnessAdjustment",
97
105
  "forceHttp",
98
106
  "parallelRequests",
99
107
  "stealth",
@@ -144,13 +144,15 @@ class DeconzAccessory extends homebridgeLib.AccessoryDelegate {
144
144
  if (params.serviceName === 'Battery') {
145
145
  service = this.serviceByServiceName.Battery
146
146
  } else if (params.serviceName === 'Consumption') {
147
- service = this.serviceByServiceName.Light ||
147
+ service = this.serviceByServiceName.Outlet ||
148
+ this.serviceByServiceName.Light ||
148
149
  this.serviceByServiceName.Power
149
150
  if (service != null) {
150
151
  service.addResource(resource)
151
152
  }
152
153
  } else if (params.serviceName === 'Power') {
153
- service = this.serviceByServiceName.Light ||
154
+ service = this.serviceByServiceName.Outlet ||
155
+ this.serviceByServiceName.Light ||
154
156
  this.serviceByServiceName.Consumption
155
157
  if (service != null) {
156
158
  service.addResource(resource)
@@ -25,6 +25,7 @@ class DeconzPlatform extends homebridgeLib.Platform {
25
25
 
26
26
  parseConfigJson (configJson) {
27
27
  this.config = {
28
+ brightnessAdjustment: 100,
28
29
  forceHttp: false,
29
30
  hosts: [],
30
31
  noResponse: false,
@@ -44,6 +45,7 @@ class DeconzPlatform extends homebridgeLib.Platform {
44
45
  })
45
46
  .stringKey('name')
46
47
  .stringKey('platform')
48
+ .intKey('brightnessAdjustment', 10, 100)
47
49
  .boolKey('forceHttp')
48
50
  .stringKey('host')
49
51
  .arrayKey('hosts')
@@ -61,6 +63,7 @@ class DeconzPlatform extends homebridgeLib.Platform {
61
63
 
62
64
  try {
63
65
  optionParser.parse(configJson)
66
+ this.config.brightnessAdjustment /= 100
64
67
  if (this.config.host != null) {
65
68
  this.config.hosts.push(this.config.host)
66
69
  }
@@ -170,7 +173,8 @@ class DeconzPlatform extends homebridgeLib.Platform {
170
173
  }
171
174
  for (const id in this.gatewayMap) {
172
175
  const gateway = this.gatewayMap[id]
173
- dumpInfo.gatewayMap[id] = gateway.context
176
+ dumpInfo.gatewayMap[id] = Object.assign({}, gateway.context)
177
+ dumpInfo.gatewayMap[id].deviceById = gateway.deviceById
174
178
  }
175
179
  await this.createDumpFile(dumpInfo)
176
180
  } catch (error) { this.error(error) }
@@ -47,7 +47,7 @@ class FilterMaintenance extends DeconzService.SensorsResource {
47
47
  )
48
48
  }
49
49
  if (state.replacefilter != null) {
50
- this.values.filterChange = state.filterChange
50
+ this.values.filterChange = state.replacefilter
51
51
  ? this.Characteristics.hap.FilterChangeIndication.CHANGE_FILTER
52
52
  : this.Characteristics.hap.FilterChangeIndication.FILTER_OK
53
53
  }
@@ -158,16 +158,6 @@ class AirPurifier extends DeconzService.SensorsResource {
158
158
  }
159
159
 
160
160
  updateState (state) {
161
- if (this.values.filterLifeTime != null && state.filterruntime != null) {
162
- this.values.filterLifeLevel = 100 - Math.round(
163
- 100 * state.filterruntime / this.values.filterLifeTime
164
- )
165
- }
166
- if (state.replacefilter != null) {
167
- this.values.filterChange = state.replacefilter
168
- ? this.Characteristics.hap.FilterChangeIndication.CHANGE_FILTER
169
- : this.Characteristics.hap.FilterChangeIndication.FILTER_OK
170
- }
171
161
  if (state.speed != null) {
172
162
  this.values.active = state.speed > 0
173
163
  ? this.Characteristics.hap.Active.ACTIVE
@@ -31,6 +31,14 @@ class Consumption extends DeconzService.SensorsResource {
31
31
  unit: ' W'
32
32
  })
33
33
  }
34
+
35
+ if (service.values.lastUpdated === undefined) {
36
+ service.addCharacteristicDelegate({
37
+ key: 'lastUpdated',
38
+ Characteristic: service.Characteristics.my.LastUpdated,
39
+ silent: true
40
+ })
41
+ }
34
42
  }
35
43
 
36
44
  static updateResourceState (service, state) {
@@ -51,7 +59,7 @@ class Consumption extends DeconzService.SensorsResource {
51
59
 
52
60
  Consumption.addResource(this, resource)
53
61
 
54
- super.addCharacteristicDelegates()
62
+ super.addCharacteristicDelegates({ noLastUpdated: true })
55
63
 
56
64
  this.update(resource.body)
57
65
  }
@@ -92,11 +92,11 @@ class Light extends DeconzService.LightsResource {
92
92
  },
93
93
  value: this.resource.body.state.ct
94
94
  }).on('didSet', (value, fromHomeKit) => {
95
- this.checkAdaptiveLighting()
96
95
  const ct = Math.max(
97
96
  this.capabilities.ctMin, Math.min(value, this.capabilities.ctMax)
98
97
  )
99
98
  if (fromHomeKit) {
99
+ this.checkAdaptiveLighting()
100
100
  this.put({ ct })
101
101
  this.values.colormode = 'ct'
102
102
  }
@@ -190,6 +190,7 @@ class Light extends DeconzService.LightsResource {
190
190
  this.addCharacteristicDelegates()
191
191
 
192
192
  if (this.capabilities.bri && this.capabilities.ct && !this.capabilities.hs) {
193
+ this.adaptiveLightingNotInitialised = true
193
194
  this.addCharacteristicDelegate({
194
195
  key: 'supportedTransitionConfiguration',
195
196
  Characteristic: this.Characteristics.hap
@@ -214,7 +215,7 @@ class Light extends DeconzService.LightsResource {
214
215
  const response = this.adaptiveLighting.generateControlResponse()
215
216
  const parsedResponse = this.adaptiveLighting.parseControl(response)
216
217
  this.vdebug(
217
- 'Adaptive Lighting: control update: %j => %j',
218
+ 'adaptive lighting: control update: %j => %j',
218
219
  control, parsedResponse
219
220
  )
220
221
  this.values.activeTransitionCount = parsedResponse === '' ? 0 : 1
@@ -228,7 +229,7 @@ class Light extends DeconzService.LightsResource {
228
229
  silent: true,
229
230
  value: 0
230
231
  }).on('didSet', (value) => {
231
- this.log('Adaptive Lighting: %sabled', value > 0 ? 'en' : 'dis')
232
+ this.log('adaptive lighting: %sabled', value > 0 ? 'en' : 'dis')
232
233
  if (value) {
233
234
  this.updateAdaptiveLighting()
234
235
  }
@@ -314,7 +315,6 @@ class Light extends DeconzService.LightsResource {
314
315
  }
315
316
 
316
317
  this.settings = {
317
- brightnessAdjustment: 1,
318
318
  resetTimeout: this.platform.config.resetTimeout,
319
319
  waitTimeUpdate: this.platform.config.waitTimeUpdate,
320
320
  wallSwitch: false
@@ -322,9 +322,11 @@ class Light extends DeconzService.LightsResource {
322
322
  }
323
323
 
324
324
  updateState (state) {
325
+ this.initAdaptiveLighting()
325
326
  let updateAdaptiveLighting = false
326
327
  for (const key in state) {
327
328
  const value = state[key]
329
+ // const oldValue = this.resource.body.state[key]
328
330
  this.resource.body.state[key] = value
329
331
  switch (key) {
330
332
  case 'all_on':
@@ -427,7 +429,8 @@ class Light extends DeconzService.LightsResource {
427
429
  }
428
430
 
429
431
  initAdaptiveLighting () {
430
- if (this.adaptiveLighting == null) {
432
+ if (this.adaptiveLightingNotInitialised) {
433
+ delete this.adaptiveLightingNotInitialised
431
434
  this.adaptiveLighting = new homebridgeLib.AdaptiveLighting(
432
435
  this.brightnessDelegate, this.colorTemperatureDelegate
433
436
  )
@@ -435,11 +438,11 @@ class Light extends DeconzService.LightsResource {
435
438
  const control = this.adaptiveLighting.parseControl(
436
439
  this.context.transitionControl
437
440
  )
438
- this.vdebug('Adaptive Lighting: restore control: %j', control)
441
+ this.vdebug('adaptive lighting: restore control: %j', control)
439
442
  this.adaptiveLighting.parseControl(this.context.transitionControl)
440
443
  }
441
444
  this.log(
442
- 'Adaptive Lighting: %sabled',
445
+ 'adaptive lighting: %sabled',
443
446
  this.values.activeTransitionCount > 0 ? 'en' : 'dis'
444
447
  )
445
448
  }
@@ -454,24 +457,21 @@ class Light extends DeconzService.LightsResource {
454
457
  return
455
458
  }
456
459
  const ct = this.adaptiveLighting.getCt(
457
- this.values.brightness * this.settings.brightnessAdjustment
460
+ this.values.brightness * this.platform.config.brightnessAdjustment
458
461
  )
459
462
  if (ct == null) {
460
- this.warn('assertion failed')
463
+ this.warn('adaptive lighting: cannot compute Color Temperature')
461
464
  return
462
465
  }
463
- this.debug(
464
- '/%s/%d: adaptive lighting: {"state":{"ct": %d}}',
465
- this.rtype, this.rid, ct
466
- )
467
466
  if (this.values.colormode === 'ct' && ct === this.values.colorTemperature) {
468
467
  return
469
468
  }
469
+ this.debug('adaptive lighting: set Color Temperature to %d mired', ct)
470
470
  this.put({ ct })
471
471
  this.fromAdaptiveLighting = true
472
472
  this.values.colormode = 'ct'
473
473
  if (ct !== this.values.colorTemperature) {
474
- this.values.colorTemperature = ct
474
+ this.values.colorTemperature = ct // should only do this when PUT succeeds
475
475
  } else if (this.capabilities.xy) { // colormode changed
476
476
  const { h, s } = xyToHsv(ctToXy(ct), this.capabilities.gamut)
477
477
  this.values.hue = h
@@ -17,6 +17,7 @@ class LightsResource extends DeconzService {
17
17
  super(accessory, resource, params)
18
18
  this.rpath += resource.rtype === 'groups' ? '/action' : '/state'
19
19
 
20
+ this.updating = 0
20
21
  this.targetState = {}
21
22
  this.deferrals = []
22
23
  }
@@ -65,16 +66,15 @@ class LightsResource extends DeconzService {
65
66
  // Send the request (for the combined changes) to the gateway.
66
67
  async _put () {
67
68
  try {
68
- if (this.updating) {
69
- return
70
- }
71
- this.updating = true
72
69
  if (this.platform.config.waitTimeUpdate > 0) {
70
+ this.updating++
73
71
  await timeout(this.platform.config.waitTimeUpdate)
72
+ if (--this.updating > 0) {
73
+ return
74
+ }
74
75
  }
75
76
  const targetState = this.targetState
76
77
  this.targetState = {}
77
- this.updating = false
78
78
  if (
79
79
  this.gateway.transitionTime !== this.gateway.defaultTransitionTime &&
80
80
  targetState.transitiontime === undefined
@@ -69,7 +69,7 @@ class Power extends DeconzService.SensorsResource {
69
69
 
70
70
  Power.addResource(this, resource)
71
71
 
72
- super.addCharacteristicDelegates()
72
+ super.addCharacteristicDelegates({ noLastUpdated: true })
73
73
 
74
74
  this.update(resource.body)
75
75
  }
@@ -29,13 +29,13 @@ class Switch extends DeconzService.SensorsResource {
29
29
  }
30
30
 
31
31
  createButtonServices (resource) {
32
- if (resource.body.type === 'ZHASwitch') {
32
+ if (resource.body.type.endsWith('Switch')) {
33
33
  this.buttonResources[resource.rpath] = {
34
34
  buttonEvent: resource.body.state.buttonevent,
35
35
  lastUpdated: '',
36
36
  toButtonEvent: resource.capabilities.toButtonEvent
37
37
  }
38
- } else if (resource.body.type === 'ZHARelativeRotary') {
38
+ } else if (resource.body.type.endsWith('RelativeRotary')) {
39
39
  const keys = Object.keys(resource.capabilities.buttons)
40
40
  this.buttonResources[resource.rpath] = {
41
41
  lastUpdated: '',
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.18",
7
+ "version": "0.0.22",
8
8
  "keywords": [
9
9
  "homebridge-plugin",
10
10
  "homekit",
@@ -22,10 +22,10 @@
22
22
  "engines": {
23
23
  "deCONZ": "2.17.1",
24
24
  "homebridge": "^1.5.0",
25
- "node": "^16.16.0"
25
+ "node": "^16.17.0"
26
26
  },
27
27
  "dependencies": {
28
- "homebridge-lib": "~5.6.4",
28
+ "homebridge-lib": "~5.6.5",
29
29
  "semver": "^7.3.7",
30
30
  "ws": "^8.8.1",
31
31
  "xml2js": "~0.4.23"