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.
- 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 +12 -20
- 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 +28 -49
- package/lib/ServiceDelegate/History/Light.js +15 -23
- package/lib/ServiceDelegate/History/On.js +29 -33
- package/lib/ServiceDelegate/History/Power.js +43 -52
- package/lib/ServiceDelegate/History/Sensor.js +215 -0
- package/lib/ServiceDelegate/History/Thermo.js +19 -33
- package/lib/ServiceDelegate/History/index.js +137 -186
- package/lib/ServiceDelegate/ServiceLabel.js +1 -1
- package/lib/ServiceDelegate/index.js +13 -11
- package/lib/SystemInfo.js +3 -2
- package/lib/UiServer.js +1 -1
- package/lib/UpnpClient.js +1 -1
- package/package.json +2 -2
- package/lib/ServiceDelegate/History/Contact.js +0 -96
- package/lib/ServiceDelegate/History/Motion.js +0 -155
- package/lib/ServiceDelegate/History/Room.js +0 -112
- package/lib/ServiceDelegate/History/Weather.js +0 -124
|
@@ -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,19 @@ 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
|
+
/** Convert date (in # seconds since NodeJS epoch) to string.
|
|
24
|
+
* @param {integer} d - # seconds since NodeJS epoch.
|
|
25
25
|
* @returns {string} Human readable date string.
|
|
26
26
|
*/
|
|
27
27
|
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
|
|
28
|
+
return new Date(1000 * d).toString().slice(0, 24)
|
|
64
29
|
}
|
|
65
30
|
|
|
66
31
|
/** Abstract superclass for an Eve _History_ service delegate.
|
|
@@ -81,28 +46,19 @@ function numToHex (value, length) {
|
|
|
81
46
|
*/
|
|
82
47
|
class History extends ServiceDelegate {
|
|
83
48
|
static get Consumption () { return require('./Consumption') }
|
|
84
|
-
static get Contact () { return require('./Contact') }
|
|
85
49
|
static get Light () { return require('./Light') }
|
|
86
|
-
static get Motion () { return require('./Motion') }
|
|
87
50
|
static get On () { return require('./On') }
|
|
88
51
|
static get Power () { return require('./Power') }
|
|
89
|
-
static get
|
|
52
|
+
static get Sensor () { return require('./Sensor') }
|
|
90
53
|
static get Thermo () { return require('./Thermo') }
|
|
91
|
-
static get Weather () { return require('./Weather') }
|
|
92
|
-
|
|
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
54
|
|
|
99
55
|
/** Create a new instance of an Eve _History_ service delegate.
|
|
100
56
|
* @param {!AccessoryDelegate} accessoryDelegate - The delegate of the
|
|
101
57
|
* corresponding HomeKit accessory.
|
|
102
58
|
* @param {!object} params - The parameters for the
|
|
103
59
|
* _History_ HomeKit service.
|
|
104
|
-
* @param {integer} [params.memorySize=
|
|
105
|
-
* history entries. The default is 4 weeks of
|
|
60
|
+
* @param {integer} [params.memorySize=4032] - The memory size, in number of
|
|
61
|
+
* history entries. The default is 4 weeks of 1 entry per 10 minutes.
|
|
106
62
|
* @param {?boolean} params.config - Expose config.
|
|
107
63
|
*/
|
|
108
64
|
constructor (accessoryDelegate, params = {}) {
|
|
@@ -110,35 +66,39 @@ class History extends ServiceDelegate {
|
|
|
110
66
|
params.Service = accessoryDelegate.Services.eve.History
|
|
111
67
|
params.hidden = true
|
|
112
68
|
super(accessoryDelegate, params)
|
|
113
|
-
|
|
69
|
+
const memorySize = params.memorySize == null ? defaultMemorySize : params.memorySize
|
|
114
70
|
this._transfer = false
|
|
115
|
-
this._restarted = true
|
|
116
71
|
|
|
117
72
|
this.addCharacteristicDelegate({
|
|
118
73
|
key: 'history',
|
|
119
74
|
silent: true
|
|
120
75
|
})
|
|
121
|
-
if (this.context._history != null) {
|
|
122
|
-
this.values.history = this.context._history
|
|
123
|
-
delete this.context._history
|
|
124
|
-
}
|
|
125
76
|
this._h = this.values.history
|
|
126
77
|
if (this._h == null) {
|
|
127
78
|
this.values.history = {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
initialTime:
|
|
79
|
+
memorySize,
|
|
80
|
+
firstEntry: 1,
|
|
81
|
+
lastEntry: 1,
|
|
82
|
+
entryOffset: 0,
|
|
83
|
+
entries: [null, null],
|
|
84
|
+
initialTime: History.now()
|
|
85
|
+
}
|
|
86
|
+
this._h = this.values.history
|
|
87
|
+
} else if (this._h.memorySize !== memorySize) {
|
|
88
|
+
this.values.history = {
|
|
89
|
+
memorySize,
|
|
90
|
+
firstEntry: this._h.lastEntry,
|
|
91
|
+
lastEntry: this._h.lastEntry,
|
|
92
|
+
entryOffset: this._h.lastEntry - 1,
|
|
93
|
+
entries: [null, null],
|
|
94
|
+
initialTime: this._h.initialTime
|
|
134
95
|
}
|
|
135
96
|
this._h = this.values.history
|
|
136
97
|
} else {
|
|
137
|
-
this.debug(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
delete this._h.refTime
|
|
98
|
+
this.debug(
|
|
99
|
+
'restored %d history entries (%d to %d)', this._h.entries.length,
|
|
100
|
+
this._h.firstEntry, this._h.lastEntry
|
|
101
|
+
)
|
|
142
102
|
}
|
|
143
103
|
|
|
144
104
|
this.addCharacteristicDelegate({
|
|
@@ -156,8 +116,8 @@ class History extends ServiceDelegate {
|
|
|
156
116
|
silent: true
|
|
157
117
|
}).on('didSet', (value) => {
|
|
158
118
|
const buffer = Buffer.from(value, 'base64')
|
|
159
|
-
this.
|
|
160
|
-
const date = dateToString(buffer.readUInt32LE())
|
|
119
|
+
this.vdebug('SetTime changed to %j', buffer.toString('hex'))
|
|
120
|
+
const date = dateToString(buffer.readUInt32LE() + epoch)
|
|
161
121
|
this.debug('SetTime changed to %s', date)
|
|
162
122
|
})
|
|
163
123
|
|
|
@@ -202,157 +162,148 @@ class History extends ServiceDelegate {
|
|
|
202
162
|
.once('heartbeat', (beat) => {
|
|
203
163
|
this._historyBeat = (beat % 600) + 5
|
|
204
164
|
})
|
|
205
|
-
.on('heartbeat',
|
|
165
|
+
.on('heartbeat', (beat) => {
|
|
166
|
+
if (beat % 600 === this._historyBeat) {
|
|
167
|
+
this.addEntry(
|
|
168
|
+
Object.assign({ time: History.now() }, this.entry)
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
})
|
|
206
172
|
.on('shutdown', () => {
|
|
207
|
-
this.debug(
|
|
173
|
+
this.debug(
|
|
174
|
+
'saved %d history entries (%d to %d)', this._h.entries.length,
|
|
175
|
+
this._h.firstEntry, this._h.lastEntry
|
|
176
|
+
)
|
|
208
177
|
})
|
|
209
178
|
}
|
|
210
179
|
|
|
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
|
|
180
|
+
/** Return current time as # seconds since NodeJS epoch.
|
|
181
|
+
* @returns {integer} # seconds since NodeJS epoch.
|
|
182
|
+
*/
|
|
183
|
+
static now () { return Math.round(new Date().valueOf() / 1000) }
|
|
246
184
|
|
|
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
|
|
185
|
+
/** Convert date intp `Characteristics.eve.LastActivation` characteristic value.
|
|
186
|
+
* @param {integer} date - # seconds since NodeJS epoch.
|
|
187
|
+
* @returns {integer} Value for last activation.
|
|
188
|
+
*/
|
|
189
|
+
lastActivationValue (date = History.now()) { return date - this._h.initialTime }
|
|
271
190
|
|
|
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
|
-
)
|
|
191
|
+
/** Return the history fingerprint.
|
|
192
|
+
* @abstract
|
|
193
|
+
* @returns {string} fingerprint - Hex string with the fingerprint.
|
|
194
|
+
*/
|
|
195
|
+
get fingerPrint () { return '00' }
|
|
281
196
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
197
|
+
/** Convert a history entry to a buffer.
|
|
198
|
+
* @abstract
|
|
199
|
+
* @param {object} entry - The entry.
|
|
200
|
+
* @returns {Buffer} A Buffer with the values from the entry.
|
|
201
|
+
*/
|
|
202
|
+
entryToBuffer (entry) {
|
|
203
|
+
return Buffer.alloc(0)
|
|
286
204
|
}
|
|
287
205
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
206
|
+
/** Add an entry to the history.
|
|
207
|
+
* @param {object} entry - The entry.
|
|
208
|
+
*/
|
|
209
|
+
addEntry (entry) {
|
|
210
|
+
if (this._h.memorySize > 0) {
|
|
211
|
+
if (this._h.lastEntry >= this._h.memorySize) {
|
|
212
|
+
this._h.firstEntry++
|
|
213
|
+
}
|
|
214
|
+
this._h.lastEntry++
|
|
215
|
+
const index = (this._h.lastEntry - this._h.entryOffset) % this._h.memorySize
|
|
216
|
+
this.debug(
|
|
217
|
+
'History Entries: set entry %d (index %d) to %j',
|
|
218
|
+
this._h.lastEntry, index, entry
|
|
219
|
+
)
|
|
220
|
+
this._h.entries[index] = entry
|
|
291
221
|
}
|
|
222
|
+
|
|
223
|
+
this.debug('set History Status to %d .. %d', this._h.firstEntry, this._h.lastEntry)
|
|
224
|
+
const buffer = Buffer.alloc(1024)
|
|
225
|
+
let offset = 0
|
|
226
|
+
buffer.writeUInt32LE(entry.time - this._h.initialTime, offset); offset += 4
|
|
227
|
+
buffer.writeUInt32LE(0, offset); offset += 4
|
|
228
|
+
buffer.writeUInt32LE(this._h.initialTime - epoch, offset); offset += 4
|
|
229
|
+
buffer.write(this.fingerPrint.replace(/[^0-9A-F]/ig, ''), offset, 'hex')
|
|
230
|
+
offset += 1 + 2 * parseInt(this.fingerPrint.slice(0, 2))
|
|
231
|
+
buffer.writeUInt16LE(this._h.lastEntry - this._h.firstEntry + 1, offset); offset += 2
|
|
232
|
+
buffer.writeUInt16LE(this._h.memorySize, offset); offset += 2
|
|
233
|
+
buffer.writeUInt32LE(this._h.firstEntry, offset); offset += 4
|
|
234
|
+
buffer.writeUInt32LE(0, offset); offset += 4
|
|
235
|
+
buffer.writeUInt8(1, offset); offset += 1
|
|
236
|
+
buffer.writeUInt8(1, offset); offset += 1
|
|
237
|
+
const value = buffer.slice(0, offset)
|
|
238
|
+
this.values.historyStatus = value.toString('base64')
|
|
292
239
|
}
|
|
293
240
|
|
|
294
241
|
async _onSetHistoryRequest (value) {
|
|
295
242
|
const buffer = Buffer.from(value, 'base64')
|
|
296
|
-
this.
|
|
243
|
+
this.vdebug('History Request changed to %j', buffer.toString('hex'))
|
|
297
244
|
const entry = buffer.readUInt32LE(2)
|
|
298
|
-
this.debug(
|
|
299
|
-
|
|
300
|
-
this._h.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
245
|
+
this.debug(
|
|
246
|
+
'History Request changed to %d (%d to %d)', entry,
|
|
247
|
+
this._h.firstEntry, this._h.lastEntry
|
|
248
|
+
)
|
|
249
|
+
this._currentEntry = Math.max(this._h.firstEntry, entry)
|
|
304
250
|
this._transfer = true
|
|
305
251
|
}
|
|
306
252
|
|
|
307
253
|
async _onGetEntries () {
|
|
308
|
-
if (this.
|
|
309
|
-
this.debug('
|
|
254
|
+
if (this._currentEntry > this._h.lastEntry || !this._transfer) {
|
|
255
|
+
this.debug('History Entries: no entry')
|
|
256
|
+
this.vdebug('History Entries: send data: 00')
|
|
310
257
|
this._transfer = false
|
|
311
|
-
return
|
|
258
|
+
return Buffer.from('00', 'hex').toString('base64')
|
|
312
259
|
}
|
|
313
260
|
|
|
314
|
-
|
|
261
|
+
const buffer = Buffer.alloc(1024)
|
|
262
|
+
let offset = 0
|
|
315
263
|
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
|
-
) {
|
|
264
|
+
const index = this._h.memorySize === 0
|
|
265
|
+
? 1
|
|
266
|
+
: (this._currentEntry - this._h.entryOffset) % this._h.memorySize
|
|
267
|
+
if (this._currentEntry === this._h.firstEntry) {
|
|
323
268
|
this.debug(
|
|
324
|
-
'
|
|
325
|
-
|
|
326
|
-
|
|
269
|
+
'History Entries (%d/11): entry %d (index: %d): %j (%s)',
|
|
270
|
+
i, this._currentEntry, index, { initialTime: this._h.initialTime - epoch },
|
|
271
|
+
dateToString(this._h.initialTime)
|
|
327
272
|
)
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
273
|
+
buffer.writeUInt8(21, offset); offset += 1
|
|
274
|
+
buffer.writeUInt32LE(this._currentEntry, offset); offset += 4
|
|
275
|
+
buffer.write('0100000081', offset, 'hex'); offset += 5
|
|
276
|
+
buffer.writeUInt32LE(this._h.initialTime - epoch, offset); offset += 4
|
|
277
|
+
buffer.write('00000000000000', offset, 'hex'); offset += 7
|
|
332
278
|
} else {
|
|
279
|
+
const entry = this._h.entries[index]
|
|
333
280
|
this.debug(
|
|
334
|
-
'
|
|
335
|
-
|
|
336
|
-
new Date(1000 * this._h.history[address].time).toString().slice(0, 24)
|
|
281
|
+
'History Entries (%d/11): entry %d (index: %d): %j (%s)',
|
|
282
|
+
i, this._currentEntry, index, entry, dateToString(entry.time)
|
|
337
283
|
)
|
|
338
|
-
|
|
284
|
+
const b = this.entryToBuffer(entry)
|
|
285
|
+
buffer.writeUInt8(b.length + 9, offset); offset += 1
|
|
286
|
+
buffer.writeUInt32LE(this._currentEntry, offset); offset += 4
|
|
287
|
+
buffer.writeUInt32LE(entry.time - this._h.initialTime, offset); offset += 4
|
|
288
|
+
b.copy(buffer, offset); offset += b.length
|
|
339
289
|
}
|
|
340
|
-
this.
|
|
341
|
-
if (this.
|
|
290
|
+
this._currentEntry++
|
|
291
|
+
if (this._currentEntry > this._h.lastEntry) {
|
|
342
292
|
break
|
|
343
293
|
}
|
|
344
294
|
}
|
|
345
|
-
|
|
346
|
-
|
|
295
|
+
const value = buffer.slice(0, offset)
|
|
296
|
+
this.vdebug('History Entries: send data: %s', value.toString('hex'))
|
|
297
|
+
return value.toString('base64')
|
|
347
298
|
}
|
|
348
299
|
|
|
349
300
|
async _onSetConfig (value) {
|
|
350
|
-
|
|
351
|
-
this.
|
|
301
|
+
const buffer = Buffer.from(value, 'base64')
|
|
302
|
+
this.vdebug('Config Request changed to %j', buffer.toString('hex'))
|
|
352
303
|
}
|
|
353
304
|
|
|
354
305
|
async _onGetConfig () {
|
|
355
|
-
return
|
|
306
|
+
return Buffer.from('D200', 'hex').toString('base64')
|
|
356
307
|
}
|
|
357
308
|
}
|
|
358
309
|
|
|
@@ -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
|
}
|
|
@@ -142,7 +145,6 @@ class ServiceDelegate extends homebridgeLib.Delegate {
|
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
this.once('initialised', () => {
|
|
145
|
-
this.values.configuredName = this.name
|
|
146
148
|
const staleCharacteristics = []
|
|
147
149
|
for (const uuid in this._service.characteristics) {
|
|
148
150
|
const characteristic = this._service.characteristics[uuid]
|
|
@@ -173,7 +175,7 @@ class ServiceDelegate extends homebridgeLib.Delegate {
|
|
|
173
175
|
* Removes the associated HomeKit service.
|
|
174
176
|
*/
|
|
175
177
|
destroy () {
|
|
176
|
-
this.debug('destroy %s (%s)', this._key, this.
|
|
178
|
+
this.debug('destroy %s (%s)', this._key, this.constructor.name)
|
|
177
179
|
this._accessoryDelegate._unlinkServiceDelegate(this)
|
|
178
180
|
this.removeAllListeners()
|
|
179
181
|
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',
|
package/lib/UiServer.js
CHANGED
package/lib/UpnpClient.js
CHANGED
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.0
|
|
6
|
+
"version": "6.2.0",
|
|
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.
|
|
25
|
+
"node": "^18.13.0"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@homebridge/plugin-ui-utils": "~0.0.19",
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// homebridge-lib/lib/ServiceDelegate/History/Contact.js
|
|
2
|
-
//
|
|
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.
|
|
9
|
-
|
|
10
|
-
'use strict'
|
|
11
|
-
|
|
12
|
-
const homebridgeLib = require('../../../index')
|
|
13
|
-
const util = require('util')
|
|
14
|
-
|
|
15
|
-
const { ServiceDelegate } = homebridgeLib
|
|
16
|
-
const { History } = ServiceDelegate
|
|
17
|
-
const { swap32, numToHex } = History
|
|
18
|
-
|
|
19
|
-
/** Class for an Eve Door _History_ service delegate.
|
|
20
|
-
*
|
|
21
|
-
* This delegate sets up a `Services.eve.History` HomeKit service
|
|
22
|
-
* with keys for the following HomeKit characteristics:
|
|
23
|
-
*
|
|
24
|
-
* key | Characteristic
|
|
25
|
-
* ---------------- | ----------------------------------
|
|
26
|
-
* `name` | `Characteristics.hap.Name`
|
|
27
|
-
* `historyRequest` | `Characteristics.eve.HistoryRequest`
|
|
28
|
-
* `setTime` | `Characteristics.eve.SetTime`
|
|
29
|
-
* `historyStatus` | `Characteristics.eve.HistoryStatus`
|
|
30
|
-
* `historyEntries` | `Characteristics.eve.HistoryEntries`
|
|
31
|
-
* `resetTotal` | `Characteristics.eve.ResetTotal`
|
|
32
|
-
*
|
|
33
|
-
* This delegate creates the history from the associated
|
|
34
|
-
* `Characteristics.hap.ContactSensorState` characteristic. It updates the
|
|
35
|
-
* values of the associated `Characteristics.eve.TimesOpened` and
|
|
36
|
-
* `Characteristics.eve.LastActivation` characteristics.
|
|
37
|
-
* @extends ServiceDelegate.History
|
|
38
|
-
* @memberof ServiceDelegate.History
|
|
39
|
-
*/
|
|
40
|
-
class Contact extends History {
|
|
41
|
-
/** Create a new instance of an Eve Door & Window _History_ service delegate.
|
|
42
|
-
* @param {!AccessoryDelegate} accessoryDelegate - The delegate of the
|
|
43
|
-
* corresponding HomeKit accessory.
|
|
44
|
-
* @param {!object} params - The parameters for the
|
|
45
|
-
* _History_ HomeKit service.
|
|
46
|
-
* @param {!CharacteristicDelegate} params.contactDelegate - A reference to
|
|
47
|
-
* thedelegate of the associated `Characteristics.hap.ContactSensorState`
|
|
48
|
-
* characteristic.
|
|
49
|
-
* @param {!CharacteristicDelegate} params.timesOpenedDelegate - A reference
|
|
50
|
-
* to the delegate of the associated `Characteristics.eve.TimesOpened`
|
|
51
|
-
* characteristic.
|
|
52
|
-
* @param {!CharacteristicDelegate} params.lastActivationDelegate - A
|
|
53
|
-
* reference to the delegate of the associated
|
|
54
|
-
* `Characteristics.eve.LastActivation` characteristic.
|
|
55
|
-
*/
|
|
56
|
-
constructor (accessoryDelegate, params) {
|
|
57
|
-
super(accessoryDelegate, params)
|
|
58
|
-
if (!(params.contactDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
|
|
59
|
-
throw new TypeError('params.contactDelegate: not a CharacteristicDelegate')
|
|
60
|
-
}
|
|
61
|
-
if (!(params.timesOpenedDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
|
|
62
|
-
throw new TypeError('params.timesOpenedDelegate: not a CharacteristicDelegate')
|
|
63
|
-
}
|
|
64
|
-
if (!(params.lastActivationDelegate instanceof homebridgeLib.CharacteristicDelegate)) {
|
|
65
|
-
throw new TypeError('params.lastActivationDelegate: not a CharacteristicDelegate')
|
|
66
|
-
}
|
|
67
|
-
this._entry = { time: 0, status: params.contactDelegate.value }
|
|
68
|
-
params.contactDelegate.on('didSet', (value) => {
|
|
69
|
-
const now = Math.round(new Date().valueOf() / 1000)
|
|
70
|
-
params.timesOpenedDelegate.value += value
|
|
71
|
-
params.lastActivationDelegate.value = now - this._h.initialTime
|
|
72
|
-
this._entry.status = value
|
|
73
|
-
this._addEntry(now)
|
|
74
|
-
})
|
|
75
|
-
this.addCharacteristicDelegate({
|
|
76
|
-
key: 'resetTotal',
|
|
77
|
-
Characteristic: this.Characteristics.eve.ResetTotal,
|
|
78
|
-
value: params.resetTotal
|
|
79
|
-
}).on('didSet', (value) => {
|
|
80
|
-
params.timesOpenedDelegate.value = 0
|
|
81
|
-
})
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
get _fingerPrint () { return '01 0601' }
|
|
85
|
-
|
|
86
|
-
_entryStream (entry) {
|
|
87
|
-
return util.format(
|
|
88
|
-
'|0b %s %s 01 %s',
|
|
89
|
-
numToHex(swap32(this._h.currentEntry), 8),
|
|
90
|
-
numToHex(swap32(entry.time - this._h.initialTime), 8),
|
|
91
|
-
numToHex(entry.status, 2)
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
module.exports = Contact
|