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
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/OptionParser.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
 
@@ -769,6 +769,31 @@ class OptionParser extends events.EventEmitter {
769
769
  return this
770
770
  }
771
771
 
772
+ /** Defines a key that takes an number value,
773
+ * optionally clamped between min and max.
774
+ *
775
+ * @param {!string} key - The key.
776
+ * @param {?number} min - Minimum value returned.
777
+ * @param {?number} max - Maximum value returned.
778
+ * @return {OptionParser} this - For chaining.
779
+ * @throws {TypeError} When key is not a string.
780
+ * @throws {RangeError} When key is empty string.
781
+ * @throws {SyntaxError} On duplicate key.
782
+ */
783
+ numberKey (key, min, max) {
784
+ key = this._toKey(key)
785
+ min = min == null ? -Infinity : OptionParser.toNumber('min', min)
786
+ max = max == null ? Infinity : OptionParser.toNumber('max', max)
787
+ if (max < min) {
788
+ throw newRangeError('max: smaller than min')
789
+ }
790
+
791
+ this._callbacks[key] = (value) => {
792
+ this._object[key] = OptionParser.toNumber(key, value, min, max, this._userInput)
793
+ }
794
+ return this
795
+ }
796
+
772
797
  /** Defines a key that takes an object as value.
773
798
  *
774
799
  * @param {!string} key - The key.
@@ -832,7 +857,7 @@ class OptionParser extends events.EventEmitter {
832
857
  * @throws {TypeError} When option has wrong type.
833
858
  * @throws {RangeError} When option has wrong value.
834
859
  * @throws {SyntaxError} Unknown option.
835
- * @throws {UserError} On error, when value was input by user.
860
+ * @throws {UserInputError} On error, when value was input by user.
836
861
  */
