homebridge-nest-accfactory 0.2.1 → 0.2.3
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/CHANGELOG.md +15 -2
- package/README.md +10 -5
- package/dist/HomeKitDevice.js +19 -60
- package/dist/HomeKitHistory.js +63 -67
- package/dist/camera.js +81 -57
- package/dist/doorbell.js +2 -2
- package/dist/index.js +1 -1
- package/dist/nexustalk.js +4 -4
- package/dist/protect.js +15 -43
- package/dist/streamer.js +8 -7
- package/dist/system.js +73 -29
- package/dist/thermostat.js +6 -18
- package/dist/webrtc.js +31 -8
- package/package.json +11 -10
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `homebridge-nest-accfactory` will be documented in this file. This project tries to adhere to [Semantic Versioning](http://semver.org/).
|
|
4
4
|
|
|
5
|
-
## v0.2.
|
|
5
|
+
## v0.2.3 (2024/12/06)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- General code cleanup and bug fixes
|
|
8
|
+
- Fix for HomeKit Secure Video recording for migrated camera/doorbell to Google Home
|
|
9
|
+
|
|
10
|
+
## v0.2.2 (2024/10/05)
|
|
11
|
+
|
|
12
|
+
- Improved handling of configuration file with docker/standalone version
|
|
13
|
+
- Warning about the use of legacy configuration options with docker/standalone version
|
|
14
|
+
|
|
15
|
+
## Known Issues
|
|
16
|
+
|
|
17
|
+
- Audio from newer Nest/Google camera/doorbell devices is still blank
|
|
18
|
+
- npm package [ip](https://github.com/advisories/GHSA-2p57-rm9w-gvfp) has severity issue. This is being used in external library (werift)
|
|
19
|
+
|
|
20
|
+
## v0.2.1 (2024/10/05)
|
|
8
21
|
|
|
9
22
|
- HomeKit support for multiple speeds on thermostat(s)
|
|
10
23
|
- Audio library in docker release went walkabout. Added back in
|
package/README.md
CHANGED
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
<span align="center">
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Nest Accfactory
|
|
7
7
|
|
|
8
8
|
[](https://www.npmjs.com/package/homebridge-nest-accfactory)
|
|
9
9
|
[](https://www.npmjs.com/package/homebridge-nest-accfactory)
|
|
10
|
-
[](https://paypal.me/n0rt0nthec4t)
|
|
11
10
|
|
|
12
11
|
</span>
|
|
13
12
|
|
|
14
13
|
Formally known as [Nest_accfactory](https://github.com/n0rt0nthec4t/Nest_accfactory), this is a Homebridge plugin I have developed to allow Nest devices to be used with HomeKit including having support for HomeKit Secure Video on doorbells and camera devices
|
|
15
14
|
|
|
15
|
+
Building and maintaining this project takes time, effort, and resources. If you find it valuable, please consider sponsoring to support its development and future improvements. Your support makes a difference—thank you!
|
|
16
|
+
|
|
16
17
|
## Supported Devices
|
|
17
18
|
|
|
18
19
|
The following Nest devices are known to be supported
|
|
@@ -98,6 +99,7 @@ The following options are available in the config.json options object. These app
|
|
|
98
99
|
|-------------------|-----------------------------------------------------------------------------------------------|------------|
|
|
99
100
|
| elevation | Height above sea level for the weather station | 0 |
|
|
100
101
|
| eveHistory | Provide history in EveHome application where applicable | true |
|
|
102
|
+
| ffmegDebug | Turns on specific debugging output for when ffmpeg is envoked | false |
|
|
101
103
|
| ffmegPath | Path to an ffmpeg binary for us to use. Will look in current directory by default | |
|
|
102
104
|
| hksv | Enable HomeKit Secure Video for supported camera(s) and doorbell(s) | false |
|
|
103
105
|
| maxStreams | Maximum number of concurrent video streams in HomeKit for supported camera(s) and doorbell(s) | 2 |
|
|
@@ -114,6 +116,7 @@ The following options are available on a per-device level in the config.json dev
|
|
|
114
116
|
| elevation | Height above sea level for the specific weather station | 0 |
|
|
115
117
|
| eveHistory | Provide history in EveHome application where applicable for the specific device | true |
|
|
116
118
|
| exclude | Exclude the device | false |
|
|
119
|
+
| ffmegDebug | Turns on specific debugging output for when ffmpeg is envoked | false |
|
|
117
120
|
| hksv | Enable HomeKit Secure Video for supported camera(s) and doorbell(s) | false |
|
|
118
121
|
| humiditySensor | Create a seperate humidity sensor for supported thermostat(s) | false |
|
|
119
122
|
| localAccess | Use direct access to supported camera(s) and doorbell(s) for video streaming and recording | false |
|
|
@@ -132,8 +135,10 @@ To support streaming and recording from cameras, an ffmpeg binary needs to be pr
|
|
|
132
135
|
- libspeex
|
|
133
136
|
- libopus
|
|
134
137
|
|
|
135
|
-
By default, we look in the current directory where the plug-in excutes for an ffmpeg binary, however, you can specify a specific ffmpeg binary to use
|
|
138
|
+
By default, we look in the current directory where the plug-in excutes for an ffmpeg binary, however, you can specify a specific ffmpeg binary to use via the configuration option 'ffmpegPath'
|
|
139
|
+
|
|
140
|
+
## Disclaimer
|
|
136
141
|
|
|
137
|
-
|
|
142
|
+
This is a personal hobby project, provided "as-is," with no warranty whatsoever, express or implied, including but not limited to warranties of merchantability or fitness for a particular purpose. Building and running this project is done entirely at your own risk.
|
|
138
143
|
|
|
139
|
-
|
|
144
|
+
Please note that I am not affiliated with any companies, including but not limited to Google, Apple, or any other entities. The author of this project shall not be held liable for any damages or issues arising from its use. If you do encounter any problems with the source code, feel free to reach out, and we can discuss possible solutions
|
package/dist/HomeKitDevice.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
// description
|
|
20
20
|
// manufacturer
|
|
21
21
|
// model
|
|
22
|
+
// hkUsername
|
|
22
23
|
// hkPairingCode
|
|
23
24
|
//
|
|
24
25
|
// Following constants should be overridden in the module loading this class file
|
|
@@ -34,14 +35,13 @@
|
|
|
34
35
|
// HomeKitDevice.updateServices(deviceData)
|
|
35
36
|
// HomeKitDevice.messageServices(type, message)
|
|
36
37
|
//
|
|
37
|
-
// Code version
|
|
38
|
+
// Code version 8/10/2024
|
|
38
39
|
// Mark Hulskamp
|
|
39
40
|
'use strict';
|
|
40
41
|
|
|
41
42
|
// Define nodejs module requirements
|
|
42
43
|
import crypto from 'crypto';
|
|
43
44
|
import EventEmitter from 'node:events';
|
|
44
|
-
import { Buffer } from 'node:buffer';
|
|
45
45
|
|
|
46
46
|
// Define our HomeKit device class
|
|
47
47
|
export default class HomeKitDevice {
|
|
@@ -154,9 +154,11 @@ export default class HomeKitDevice {
|
|
|
154
154
|
typeof this.deviceData?.manufacturer !== 'string' ||
|
|
155
155
|
this.deviceData.manufacturer === '' ||
|
|
156
156
|
(this.#platform === undefined &&
|
|
157
|
-
typeof this.deviceData?.hkPairingCode !== 'string'
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
(typeof this.deviceData?.hkPairingCode !== 'string' ||
|
|
158
|
+
(new RegExp(/^([0-9]{3}-[0-9]{2}-[0-9]{3})$/).test(this.deviceData.hkPairingCode) === false &&
|
|
159
|
+
new RegExp(/^([0-9]{4}-[0-9]{4})$/).test(this.deviceData.hkPairingCode) === false) ||
|
|
160
|
+
typeof this.deviceData?.hkUsername !== 'string' ||
|
|
161
|
+
new RegExp(/^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/).test(this.deviceData.hkUsername) === false))
|
|
160
162
|
) {
|
|
161
163
|
return;
|
|
162
164
|
}
|
|
@@ -172,13 +174,7 @@ export default class HomeKitDevice {
|
|
|
172
174
|
// Create HAP-NodeJS libray accessory
|
|
173
175
|
this.accessory = new this.hap.Accessory(accessoryName, this.uuid);
|
|
174
176
|
|
|
175
|
-
|
|
176
|
-
// Use a Nest Labs prefix for first 6 digits, followed by a CRC24 based off serial number for last 6 digits.
|
|
177
|
-
this.accessory.username = ('18B430' + crc24(this.deviceData.serialNumber.toUpperCase()))
|
|
178
|
-
.toString('hex')
|
|
179
|
-
.split(/(..)/)
|
|
180
|
-
.filter((s) => s)
|
|
181
|
-
.join(':');
|
|
177
|
+
this.accessory.username = this.deviceData.hkUsername;
|
|
182
178
|
this.accessory.pincode = this.deviceData.hkPairingCode;
|
|
183
179
|
this.accessory.category = accessoryCategory;
|
|
184
180
|
}
|
|
@@ -201,18 +197,15 @@ export default class HomeKitDevice {
|
|
|
201
197
|
if (typeof this.addServices === 'function') {
|
|
202
198
|
try {
|
|
203
199
|
let postSetupDetails = await this.addServices();
|
|
204
|
-
|
|
200
|
+
this?.log?.info &&
|
|
205
201
|
this.log.info('Setup %s %s as "%s"', this.deviceData.manufacturer, this.deviceData.model, this.deviceData.description);
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
}
|
|
202
|
+
if (this.historyService?.EveHome !== undefined) {
|
|
203
|
+
this?.log?.info && this.log.info(' += EveHome support as "%s"', this.historyService.EveHome.evetype);
|
|
204
|
+
}
|
|
205
|
+
if (typeof postSetupDetails === 'object') {
|
|
206
|
+
postSetupDetails.forEach((output) => {
|
|
207
|
+
this?.log?.info && this.log.info(' += %s', output);
|
|
208
|
+
});
|
|
216
209
|
}
|
|
217
210
|
} catch (error) {
|
|
218
211
|
this?.log?.error && this.log.error('addServices call for device "%s" failed. Error was', this.deviceData.description, error);
|
|
@@ -229,10 +222,9 @@ export default class HomeKitDevice {
|
|
|
229
222
|
pincode: this.accessory.pincode,
|
|
230
223
|
category: this.accessory.category,
|
|
231
224
|
});
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
225
|
+
|
|
226
|
+
this?.log?.info && this.log.info(' += Advertising as "%s"', this.accessory.displayName);
|
|
227
|
+
this?.log?.info && this.log.info(' += Pairing code is "%s"', this.accessory.pincode);
|
|
236
228
|
}
|
|
237
229
|
|
|
238
230
|
return this.accessory; // Return our HomeKit accessory
|
|
@@ -440,36 +432,3 @@ export default class HomeKitDevice {
|
|
|
440
432
|
}
|
|
441
433
|
}
|
|
442
434
|
}
|
|
443
|
-
|
|
444
|
-
// General helper functions which don't need to be part of an object class
|
|
445
|
-
function crc24(valueToHash) {
|
|
446
|
-
const crc24HashTable = [
|
|
447
|
-
0x000000, 0x864cfb, 0x8ad50d, 0x0c99f6, 0x93e6e1, 0x15aa1a, 0x1933ec, 0x9f7f17, 0xa18139, 0x27cdc2, 0x2b5434, 0xad18cf, 0x3267d8,
|
|
448
|
-
0xb42b23, 0xb8b2d5, 0x3efe2e, 0xc54e89, 0x430272, 0x4f9b84, 0xc9d77f, 0x56a868, 0xd0e493, 0xdc7d65, 0x5a319e, 0x64cfb0, 0xe2834b,
|
|
449
|
-
0xee1abd, 0x685646, 0xf72951, 0x7165aa, 0x7dfc5c, 0xfbb0a7, 0x0cd1e9, 0x8a9d12, 0x8604e4, 0x00481f, 0x9f3708, 0x197bf3, 0x15e205,
|
|
450
|
-
0x93aefe, 0xad50d0, 0x2b1c2b, 0x2785dd, 0xa1c926, 0x3eb631, 0xb8faca, 0xb4633c, 0x322fc7, 0xc99f60, 0x4fd39b, 0x434a6d, 0xc50696,
|
|
451
|
-
0x5a7981, 0xdc357a, 0xd0ac8c, 0x56e077, 0x681e59, 0xee52a2, 0xe2cb54, 0x6487af, 0xfbf8b8, 0x7db443, 0x712db5, 0xf7614e, 0x19a3d2,
|
|
452
|
-
0x9fef29, 0x9376df, 0x153a24, 0x8a4533, 0x0c09c8, 0x00903e, 0x86dcc5, 0xb822eb, 0x3e6e10, 0x32f7e6, 0xb4bb1d, 0x2bc40a, 0xad88f1,
|
|
453
|
-
0xa11107, 0x275dfc, 0xdced5b, 0x5aa1a0, 0x563856, 0xd074ad, 0x4f0bba, 0xc94741, 0xc5deb7, 0x43924c, 0x7d6c62, 0xfb2099, 0xf7b96f,
|
|
454
|
-
0x71f594, 0xee8a83, 0x68c678, 0x645f8e, 0xe21375, 0x15723b, 0x933ec0, 0x9fa736, 0x19ebcd, 0x8694da, 0x00d821, 0x0c41d7, 0x8a0d2c,
|
|
455
|
-
0xb4f302, 0x32bff9, 0x3e260f, 0xb86af4, 0x2715e3, 0xa15918, 0xadc0ee, 0x2b8c15, 0xd03cb2, 0x567049, 0x5ae9bf, 0xdca544, 0x43da53,
|
|
456
|
-
0xc596a8, 0xc90f5e, 0x4f43a5, 0x71bd8b, 0xf7f170, 0xfb6886, 0x7d247d, 0xe25b6a, 0x641791, 0x688e67, 0xeec29c, 0x3347a4, 0xb50b5f,
|
|
457
|
-
0xb992a9, 0x3fde52, 0xa0a145, 0x26edbe, 0x2a7448, 0xac38b3, 0x92c69d, 0x148a66, 0x181390, 0x9e5f6b, 0x01207c, 0x876c87, 0x8bf571,
|
|
458
|
-
0x0db98a, 0xf6092d, 0x7045d6, 0x7cdc20, 0xfa90db, 0x65efcc, 0xe3a337, 0xef3ac1, 0x69763a, 0x578814, 0xd1c4ef, 0xdd5d19, 0x5b11e2,
|
|
459
|
-
0xc46ef5, 0x42220e, 0x4ebbf8, 0xc8f703, 0x3f964d, 0xb9dab6, 0xb54340, 0x330fbb, 0xac70ac, 0x2a3c57, 0x26a5a1, 0xa0e95a, 0x9e1774,
|
|
460
|
-
0x185b8f, 0x14c279, 0x928e82, 0x0df195, 0x8bbd6e, 0x872498, 0x016863, 0xfad8c4, 0x7c943f, 0x700dc9, 0xf64132, 0x693e25, 0xef72de,
|
|
461
|
-
0xe3eb28, 0x65a7d3, 0x5b59fd, 0xdd1506, 0xd18cf0, 0x57c00b, 0xc8bf1c, 0x4ef3e7, 0x426a11, 0xc426ea, 0x2ae476, 0xaca88d, 0xa0317b,
|
|
462
|
-
0x267d80, 0xb90297, 0x3f4e6c, 0x33d79a, 0xb59b61, 0x8b654f, 0x0d29b4, 0x01b042, 0x87fcb9, 0x1883ae, 0x9ecf55, 0x9256a3, 0x141a58,
|
|
463
|
-
0xefaaff, 0x69e604, 0x657ff2, 0xe33309, 0x7c4c1e, 0xfa00e5, 0xf69913, 0x70d5e8, 0x4e2bc6, 0xc8673d, 0xc4fecb, 0x42b230, 0xddcd27,
|
|
464
|
-
0x5b81dc, 0x57182a, 0xd154d1, 0x26359f, 0xa07964, 0xace092, 0x2aac69, 0xb5d37e, 0x339f85, 0x3f0673, 0xb94a88, 0x87b4a6, 0x01f85d,
|
|
465
|
-
0x0d61ab, 0x8b2d50, 0x145247, 0x921ebc, 0x9e874a, 0x18cbb1, 0xe37b16, 0x6537ed, 0x69ae1b, 0xefe2e0, 0x709df7, 0xf6d10c, 0xfa48fa,
|
|
466
|
-
0x7c0401, 0x42fa2f, 0xc4b6d4, 0xc82f22, 0x4e63d9, 0xd11cce, 0x575035, 0x5bc9c3, 0xdd8538,
|
|
467
|
-
];
|
|
468
|
-
|
|
469
|
-
let crc24 = 0xb704ce; // init crc24 hash;
|
|
470
|
-
valueToHash = Buffer.from(valueToHash); // convert value into buffer for processing
|
|
471
|
-
for (let index = 0; index < valueToHash.length; index++) {
|
|
472
|
-
crc24 = (crc24HashTable[((crc24 >> 16) ^ valueToHash[index]) & 0xff] ^ (crc24 << 8)) & 0xffffff;
|
|
473
|
-
}
|
|
474
|
-
return crc24.toString(16); // return crc24 as hex string
|
|
475
|
-
}
|
package/dist/HomeKitHistory.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
//
|
|
11
11
|
// Credit to https://github.com/simont77/fakegato-history for the work on starting the EveHome comms protocol decoding
|
|
12
12
|
//
|
|
13
|
-
// Version
|
|
13
|
+
// Version 15/10/2024
|
|
14
14
|
// Mark Hulskamp
|
|
15
15
|
|
|
16
16
|
// Define nodejs module requirements
|
|
@@ -361,7 +361,11 @@ export default class HomeKitHistory {
|
|
|
361
361
|
// Update types we have in history. This will just be the main type and its latest location in history
|
|
362
362
|
let typeIndex = this.historyData.types.findIndex((type) => type.type === historyEntry.type && type.sub === historyEntry.sub);
|
|
363
363
|
if (typeIndex === -1) {
|
|
364
|
-
this.historyData.types.push({
|
|
364
|
+
this.historyData.types.push({
|
|
365
|
+
type: historyEntry.type,
|
|
366
|
+
sub: historyEntry.sub,
|
|
367
|
+
lastEntry: this.historyData.next - 1,
|
|
368
|
+
});
|
|
365
369
|
} else {
|
|
366
370
|
this.historyData.types[typeIndex].lastEntry = this.historyData.next - 1;
|
|
367
371
|
}
|
|
@@ -382,44 +386,36 @@ export default class HomeKitHistory {
|
|
|
382
386
|
// returns a JSON object of all history for this service and subtype
|
|
383
387
|
// handles if we've rolled over history also
|
|
384
388
|
let tempHistory = [];
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if (typeof subtype !== 'undefined' && subtype !== null) {
|
|
388
|
-
findSub = subtype;
|
|
389
|
+
if (specifickey === undefined) {
|
|
390
|
+
specifickey = {};
|
|
389
391
|
}
|
|
390
|
-
|
|
392
|
+
|
|
393
|
+
if (service !== undefined && service !== '') {
|
|
391
394
|
// passed in UUID byself, rather than service object
|
|
392
|
-
|
|
395
|
+
specifickey.type = service;
|
|
393
396
|
}
|
|
394
|
-
|
|
395
|
-
|
|
397
|
+
|
|
398
|
+
if (service?.UUID !== undefined && service.UUID !== '') {
|
|
399
|
+
specifickey.type = service.UUID;
|
|
396
400
|
}
|
|
397
|
-
|
|
398
|
-
|
|
401
|
+
|
|
402
|
+
if (service?.subtype === undefined && typeof subtype === undefined) {
|
|
403
|
+
specifickey.sub = subtype;
|
|
399
404
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
return historyEntry;
|
|
415
|
-
}
|
|
416
|
-
} else if (
|
|
417
|
-
(findSub === null && historyEntry.type === findUUID) ||
|
|
418
|
-
(findSub !== null && historyEntry.type === findUUID && historyEntry.sub === findSub)
|
|
419
|
-
) {
|
|
420
|
-
return historyEntry;
|
|
421
|
-
}
|
|
422
|
-
});
|
|
405
|
+
|
|
406
|
+
if (subtype !== undefined && subtype !== null) {
|
|
407
|
+
specifickey.sub = subtype;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
tempHistory = tempHistory
|
|
411
|
+
.concat(
|
|
412
|
+
this.historyData.data.slice(this.historyData.next, this.historyData.data.length),
|
|
413
|
+
this.historyData.data.slice(0, this.historyData.next),
|
|
414
|
+
)
|
|
415
|
+
.filter((historyEntry) => {
|
|
416
|
+
return Object.entries(specifickey).every(([key, value]) => historyEntry[key] === value);
|
|
417
|
+
});
|
|
418
|
+
|
|
423
419
|
return tempHistory;
|
|
424
420
|
}
|
|
425
421
|
|
|
@@ -428,7 +424,10 @@ export default class HomeKitHistory {
|
|
|
428
424
|
// we get all the data for the service, ignoring the specific subtypes
|
|
429
425
|
let tempHistory = this.getHistory(service, null); // all history
|
|
430
426
|
if (tempHistory.length !== 0) {
|
|
431
|
-
let writer = fs.createWriteStream(csvfile, {
|
|
427
|
+
let writer = fs.createWriteStream(csvfile, {
|
|
428
|
+
flags: 'w',
|
|
429
|
+
autoClose: 'true',
|
|
430
|
+
});
|
|
432
431
|
if (writer !== null) {
|
|
433
432
|
// write header, we'll use the first record keys for the header keys
|
|
434
433
|
let header = 'time,subtype';
|
|
@@ -457,27 +456,8 @@ export default class HomeKitHistory {
|
|
|
457
456
|
|
|
458
457
|
lastHistory(service, subtype) {
|
|
459
458
|
// returns the last history event for this service type and subtype
|
|
460
|
-
let
|
|
461
|
-
|
|
462
|
-
if (typeof subtype !== 'undefined') {
|
|
463
|
-
findSub = subtype;
|
|
464
|
-
}
|
|
465
|
-
if (typeof service !== 'object') {
|
|
466
|
-
// passed in UUID byself, rather than service object
|
|
467
|
-
findUUID = service;
|
|
468
|
-
}
|
|
469
|
-
if (typeof service?.UUID === 'string') {
|
|
470
|
-
findUUID = service.UUID;
|
|
471
|
-
}
|
|
472
|
-
if (typeof service.subtype === 'undefined' && typeof subtype === 'undefined') {
|
|
473
|
-
findSub = 0;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// If subtype is 'null' find newest event based on time
|
|
477
|
-
let typeIndex = this.historyData.types.findIndex(
|
|
478
|
-
(type) => (type.type === findUUID && type.sub === findSub && subtype !== null) || (type.type === findUUID && subtype === null),
|
|
479
|
-
);
|
|
480
|
-
return typeIndex !== -1 ? this.historyData.data[this.historyData.types[typeIndex].lastEntry] : null;
|
|
459
|
+
let lastHistory = this.getHistory(service, subtype);
|
|
460
|
+
return lastHistory.length > 0 ? lastHistory?.[lastHistory.length - 1] : undefined;
|
|
481
461
|
}
|
|
482
462
|
|
|
483
463
|
entryCount(service, subtype, specifickey) {
|
|
@@ -501,7 +481,11 @@ export default class HomeKitHistory {
|
|
|
501
481
|
(typeof type.sub === 'undefined' && type.type === this.historyData.data[index].type),
|
|
502
482
|
) === -1
|
|
503
483
|
) {
|
|
504
|
-
this.historyData.types.push({
|
|
484
|
+
this.historyData.types.push({
|
|
485
|
+
type: this.historyData.data[index].type,
|
|
486
|
+
sub: this.historyData.data[index].sub,
|
|
487
|
+
lastEntry: index,
|
|
488
|
+
});
|
|
505
489
|
}
|
|
506
490
|
}
|
|
507
491
|
}
|
|
@@ -534,7 +518,7 @@ export default class HomeKitHistory {
|
|
|
534
518
|
// Callbacks setup below after this is created
|
|
535
519
|
let historyService = this.#createHistoryService(service, [
|
|
536
520
|
this.hap.Characteristic.EveLastActivation,
|
|
537
|
-
this.hap.Characteristic.
|
|
521
|
+
this.hap.Characteristic.EveOpenedDuration,
|
|
538
522
|
this.hap.Characteristic.EveTimesOpened,
|
|
539
523
|
]);
|
|
540
524
|
|
|
@@ -561,12 +545,13 @@ export default class HomeKitHistory {
|
|
|
561
545
|
service.updateCharacteristic(
|
|
562
546
|
this.hap.Characteristic.EveTimesOpened,
|
|
563
547
|
this.entryCount(this.EveHome.type, this.EveHome.sub, { status: 1 }),
|
|
564
|
-
);
|
|
548
|
+
);
|
|
565
549
|
service.updateCharacteristic(this.hap.Characteristic.EveLastActivation, this.#EveLastEventTime());
|
|
566
550
|
|
|
567
551
|
// Setup callbacks for characteristics
|
|
568
552
|
service.getCharacteristic(this.hap.Characteristic.EveTimesOpened).onGet(() => {
|
|
569
|
-
|
|
553
|
+
// Count of entries based upon status = 1, opened
|
|
554
|
+
return this.entryCount(this.EveHome.type, this.EveHome.sub, { status: 1 });
|
|
570
555
|
});
|
|
571
556
|
|
|
572
557
|
service.getCharacteristic(this.hap.Characteristic.EveLastActivation).onGet(() => {
|
|
@@ -834,7 +819,10 @@ export default class HomeKitHistory {
|
|
|
834
819
|
//let nowTemp = valHex.substr(index, 2) === '80' ? null : parseInt(valHex.substr(index, 2), 16) * 0.5;
|
|
835
820
|
let ecoTemp = valHex.substr(index + 2, 2) === '80' ? null : parseInt(valHex.substr(index + 2, 2), 16) * 0.5;
|
|
836
821
|
let comfortTemp = valHex.substr(index + 4, 2) === '80' ? null : parseInt(valHex.substr(index + 4, 2), 16) * 0.5;
|
|
837
|
-
processedData.scheduleTemps = {
|
|
822
|
+
processedData.scheduleTemps = {
|
|
823
|
+
eco: ecoTemp,
|
|
824
|
+
comfort: comfortTemp,
|
|
825
|
+
};
|
|
838
826
|
index += 6;
|
|
839
827
|
break;
|
|
840
828
|
}
|
|
@@ -883,7 +871,11 @@ export default class HomeKitHistory {
|
|
|
883
871
|
}
|
|
884
872
|
index += 4;
|
|
885
873
|
}
|
|
886
|
-
programs.push({
|
|
874
|
+
programs.push({
|
|
875
|
+
id: programs.length + 1,
|
|
876
|
+
days: DAYSOFWEEK[index2],
|
|
877
|
+
schedule: times,
|
|
878
|
+
});
|
|
887
879
|
}
|
|
888
880
|
|
|
889
881
|
this.EveThermoPersist.programs = programs;
|
|
@@ -1442,7 +1434,11 @@ export default class HomeKitHistory {
|
|
|
1442
1434
|
offset: start_offset,
|
|
1443
1435
|
});
|
|
1444
1436
|
}
|
|
1445
|
-
programs.push({
|
|
1437
|
+
programs.push({
|
|
1438
|
+
id: programs.length + 1,
|
|
1439
|
+
days: [],
|
|
1440
|
+
schedule: times,
|
|
1441
|
+
});
|
|
1446
1442
|
}
|
|
1447
1443
|
index2 = index2 + 4 + scheduleSize; // Move to next program
|
|
1448
1444
|
}
|
|
@@ -1756,7 +1752,7 @@ export default class HomeKitHistory {
|
|
|
1756
1752
|
// calculate time in seconds since first event to last event. If no history we'll use the current time as the last event time
|
|
1757
1753
|
let historyEntry = this.lastHistory(this.EveHome.type, this.EveHome.sub);
|
|
1758
1754
|
let lastTime = Math.floor(Date.now() / 1000) - (this.EveHome.reftime + EPOCH_OFFSET);
|
|
1759
|
-
if (
|
|
1755
|
+
if (isNaN(historyEntry?.time) === false) {
|
|
1760
1756
|
lastTime -= Math.floor(Date.now() / 1000) - historyEntry.time;
|
|
1761
1757
|
}
|
|
1762
1758
|
return lastTime;
|
|
@@ -2259,8 +2255,8 @@ export default class HomeKitHistory {
|
|
|
2259
2255
|
'%s %s %s',
|
|
2260
2256
|
numberToEveHexString(parseInt('11', 2), 2), // Field include/exclude mask
|
|
2261
2257
|
numberToEveHexString(historyEntry.watts * 10, 4), // Power in watts
|
|
2262
|
-
numberToEveHexString(historyEntry.status, 2),
|
|
2263
|
-
);
|
|
2258
|
+
numberToEveHexString(historyEntry.status, 2), // Power status, 1 = on, 0 = off
|
|
2259
|
+
);
|
|
2264
2260
|
break;
|
|
2265
2261
|
}
|
|
2266
2262
|
|