homebridge-lib 6.0.2 → 6.1.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.
- package/README.md +1 -1
- package/cli/hap.js +1 -1
- package/cli/json.js +1 -1
- package/cli/sysinfo.js +1 -1
- package/cli/upnp.js +1 -1
- package/index.js +1 -1
- package/lib/AccessoryDelegate.js +30 -27
- package/lib/AdaptiveLighting.js +1 -1
- package/lib/CharacteristicDelegate.js +22 -36
- package/lib/Colour.js +1 -1
- package/lib/CommandLineParser.js +1 -1
- package/lib/CommandLineTool.js +1 -1
- package/lib/CustomHomeKitTypes.js +1 -1
- package/lib/Delegate.js +31 -33
- package/lib/EveHomeKitTypes.js +62 -52
- package/lib/HttpClient.js +1 -1
- package/lib/JsonFormatter.js +1 -1
- package/lib/MyHomeKitTypes.js +88 -97
- package/lib/OptionParser.js +27 -2
- package/lib/Platform.js +3 -17
- package/lib/PropertyDelegate.js +8 -11
- package/lib/ServiceDelegate/AccessoryInformation.js +1 -1
- package/lib/ServiceDelegate/Battery.js +1 -1
- package/lib/ServiceDelegate/Dummy.js +1 -1
- package/lib/ServiceDelegate/History/Consumption.js +31 -49
- package/lib/ServiceDelegate/History/Contact.js +14 -22
- package/lib/ServiceDelegate/History/Light.js +15 -23
- package/lib/ServiceDelegate/History/LightLevel.js +113 -0
- package/lib/ServiceDelegate/History/Motion.js +67 -80
- package/lib/ServiceDelegate/History/On.js +27 -33
- package/lib/ServiceDelegate/History/Power.js +46 -52
- package/lib/ServiceDelegate/History/Room.js +28 -50
- package/lib/ServiceDelegate/History/Thermo.js +19 -33
- package/lib/ServiceDelegate/History/Weather.js +33 -56
- package/lib/ServiceDelegate/History/index.js +155 -182
- package/lib/ServiceDelegate/ServiceLabel.js +1 -1
- package/lib/ServiceDelegate/index.js +13 -10
- package/lib/SystemInfo.js +3 -2
- package/lib/UiServer.js +1 -1
- package/lib/UpnpClient.js +1 -1
- package/package.json +2 -2
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
// homebridge-lib/lib/ServiceDelegate/History/Weather.js
|
|
2
2
|
//
|
|
3
3
|
// Library for Homebridge plugins.
|
|
4
|
-
// Copyright © 2017-
|
|
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 {
|
|
16
|
-
const { History } = ServiceDelegate
|
|
17
|
-
const { swap16, swap32, numToHex } = History
|
|
10
|
+
const { History } = homebridgeLib.ServiceDelegate
|
|
18
11
|
|
|
19
12
|
/** Class for an Eve Weather _History_ service delegate.
|
|
20
13
|
*
|
|
@@ -36,7 +29,7 @@ const { swap16, swap32, numToHex } = History
|
|
|
36
29
|
* @extends ServiceDelegate.History
|
|
37
30
|
* @memberof ServiceDelegate.History
|
|
38
31
|
*/
|
|
39
|
-
class Weather extends
|
|
32
|
+
class Weather extends History {
|
|
40
33
|
/** Create a new instance of an Eve Weather _History_ service delegate.
|
|
41
34
|
* @param {!AccessoryDelegate} accessoryDelegate - The delegate of the
|
|
42
35
|
* corresponding HomeKit accessory.
|
|
@@ -57,67 +50,51 @@ class Weather extends ServiceDelegate.History {
|
|
|
57
50
|
if (!(params.temperatureDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
|
|
58
51
|
throw new TypeError('params.temperatureDelegate: not a CharacteristicDelegate')
|
|
59
52
|
}
|
|
60
|
-
|
|
61
|
-
params.humidityDelegate != null &&
|
|
62
|
-
!(params.humidityDelegate instanceof homebridgeLib.CharacteristicDelegate)
|
|
63
|
-
) {
|
|
64
|
-
throw new TypeError('params.humidityDelegate: not a CharacteristicDelegate')
|
|
65
|
-
}
|
|
66
|
-
if (
|
|
67
|
-
params.airPressureDelegate != null &&
|
|
68
|
-
!(params.airPressureDelegate instanceof homebridgeLib.CharacteristicDelegate)
|
|
69
|
-
) {
|
|
70
|
-
throw new TypeError('params.airPressureDelegate: not a CharacteristicDelegate')
|
|
71
|
-
}
|
|
72
|
-
this._entry = {
|
|
73
|
-
time: 0,
|
|
74
|
-
temp: params.temperatureDelegate.value
|
|
75
|
-
}
|
|
53
|
+
this.entry = { t: params.temperatureDelegate.value }
|
|
76
54
|
params.temperatureDelegate.on('didSet', (value) => {
|
|
77
|
-
this.
|
|
55
|
+
this.entry.t = value
|
|
78
56
|
})
|
|
79
57
|
if (params.humidityDelegate != null) {
|
|
80
|
-
|
|
58
|
+
if (!(params.humidityDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
|
|
59
|
+
throw new TypeError('params.humidityDelegate: not a CharacteristicDelegate')
|
|
60
|
+
}
|
|
61
|
+
this.entry.h = params.humidityDelegate.value
|
|
81
62
|
params.humidityDelegate.on('didSet', (value) => {
|
|
82
|
-
this.
|
|
63
|
+
this.entry.h = value
|
|
83
64
|
})
|
|
84
65
|
if (params.airPressureDelegate != null) {
|
|
85
|
-
|
|
66
|
+
if (!(params.airPressureDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
|
|
67
|
+
throw new TypeError('params.airPressureDelegate: not a CharacteristicDelegate')
|
|
68
|
+
}
|
|
69
|
+
this.entry.p = params.airPressureDelegate.value
|
|
86
70
|
params.airPressureDelegate.on('didSet', (value) => {
|
|
87
|
-
this.
|
|
71
|
+
this.entry.p = value
|
|
88
72
|
})
|
|
89
73
|
}
|
|
90
74
|
}
|
|
91
75
|
}
|
|
92
76
|
|
|
93
|
-
get
|
|
77
|
+
get fingerPrint () { return '03 0102 0202 0302' }
|
|
94
78
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
79
|
+
entryToBuffer (entry) {
|
|
80
|
+
const buffer = Buffer.alloc(7)
|
|
81
|
+
let o = 0
|
|
82
|
+
if (entry.h == null) {
|
|
83
|
+
buffer.writeUInt8(0x01, o); o += 1
|
|
84
|
+
buffer.writeUInt16LE(entry.t * 100, o); o += 2
|
|
85
|
+
return buffer.slice(0, o)
|
|
103
86
|
}
|
|
104
|
-
if (entry.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
numToHex(swap16(entry.temp * 100), 4),
|
|
110
|
-
numToHex(swap16(entry.humidity * 100), 4)
|
|
111
|
-
)
|
|
87
|
+
if (entry.p == null) {
|
|
88
|
+
buffer.writeUInt8(0x03, o); o += 1
|
|
89
|
+
buffer.writeUInt16LE(entry.t * 100, o); o += 2
|
|
90
|
+
buffer.writeUInt16LE(entry.h * 100, o); o += 2
|
|
91
|
+
return buffer.slice(0, o)
|
|
112
92
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
numToHex(swap16(entry.humidity * 100), 4),
|
|
119
|
-
numToHex(swap16(entry.pressure * 10), 4)
|
|
120
|
-
)
|
|
93
|
+
buffer.writeUInt8(0x07, o); o += 1
|
|
94
|
+
buffer.writeUInt16LE(entry.t * 100, o); o += 2
|
|
95
|
+
buffer.writeUInt16LE(entry.h * 100, o); o += 2
|
|
96
|
+
buffer.writeUInt16LE(entry.p * 10, o); o += 2
|
|
97
|
+
return buffer.slice(0, o)
|
|
121
98
|
}
|
|
122
99
|
}
|
|
123
100
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// homebridge-lib/lib/ServiceDelegate/History/index.js
|
|
2
2
|
//
|
|
3
3
|
// Library for Homebridge plugins.
|
|
4
|
-
// Copyright © 2017-
|
|
4
|
+
// Copyright © 2017-2023 Erik Baauw. All rights reserved.
|
|
5
5
|
//
|
|
6
|
-
// The logic for handling Eve history was
|
|
6
|
+
// The logic for handling Eve history was inspired by Simone Tisa's
|
|
7
7
|
// fakagato-history repository, copyright © 2017 simont77.
|
|
8
8
|
// See https://github.com/simont77/fakegato-history.
|
|
9
9
|
|
|
@@ -13,54 +13,37 @@ const homebridgeLib = require('../../../index')
|
|
|
13
13
|
|
|
14
14
|
const { ServiceDelegate } = homebridgeLib
|
|
15
15
|
|
|
16
|
-
const util = require('util')
|
|
17
|
-
|
|
18
16
|
/** Eve history keeps time as # seconds since epoch of 2001/01/01.
|
|
19
17
|
* @type {integer}
|
|
20
18
|
*/
|
|
21
19
|
const epoch = Math.round(new Date('2001-01-01T00:00:00Z').valueOf() / 1000)
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const defaultMemorySize = 6 * 24 * 7 * 4 // 4 weeks of 1 entry per 10 minutes
|
|
22
|
+
|
|
23
|
+
// const historyEntryTypes = {
|
|
24
|
+
// airPressure: { tag: 0x03, length: 2 },
|
|
25
|
+
// consumption: { tag: 0x07, length: 2 },
|
|
26
|
+
// contact: { tag: 0x06, length: 1, event: true },
|
|
27
|
+
// humidity: { tag: 0x02, length: 2 },
|
|
28
|
+
// lastActivation: { },
|
|
29
|
+
// lightLevel: { tag: 0x30, length: 2 },
|
|
30
|
+
// motion: { tag: 0x1C, length: 1, event: true },
|
|
31
|
+
// on: { tag: 0x0E, length: 1, event: true },
|
|
32
|
+
// power: { tag: 0x07, length: 2 },
|
|
33
|
+
// targetTemperature: { tag: 0x11, length: 2 },
|
|
34
|
+
// currentTemperature: { tag: 0x01, length: 2 },
|
|
35
|
+
// timesOpened: { },
|
|
36
|
+
// totalConsumption: { },
|
|
37
|
+
// valvePosition: { tag: 0x10, length: 1 },
|
|
38
|
+
// vocDensity: { tag: 0x22, length: 2 }
|
|
39
|
+
// }
|
|
40
|
+
|
|
41
|
+
/** Convert date (in # seconds since NodeJS epoch) to string.
|
|
42
|
+
* @param {integer} d - # seconds since NodeJS epoch.
|
|
25
43
|
* @returns {string} Human readable date string.
|
|
26
44
|
*/
|
|
27
45
|
function dateToString (d) {
|
|
28
|
-
return new Date(1000 *
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function hexToBase64 (value) {
|
|
32
|
-
if (value == null || typeof value !== 'string') {
|
|
33
|
-
throw new TypeError('value: not a string')
|
|
34
|
-
}
|
|
35
|
-
return Buffer.from((value).replace(/[^0-9A-F]/ig, ''), 'hex')
|
|
36
|
-
.toString('base64')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function base64ToHex (value) {
|
|
40
|
-
if (value == null || typeof value !== 'string') {
|
|
41
|
-
throw new TypeError('value: not a string')
|
|
42
|
-
}
|
|
43
|
-
return Buffer.from(value, 'base64').toString('hex')
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function swap16 (value) {
|
|
47
|
-
return ((value & 0xFF) << 8) | ((value >>> 8) & 0xFF)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function swap32 (value) {
|
|
51
|
-
return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) |
|
|
52
|
-
((value >>> 8) & 0xFF00) | ((value >>> 24) & 0xFF)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function numToHex (value, length) {
|
|
56
|
-
let s = Number(value >>> 0).toString(16)
|
|
57
|
-
if (s.length % 2 !== 0) {
|
|
58
|
-
s = '0' + s
|
|
59
|
-
}
|
|
60
|
-
if (length) {
|
|
61
|
-
return ('0000000000000' + s).slice(-length)
|
|
62
|
-
}
|
|
63
|
-
return s
|
|
46
|
+
return new Date(1000 * d).toString().slice(0, 24)
|
|
64
47
|
}
|
|
65
48
|
|
|
66
49
|
/** Abstract superclass for an Eve _History_ service delegate.
|
|
@@ -83,6 +66,7 @@ class History extends ServiceDelegate {
|
|
|
83
66
|
static get Consumption () { return require('./Consumption') }
|
|
84
67
|
static get Contact () { return require('./Contact') }
|
|
85
68
|
static get Light () { return require('./Light') }
|
|
69
|
+
static get LightLevel () { return require('./LightLevel') }
|
|
86
70
|
static get Motion () { return require('./Motion') }
|
|
87
71
|
static get On () { return require('./On') }
|
|
88
72
|
static get Power () { return require('./Power') }
|
|
@@ -90,19 +74,13 @@ class History extends ServiceDelegate {
|
|
|
90
74
|
static get Thermo () { return require('./Thermo') }
|
|
91
75
|
static get Weather () { return require('./Weather') }
|
|
92
76
|
|
|
93
|
-
static get hexToBase64 () { return hexToBase64 }
|
|
94
|
-
static get base64ToHex () { return base64ToHex }
|
|
95
|
-
static get swap16 () { return swap16 }
|
|
96
|
-
static get swap32 () { return swap32 }
|
|
97
|
-
static get numToHex () { return numToHex }
|
|
98
|
-
|
|
99
77
|
/** Create a new instance of an Eve _History_ service delegate.
|
|
100
78
|
* @param {!AccessoryDelegate} accessoryDelegate - The delegate of the
|
|
101
79
|
* corresponding HomeKit accessory.
|
|
102
80
|
* @param {!object} params - The parameters for the
|
|
103
81
|
* _History_ HomeKit service.
|
|
104
|
-
* @param {integer} [params.memorySize=
|
|
105
|
-
* history entries. The default is 4 weeks of
|
|
82
|
+
* @param {integer} [params.memorySize=4032] - The memory size, in number of
|
|
83
|
+
* history entries. The default is 4 weeks of 1 entry per 10 minutes.
|
|
106
84
|
* @param {?boolean} params.config - Expose config.
|
|
107
85
|
*/
|
|
108
86
|
constructor (accessoryDelegate, params = {}) {
|
|
@@ -110,35 +88,39 @@ class History extends ServiceDelegate {
|
|
|
110
88
|
params.Service = accessoryDelegate.Services.eve.History
|
|
111
89
|
params.hidden = true
|
|
112
90
|
super(accessoryDelegate, params)
|
|
113
|
-
|
|
91
|
+
const memorySize = params.memorySize == null ? defaultMemorySize : params.memorySize
|
|
114
92
|
this._transfer = false
|
|
115
|
-
this._restarted = true
|
|
116
93
|
|
|
117
94
|
this.addCharacteristicDelegate({
|
|
118
95
|
key: 'history',
|
|
119
96
|
silent: true
|
|
120
97
|
})
|
|
121
|
-
if (this.context._history != null) {
|
|
122
|
-
this.values.history = this.context._history
|
|
123
|
-
delete this.context._history
|
|
124
|
-
}
|
|
125
98
|
this._h = this.values.history
|
|
126
99
|
if (this._h == null) {
|
|
127
100
|
this.values.history = {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
initialTime:
|
|
101
|
+
memorySize,
|
|
102
|
+
firstEntry: 1,
|
|
103
|
+
lastEntry: 1,
|
|
104
|
+
entryOffset: 0,
|
|
105
|
+
entries: [null, null],
|
|
106
|
+
initialTime: History.now()
|
|
107
|
+
}
|
|
108
|
+
this._h = this.values.history
|
|
109
|
+
} else if (this._h.memorySize !== memorySize) {
|
|
110
|
+
this.values.history = {
|
|
111
|
+
memorySize,
|
|
112
|
+
firstEntry: this._h.lastEntry,
|
|
113
|
+
lastEntry: this._h.lastEntry,
|
|
114
|
+
entryOffset: this._h.lastEntry - 1,
|
|
115
|
+
entries: [null, null],
|
|
116
|
+
initialTime: this._h.initialTime
|
|
134
117
|
}
|
|
135
118
|
this._h = this.values.history
|
|
136
119
|
} else {
|
|
137
|
-
this.debug(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
delete this._h.refTime
|
|
120
|
+
this.debug(
|
|
121
|
+
'restored %d history entries (%d to %d)', this._h.entries.length,
|
|
122
|
+
this._h.firstEntry, this._h.lastEntry
|
|
123
|
+
)
|
|
142
124
|
}
|
|
143
125
|
|
|
144
126
|
this.addCharacteristicDelegate({
|
|
@@ -156,8 +138,8 @@ class History extends ServiceDelegate {
|
|
|
156
138
|
silent: true
|
|
157
139
|
}).on('didSet', (value) => {
|
|
158
140
|
const buffer = Buffer.from(value, 'base64')
|
|
159
|
-
this.
|
|
160
|
-
const date = dateToString(buffer.readUInt32LE())
|
|
141
|
+
this.vdebug('SetTime changed to %j', buffer.toString('hex'))
|
|
142
|
+
const date = dateToString(buffer.readUInt32LE() + epoch)
|
|
161
143
|
this.debug('SetTime changed to %s', date)
|
|
162
144
|
})
|
|
163
145
|
|
|
@@ -202,157 +184,148 @@ class History extends ServiceDelegate {
|
|
|
202
184
|
.once('heartbeat', (beat) => {
|
|
203
185
|
this._historyBeat = (beat % 600) + 5
|
|
204
186
|
})
|
|
205
|
-
.on('heartbeat',
|
|
187
|
+
.on('heartbeat', (beat) => {
|
|
188
|
+
if (beat % 600 === this._historyBeat) {
|
|
189
|
+
this.addEntry(
|
|
190
|
+
Object.assign({ time: History.now() }, this.entry)
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
})
|
|
206
194
|
.on('shutdown', () => {
|
|
207
|
-
this.debug(
|
|
195
|
+
this.debug(
|
|
196
|
+
'saved %d history entries (%d to %d)', this._h.entries.length,
|
|
197
|
+
this._h.firstEntry, this._h.lastEntry
|
|
198
|
+
)
|
|
208
199
|
})
|
|
209
200
|
}
|
|
210
201
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
this._h.firstEntry = 0
|
|
216
|
-
this._h.lastEntry = this._h.usedMemory
|
|
217
|
-
} else {
|
|
218
|
-
this._h.firstEntry++
|
|
219
|
-
this._h.lastEntry = this._h.firstEntry + this._h.usedMemory
|
|
220
|
-
if (this._restarted === true) {
|
|
221
|
-
this._h.history[this._h.lastEntry % this._memorySize] = {
|
|
222
|
-
time: this._entry.time,
|
|
223
|
-
setRefTime: 1
|
|
224
|
-
}
|
|
225
|
-
this._h.firstEntry++
|
|
226
|
-
this._h.lastEntry = this._h.firstEntry + this._h.usedMemory
|
|
227
|
-
this._restarted = false
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (this._h.initialTime === 0) {
|
|
232
|
-
this._h.history[this._h.lastEntry] = {
|
|
233
|
-
time: this._entry.time,
|
|
234
|
-
setRefTime: 1
|
|
235
|
-
}
|
|
236
|
-
this._h.initialTime = this._entry.time
|
|
237
|
-
this._h.lastEntry++
|
|
238
|
-
this._h.usedMemory++
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
this._h.history[this._h.lastEntry % this._memorySize] =
|
|
242
|
-
Object.assign({}, this._entry)
|
|
243
|
-
|
|
244
|
-
const usedMemeoryOffset = this._h.usedMemory < this._memorySize ? 1 : 0
|
|
245
|
-
const firstEntryOffset = this._h.usedMemory < this._memorySize ? 0 : 1
|
|
202
|
+
/** Return current time as # seconds since NodeJS epoch.
|
|
203
|
+
* @returns {integer} # seconds since NodeJS epoch.
|
|
204
|
+
*/
|
|
205
|
+
static now () { return Math.round(new Date().valueOf() / 1000) }
|
|
246
206
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
// offset += 4
|
|
253
|
-
// buffer.writeUInt32LE(this._h.initialTime - epoch, offset)
|
|
254
|
-
// offset += 4
|
|
255
|
-
// buffer.write(this._fingerPrint.replace(/[^0-9A-F]/ig, ''), offset, 'hex')
|
|
256
|
-
// const length = 1 + 2 * parseInt(this._fingerPrint.slice(0, 2))
|
|
257
|
-
// this.debug('fingerprint length: %d', length)
|
|
258
|
-
// offset += length
|
|
259
|
-
// buffer.writeUInt16LE(this._h.usedMemory + usedMemeoryOffset, offset)
|
|
260
|
-
// offset += 2
|
|
261
|
-
// buffer.writeUInt16LE(this._memorySize, offset)
|
|
262
|
-
// offset += 2
|
|
263
|
-
// buffer.writeUInt32LE(this._h.firstEntry + firstEntryOffset, offset)
|
|
264
|
-
// offset += 4
|
|
265
|
-
// buffer.writeUInt32LE(0, offset)
|
|
266
|
-
// offset += 4
|
|
267
|
-
// buffer.writeUint8(1, offset)
|
|
268
|
-
// offset += 1
|
|
269
|
-
// buffer.writeUint8(1, offset)
|
|
270
|
-
// offset += 1
|
|
207
|
+
/** Convert date intp `Characteristics.eve.LastActivation` characteristic value.
|
|
208
|
+
* @param {integer} date - # seconds since NodeJS epoch.
|
|
209
|
+
* @returns {integer} Value for last activation.
|
|
210
|
+
*/
|
|
211
|
+
lastActivationValue (date = History.now()) { return date - this._h.initialTime }
|
|
271
212
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
numToHex(swap16(this._h.usedMemory + usedMemeoryOffset), 4),
|
|
278
|
-
numToHex(swap16(this._memorySize), 4),
|
|
279
|
-
numToHex(swap32(this._h.firstEntry + firstEntryOffset), 8)
|
|
280
|
-
)
|
|
213
|
+
/** Return the history fingerprint.
|
|
214
|
+
* @abstract
|
|
215
|
+
* @returns {string} fingerprint - Hex string with the fingerprint.
|
|
216
|
+
*/
|
|
217
|
+
get fingerPrint () { return '00' }
|
|
281
218
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
219
|
+
/** Convert a history entry to a buffer.
|
|
220
|
+
* @abstract
|
|
221
|
+
* @param {object} entry - The entry.
|
|
222
|
+
* @returns {Buffer} A Buffer with the values from the entry.
|
|
223
|
+
*/
|
|
224
|
+
entryToBuffer (entry) {
|
|
225
|
+
return Buffer.alloc(0)
|
|
286
226
|
}
|
|
287
227
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
228
|
+
/** Add an entry to the history.
|
|
229
|
+
* @param {object} entry - The entry.
|
|
230
|
+
*/
|
|
231
|
+
addEntry (entry) {
|
|
232
|
+
if (this._h.memorySize > 0) {
|
|
233
|
+
if (this._h.lastEntry >= this._h.memorySize) {
|
|
234
|
+
this._h.firstEntry++
|
|
235
|
+
}
|
|
236
|
+
this._h.lastEntry++
|
|
237
|
+
const index = (this._h.lastEntry - this._h.entryOffset) % this._h.memorySize
|
|
238
|
+
this.debug(
|
|
239
|
+
'History Entries: set entry %d (index %d) to %j',
|
|
240
|
+
this._h.lastEntry, index, entry
|
|
241
|
+
)
|
|
242
|
+
this._h.entries[index] = entry
|
|
291
243
|
}
|
|
244
|
+
|
|
245
|
+
this.debug('set History Status to %d .. %d', this._h.firstEntry, this._h.lastEntry)
|
|
246
|
+
const buffer = Buffer.alloc(1024)
|
|
247
|
+
let offset = 0
|
|
248
|
+
buffer.writeUInt32LE(entry.time - this._h.initialTime, offset); offset += 4
|
|
249
|
+
buffer.writeUInt32LE(0, offset); offset += 4
|
|
250
|
+
buffer.writeUInt32LE(this._h.initialTime - epoch, offset); offset += 4
|
|
251
|
+
buffer.write(this.fingerPrint.replace(/[^0-9A-F]/ig, ''), offset, 'hex')
|
|
252
|
+
offset += 1 + 2 * parseInt(this.fingerPrint.slice(0, 2))
|
|
253
|
+
buffer.writeUInt16LE(this._h.lastEntry - this._h.firstEntry + 1, offset); offset += 2
|
|
254
|
+
buffer.writeUInt16LE(this._h.memorySize, offset); offset += 2
|
|
255
|
+
buffer.writeUInt32LE(this._h.firstEntry, offset); offset += 4
|
|
256
|
+
buffer.writeUInt32LE(0, offset); offset += 4
|
|
257
|
+
buffer.writeUInt8(1, offset); offset += 1
|
|
258
|
+
buffer.writeUInt8(1, offset); offset += 1
|
|
259
|
+
const value = buffer.slice(0, offset)
|
|
260
|
+
this.values.historyStatus = value.toString('base64')
|
|
292
261
|
}
|
|
293
262
|
|
|
294
263
|
async _onSetHistoryRequest (value) {
|
|
295
264
|
const buffer = Buffer.from(value, 'base64')
|
|
296
|
-
this.
|
|
265
|
+
this.vdebug('History Request changed to %j', buffer.toString('hex'))
|
|
297
266
|
const entry = buffer.readUInt32LE(2)
|
|
298
|
-
this.debug(
|
|
299
|
-
|
|
300
|
-
this._h.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
267
|
+
this.debug(
|
|
268
|
+
'History Request changed to %d (%d to %d)', entry,
|
|
269
|
+
this._h.firstEntry, this._h.lastEntry
|
|
270
|
+
)
|
|
271
|
+
this._currentEntry = Math.max(this._h.firstEntry, entry)
|
|
304
272
|
this._transfer = true
|
|
305
273
|
}
|
|
306
274
|
|
|
307
275
|
async _onGetEntries () {
|
|
308
|
-
if (this.
|
|
309
|
-
this.debug('
|
|
276
|
+
if (this._currentEntry > this._h.lastEntry || !this._transfer) {
|
|
277
|
+
this.debug('History Entries: no entry')
|
|
278
|
+
this.vdebug('History Entries: send data: 00')
|
|
310
279
|
this._transfer = false
|
|
311
|
-
return
|
|
280
|
+
return Buffer.from('00', 'hex').toString('base64')
|
|
312
281
|
}
|
|
313
282
|
|
|
314
|
-
|
|
283
|
+
const buffer = Buffer.alloc(1024)
|
|
284
|
+
let offset = 0
|
|
315
285
|
for (let i = 0; i < 11; i++) {
|
|
316
|
-
const
|
|
317
|
-
?
|
|
318
|
-
: this._h.
|
|
319
|
-
if (
|
|
320
|
-
this._h.history[address].setRefTime === 1 ||
|
|
321
|
-
this._h.currentEntry === this._h.firstEntry + 1
|
|
322
|
-
) {
|
|
286
|
+
const index = this._h.memorySize === 0
|
|
287
|
+
? 1
|
|
288
|
+
: (this._currentEntry - this._h.entryOffset) % this._h.memorySize
|
|
289
|
+
if (this._currentEntry === this._h.firstEntry) {
|
|
323
290
|
this.debug(
|
|
324
|
-
'
|
|
325
|
-
|
|
326
|
-
|
|
291
|
+
'History Entries (%d/11): entry %d (index: %d): %j (%s)',
|
|
292
|
+
i, this._currentEntry, index, { initialTime: this._h.initialTime - epoch },
|
|
293
|
+
dateToString(this._h.initialTime)
|
|
327
294
|
)
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
295
|
+
buffer.writeUInt8(21, offset); offset += 1
|
|
296
|
+
buffer.writeUInt32LE(this._currentEntry, offset); offset += 4
|
|
297
|
+
buffer.write('0100000081', offset, 'hex'); offset += 5
|
|
298
|
+
buffer.writeUInt32LE(this._h.initialTime - epoch, offset); offset += 4
|
|
299
|
+
buffer.write('00000000000000', offset, 'hex'); offset += 7
|
|
332
300
|
} else {
|
|
301
|
+
const entry = this._h.entries[index]
|
|
333
302
|
this.debug(
|
|
334
|
-
'
|
|
335
|
-
|
|
336
|
-
new Date(1000 * this._h.history[address].time).toString().slice(0, 24)
|
|
303
|
+
'History Entries (%d/11): entry %d (index: %d): %j (%s)',
|
|
304
|
+
i, this._currentEntry, index, entry, dateToString(entry.time)
|
|
337
305
|
)
|
|
338
|
-
|
|
306
|
+
const b = this.entryToBuffer(entry)
|
|
307
|
+
buffer.writeUInt8(b.length + 9, offset); offset += 1
|
|
308
|
+
buffer.writeUInt32LE(this._currentEntry, offset); offset += 4
|
|
309
|
+
buffer.writeUInt32LE(entry.time - this._h.initialTime, offset); offset += 4
|
|
310
|
+
b.copy(buffer, offset); offset += b.length
|
|
339
311
|
}
|
|
340
|
-
this.
|
|
341
|
-
if (this.
|
|
312
|
+
this._currentEntry++
|
|
313
|
+
if (this._currentEntry > this._h.lastEntry) {
|
|
342
314
|
break
|
|
343
315
|
}
|
|
344
316
|
}
|
|
345
|
-
|
|
346
|
-
|
|
317
|
+
const value = buffer.slice(0, offset)
|
|
318
|
+
this.vdebug('History Entries: send data: %s', value.toString('hex'))
|
|
319
|
+
return value.toString('base64')
|
|
347
320
|
}
|
|
348
321
|
|
|
349
322
|
async _onSetConfig (value) {
|
|
350
|
-
|
|
351
|
-
this.
|
|
323
|
+
const buffer = Buffer.from(value, 'base64')
|
|
324
|
+
this.vdebug('Config Request changed to %j', buffer.toString('hex'))
|
|
352
325
|
}
|
|
353
326
|
|
|
354
327
|
async _onGetConfig () {
|
|
355
|
-
return
|
|
328
|
+
return Buffer.from('D200', 'hex').toString('base64')
|
|
356
329
|
}
|
|
357
330
|
}
|
|
358
331
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// homebridge-lib/lib/ServiceDelegate/index.js
|
|
2
2
|
//
|
|
3
3
|
// Library for Homebridge plugins.
|
|
4
|
-
// Copyright © 2017-
|
|
4
|
+
// Copyright © 2017-2023 Erik Baauw. All rights reserved.
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
@@ -78,7 +78,7 @@ class ServiceDelegate extends homebridgeLib.Delegate {
|
|
|
78
78
|
: this._accessory.getServiceByUUIDAndSubType(params.Service, params.subtype)
|
|
79
79
|
if (this._service == null) {
|
|
80
80
|
this._service = this._accessory.addService(
|
|
81
|
-
new params.Service(
|
|
81
|
+
new params.Service(null, params.subtype)
|
|
82
82
|
)
|
|
83
83
|
}
|
|
84
84
|
this._accessoryDelegate._linkServiceDelegate(this)
|
|
@@ -116,25 +116,28 @@ class ServiceDelegate extends homebridgeLib.Delegate {
|
|
|
116
116
|
this.addCharacteristicDelegate({
|
|
117
117
|
key: 'name',
|
|
118
118
|
Characteristic: this.Characteristics.hap.Name,
|
|
119
|
-
silent: true,
|
|
120
119
|
value: params.name
|
|
121
120
|
})
|
|
122
|
-
|
|
123
|
-
if (params.exposeConfiguredName) {
|
|
121
|
+
if (this._service.constructor.name !== 'AccessoryInformation') {
|
|
124
122
|
this.addCharacteristicDelegate({
|
|
125
123
|
key: 'configuredName',
|
|
126
124
|
Characteristic: this.Characteristics.hap.ConfiguredName,
|
|
125
|
+
props: {
|
|
126
|
+
perms: [
|
|
127
|
+
this.Characteristic.Perms.PAIRED_READ,
|
|
128
|
+
this.Characteristic.Perms.NOTIFY,
|
|
129
|
+
this.Characteristic.Perms.PAIRED_WRITE,
|
|
130
|
+
this.Characteristic.Perms.HIDDEN
|
|
131
|
+
]
|
|
132
|
+
},
|
|
127
133
|
value: params.name,
|
|
128
134
|
setter: (value) => {
|
|
129
135
|
if (value == null || value === '') {
|
|
130
|
-
throw new
|
|
136
|
+
throw new RangeError('cannot be empty')
|
|
131
137
|
}
|
|
132
138
|
}
|
|
133
139
|
}).on('didSet', (value) => {
|
|
134
140
|
this.name = value
|
|
135
|
-
for (const key in this._characteristicDelegates) {
|
|
136
|
-
this._characteristicDelegates[key].name = value
|
|
137
|
-
}
|
|
138
141
|
if (params.primaryService) {
|
|
139
142
|
accessoryDelegate.values.name = value
|
|
140
143
|
}
|
|
@@ -173,7 +176,7 @@ class ServiceDelegate extends homebridgeLib.Delegate {
|
|
|
173
176
|
* Removes the associated HomeKit service.
|
|
174
177
|
*/
|
|
175
178
|
destroy () {
|
|
176
|
-
this.debug('destroy %s (%s)', this._key, this.
|
|
179
|
+
this.debug('destroy %s (%s)', this._key, this.constructor.name)
|
|
177
180
|
this._accessoryDelegate._unlinkServiceDelegate(this)
|
|
178
181
|
this.removeAllListeners()
|
|
179
182
|
for (const key in this._characteristicDelegates) {
|
package/lib/SystemInfo.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// homebridge-lib/lib/SystemInfo.js
|
|
2
2
|
//
|
|
3
3
|
// Library for Homebridge plugins.
|
|
4
|
-
// Copyright © 2019-
|
|
4
|
+
// Copyright © 2019-2023 Erik Baauw. All rights reserved.
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
@@ -49,7 +49,8 @@ const rpiInfo = {
|
|
|
49
49
|
17: '4B',
|
|
50
50
|
18: 'Zero 2 W',
|
|
51
51
|
19: '400',
|
|
52
|
-
20: 'CM4'
|
|
52
|
+
20: 'CM4',
|
|
53
|
+
21: 'CM4S'
|
|
53
54
|
},
|
|
54
55
|
processors: {
|
|
55
56
|
0: 'BCM2835',
|