837
862
  parse (options) {
838
863
  options = OptionParser.toObject('options', options)
package/lib/Platform.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/Platform.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
 
@@ -28,7 +28,9 @@ const context = {
28
28
  recommendedHomebridgeVersion:
29
29
  semver.minVersion(libPackageJson.engines.homebridge).toString(),
30
30
  saveInterval: 3600,
31
- checkInterval: 7 * 24 * 3600
31
+ checkInterval: 7 * 24 * 3600,
32
+ driftDebugThreshold: 250,
33
+ driftWarningThreshold: 2500
32
34
  }
33
35
 
34
36
  /** Homebridge dynamic platform plugin.
@@ -139,7 +141,7 @@ class Platform extends homebridgeLib.Delegate {
139
141
  this._log = log
140
142
  this._configJson = configJson
141
143
  this._homebridge = homebridge
142
- this._myContext = context[this.className]
144
+ this._myContext = context[this.constructor.name]
143
145
  this._platformName = this._myContext.platformName
144
146
  this._pluginName = this._myContext.packageJson.name
145
147
  this._pluginVersion = this._myContext.packageJson.version
@@ -266,8 +268,12 @@ class Platform extends homebridgeLib.Delegate {
266
268
  this.debug('last heartbeat %d, drift %d', beat, drift)
267
269
  return
268
270
  }
269
- if (drift < -250 || drift > 250) {
270
- this.warn('heartbeat %d, drift %d', beat, drift)
271
+ if (drift < -context.driftDebugThreshold || drift > context.driftDebugThreshold) {
272
+ if (drift < -context.driftWarningThreshold || drift > context.driftWarningThreshold) {
273
+ this.warn('heartbeat %d, drift %d', beat, drift)
274
+ } else {
275
+ this.debug('heartbeat %d, drift %d', beat, drift)
276
+ }
271
277
  }
272
278
  setTimeout(() => {
273
279
  this._beat(beat)
@@ -460,8 +466,7 @@ class Platform extends homebridgeLib.Delegate {
460
466
 
461
467
  // Get or create accessory.
462
468
  _getAccessory (delegate, params) {
463
- const className = delegate.className
464
- const version = this._pluginVersion
469
+ const className = delegate.constructor.name
465
470
  const id = params.id
466
471
  const name = params.name
467
472
  let accessory = this._accessories[id]
@@ -473,11 +478,6 @@ class Platform extends homebridgeLib.Delegate {
473
478
  this._accessories[id] = accessory
474
479
  accessory.displayName = name
475
480
  accessory.context = {
476
- className,
477
- version,
478
- id,
479
- name,
480
- logLevel: this.logLevel,
481
481
  context: {}
482
482
  }
483
483
  delegate.once('initialised', () => {
@@ -507,14 +507,6 @@ class Platform extends homebridgeLib.Delegate {
507
507
  delegate.emit('exposeError', error)
508
508
  }
509
509
  })
510
- } else {
511
- // Allow for plugin to change delegate class, version, and name.
512
- accessory.context.className = className
513
- accessory.context.version = version
514
- accessory.context.name = name
515
- if (accessory.context.logLevel == null) {
516
- accessory.context.logLevel = this.logLevel
517
- }
518
510
  }
519
511
  this._accessoryDelegates[id] = delegate
520
512
  return accessory
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/PropertyDelegate.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
 
@@ -22,8 +22,7 @@ class PropertyDelegate extends homebridgeLib.Delegate {
22
22
  /** Instantiate a property delegate.
23
23
  *
24
24
  * Note that instances are normally created by invoking
25
- * {@link AccessoryDelegate#addPropertyDelegate addPropertyDelegate()} or
26
- * {@link ServiceDelegate#addPropertyDelegate addPropertyDelegate()}.
25
+ * {@link AccessoryDelegate#addPropertyDelegate addPropertyDelegate()}.
27
26
  * @param {!AccessoryDelegate|ServiceDelegate} delegate - Reference to the
28
27
  * delegate of the corresponding HomeKit accessory or service.
29
28
  * @param {!object} params - Parameters of the property delegate.
@@ -41,10 +40,7 @@ class PropertyDelegate extends homebridgeLib.Delegate {
41
40
  * optional parameter is not applicable.
42
41
  */
43
42
  constructor (parent, params = {}) {
44
- if (!(
45
- parent instanceof homebridgeLib.AccessoryDelegate ||
46
- parent instanceof homebridgeLib.ServiceDelegate
47
- )) {
43
+ if (!(parent instanceof homebridgeLib.AccessoryDelegate)) {
48
44
  throw new TypeError('parent: not an AccessoryDelegate')
49
45
  }
50
46
  super(parent.platform, parent.name + ': ' + params.key)
@@ -61,8 +57,6 @@ class PropertyDelegate extends homebridgeLib.Delegate {
61
57
  if (this.value == null && params.value != null) {
62
58
  this.value = params.value
63
59
  }
64
-
65
- this.vdebug('created')
66
60
  }
67
61
 
68
62
  /** Destroy the propery delegate.
@@ -92,6 +86,10 @@ class PropertyDelegate extends homebridgeLib.Delegate {
92
86
  return this._parent.logLevel
93
87
  }
94
88
 
89
+ get _namePrefix () {
90
+ return this._parent._namePrefix + this._key + ': '
91
+ }
92
+
95
93
  validate (value) {
96
94
  // Todo: check value against type.
97
95
  return { value, s: '' }
@@ -116,8 +114,7 @@ class PropertyDelegate extends homebridgeLib.Delegate {
116
114
  this._log('set to %j%s%s', value, this._unit, s)
117
115
  } else {
118
116
  this._log(
119
- 'set to %j%s%s (from %j%s)', value, this._unit, s,
120
- this.value, this._unit
117
+ 'set to %j%s%s (from %j%s)', value, this._unit, s, this.value, this._unit
121
118
  )
122
119
  }
123
120
 
@@ -1,7 +1,7 @@
1
1
  // homebridge-lib/lib/ServiceDelegate/AccessoryInformation.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/ServiceDelegate/Battery.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/ServiceDelegate/Dummy.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,20 +1,13 @@
1
1
  // homebridge-lib/lib/ServiceDelegate/History/Consumption.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
5
- //
6
- // The logic for handling Eve history was copied from Simone Tisa's
7
- // fakagato-history repository, copyright © 2017 simont77.
8
- // See https://github.com/simont77/fakegato-history.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
9
5
 
10
6
  'use strict'
11
7
 
12
8
  const homebridgeLib = require('../../../index')
13
- const util = require('util')
14
9
 
15
- const { ServiceDelegate } = homebridgeLib
16
- const { History } = ServiceDelegate
17
- const { swap16, swap32, numToHex } = History
10
+ const { History } = homebridgeLib.ServiceDelegate
18
11
 
19
12
  /** Class for an Eve Energy _History_ service delegate.
20
13
  *
@@ -53,9 +46,9 @@ class Consumption extends History {
53
46
  * @param {?CharacteristicDelegate} params.powerDelegate - A reference to the
54
47
  * delegate of the associated `Characteristics.eve.CurrentConsumption`
55
48
  * characteristic.
56
- * @param {!CharacteristicDelegate} params.onDelegate - A reference to the
49
+ * @param {?CharacteristicDelegate} params.onDelegate - A reference to the
57
50
  * delegate of the associated `Characteristics.hap.On` characteristic.
58
- * @param {!CharacteristicDelegate} params.lastActivationDelegate - A
51
+ * @param {?CharacteristicDelegate} params.lastActivationDelegate - A
59
52
  * reference to the delegate of the associated
60
53
  * `Characteristics.eve.LastActivation` characteristic.
61
54
  */
@@ -85,66 +78,52 @@ class Consumption extends History {
85
78
  this._consumptionDelegate = params.consumptionDelegate
86
79
  this._powerDelegate = params.powerDelegate
87
80
 
88
- this._entry = { time: 0, power: 0 }
81
+ this.entry = { p: 0 }
89
82
  if (params.onDelegate != null) {
90
- this._entry.on = params.onDelegate.value ? 1 : 0
83
+ this.entry.o = params.onDelegate.value ? 1 : 0
91
84
  params.onDelegate.on('didSet', (value) => {
92
- const now = Math.round(new Date().valueOf() / 1000)
85
+ const now = History.now()
93
86
  if (params.lastActivationDelegate != null) {
94
- params.lastActivationDelegate.value = now - this._h.initialTime
87
+ params.lastActivationDelegate.value = this.lastActivationValue(now)
95
88
  }
96
- this._entry.on = value ? 1 : 0
97
- const power = this._entry.power
98
- this._entry.power = null
99
- super._addEntry(now)
100
- this._entry.power = power
89
+ this.entry.o = value ? 1 : 0
90
+ super.addEntry({ time: now, o: this.entry.o })
101
91
  })
102
92
  }
103
93
  }
104
94
 
105
- _addEntry () {
106
- const now = Math.round(new Date().valueOf() / 1000)
95
+ addEntry (entry) {
107
96
  // Sensor deliveres totalConsumption, optionally compute currentConsumption
108
97
  if (this._consumption != null && this._time != null) {
109
98
  const delta = this._consumptionDelegate.value - this._consumption // kWh
110
- const period = now - this._time // s
99
+ const period = entry.time - this._time // s
111
100
  const power = 1000 * 3600 * delta / period // W
112
101
  if (this._powerDelegate != null) {
113
102
  this._powerDelegate.value = Math.round(power) // W
114
103
  }
115
- this._entry.power = Math.round(power * 10) // 0.1 W * 10 min
116
- super._addEntry(now)
104
+ entry.p = Math.round(power * 10) // 0.1 W * 10 min
117
105
  }
106
+ super.addEntry(entry)
118
107
  this._consumption = this._consumptionDelegate.value
119
- this._time = now
108
+ this._time = entry.time
120
109
  }
121
110
 
122
- get _fingerPrint () { return '02 0702 0E01' }
111
+ get fingerPrint () { return '02 0702 0E01' }
123
112
 
124
- _entryStream (entry) {
125
- if (entry.on == null) {
126
- return util.format(
127
- '|0c %s %s 01 %s',
128
- numToHex(swap32(this._h.currentEntry), 8),
129
- numToHex(swap32(entry.time - this._h.initialTime), 8),
130
- numToHex(swap16(entry.power), 4)
131
- )
113
+ entryToBuffer (entry) {
114
+ const buffer = Buffer.alloc(16)
115
+ let mask = 0
116
+ let o = 1
117
+ if (entry.p != null) {
118
+ mask |= 0x01
119
+ buffer.writeUInt16LE(entry.p, o); o += 2
132
120
  }
133
- if (entry.power == null) {
134
- return util.format(
135
- '|0b %s %s 02 %s',
136
- numToHex(swap32(this._h.currentEntry), 8),
137
- numToHex(swap32(entry.time - this._h.initialTime), 8),
138
- numToHex(entry.on, 2)
139
- )
121
+ if (entry.o != null) {
122
+ mask |= 0x02
123
+ buffer.writeUInt8(entry.o, o); o += 1
140
124
  }
141
- return util.format(
142
- '|0d %s %s 03 %s %s',
143
- numToHex(swap32(this._h.currentEntry), 8),
144
- numToHex(swap32(entry.time - this._h.initialTime), 8),
145
- numToHex(swap16(entry.power), 4),
146
- numToHex(entry.on, 2)
147
- )
125
+ buffer.writeUInt8(mask, 0)
126
+ return buffer.slice(0, o)
148
127
  }
149
128
  }
150
129
 
@@ -1,18 +1,13 @@
1
1
  // homebridge-lib/lib/ServiceDelegate/History/On.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
5
- //
6
- // The logic for handling Eve history was copied from Simone Tisa's
7
- // fakagato-history repository, copyright © 2017 simont77.
8
- // See https://github.com/simont77/fakegato-history.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
9
5
 
10
6
  'use strict'
11
7
 
12
8
  const homebridgeLib = require('../../../index')
13
9
 
14
- const { ServiceDelegate } = homebridgeLib
15
- const { History } = ServiceDelegate
10
+ const { History } = homebridgeLib.ServiceDelegate
16
11
 
17
12
  /** Class for an Eve Light Strip _History_ service delegate.
18
13
  *
@@ -28,7 +23,12 @@ const { History } = ServiceDelegate
28
23
  * `historyEntries` | `Characteristics.eve.HistoryEntries`
29
24
  *
30
25
  * This delegate creates the history from the associated
31
- * `Characteristics.hap.On` characteristic.
26
+ * `Characteristics.hap.On` characteristic. It updates the
27
+ * values of the associated `Characteristics.eve.LastActivation`
28
+ * characteristic.
29
+ * Note that the Eve Light Strip doesn't actually provide history entries;
30
+ * the _History_ service is used only to provide a reference time for
31
+ * last `LastActivation`.
32
32
  * @extends ServiceDelegate.History
33
33
  * @memberof ServiceDelegate.History
34
34
  */
@@ -54,28 +54,20 @@ class Light extends History {
54
54
  if (!(params.lastActivationDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
55
55
  throw new TypeError('params.lastActivationDelegate: not a CharacteristicDelegate')
56
56
  }
57
- if (
58
- params.temperatureDelegate != null &&
59
- !(params.temperatureDelegate instanceof homebridgeLib.CharacteristicDelegate)
60
- ) {
61
- throw new TypeError('params.temperatureDelegate: not a CharacteristicDelegate')
62
- }
63
- this._entry = {
64
- time: 0
65
- }
57
+ this.entry = { }
66
58
  params.onDelegate.on('didSet', (value) => {
67
- const now = Math.round(new Date().valueOf() / 1000)
59
+ const now = History.now()
68
60
  if (params.lastActivationDelegate != null) {
69
- params.lastActivationDelegate.value = now - this._h.initialTime
61
+ params.lastActivationDelegate.value = this.lastActivationValue(now)
70
62
  }
71
- this._addEntry(now)
63
+ this.addEntry({ time: now })
72
64
  })
73
65
  }
74
66
 
75
- get _fingerPrint () { return '00' }
67
+ get fingerPrint () { return '00' }
76
68
 
77
- _entryStream (entry) {
78
- return ''
69
+ entryToBuffer (entry) {
70
+ return Buffer.alloc(0)
79
71
  }
80
72
  }
81
73
 
@@ -1,20 +1,13 @@
1
1
  // homebridge-lib/lib/ServiceDelegate/History/On.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
5
- //
6
- // The logic for handling Eve history was copied from Simone Tisa's
7
- // fakagato-history repository, copyright © 2017 simont77.
8
- // See https://github.com/simont77/fakegato-history.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
9
5
 
10
6
  'use strict'
11
7
 
12
8
  const homebridgeLib = require('../../../index')
13
- const util = require('util')
14
9
 
15
- const { ServiceDelegate } = homebridgeLib
16
- const { History } = ServiceDelegate
17
- const { swap32, numToHex } = History
10
+ const { History } = homebridgeLib.ServiceDelegate
18
11
 
19
12
  /** Class for a Raspberry Pi _History_ service delegate.
20
13
  *
@@ -61,41 +54,44 @@ class On extends History {
61
54
  ) {
62
55
  throw new TypeError('params.lastActivationDelegate: not a CharacteristicDelegate')
63
56
  }
64
- if (
65
- params.temperatureDelegate != null &&
66
- !(params.temperatureDelegate instanceof homebridgeLib.CharacteristicDelegate)
67
- ) {
68
- throw new TypeError('params.temperatureDelegate: not a CharacteristicDelegate')
69
- }
70
- this._entry = {
71
- time: 0,
72
- on: params.onDelegate.value ? 1 : 0
73
- }
57
+
58
+ this.entry = { o: params.onDelegate.value ? 1 : 0 }
74
59
  params.onDelegate.on('didSet', (value) => {
75
- const now = Math.round(new Date().valueOf() / 1000)
60
+ const now = History.now()
76
61
  if (params.lastActivationDelegate != null) {
77
- params.lastActivationDelegate.value = now - this._h.initialTime
62
+ params.lastActivationDelegate.value = this.lastActivationValue(now)
78
63
  }
79
- this._entry.on = value ? 1 : 0
80
- this._addEntry(now)
64
+ this.entry.o = value ? 1 : 0
65
+ this.addEntry({ time: now, o: this.entry.o })
81
66
  })
67
+
82
68
  if (params.temperatureDelegate != null) {
83
- this._entry.temp = params.temperatureDelegate.value
69
+ if (!(params.temperatureDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
70
+ throw new TypeError('params.temperatureDelegate: not a CharacteristicDelegate')
71
+ }
72
+ this.entry.t = params.temperatureDelegate.value * 100
84
73
  params.temperatureDelegate.on('didSet', (value) => {
85
- this._entry.temp = value
74
+ this.entry.t = value * 100
86
75
  })
87
76
  }
88
77
  }
89
78
 
90
- get _fingerPrint () { return '01 0E01' }
79
+ get fingerPrint () { return '01 0E01 0102' }
91
80
 
92
- _entryStream (entry) {
93
- return util.format(
94
- '|0b %s %s 01 %s',
95
- numToHex(swap32(this._h.currentEntry), 8),
96
- numToHex(swap32(entry.time - this._h.initialTime), 8),
97
- numToHex(entry.on, 2)
98
- )
81
+ entryToBuffer (entry) {
82
+ const buffer = Buffer.alloc(16)
83
+ let mask = 0
84
+ let o = 1
85
+ if (entry.o != null) {
86
+ mask |= 0x01
87
+ buffer.writeUInt8(entry.o, o); o += 1
88
+ }
89
+ if (entry.t != null) {
90
+ mask |= 0x02
91
+ buffer.writeUInt16LE(entry.t, o); o += 2
92
+ }
93
+ buffer.writeUInt8(mask, 0)
94
+ return buffer.slice(0, o)
99
95
  }
100
96
  }
101
97
 
@@ -1,20 +1,13 @@
1
1
  // homebridge-lib/lib/ServiceDelegate/History/Power.js
2
2
  //
3
3
  // Library for Homebridge plugins.
4
- // Copyright © 2017-2022 Erik Baauw. All rights reserved.
5
- //
6
- // The logic for handling Eve history was copied from Simone Tisa's
7
- // fakagato-history repository, copyright © 2017 simont77.
8
- // See https://github.com/simont77/fakegato-history.
4
+ // Copyright © 2017-2023 Erik Baauw. All rights reserved.
9
5
 
10
6
  'use strict'
11
7
 
12
8
  const homebridgeLib = require('../../../index')
13
- const util = require('util')
14
9
 
15
- const { ServiceDelegate } = homebridgeLib
16
- const { History } = ServiceDelegate
17
- const { swap16, swap32, numToHex } = History
10
+ const { History } = homebridgeLib.ServiceDelegate
18
11
 
19
12
  /** Class for an Eve Energy _History_ service delegate.
20
13
  *
@@ -49,8 +42,11 @@ class Power extends History {
49
42
  * @param {!CharacteristicDelegate} params.consumptionDelegate - A reference
50
43
  * to the delegate of the associated `Characteristics.eve.TotalConsumption`
51
44
  * characteristic.
52
- * @param {!CharacteristicDelegate} params.onDelegate - A reference to the
45
+ * @param {?CharacteristicDelegate} params.onDelegate - A reference to the
53
46
  * delegate of the associated `Characteristics.hap.On` characteristic.
47
+ * @param {?CharacteristicDelegate} params.lastActivationDelegate - A
48
+ * reference to the delegate of the associated
49
+ * `Characteristics.eve.LastActivation` characteristic.
54
50
  */
55
51
  constructor (accessoryDelegate, params) {
56
52
  super(accessoryDelegate, params)
@@ -64,15 +60,24 @@ class Power extends History {
64
60
  params.onDelegate != null &&
65
61
  !(params.onDelegate instanceof homebridgeLib.CharacteristicDelegate)
66
62
  ) {
67
- throw new TypeError('params.temperatureDelegate: not a CharacteristicDelegate')
63
+ throw new TypeError('params.onDelegate: not a CharacteristicDelegate')
64
+ }
65
+ if (
66
+ params.lastActivationDelegate != null &&
67
+ !(params.lastActivationDelegate instanceof homebridgeLib.CharacteristicDelegate)
68
+ ) {
69
+ throw new TypeError('params.lastActivationDelegate: not a CharacteristicDelegate')
68
70
  }
69
71
  this._powerDelegate = params.powerDelegate
70
72
  this._consumptionDelegate = params.consumptionDelegate
71
- this._entry = { time: 0, power: 0 }
73
+
74
+ this.entry = { p: 0 }
72
75
  this._runningConsumption = 0 // 10-min-interval running value
73
76
  this._totalConsumption = params.consumptionDelegate.value // life-time value
77
+ this._power = params.powerDelegate.value // current power
78
+ this._time = History.now // start time of current power
74
79
  params.powerDelegate.on('didSet', (value) => {
75
- const now = Math.round(new Date().valueOf() / 1000)
80
+ const now = History.now
76
81
  if (this._time != null) {
77
82
  const delta = this._power * (now - this._time) // Ws
78
83
  this._runningConsumption += Math.round(delta / 60.0) // 0.1W * 10 min
@@ -81,6 +86,7 @@ class Power extends History {
81
86
  this._power = value
82
87
  this._time = now
83
88
  })
89
+
84
90
  this.addCharacteristicDelegate({
85
91
  key: 'resetTotal',
86
92
  Characteristic: this.Characteristics.eve.ResetTotal,
@@ -90,66 +96,51 @@ class Power extends History {
90
96
  this._totalConsumption = 0
91
97
  this._consumptionDelegate.value = this._totalConsumption
92
98
  })
99
+
93
100
  if (params.onDelegate != null) {
94
- this._entry.on = params.onDelegate.value ? 1 : 0
101
+ this.entry.o = params.onDelegate.value ? 1 : 0
95
102
  params.onDelegate.on('didSet', (value) => {
96
- const now = Math.round(new Date().valueOf() / 1000)
103
+ const now = History.now
97
104
  if (params.lastActivationDelegate != null) {
98
- params.lastActivationDelegate.value = now - this._h.initialTime
105
+ params.lastActivationDelegate.value = this.lastActivationValue(now)
99
106
  }
100
- this._entry.on = value ? 1 : 0
101
- const power = this._entry.power
102
- this._entry.power = null
103
- super._addEntry(now)
104
- this._entry.power = power
107
+ this.entry.o = value ? 1 : 0
108
+ super.addEntry({ time: now, o: this.entry.o })
105
109
  })
106
110
  }
107
111
  }
108
112
 
109
- _addEntry () {
110
- const now = Math.round(new Date().valueOf() / 1000)
113
+ addEntry (entry) {
111
114
  // Sensor delivers currentConsumption, compute totalConsumption
112
115
  if (this._time != null) {
113
- const delta = this._power * (now - this._time) // Ws
116
+ const delta = this._power * (entry.time - this._time) // Ws
114
117
  this._runningConsumption += delta / 60.0 // 0.1 W * 10 min
115
118
  this._totalConsumption += delta / 36000.0 // 0.01 kWh
116
119
  this._consumptionDelegate.value = Math.round(this._totalConsumption) / 100.0 // kWh
117
- this._entry.power = Math.round(this._runningConsumption) // 0.1 W * 10 min
118
- super._addEntry(now)
119
- } else if (this._entry.on != null) {
120
- super._addEntry(now)
120
+ entry.p = Math.round(this._runningConsumption) // 0.1 W * 10 min
121
121
  }
122
+ super.addEntry(entry)
122
123
  this._power = this._powerDelegate.value
123
- this._time = now
124
+ this._time = entry.time
124
125
  this._runningConsumption = 0
125
126
  }
126
127
 
127
- get _fingerPrint () { return '02 0702 0E01' }
128
+ get fingerPrint () { return '02 0702 0E01' }
128
129
 
129
- _entryStream (entry) {
130
- if (entry.on == null) {
131
- return util.format(
132
- '|0c %s %s 01 %s',
133
- numToHex(swap32(this._h.currentEntry), 8),
134
- numToHex(swap32(entry.time - this._h.initialTime), 8),
135
- numToHex(swap16(entry.power), 4)
136
- )
130
+ entryToBuffer (entry) {
131
+ const buffer = Buffer.alloc(16)
132
+ let mask = 0
133
+ let o = 1
134
+ if (entry.p != null) {
135
+ mask |= 0x01
136
+ buffer.writeUInt16LE(entry.p, o); o += 2
137
137
  }
138
- if (entry.power == null) {
139
- return util.format(
140
- '|0b %s %s 02 %s',
141
- numToHex(swap32(this._h.currentEntry), 8),
142
- numToHex(swap32(entry.time - this._h.initialTime), 8),
143
- numToHex(entry.on, 2)
144
- )
138
+ if (entry.o != null) {
139
+ mask |= 0x02
140
+ buffer.writeUInt8(entry.o, o); o += 1
145
141
  }
146
- return util.format(
147
- '|0d %s %s 03 %s %s',
148
- numToHex(swap32(this._h.currentEntry), 8),
149
- numToHex(swap32(entry.time - this._h.initialTime), 8),
150
- numToHex(swap16(entry.power), 4),
151
- numToHex(entry.on, 2)
152
- )
142
+ buffer.writeUInt8(mask, 0)
143
+ return buffer.slice(0, o)
153
144
  }
154
145
  }
155
146