homebridge-lib 6.0.2 → 6.2.0

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 (41) hide show
  1. package/README.md +1 -1
  2. package/cli/hap.js +1 -1
  3. package/cli/json.js +1 -1
  4. package/cli/sysinfo.js +1 -1
  5. package/cli/upnp.js +1 -1
  6. package/index.js +1 -1
  7. package/lib/AccessoryDelegate.js +30 -27
  8. package/lib/AdaptiveLighting.js +1 -1
  9. package/lib/CharacteristicDelegate.js +22 -36
  10. package/lib/Colour.js +1 -1
  11. package/lib/CommandLineParser.js +1 -1
  12. package/lib/CommandLineTool.js +1 -1
  13. package/lib/CustomHomeKitTypes.js +1 -1
  14. package/lib/Delegate.js +31 -33
  15. package/lib/EveHomeKitTypes.js +62 -52
  16. package/lib/HttpClient.js +1 -1
  17. package/lib/JsonFormatter.js +1 -1
  18. package/lib/MyHomeKitTypes.js +88 -97
  19. package/lib/OptionParser.js +27 -2
  20. package/lib/Platform.js +12 -20
  21. package/lib/PropertyDelegate.js +8 -11
  22. package/lib/ServiceDelegate/AccessoryInformation.js +1 -1
  23. package/lib/ServiceDelegate/Battery.js +1 -1
  24. package/lib/ServiceDelegate/Dummy.js +1 -1
  25. package/lib/ServiceDelegate/History/Consumption.js +28 -49
  26. package/lib/ServiceDelegate/History/Light.js +15 -23
  27. package/lib/ServiceDelegate/History/On.js +29 -33
  28. package/lib/ServiceDelegate/History/Power.js +43 -52
  29. package/lib/ServiceDelegate/History/Sensor.js +215 -0
  30. package/lib/ServiceDelegate/History/Thermo.js +19 -33
  31. package/lib/ServiceDelegate/History/index.js +137 -186
  32. package/lib/ServiceDelegate/ServiceLabel.js +1 -1
  33. package/lib/ServiceDelegate/index.js +13 -11
  34. package/lib/SystemInfo.js +3 -2
  35. package/lib/UiServer.js +1 -1
  36. package/lib/UpnpClient.js +1 -1
  37. package/package.json +2 -2
  38. package/lib/ServiceDelegate/History/Contact.js +0 -96
  39. package/lib/ServiceDelegate/History/Motion.js +0 -155
  40. package/lib/ServiceDelegate/History/Room.js +0 -112
  41. package/lib/ServiceDelegate/History/Weather.js +0 -124
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  </span>
14
14
 
15
15
  ## Library for Homebridge Plugins
16
- Copyright © 2018-2022 Erik Baauw. All rights reserved.
16
+ Copyright © 2018-2023 Erik Baauw. All rights reserved.
17
17
 
