homebridge-lib 6.3.3 → 6.3.5

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.
@@ -34,6 +34,7 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
34
34
  * @param {!string} params.firmware - The accessory firmware revision.
35
35
  * @param {?string} params.hardware - The accessory hardware revision.
36
36
  * @param {?string} params.software - The accessory software revision.
37
+ * @param {?integer} params.logLevel - The log level for the accessory
37
38
  */
38
39
  constructor (platform, params = {}) {
39
40
  if (params.name == null) {
@@ -46,6 +47,9 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
46
47
  if (params.id === '') {
47
48
  throw new RangeError('params.id: invalid id')
48
49
  }
50
+ if (params.logLevel == null) {
51
+ params.logLevel = platform.logLevel
52
+ }
49
53
 
50
54
  // Link or create associated PlatformAccessory.
51
55
  this._accessory = this._platform._getAccessory(this, params)
@@ -59,10 +63,13 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
59
63
  this.addPropertyDelegate({ key: 'version', silent: true })
60
64
  this.values.version = platform.packageJson.version
61
65
  this.addPropertyDelegate({ key: 'id', value: params.id, silent: true })
62
- this.addPropertyDelegate({ key: 'logLevel', value: platform.logLevel })
66
+ this.addPropertyDelegate({ key: 'logLevel', value: params.logLevel })
63
67
  this.addPropertyDelegate({ key: 'name', value: this.name, silent: true })
64
68
  .on('didSet', (name) => { this.name = name })
65
- this.addPropertyDelegate({ key: 'uiPort', silent: true })
69
+ if (platform._ui != null) {
70
+ this._context.uiPort = platform._ui.port
71
+ this.addPropertyDelegate({ key: 'uiPort', silent: true })
72
+ }
66
73
 
67
74
  // Create delegate for AccessoryInformation service.
68
75
  this._serviceDelegates = {}
@@ -109,9 +116,22 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
109
116
  })
110
117
  }
111
118
 
112
- // Remove associated accessory from platform
113
- destroy () {
119
+ /** Destroy accessory delegate and associated HomeKit accessory.
120
+ * @params {boolean} [delegateOnly=false] - Destroy the delegate, but keep the
121
+ * associated HomeKit accessory (including context).
122
+ */
123
+ destroy (delegateOnly = false) {
114
124
  this.removeAllListeners()
125
+ for (const key in this._serviceDelegates) {
126
+ this._serviceDelegates[key].destroy(delegateOnly)
127
+ }
128
+ for (const key in this._propertyDelegates) {
129
+ this._propertyDelegates[key]._destroy(delegateOnly)
130
+ }
131
+ if (delegateOnly) {
132
+ this._accessory.removeAllListeners()
133
+ return
134
+ }
115
135
  this._platform._removeAccessory(this._accessory)
116
136
  }
117
137
 
@@ -122,10 +142,13 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
122
142
  return serviceDelegate
123
143
  }
124
144
 
125
- _unlinkServiceDelegate (serviceDelegate) {
145
+ _unlinkServiceDelegate (serviceDelegate, delegateOnly) {
126
146
  const key = serviceDelegate._key
127
147
  // this.debug('unlink service %s', key)
128
148
  delete this._serviceDelegates[key]
149
+ if (delegateOnly) {
150
+ return
151
+ }
129
152
  delete this._context[key]
130
153
  }
131
154
 
@@ -136,6 +136,7 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
136
136
  // Install getter and setter when needed.
137
137
  if (params.getter != null && typeof params.getter === 'function') {
138
138
  this._getter = params.getter
139
+ this._onGetCount = 0
139
140
  this._characteristic.on('get', this._onGet.bind(this))
140
141
  }
141
142
  if (this._canWrite && Characteristic !== this.Characteristics.hap.Identify) {
@@ -167,13 +168,21 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
167
168
  }
168
169
  }
169
170
 
170
- /** Destroy the HomeKit characteristic delegate.
171
- *
172
- * Removes the associated HomeKit characteristic.
171
+ /** Destroy characteristic delegate and delete associated HomeKit characteristic.
172
+ * @params {boolean} [delegateOnly=false] - Destroy the delegate, but keep the
173
+ * associated HomeKit characteristic (including context).
173
174
  */
