homebridge-nest-accfactory 0.3.0 → 0.3.1
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 +4 -0
- package/dist/HomeKitDevice.js +43 -34
- package/dist/config.js +10 -10
- package/dist/devices.js +14 -9
- package/dist/nexustalk.js +28 -28
- package/dist/plugins/camera.js +22 -20
- package/dist/plugins/protect.js +3 -3
- package/dist/plugins/tempsensor.js +3 -3
- package/dist/plugins/thermostat.js +3 -3
- package/dist/streamer.js +27 -27
- package/dist/system.js +79 -93
- package/dist/webrtc.js +12 -12
- package/package.json +5 -5
package/dist/streamer.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
//
|
|
18
18
|
// blankAudio - Buffer containing a blank audio segment for the type of audio being used
|
|
19
19
|
//
|
|
20
|
-
// Code version 2025.06.
|
|
20
|
+
// Code version 2025.06.15
|
|
21
21
|
// Mark Hulskamp
|
|
22
22
|
'use strict';
|
|
23
23
|
|
|
@@ -29,23 +29,23 @@ import path from 'node:path';
|
|
|
29
29
|
import { fileURLToPath } from 'node:url';
|
|
30
30
|
|
|
31
31
|
// Define constants
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
const CAMERA_RESOURCE = {
|
|
33
|
+
OFFLINE: 'Nest_camera_offline.h264',
|
|
34
|
+
OFF: 'Nest_camera_off.h264',
|
|
35
|
+
TRANSFER: 'Nest_camera_transfer.h264',
|
|
36
36
|
};
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
37
|
+
const TALKBACK_AUDIO_TIMEOUT = 1000;
|
|
38
|
+
const H264_NAL_START_CODE = Buffer.from([0x00, 0x00, 0x00, 0x01]);
|
|
39
|
+
const MAX_BUFFER_AGE = 5000; // Keep last 5s of media in buffer
|
|
40
|
+
const STREAM_FRAME_INTERVAL = 1000 / 30; // 30fps approx
|
|
41
|
+
const RESOURCE_PATH = './res';
|
|
42
42
|
const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Make a defined for JS __dirname
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
const LOG_LEVELS = {
|
|
44
|
+
INFO: 'info',
|
|
45
|
+
SUCCESS: 'success',
|
|
46
|
+
WARN: 'warn',
|
|
47
|
+
ERROR: 'error',
|
|
48
|
+
DEBUG: 'debug',
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
// Streamer object
|
|
@@ -72,7 +72,7 @@ export default class Streamer {
|
|
|
72
72
|
|
|
73
73
|
constructor(deviceData, options) {
|
|
74
74
|
// Setup logger object if passed as option
|
|
75
|
-
if (Object.
|
|
75
|
+
if (Object.values(LOG_LEVELS).every((fn) => typeof options?.log?.[fn] === 'function')) {
|
|
76
76
|
this.log = options.log;
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -86,7 +86,7 @@ export default class Streamer {
|
|
|
86
86
|
// Load support video frame files as required
|
|
87
87
|
const loadFrameIfExists = (filename, label) => {
|
|
88
88
|
let buffer = undefined;
|
|
89
|
-
let file = path.resolve(__dirname,
|
|
89
|
+
let file = path.resolve(__dirname, RESOURCE_PATH, filename);
|
|
90
90
|
if (fs.existsSync(file) === true) {
|
|
91
91
|
buffer = fs.readFileSync(file);
|
|
92
92
|
} else {
|
|
@@ -95,9 +95,9 @@ export default class Streamer {
|
|
|
95
95
|
return buffer;
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
-
this.#cameraOfflineFrame = loadFrameIfExists(
|
|
99
|
-
this.#cameraVideoOffFrame = loadFrameIfExists(
|
|
100
|
-
this.#cameraTransferringFrame = loadFrameIfExists(
|
|
98
|
+
this.#cameraOfflineFrame = loadFrameIfExists(CAMERA_RESOURCE.OFFLINE, 'offline');
|
|
99
|
+
this.#cameraVideoOffFrame = loadFrameIfExists(CAMERA_RESOURCE.OFF, 'video off');
|
|
100
|
+
this.#cameraTransferringFrame = loadFrameIfExists(CAMERA_RESOURCE.TRANSFER, 'transferring');
|
|
101
101
|
|
|
102
102
|
// Start a non-blocking loop for output to the various streams which connect to our streamer object
|
|
103
103
|
// This process will also handle the rolling-buffer size we require
|
|
@@ -106,7 +106,7 @@ export default class Streamer {
|
|
|
106
106
|
let lastVideoFrameTime = Date.now();
|
|
107
107
|
this.#outputTimer = setInterval(() => {
|
|
108
108
|
let dateNow = Date.now();
|
|
109
|
-
let outputVideoFrame = dateNow - lastVideoFrameTime >=
|
|
109
|
+
let outputVideoFrame = dateNow - lastVideoFrameTime >= STREAM_FRAME_INTERVAL;
|
|
110
110
|
Object.values(this.#outputs).forEach((output) => {
|
|
111
111
|
// Monitor for camera going offline, video enabled/disabled or being transferred between Nest/Google Home
|
|
112
112
|
// We'll insert the appropriate video frame into the stream
|
|
@@ -132,7 +132,7 @@ export default class Streamer {
|
|
|
132
132
|
// Keep our 'main' rolling buffer under a certain size
|
|
133
133
|
// Live/record buffers will always reduce in length in the next section
|
|
134
134
|
if (output.type === 'buffer') {
|
|
135
|
-
let cutoffTime = dateNow -
|
|
135
|
+
let cutoffTime = dateNow - MAX_BUFFER_AGE;
|
|
136
136
|
while (output.buffer.length > 0 && output.buffer[0].time < cutoffTime) {
|
|
137
137
|
output.buffer.shift();
|
|
138
138
|
}
|
|
@@ -142,7 +142,7 @@ export default class Streamer {
|
|
|
142
142
|
if (output.type === 'live' || output.type === 'record') {
|
|
143
143
|
let packet = output.buffer.shift();
|
|
144
144
|
if (packet?.type === 'video' && typeof output?.video?.write === 'function') {
|
|
145
|
-
packet.data = Buffer.concat([
|
|
145
|
+
packet.data = Buffer.concat([H264_NAL_START_CODE, packet.data]);
|
|
146
146
|
output.video.write(packet.data);
|
|
147
147
|
}
|
|
148
148
|
if (packet?.type === 'audio' && typeof output?.audio?.write === 'function') {
|
|
@@ -203,7 +203,7 @@ export default class Streamer {
|
|
|
203
203
|
talkbackTimeout = setTimeout(() => {
|
|
204
204
|
// no audio received in 1000ms, so mark end of stream
|
|
205
205
|
this.talkingAudio(Buffer.alloc(0));
|
|
206
|
-
},
|
|
206
|
+
}, TALKBACK_AUDIO_TIMEOUT);
|
|
207
207
|
}
|
|
208
208
|
});
|
|
209
209
|
}
|
|
@@ -351,9 +351,9 @@ export default class Streamer {
|
|
|
351
351
|
return;
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
-
if (data.indexOf(
|
|
354
|
+
if (data.indexOf(H264_NAL_START_CODE) === 0) {
|
|
355
355
|
// Strip H264 start code from input buffer. We'll handle this later
|
|
356
|
-
data = data.subarray(
|
|
356
|
+
data = data.subarray(H264_NAL_START_CODE.length);
|
|
357
357
|
}
|
|
358
358
|
|
|
359
359
|
Object.values(this.#outputs).forEach((output) => {
|