18
18
  While developing a number of [Homebridge](https://github.com/homebridge/homebridge) plugins, I find myself duplicating a lot of code.
19
19
  The idea behind this library is to ease developing and maintaining Homebridge plugins by separating this generic code, dealing with [HomeKit](http://www.apple.com/ios/home/) and Homebridge, from the specific code, dealing with the actual devices being exposed to HomeKit.
package/cli/hap.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // homebridge-lib/cli/hap.js
4
4
  //
5
5
  // Library for Homebridge plugins.
6
- // Copyright © 2018-2022 Erik Baauw. All rights reserved.
6
+ // Copyright © 2018-2023 Erik Baauw. All rights reserved.
7
7
  //
8
8
  // Logger for HomeKit accessory announcements.
9
9
 
package/cli/json.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // homebridge-lib/cli/json.js
4
4
  //
5
5
  // Library for Homebridge plugins.
6
- // Copyright © 2018-2022 Erik Baauw. All rights reserved.
6
+ // Copyright © 2018-2023 Erik Baauw. All rights reserved.
7
7
  //
8
8
  // JSON formatter.
9
9
 
package/cli/sysinfo.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // homebridge-lib/cli/sysinfo.js
4
4
  //
5
5
  // Library for Homebridge plugins.
6
- // Copyright © 2021-2022 Erik Baauw. All rights reserved.
6
+ // Copyright © 2021-2023 Erik Baauw. All rights reserved.
7
7
  //
8
8
  // Show system info.
9
9
 
package/cli/upnp.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // homebridge-lib/cli/upnp.js
4
4
  //
5
5
  // Library for Homebridge plugins.
6
- // Copyright © 2018-2022 Erik Baauw. All rights reserved.
6
+ // Copyright © 2018-2023 Erik Baauw. All rights reserved.
7
7
  //
8
8
  // Logger for UPnP device announcements.
9
9
 
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/index.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  'use strict'
7
7
 
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/AccessoryDelegate.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  'use strict'
7
7
 
@@ -49,23 +49,20 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
49
49
 
50
50
  // Link or create associated PlatformAccessory.
51
51
  this._accessory = this._platform._getAccessory(this, params)
52
-
53
- if (params.logLevel != null) {
54
- this.warn('params.logLevel: deprecated')
55
- }
56
- if (params.inheritLogLevel != null) {
57
- this.warn('params.inheritLogLevel: deprecated')
58
- }
59
52
  this._context = this._accessory.context
60
53
 
61
- delete this._context.logLevel
62
-
63
54
  // Setup shortcut for property values and values of the characteristics
64
55
  // of the _Accessory Information_ service.
65
56
  this._values = {} // by key
66
57
  this._propertyDelegates = {}
58
+ this.addPropertyDelegate({ key: 'className', value: this.constructor.name, silent: true })
59
+ this.addPropertyDelegate({ key: 'version', silent: true })
60
+ this.values.version = platform.packageJson.version
61
+ this.addPropertyDelegate({ key: 'id', value: params.id, silent: true })
62
+ this.addPropertyDelegate({ key: 'logLevel', value: platform.logLevel })
67
63
  this.addPropertyDelegate({ key: 'name', value: this.name, silent: true })
68
64
  .on('didSet', (name) => { this.name = name })
65
+ this.addPropertyDelegate({ key: 'uiPort', silent: true })
69
66
 
70
67
  // Create delegate for AccessoryInformation service.
71
68
  this._serviceDelegates = {}
@@ -76,30 +73,37 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
76
73
  this._accessory.on('identify', this._identify.bind(this))
77
74
 
78
75
  this.once('initialised', () => {
79
- const services = []
76
+ const staleServices = []
80
77
  for (const service of this._accessory.services) {
81
78
  const key = service.UUID +
82
79
  (service.subtype == null ? '' : '.' + service.subtype)
83
80
  if (this._serviceDelegates[key] == null) {
84
81
  if (service.UUID !== this.Services.hap.ProtocolInformation.UUID) {
85
- services.push(service)
82
+ service.key = key
83
+ staleServices.push(service)
86
84
  }
87
85
  } else {
88
86
  this._serviceDelegates[key].emit('initialised')
89
87
  }
90
88
  }
91
- for (const service of services) {
92
- this.debug('remove stale service %s', service.displayName)
89
+ for (const service of staleServices) {
90
+ this.warn('remove stale service %s (%s)', service.key, service.constructor.name)
93
91
  this._accessory.removeService(service)
94
92
  }
95
93
  const staleKeys = []
96
94
  for (const key in this._context) {
97
- if (this._serviceDelegates[key] == null && startsWithUuid.test(key)) {
98
- staleKeys.push(key)
95
+ if (startsWithUuid.test(key)) {
96
+ if (this._serviceDelegates[key] == null) {
97
+ staleKeys.push(key)
98
+ }
99
+ } else {
100
+ if (key !== 'context' && this._propertyDelegates[key] == null) {
101
+ staleKeys.push(key)
102
+ }
99
103
  }
100
104
  }
101
105
  for (const key of staleKeys) {
102
- this.debug('remove stale context %s', key)
106
+ this.warn('remove stale context %s', key)
103
107
  delete this._context[key]
104
108
  }
105
109
  })
@@ -142,10 +146,6 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
142
146
  * @param {?boolean} params.logLevel - Level for homebridge log messages
143
147
  * when property was set or has been changed.
144
148
  * @param {?string} params.unit - The unit of the value of the property.
145
- * @throws {TypeError} When a parameter has an invalid type.
146
- * @throws {RangeError} When a parameter has an invalid value.
147
- * @throws {SyntaxError} When a mandatory parameter is missing or an
148
- * optional parameter is not applicable.
149
149
  * @returns {PropertyDelegate}
150
150
  * @throws {TypeError} When a parameter has an invalid type.
151
151
  * @throws {RangeError} When a parameter has an invalid value.
@@ -186,7 +186,7 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
186
186
  const delegate = this._propertyDelegates[key]
187
187
  delegate._destroy()
188
188
  delete this._propertyDelegates[key]
189
- delete this._context[key]
189
+ delete this.context[key]
190
190
  }
191
191
 
192
192
  /** Returns the property delegate correspondig to the property key.
@@ -251,7 +251,7 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
251
251
  * @type {!integer}
252
252
  */
253
253
  get logLevel () {
254
- return this.platform.logLevel
254
+ return this.values.logLevel == null ? this.platform.logLevel : this.values.logLevel
255
255
  }
256
256
 
257
257
  /** Inherit `logLevel` from another accessory delegate.
@@ -271,14 +271,17 @@ class AccessoryDelegate extends homebridgeLib.Delegate {
271
271
  }
272
272
 
273
273
  /** Manage `logLevel` from characteristic delegate.
274
- * @param {CharacteristicDelegate} delegate - The delegate of the `logLevel`
275
- * characteristic.
274
+ * @param {CharacteristicDelegate|PropertyDelegate} delegate - The delegate
275
+ * of the `logLevel` characteristic.
276
276
  * @param {Boolean} [forPlatform=false] - Manage the Platform `logLevel` as
277
277
  * well.
278
278
  */
279
279
  manageLogLevel (delegate, forPlatform = false) {
280
- if (!(delegate instanceof homebridgeLib.CharacteristicDelegate)) {
281
- throw new TypeError('delegate: not an CharacteristicDelegate')
280
+ if (
281
+ !(delegate instanceof homebridgeLib.CharacteristicDelegate) &&
282
+ !(delegate instanceof homebridgeLib.PropertyDelegate)
283
+ ) {
284
+ throw new TypeError('delegate: not a CharacteristicDelegate or PropertyDelegate')
282
285
  }
283
286
  Object.defineProperty(this, 'logLevel', {
284
287
  get () { return delegate.value }
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/AdaptiveLighting.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2020-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2020-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  'use strict'
7
7
 
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/CharacteristicDelegate.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  'use strict'
7
7
 
@@ -121,11 +121,13 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
121
121
  const Characteristic = params.Characteristic
122
122
  if (this._service.testCharacteristic(Characteristic)) {
123
123
  this._characteristic = this._service.getCharacteristic(Characteristic)
124
- this._characteristic.props = new Characteristic().props
125
124
  } else {
126
125
  this._characteristic = this._service.addCharacteristic(Characteristic)
127
126
  }
128
127
  if (params.props != null) {
128
+ if (this._characteristic.value < params.props.minValue) {
129
+ this._characteristic.updateValue(params.props.minValue)
130
+ }
129
131
  this._characteristic.setProps(params.props)
130
132
  }
131
133
  if (this._characteristic.props.unit != null) {
@@ -147,10 +149,7 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
147
149
  )
148
150
  // Check that we are the only listener
149
151
  if (this._characteristic.listenerCount('set') > 1) {
150
- this.warn(
151
- '%s: %d listeners', this.displayName,
152
- this._characteristic.listenerCount('set')
153
- )
152
+ this.warn('%d listeners', this._characteristic.listenerCount('set'))
154
153
  }
155
154
  }
156
155
  if (params.unit != null) {
@@ -173,7 +172,7 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
173
172
  * Removes the associated HomeKit characteristic.
174
173
  */
175
174
  _destroy () {
176
- this.debug('destroy %s (%s)', this._key, this.displayName)
175
+ this.debug('destroy %s', this._key)
177
176
  this.removeAllListeners()
178
177
  if (this._characteristic != null) {
179
178
  this._service.removeCharacteristic(this._characteristic)
@@ -189,11 +188,11 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
189
188
  }
190
189
 
191
190
  get _canRead () {
192
- return this._hasPerm(this.Characteristic.Perms.READ)
191
+ return this._hasPerm(this.Characteristic.Perms.PAIRED_READ)
193
192
  }
194
193
 
195
194
  get _canWrite () {
196
- return this._hasPerm(this.Characteristic.Perms.WRITE)
195
+ return this._hasPerm(this.Characteristic.Perms.PAIRED_WRITE)
197
196
  }
198
197
 
199
198
  get _canNotify () {
@@ -240,6 +239,10 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
240
239
  : this._characteristic.displayName
241
240
  }
242
241
 
242
+ get _namePrefix () {
243
+ return this._serviceDelegate._namePrefix + this.displayName + ': '
244
+ }
245
+
243
246
  validate (value) {
244
247
  let s = ''
245
248
  if (this._characteristic != null) {
@@ -293,20 +296,11 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
293
296
 
294
297
  // Issue info message that Characteristic value is updated by the plugin.
295
298
  if (this._notifyOnly) {
296
- this._log(
297
- '%s: %s%s', this.displayName,
298
- ['Single Press', 'Double Press', 'Long Press'][value], s
299
- )
299
+ this._log('%s%s', ['Single Press', 'Double Press', 'Long Press'][value], s)
300
300
  } else if (this.value == null) {
301
- this._log(
302
- 'set %s to %j%s%s', this.displayName,
303
- value, this._unit, s
304
- )
301
+ this._log('set to %j%s%s', value, this._unit, s)
305
302
  } else {
306
- this._log(
307
- 'set %s from %j%s to %j%s%s', this.displayName,
308
- this.value, this._unit, value, this._unit, s
309
- )
303
+ this._log('set to %j%s%s (from %j%s)', value, this._unit, s, this.value, this._unit)
310
304
  }
311
305
 
312
306
  // Update persisted value in ~/.homebridge/accessories/cachedAccessories.
@@ -344,10 +338,7 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
344
338
  let value = this.value
345
339
  const timeout = setTimeout(() => {
346
340
  timedOut = true
347
- this.warn(
348
- 'get %s: timed out - return previous value %j%s',
349
- this.displayName, this.value, this._unit
350
- )
341
+ this.warn('get: timed out - return previous value %j%s', this.value, this._unit)
351
342
  callback(null, this.value)
352
343
  }, this._timeout)
353
344
  try {
@@ -358,12 +349,10 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
358
349
  clearTimeout(timeout)
359
350
 
360
351
  if (timedOut) {
361
- this._log(
362
- 'get %s: ignore %j%s - timed out', this.displayName, value, this._unit
363
- )
352
+ this._log('get: ignore %j%s - timed out', value, this._unit)
364
353
  } else {
365
354
  // Return value to HomeKit.
366
- this._log('get %s: return %j%s', this.displayName, value, this._unit)
355
+ this._log('get: return %j%s', value, this._unit)
367
356
  callback(null, value)
368
357
  }
369
358
 
@@ -383,12 +372,9 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
383
372
 
384
373
  // Issue info message that Characteristic value was updated from HomeKit.
385
374
  if (this._writeOnly || this.value == null) {
386
- this._log('%s changed to %j%s', this.displayName, value, this._unit)
375
+ this._log('changed to %j%s', value, this._unit)
387
376
  } else if (value !== this.value) {
388
- this._log(
389
- '%s changed from %j%s to %j%s', this.displayName,
390
- this.value, this._unit, value, this._unit
391
- )
377
+ this._log('changed to %j%s (from %j%s)', value, this._unit, this.value, this._unit)
392
378
  }
393
379
 
394
380
  // Check for actual change.
@@ -408,14 +394,14 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
408
394
  let timedOut = false
409
395
  const timeout = setTimeout(() => {
410
396
  timedOut = true
411
- this.warn('set %s: timed out', this.displayName)
397
+ this.warn('set: timed out')
412
398
  callback(new Error('timed out'))
413
399
  }, this._timeout)
414
400
  try {
415
401
  result = await this._setter(value)
416
402
  } catch (error) {
417
403
  clearTimeout(timeout)
418
- this.warn('set %s: %s', this.displayName, error)
404
+ this.warn('set: %s', error)
419
405
  if (!timedOut) {
420
406
  callback(error)
421
407
  }
package/lib/Colour.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/Colour.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2016-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2016-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  'use strict'
7
7
 
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/CommandLineParser.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  // TODO:
7
7
  // - Change parameters to (params, callback) with:
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/CommandLineUtility.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2018-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2018-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  'use strict'
7
7
 
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/CustomeHomeKitTypes.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  const regExps = {
7
7
  uuid: /^[0-9A-F]{8}-[0-9A-F]{4}-[1-5][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/,
package/lib/Delegate.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/Delegate.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
5
5
 
6
6
  'use strict'
7
7
 
@@ -93,6 +93,29 @@ class Delegate extends events.EventEmitter {
93
93
  */
94
94
  get Services () { return this._platform.Services }
95
95
 
96
+ /** Current log level.
97
+ *
98
+ * The log level determines what type of messages are printed:
99
+ *
100
+ * 0. Print error and warning messages.
101
+ * 1. Print error, warning, and log messages.
102
+ * 2. Print error, warning, log, and debug messages.
103
+ * 3. Print error, warning, log, debug, and verbose debug messages.
104
+ * 3. Print error, warning, log, debug, verbose debug, and very verbose
105
+ * debug messages.
106
+ *
107
+ * Note that debug messages (level 2, 3 and 4) are only printed when
108
+ * Homebridge was started with the `-D` or `--debug` command line option.
109
+ *
110
+ * The log level defaults at 2.
111
+ *
112
+ * @type {!integer}
113
+ * @readonly
114
+ */
115
+ get logLevel () {
116
+ return 2
117
+ }
118
+
96
119
  /** The name used to prefix log and error messages.
97
120
  * @type {string}
98
121
  */
@@ -108,7 +131,13 @@ class Delegate extends events.EventEmitter {
108
131
  throw new RangeError(`${name}: invalid name`)
109
132
  }
110
133
  this._name = name
111
- this._namePrefix = this._name == null ? '' : name + ': '
134
+ }
135
+
136
+ /** The name prefix for log messages.
137
+ * @type {string}
138
+ */
139
+ get _namePrefix () {
140
+ return this._name == null ? '' : this._name + ': '
112
141
  }
113
142
 
114
143
  /** Reference to the corresponding platform plugin instance.
@@ -121,37 +150,6 @@ class Delegate extends events.EventEmitter {
121
150
  return this._platform
122
151
  }
123
152
 
124
- /** Name of the (final) class of this instance.
125
- * @type {!string}
126
- * @readonly
127
- */
128
- get className () {
129
- return this.constructor.name
130
- }
131
-
132
- /** Current log level.
133
- *
134
- * The log level determines what type of messages are printed:
135
- *
136
- * 0. Print error and warning messages.
137
- * 1. Print error, warning, and log messages.
138
- * 2. Print error, warning, log, and debug messages.
139
- * 3. Print error, warning, log, debug, and verbose debug messages.
140
- * 3. Print error, warning, log, debug, verbose debug, and very verbose
141
- * debug messages.
142
- *
143
- * Note that debug messages (level 2, 3 and 4) are only printed when
144
- * Homebridge was started with the `-D` or `--debug` command line option.
145
- *
146
- * The log level defaults at 2.
147
- *
148
- * @type {!integer}
149
- * @readonly
150
- */
151
- get logLevel () {
152
- return 2
153
- }
154
-
155
153
  /** Print a debug message to Homebridge standard output.
156
154
  * <br>The message is printed only, when the current log level >= 2 and when
157
155
  * Homebridge was started with the `-D` or `--debug` command line option.