174
- _destroy () {
175
+ _destroy (delegateOnly = false) {
175
176
  this.debug('destroy %s', this._key)
176
177
  this.removeAllListeners()
178
+ if (delegateOnly) {
179
+ if (this._characteristic != null) {
180
+ // this._characteristic.removeAllListeners() // Doesn't work ?!
181
+ this._characteristic.removeAllListeners('get')
182
+ this._characteristic.removeAllListeners('set')
183
+ }
184
+ return
185
+ }
177
186
  if (this._characteristic != null) {
178
187
  this._service.removeCharacteristic(this._characteristic)
179
188
  }
@@ -338,7 +347,6 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
338
347
  let value = this.value
339
348
  const timeout = setTimeout(() => {
340
349
  timedOut = true
341
- this.warn('get: timed out - return previous value %j%s', this.value, this._unit)
342
350
  callback(null, this.value)
343
351
  }, this._timeout)
344
352
  try {
@@ -60,10 +60,15 @@ class PropertyDelegate extends homebridgeLib.Delegate {
60
60
  }
61
61
 
62
62
  /** Destroy the propery delegate.
63
+ * @params {boolean} [delegateOnly=false] - Destroy the delegate, but keep the
64
+ * associated value in context.
63
65
  */
64
- _destroy () {
66
+ _destroy (delegateOnly = false) {
65
67
  this.vdebug('destroy')
66
68
  this.removeAllListeners()
69
+ if (delegateOnly) {
70
+ return
71
+ }
67
72
  delete this._parent._context[this.key]
68
73
  }
69
74
 
@@ -102,6 +102,11 @@ class AirPressureValue extends HistoryValue {
102
102
  prepareEntry (entry) { entry[this.id] = this._delegate.value * 10 }
103
103
  }
104
104
 
105
+ class VocLevelValue extends HistoryValue {
106
+ get tag () { return 0x04 }
107
+ get id () { return 'r' }
108
+ }
109
+
105
110
  class ContactValue extends HistoryValue {
106
111
  get tag () { return 0x06 }
107
112
  get length () { return 1 }
@@ -145,7 +150,7 @@ class ConsumptionValue extends HistoryValue {
145
150
  prepareEntry (entry) {
146
151
  const delta = this._delegate.value - this._consumption // kWh
147
152
  const period = entry.time - this._time // s
148
- const power = 1000 * 3600 * delta / period // W
153
+ const power = period === 0 ? 0 : 1000 * 3600 * delta / period // W
149
154
  if (this._parent.computedPowerDelegate != null) {
150
155
  this._parent.computedPowerDelegate.value = Math.round(power) // W
151
156
  }
@@ -195,6 +200,25 @@ class PowerValue extends HistoryValue {
195
200
  }
196
201
  }
197
202
 
203
+ class SwitchOnValue extends HistoryValue {
204
+ get tag () { return 0x0E }
205
+ get length () { return 1 }
206
+ get id () { return 'w' }
207
+ prepareEntry (entry) { entry[this.id] = this._delegate.value ? 1 : 0 }
208
+ writeEntry (entry, buffer, offset) { buffer.writeInt8(entry[this.id], offset) }
209
+
210
+ constructor (parent, delegate) {
211
+ super(parent, delegate)
212
+ delegate.on('didSet', (value) => {
213
+ const now = History.now()
214
+ const entry = { time: now }
215
+ entry[this.id] = this._delegate.value ? 1 : 0
216
+ this._parent.addEntry(entry)
217
+ parent.lastSwitchOnDelegate.value = parent.lastActivationValue(now)
218
+ })
219
+ }
220
+ }
221
+
198
222
  class ValvePositionValue extends HistoryValue {
199
223
  get tag () { return 0x10 }
200
224
  get length () { return 1 }
@@ -261,9 +285,11 @@ class LightLevelValue extends HistoryValue {
261
285
  const historyValueTypes = {
262
286
  temperature: TemperatureValue,
263
287
  humidity: HumidityValue,
288
+ vocLevel: VocLevelValue,
264
289
  airPressure: AirPressureValue,
265
290
  contact: ContactValue,
266
291
  power: PowerValue,
292
+ switchOn: SwitchOnValue,
267
293
  consumption: ConsumptionValue,
268
294
  valvePosition: ValvePositionValue,
269
295
  targetTemperature: TargetTemperatureValue,
@@ -280,6 +306,7 @@ const historyDerivedTypes = {
280
306
  lastMotion: 'motion',
281
307
  lastOn: 'on',
282
308
  lastLightOn: 'lightOn',
309
+ lastSwitchOn: 'switchOn',
283
310
  computedConsumption: 'power',
284
311
  computedPower: 'consumption'
285
312
  }
@@ -347,12 +374,6 @@ class History extends ServiceDelegate {
347
374
  * @param {?CharacteristicDelegate} params.lastOnDelegate - The
348
375
  * `.eve.LastActivation` characteristic delegate
349
376
  * for a `hap.Outlet` service.
350
- * @param {?CharacteristicDelegate} params.lightOnDelegate - The
351
- * `Characteristics.hap.On` characteristic delegate
352
- * for a `hap.Lightbulb` service.
353
- * @param {?CharacteristicDelegate} params.lastLightOnDelegate - A
354
- * `.eve.LastActivation` characteristic delegate
355
- * for a `hap.Lightbulb` service.
356
377
  * @param {?CharacteristicDelegate} params.powerDelegate - The
357
378
  * `.eve.CurrentConsumption` characteristic delegate
358
379
  * for a `hap.Outlet` or `eve.Consumption` service
@@ -369,6 +390,18 @@ class History extends ServiceDelegate {
369
390
  * `.eve.CurrentConsumption` characteristic delegate
370
391
  * for a `hap.Outlet` or `eve.Consumption` service
371
392
  * for a device that reports total consumption but not current consumption.
393
+ * @param {?CharacteristicDelegate} params.lightOnDelegate - The
394
+ * `Characteristics.hap.On` characteristic delegate
395
+ * for a `hap.Lightbulb` service.
396
+ * @param {?CharacteristicDelegate} params.lastLightOnDelegate - A
397
+ * `.eve.LastActivation` characteristic delegate
398
+ * for a `hap.Lightbulb` service.
399
+ * @param {?CharacteristicDelegate} params.switchOnDelegate - The
400
+ * `Characteristics.hap.On` characteristic delegate
401
+ * for a `hap.Switch` service.
402
+ * @param {?CharacteristicDelegate} params.lastSwitchOnDelegate - A
403
+ * `.eve.LastActivation` characteristic delegate
404
+ * for a `hap.Switch` service.
372
405
  * @param {integer} [params.memorySize=4032] - The memory size, in number of
373
406
  * history entries. The default is 4 weeks of 1 entry per 10 minutes.
374
407
  * @param {?boolean} params.config - Expose config.
@@ -383,20 +416,25 @@ class History extends ServiceDelegate {
383
416
  let i = 0
384
417
  for (const param of Object.keys(params)) {
385
418
  if (param.endsWith('Delegate')) {
419
+ if (params[param] == null) {
420
+ continue
421
+ }
386
422
  if (!(params[param] instanceof CharacteristicDelegate)) {
387
423
  throw new TypeError(`params.${param}: not a CharacteristicDelegate`)
388
424
  }
389
425
  const key = param.slice(0, -8)
390
426
  if (historyDerivedTypes[key] != null) {
391
427
  if (params[historyDerivedTypes[key] + 'Delegate'] == null) {
392
- throw new SyntaxError(`params.${param}: missing params.${key}Delegate`)
428
+ throw new SyntaxError(
429
+ `params.${param}: missing params.${historyDerivedTypes[key]}Delegate`
430
+ )
393
431
  }
394
432
  this[param] = params[param]
395
433
  continue
396
434
  }
397
435
  if (key === 'lightOn') {
398
436
  if (!(params.lastLightOnDelegate instanceof CharacteristicDelegate)) {
399
- throw new SyntaxError(`params.${param}: missing params.${key}Delegate`)
437
+ throw new SyntaxError(`params.${param}: missing params.lastLightOnDelegate`)
400
438
  }
401
439
  params[param].on('didSet', (value) => {
402
440
  const now = History.now()
@@ -169,17 +169,20 @@ class ServiceDelegate extends homebridgeLib.Delegate {
169
169
  })
170
170
  }
171
171
 
172
- /** Destroy the HomeKit service delegate.
173
- *
174
- * Destroys the associated HomeKit characteristic delegates.
175
- * Removes the associated HomeKit service.
172
+ /** Destroy service delegate and associated HomeKit service.
173
+ * @params {boolean} [delegateOnly=false] - Destroy the delegate, but keep the
174
+ * associated HomeKit service (including context).
176
175
  */
177
- destroy () {
176
+ destroy (delegateOnly = false) {
178
177
  this.debug('destroy %s (%s)', this._key, this.constructor.name)
179
- this._accessoryDelegate._unlinkServiceDelegate(this)
178
+ this._accessoryDelegate._unlinkServiceDelegate(this, delegateOnly)
180
179
  this.removeAllListeners()
181
180
  for (const key in this._characteristicDelegates) {
182
- this._characteristicDelegates[key]._destroy()
181
+ this._characteristicDelegates[key]._destroy(delegateOnly)
182
+ }
183
+ if (delegateOnly) {
184
+ this._service.removeAllListeners()
185
+ return
183
186
  }
184
187
  this._accessory.removeService(this._service)
185
188
  delete this._accessory.context[this._key]
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Library for homebridge plugins",
4
4
  "author": "Erik Baauw",
5
5
  "license": "Apache-2.0",
6
- "version": "6.3.3",
6
+ "version": "6.3.5",
7
7
  "keywords": [
8
8
  "homekit",
9
9
  "homebridge"
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "engines": {
24
24
  "homebridge": "^1.6.0",
25
- "node": "^18.13.0"
25
+ "node": "^18.14.0"
26
26
  },
27
27
  "dependencies": {
28
28
  "@homebridge/plugin-ui-utils": "~0.0.19",