homebridge-unifi-protect 6.21.1 → 7.0.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 +29 -29
- package/config.schema.json +5 -15
- package/dist/devices/protect-camera-package.d.ts +0 -2
- package/dist/devices/protect-camera-package.js +4 -12
- package/dist/devices/protect-camera-package.js.map +1 -1
- package/dist/devices/protect-camera.d.ts +8 -9
- package/dist/devices/protect-camera.js +30 -119
- package/dist/devices/protect-camera.js.map +1 -1
- package/dist/devices/protect-chime.js +2 -6
- package/dist/devices/protect-chime.js.map +1 -1
- package/dist/devices/protect-device.d.ts +11 -5
- package/dist/devices/protect-device.js +17 -20
- package/dist/devices/protect-device.js.map +1 -1
- package/dist/devices/protect-doorbell.d.ts +0 -2
- package/dist/devices/protect-doorbell.js +39 -58
- package/dist/devices/protect-doorbell.js.map +1 -1
- package/dist/devices/protect-light.js +1 -3
- package/dist/devices/protect-light.js.map +1 -1
- package/dist/devices/protect-liveviews.js +2 -1
- package/dist/devices/protect-liveviews.js.map +1 -1
- package/dist/devices/protect-nvr-systeminfo.js +1 -1
- package/dist/devices/protect-nvr-systeminfo.js.map +1 -1
- package/dist/devices/protect-securitysystem.js +4 -4
- package/dist/devices/protect-securitysystem.js.map +1 -1
- package/dist/devices/protect-sensor.js +2 -6
- package/dist/devices/protect-sensor.js.map +1 -1
- package/dist/ffmpeg/protect-ffmpeg-codecs.js.map +1 -1
- package/dist/ffmpeg/protect-ffmpeg-exec.js.map +1 -1
- package/dist/ffmpeg/protect-ffmpeg-options.js +2 -20
- package/dist/ffmpeg/protect-ffmpeg-options.js.map +1 -1
- package/dist/ffmpeg/protect-ffmpeg-record.js +2 -1
- package/dist/ffmpeg/protect-ffmpeg-record.js.map +1 -1
- package/dist/ffmpeg/protect-ffmpeg-stream.js +14 -8
- package/dist/ffmpeg/protect-ffmpeg-stream.js.map +1 -1
- package/dist/ffmpeg/protect-ffmpeg.d.ts +2 -2
- package/dist/ffmpeg/protect-ffmpeg.js.map +1 -1
- package/dist/protect-events.d.ts +1 -1
- package/dist/protect-events.js +36 -33
- package/dist/protect-events.js.map +1 -1
- package/dist/protect-nvr.d.ts +7 -11
- package/dist/protect-nvr.js +14 -60
- package/dist/protect-nvr.js.map +1 -1
- package/dist/protect-options.d.ts +8 -23
- package/dist/protect-options.js +7 -129
- package/dist/protect-options.js.map +1 -1
- package/dist/protect-platform.d.ts +2 -4
- package/dist/protect-platform.js +3 -28
- package/dist/protect-platform.js.map +1 -1
- package/dist/protect-record.d.ts +2 -1
- package/dist/protect-record.js +21 -27
- package/dist/protect-record.js.map +1 -1
- package/dist/protect-snapshot.d.ts +2 -2
- package/dist/protect-snapshot.js +7 -3
- package/dist/protect-snapshot.js.map +1 -1
- package/dist/protect-stream.d.ts +3 -3
- package/dist/protect-stream.js +102 -93
- package/dist/protect-stream.js.map +1 -1
- package/dist/protect-timeshift.d.ts +9 -3
- package/dist/protect-timeshift.js +76 -24
- package/dist/protect-timeshift.js.map +1 -1
- package/dist/protect-types.d.ts +0 -7
- package/dist/protect-types.js +0 -1
- package/dist/protect-types.js.map +1 -1
- package/dist/settings.d.ts +4 -1
- package/dist/settings.js +8 -2
- package/dist/settings.js.map +1 -1
- package/homebridge-ui/public/index.html +43 -22
- package/homebridge-ui/public/lib/featureoptions.js +376 -0
- package/homebridge-ui/public/lib/featureoptions.js.map +1 -0
- package/homebridge-ui/public/lib/webUi-featureoptions.mjs +836 -0
- package/homebridge-ui/public/lib/webUi.mjs +184 -0
- package/homebridge-ui/public/ui.mjs +208 -124
- package/homebridge-ui/server.js +13 -39
- package/package.json +22 -21
- package/dist/protect-mqtt.d.ts +0 -20
- package/dist/protect-mqtt.js +0 -177
- package/dist/protect-mqtt.js.map +0 -1
- package/dist/protect-rtp.d.ts +0 -26
- package/dist/protect-rtp.js +0 -180
- package/dist/protect-rtp.js.map +0 -1
- package/homebridge-ui/public/lib/featureoptions.mjs +0 -201
- package/homebridge-ui/public/protect-featureoptions.mjs +0 -736
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
*
|
|
3
3
|
* protect-timeshift.ts: UniFi Protect livestream timeshift buffer implementation to support HomeKit Secure Video.
|
|
4
4
|
*/
|
|
5
|
+
import { retry, sleep } from "homebridge-plugin-utils";
|
|
5
6
|
import { EventEmitter } from "node:events";
|
|
6
7
|
import { PROTECT_HKSV_SEGMENT_RESOLUTION } from "./settings.js";
|
|
7
8
|
// UniFi Protect livestream timeshift buffer.
|
|
@@ -10,21 +11,26 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
10
11
|
_buffer;
|
|
11
12
|
bufferSize;
|
|
12
13
|
channelId;
|
|
14
|
+
lens;
|
|
13
15
|
livestream;
|
|
14
16
|
log;
|
|
15
17
|
nvr;
|
|
16
18
|
protectCamera;
|
|
19
|
+
_isLivestreaming;
|
|
17
20
|
_isStarted;
|
|
18
21
|
_isTransmitting;
|
|
19
22
|
_segmentLength;
|
|
20
23
|
constructor(protectCamera) {
|
|
21
24
|
// Initialize the event emitter.
|
|
22
25
|
super();
|
|
23
|
-
this.accessory = protectCamera.accessory;
|
|
24
26
|
this._buffer = [];
|
|
27
|
+
this._isLivestreaming = false;
|
|
28
|
+
this._isStarted = false;
|
|
29
|
+
this._isTransmitting = false;
|
|
30
|
+
this.accessory = protectCamera.accessory;
|
|
25
31
|
this.bufferSize = 1;
|
|
26
32
|
this.channelId = 0;
|
|
27
|
-
this.
|
|
33
|
+
this.lens = undefined;
|
|
28
34
|
this.livestream = protectCamera.nvr.ufpApi.createLivestream();
|
|
29
35
|
this.log = protectCamera.log;
|
|
30
36
|
this.nvr = protectCamera.nvr;
|
|
@@ -32,12 +38,10 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
32
38
|
// We use a small value for segment resolution in our timeshift buffer to ensure we provide an optimal timeshifting experience. It's a very small amount of additional
|
|
33
39
|
// overhead for modern CPUs, but the result is a much better HKSV event recording experience.
|
|
34
40
|
this._segmentLength = PROTECT_HKSV_SEGMENT_RESOLUTION;
|
|
35
|
-
this._isTransmitting = false;
|
|
36
41
|
this.configureTimeshiftBuffer();
|
|
37
42
|
}
|
|
38
43
|
// Configure the timeshift buffer.
|
|
39
44
|
configureTimeshiftBuffer() {
|
|
40
|
-
let seenInitSegment = false;
|
|
41
45
|
// If the livestream API has closed, stop what we're doing.
|
|
42
46
|
this.livestream.on("close", () => {
|
|
43
47
|
this.log.error("The livestream API connection was unexpectedly closed by the Protect controller: " +
|
|
@@ -45,18 +49,14 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
45
49
|
this.stop();
|
|
46
50
|
});
|
|
47
51
|
// First, we need to listen for any segments sent by the UniFi Protect livestream in order to create our timeshift buffer.
|
|
48
|
-
this.livestream.on("
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// segment, so once we've seen one, we don't need to worry about it again.
|
|
53
|
-
if (!seenInitSegment && this.livestream.initSegment?.equals(segment)) {
|
|
54
|
-
seenInitSegment = true;
|
|
55
|
-
return;
|
|
52
|
+
this.livestream.on("segment", (segment) => {
|
|
53
|
+
// If we're livestreaming, notify our listeners.
|
|
54
|
+
if (this._isLivestreaming) {
|
|
55
|
+
this.emit("livestream", segment);
|
|
56
56
|
}
|
|
57
57
|
// Add the livestream segment to the end of the timeshift buffer.
|
|
58
58
|
this._buffer.push(segment);
|
|
59
|
-
// At a minimum we always want to maintain a single segment buffer.
|
|
59
|
+
// At a minimum we always want to maintain a single segment in our buffer.
|
|
60
60
|
if (this.bufferSize <= 0) {
|
|
61
61
|
this.bufferSize = 1;
|
|
62
62
|
}
|
|
@@ -66,14 +66,16 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
66
66
|
}
|
|
67
67
|
// If we're transmitting, we want to send all the segments we can so FFmpeg can consume it.
|
|
68
68
|
if (this.isTransmitting) {
|
|
69
|
-
|
|
70
|
-
this.emit("segment", segment);
|
|
71
|
-
}
|
|
69
|
+
this.transmit();
|
|
72
70
|
}
|
|
73
71
|
});
|
|
74
72
|
}
|
|
75
73
|
// Start the livestream and begin maintaining our timeshift buffer.
|
|
76
|
-
async start(channelId, lens =
|
|
74
|
+
async start(channelId = this.channelId, lens = this.lens) {
|
|
75
|
+
// If we're using a secondary lens, the channel must always be 0.
|
|
76
|
+
if (lens !== undefined) {
|
|
77
|
+
channelId = 0;
|
|
78
|
+
}
|
|
77
79
|
// Stop the timeshift buffer if it's already running.
|
|
78
80
|
this.stop();
|
|
79
81
|
// Ensure we have sane values configured for the segment resolution. We check this here instead of in the constructor because we may not have an HKSV recording
|
|
@@ -86,12 +88,14 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
86
88
|
}
|
|
87
89
|
// Clear out the timeshift buffer, if it's been previously filled, and then fire up the timeshift buffer.
|
|
88
90
|
this._buffer = [];
|
|
89
|
-
// Start the livestream and start buffering.
|
|
90
|
-
|
|
91
|
+
// Start the livestream and start buffering. We set this to reattempt establishing the livestream up to three times before giving up due to occasional controller
|
|
92
|
+
// glitches.
|
|
93
|
+
if (!(await retry(() => this.livestream.start(this.protectCamera.ufp.id, channelId, lens, this.segmentLength), 1000, 3))) {
|
|
91
94
|
// Something went wrong in communicating with the controller.
|
|
92
95
|
return false;
|
|
93
96
|
}
|
|
94
97
|
this.channelId = channelId;
|
|
98
|
+
this.lens = lens;
|
|
95
99
|
this._isStarted = true;
|
|
96
100
|
return true;
|
|
97
101
|
}
|
|
@@ -103,9 +107,38 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
103
107
|
return true;
|
|
104
108
|
}
|
|
105
109
|
// Start transmitting our timeshift buffer.
|
|
106
|
-
async
|
|
110
|
+
async livestreamStart() {
|
|
107
111
|
// If we haven't started the livestream, or it was closed for some reason, let's start it now.
|
|
108
|
-
if (!this.isStarted && !(await this.start(
|
|
112
|
+
if (!this.isStarted && !(await this.start())) {
|
|
113
|
+
this.log.error("Unable to access the Protect livestream API: this is typically due to the Protect controller or camera rebooting.");
|
|
114
|
+
await this.nvr.resetNvrConnection();
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
// Add the initialization segment to the beginning of the timeshift buffer, if we have it. If we don't, FFmpeg will still be able to generate a valid fMP4 stream,
|
|
118
|
+
// albeit a slightly less elegantly.
|
|
119
|
+
const initSegment = await this.getInitSegment();
|
|
120
|
+
if (!initSegment) {
|
|
121
|
+
this.log.error("Unable to begin the livestream: unable to retrieve initialization data from the UniFi Protect controller. " +
|
|
122
|
+
"This error is typically due to either an issue connecting to the Protect controller, or a problem on the Protect controller.");
|
|
123
|
+
await this.nvr.resetNvrConnection();
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
// Livestream everything we have queued up to get started as quickly as possible.
|
|
127
|
+
this.emit("livestream", this.buffer ?? initSegment);
|
|
128
|
+
// Let our livestream listener know that we're now transmitting.
|
|
129
|
+
this._isLivestreaming = true;
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
// Stop transmitting our timeshift buffer.
|
|
133
|
+
livestreamStop() {
|
|
134
|
+
// We're done livestreaming, flag it accordingly.
|
|
135
|
+
this._isLivestreaming = false;
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
// Start transmitting our timeshift buffer.
|
|
139
|
+
async transmitStart() {
|
|
140
|
+
// If we haven't started the livestream, or it was closed for some reason, let's start it now.
|
|
141
|
+
if (!this.isStarted && !(await this.start())) {
|
|
109
142
|
this.log.error("Unable to access the Protect livestream API: this is typically due to the Protect controller or camera rebooting. Will retry again.");
|
|
110
143
|
await this.nvr.resetNvrConnection();
|
|
111
144
|
return false;
|
|
@@ -122,16 +155,35 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
122
155
|
await this.nvr.resetNvrConnection();
|
|
123
156
|
return false;
|
|
124
157
|
}
|
|
125
|
-
//
|
|
158
|
+
// Transmit everything we have queued up to get started as quickly as possible.
|
|
159
|
+
this.transmit();
|
|
160
|
+
// Let our livestream listener know that we're now transmitting.
|
|
126
161
|
this._isTransmitting = true;
|
|
127
162
|
return true;
|
|
128
163
|
}
|
|
129
164
|
// Stop transmitting our timeshift buffer.
|
|
130
|
-
|
|
165
|
+
transmitStop() {
|
|
131
166
|
// We're done transmitting, flag it, and allow our buffer to resume maintaining itself.
|
|
132
167
|
this._isTransmitting = false;
|
|
133
168
|
return true;
|
|
134
169
|
}
|
|
170
|
+
// Transmit the contents of our timeshift buffer.
|
|
171
|
+
transmit() {
|
|
172
|
+
this.emit("segment", Buffer.concat(this._buffer));
|
|
173
|
+
this._buffer = [];
|
|
174
|
+
}
|
|
175
|
+
isIFrame(segment) {
|
|
176
|
+
// This function should parse the fMP4 segment and determine if it contains an I-frame.
|
|
177
|
+
// For simplicity, this example assumes the segment starts with an I-frame and checks the first NAL unit.
|
|
178
|
+
const NAL_UNIT_TYPE_I_FRAME_H264 = 5; // For H.264, IDR frames have NAL unit type 5
|
|
179
|
+
const NAL_UNIT_TYPE_I_FRAME_H265 = 19; // For H.265, IDR frames have NAL unit type 19
|
|
180
|
+
const index = segment.findIndex((byte, i) => (i <= (segment.length - 4)) && [0x00, 0x00, 0x00, 0x01].every((prefixByte, j) => segment[i + j] === prefixByte));
|
|
181
|
+
if (index === -1) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
// H.264 NAL unit type is in the first byte after the start code
|
|
185
|
+
return [NAL_UNIT_TYPE_I_FRAME_H264, NAL_UNIT_TYPE_I_FRAME_H264].includes(segment[index + 4] & 0x1F);
|
|
186
|
+
}
|
|
135
187
|
// Check if this is the fMP4 initialization segment.
|
|
136
188
|
isInitSegment(segment) {
|
|
137
189
|
if (this.livestream.initSegment?.equals(segment)) {
|
|
@@ -146,7 +198,7 @@ export class ProtectTimeshiftBuffer extends EventEmitter {
|
|
|
146
198
|
return this.livestream.initSegment;
|
|
147
199
|
}
|
|
148
200
|
// We haven't seen it yet, wait for a couple of seconds and check an additional time.
|
|
149
|
-
await
|
|
201
|
+
await sleep(2000);
|
|
150
202
|
// We either have it or we don't - we can't afford to wait too long for this - HKSV is time-sensitive and we need to ensure we have a reasonable upper bound on how
|
|
151
203
|
// long we wait for data from the Protect API.
|
|
152
204
|
return this.livestream.initSegment;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protect-timeshift.js","sourceRoot":"","sources":["../src/protect-timeshift.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"protect-timeshift.js","sourceRoot":"","sources":["../src/protect-timeshift.ts"],"names":[],"mappings":"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"}
|
package/dist/protect-types.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { ProtectCamera, ProtectChime, ProtectDoorbell, ProtectLight, ProtectSensor, ProtectViewer } from "./devices/index.js";
|
|
2
2
|
import { ProtectCameraConfig, ProtectChimeConfig, ProtectLightConfig, ProtectSensorConfig, ProtectViewerConfig } from "unifi-protect";
|
|
3
3
|
export declare function toCamelCase(input: string): string;
|
|
4
|
-
export interface ProtectLogging {
|
|
5
|
-
debug: (message: string, ...parameters: unknown[]) => void;
|
|
6
|
-
error: (message: string, ...parameters: unknown[]) => void;
|
|
7
|
-
info: (message: string, ...parameters: unknown[]) => void;
|
|
8
|
-
warn: (message: string, ...parameters: unknown[]) => void;
|
|
9
|
-
}
|
|
10
4
|
export type ProtectDeviceTypes = {
|
|
11
5
|
camera: ProtectCamera;
|
|
12
6
|
chime: ProtectChime;
|
|
@@ -28,7 +22,6 @@ export declare enum ProtectReservedNames {
|
|
|
28
22
|
SWITCH_DOORBELL_CHIME_NONE = "DoorbellChime.none",
|
|
29
23
|
SWITCH_DOORBELL_CHIME_SPEAKER = "DoorbellChime.speaker",
|
|
30
24
|
SWITCH_DOORBELL_TRIGGER = "DoorbellTrigger",
|
|
31
|
-
SWITCH_DYNAMIC_BITRATE = "DynamicBitrate",
|
|
32
25
|
SWITCH_HKSV_RECORDING = "HKSVRecordingSwitch",
|
|
33
26
|
SWITCH_MOTION_SENSOR = "MotionSensorSwitch",
|
|
34
27
|
SWITCH_MOTION_TRIGGER = "MotionSensorTrigger",
|
package/dist/protect-types.js
CHANGED
|
@@ -22,7 +22,6 @@ export var ProtectReservedNames;
|
|
|
22
22
|
ProtectReservedNames["SWITCH_DOORBELL_CHIME_NONE"] = "DoorbellChime.none";
|
|
23
23
|
ProtectReservedNames["SWITCH_DOORBELL_CHIME_SPEAKER"] = "DoorbellChime.speaker";
|
|
24
24
|
ProtectReservedNames["SWITCH_DOORBELL_TRIGGER"] = "DoorbellTrigger";
|
|
25
|
-
ProtectReservedNames["SWITCH_DYNAMIC_BITRATE"] = "DynamicBitrate";
|
|
26
25
|
ProtectReservedNames["SWITCH_HKSV_RECORDING"] = "HKSVRecordingSwitch";
|
|
27
26
|
ProtectReservedNames["SWITCH_MOTION_SENSOR"] = "MotionSensorSwitch";
|
|
28
27
|
ProtectReservedNames["SWITCH_MOTION_TRIGGER"] = "MotionSensorTrigger";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protect-types.js","sourceRoot":"","sources":["../src/protect-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,oBAAoB;AACpB,MAAM,UAAU,WAAW,CAAC,KAAa;IAEvC,OAAO,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;AACrE,CAAC;
|
|
1
|
+
{"version":3,"file":"protect-types.js","sourceRoot":"","sources":["../src/protect-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,oBAAoB;AACpB,MAAM,UAAU,WAAW,CAAC,KAAa;IAEvC,OAAO,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;AACrE,CAAC;AAYD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAE,CAAC;AAI1F,uBAAuB;AACvB,MAAM,CAAN,IAAY,oBAqBX;AArBD,WAAY,oBAAoB;IAE9B,mCAAmC;IACnC,+EAAuD,CAAA;IACvD,8FAAsE,CAAA;IACtE,wDAAgC,CAAA;IAChC,wEAAgD,CAAA;IAEhD,2BAA2B;IAC3B,6EAAqD,CAAA;IACrD,+EAAuD,CAAA;IACvD,qFAA6D,CAAA;IAC7D,yEAAiD,CAAA;IACjD,+EAAuD,CAAA;IACvD,mEAA2C,CAAA;IAC3C,qEAA6C,CAAA;IAC7C,mEAA2C,CAAA;IAC3C,qEAA6C,CAAA;IAC7C,iFAAyD,CAAA;IACzD,yFAAiE,CAAA;IACjE,+EAAuD,CAAA;AACzD,CAAC,EArBW,oBAAoB,KAApB,oBAAoB,QAqB/B"}
|
package/dist/settings.d.ts
CHANGED
|
@@ -15,7 +15,8 @@ export declare const PROTECT_HKSV_SEGMENT_LENGTH = 4000;
|
|
|
15
15
|
export declare const PROTECT_HKSV_SEGMENT_RESOLUTION = 100;
|
|
16
16
|
export declare const PROTECT_HKSV_TIMESHIFT_BUFFER_MAXLENGTH: number;
|
|
17
17
|
export declare const PROTECT_HOMEKIT_STREAMING_HEADROOM = 64;
|
|
18
|
-
export declare const
|
|
18
|
+
export declare const PROTECT_HKSV_IDR_INTERVAL = 4;
|
|
19
|
+
export declare const PROTECT_HOMEKIT_IDR_INTERVAL = 5;
|
|
19
20
|
export declare const PROTECT_M3U_PLAYLIST_PORT = 10110;
|
|
20
21
|
export declare const PROTECT_MOTION_DURATION = 10;
|
|
21
22
|
export declare const PROTECT_MQTT_RECONNECT_INTERVAL = 60;
|
|
@@ -23,4 +24,6 @@ export declare const PROTECT_MQTT_TOPIC = "unifi/protect";
|
|
|
23
24
|
export declare const PROTECT_OCCUPANCY_DURATION = 300;
|
|
24
25
|
export declare const PROTECT_RPI_GPU_MINIMUM = 128;
|
|
25
26
|
export declare const PROTECT_SNAPSHOT_CACHE_MAXAGE = 90;
|
|
27
|
+
export declare const PROTECT_TRANSCODE_BITRATE = 2000;
|
|
28
|
+
export declare const PROTECT_TRANSCODE_HIGH_LATENCY_BITRATE = 1000;
|
|
26
29
|
export declare const PROTECT_TWOWAY_HEARTBEAT_INTERVAL = 3;
|
package/dist/settings.js
CHANGED
|
@@ -36,8 +36,10 @@ export const PROTECT_HKSV_SEGMENT_RESOLUTION = 100;
|
|
|
36
36
|
export const PROTECT_HKSV_TIMESHIFT_BUFFER_MAXLENGTH = PROTECT_HKSV_SEGMENT_LENGTH * 2;
|
|
37
37
|
// Additional headroom for bitrates beyond what HomeKit is requesting when streaming to improve quality with a minor additional bandwidth cost.
|
|
38
38
|
export const PROTECT_HOMEKIT_STREAMING_HEADROOM = 64;
|
|
39
|
-
// HomeKit prefers a
|
|
40
|
-
export const
|
|
39
|
+
// HomeKit prefers a default I-frame interval of 4 seconds for HKSV event recordings.
|
|
40
|
+
export const PROTECT_HKSV_IDR_INTERVAL = 4;
|
|
41
|
+
// HomeKit prefers an I-frame interval of 5 seconds when livestreaming.
|
|
42
|
+
export const PROTECT_HOMEKIT_IDR_INTERVAL = 5;
|
|
41
43
|
// Default port to use to publish an M3U playlist for use in other apps that can consume one to make camera livestreams available, such as Channels DVR.
|
|
42
44
|
export const PROTECT_M3U_PLAYLIST_PORT = 10110;
|
|
43
45
|
// Default duration, in seconds, of motion events. Setting this too low will potentially cause a lot of notification spam.
|
|
@@ -52,6 +54,10 @@ export const PROTECT_OCCUPANCY_DURATION = 300;
|
|
|
52
54
|
export const PROTECT_RPI_GPU_MINIMUM = 128;
|
|
53
55
|
// Maximum age of a snapshot in seconds.
|
|
54
56
|
export const PROTECT_SNAPSHOT_CACHE_MAXAGE = 90;
|
|
57
|
+
// Bitrate, in kilobits per second, to use when transcoding to local clients.
|
|
58
|
+
export const PROTECT_TRANSCODE_BITRATE = 2000;
|
|
59
|
+
// Bitrate, in kilobits per second, to use when transcoding to high-latency clients.
|
|
60
|
+
export const PROTECT_TRANSCODE_HIGH_LATENCY_BITRATE = 1000;
|
|
55
61
|
// How often, in seconds, should we heartbeat FFmpeg in two-way audio sessions. This should be less than 5 seconds, which is FFmpeg's input timeout interval.
|
|
56
62
|
export const PROTECT_TWOWAY_HEARTBEAT_INTERVAL = 3;
|
|
57
63
|
//# sourceMappingURL=settings.js.map
|
package/dist/settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,0BAA0B;AAC1B,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAEtD,mCAAmC;AACnC,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAE7C,yFAAyF;AACzF,MAAM,CAAC,MAAM,mCAAmC,GAAG,GAAG,CAAC;AAEvD,0GAA0G;AAC1G,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,mFAAmF;AACnF,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AAExD,6IAA6I;AAC7I,MAAM,CAAC,MAAM,uCAAuC,GAAG,IAAI,CAAC;AAE5D,oHAAoH;AACpH,MAAM,CAAC,MAAM,uCAAuC,GAAG,IAAI,CAAC;AAE5D,sHAAsH;AACtH,MAAM,CAAC,MAAM,iCAAiC,GAAG,IAAI,CAAC;AAEtD,mIAAmI;AACnI,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,4GAA4G;AAC5G,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AAExD,2GAA2G;AAC3G,MAAM,CAAC,MAAM,mCAAmC,GAAG,IAAI,CAAC;AAExD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,yHAAyH;AACzH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,oGAAoG;AACpG,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAEhD,kKAAkK;AAClK,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAEnD,mJAAmJ;AACnJ,MAAM,CAAC,MAAM,uCAAuC,GAAG,2BAA2B,GAAG,CAAC,CAAC;AAEvF,+IAA+I;AAC/I,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAErD,
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,0BAA0B;AAC1B,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAEtD,mCAAmC;AACnC,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAE7C,yFAAyF;AACzF,MAAM,CAAC,MAAM,mCAAmC,GAAG,GAAG,CAAC;AAEvD,0GAA0G;AAC1G,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,mFAAmF;AACnF,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AAExD,6IAA6I;AAC7I,MAAM,CAAC,MAAM,uCAAuC,GAAG,IAAI,CAAC;AAE5D,oHAAoH;AACpH,MAAM,CAAC,MAAM,uCAAuC,GAAG,IAAI,CAAC;AAE5D,sHAAsH;AACtH,MAAM,CAAC,MAAM,iCAAiC,GAAG,IAAI,CAAC;AAEtD,mIAAmI;AACnI,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,4GAA4G;AAC5G,MAAM,CAAC,MAAM,oCAAoC,GAAG,GAAG,CAAC;AAExD,2GAA2G;AAC3G,MAAM,CAAC,MAAM,mCAAmC,GAAG,IAAI,CAAC;AAExD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,yHAAyH;AACzH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,oGAAoG;AACpG,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAEhD,kKAAkK;AAClK,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAEnD,mJAAmJ;AACnJ,MAAM,CAAC,MAAM,uCAAuC,GAAG,2BAA2B,GAAG,CAAC,CAAC;AAEvF,+IAA+I;AAC/I,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAErD,qFAAqF;AACrF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAE3C,uEAAuE;AACvE,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAE9C,wJAAwJ;AACxJ,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAE/C,0HAA0H;AAC1H,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAE1C,oGAAoG;AACpG,MAAM,CAAC,MAAM,+BAA+B,GAAG,EAAE,CAAC;AAElD,uGAAuG;AACvG,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAElD,qDAAqD;AACrD,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAE9C,2EAA2E;AAC3E,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C,wCAAwC;AACxC,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,oFAAoF;AACpF,MAAM,CAAC,MAAM,sCAAsC,GAAG,IAAI,CAAC;AAE3D,6JAA6J;AAC7J,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC"}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
.hbup-blockquote {
|
|
3
|
+
background-color: #E6EEF9;
|
|
4
|
+
border-left: 5px solid #0559C9;
|
|
5
|
+
font-size: 0.8rem;
|
|
6
|
+
font-weight: 550;
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
1
9
|
<p class="text-center">
|
|
2
10
|
<img src="https://raw.githubusercontent.com/hjdhjd/homebridge-unifi-protect/main/images/homebridge-unifi-protect.svg" alt="homebridge-unifi-protect logo" class="w-50" />
|
|
3
11
|
</p>
|
|
4
12
|
<div id="pageFirstRun" style="display: none;">
|
|
5
|
-
<div class="text-
|
|
13
|
+
<div class="mx-auto text-left" style="width: 90%;">
|
|
6
14
|
<p>Please enter the address of your UniFi Protect controller (e.g. unvr.local or 10.0.0.1) and the login credentials for a <strong>local user</strong> to get started with <strong>homebridge-unifi-protect</strong>.</p>
|
|
7
|
-
<table class="table table-sm table-borderless">
|
|
15
|
+
<table class="table table-sm table-borderless text-center">
|
|
8
16
|
<tr>
|
|
9
17
|
<td>
|
|
10
18
|
<input type="test" placeholder="Protect controller hostname or IP address" size="40" id="address"></input>
|
|
@@ -26,8 +34,18 @@
|
|
|
26
34
|
</td>
|
|
27
35
|
</tr>
|
|
28
36
|
</table>
|
|
37
|
+
<blockquote class="blockquote hbup-blockquote mb-0 mt-0 pb-0 pt-0">
|
|
38
|
+
Things to keep in mind regarding UniFi Protect:
|
|
39
|
+
<ul dir="auto">
|
|
40
|
+
<li><b>A local user account is required to use this plugin. Ubiquiti.com/UI.com accounts are not supported.</b>. You can create an account by accessing the <i>Admins & Users</i> tab in the UniFi console webUI.</li>
|
|
41
|
+
<li>If you have a large number of cameras, make sure you are running this plugin on a machine that has sufficient CPU resources for the best performance. The recommended configuration is to use any Apple Silicon-based macOS environment.</li>
|
|
42
|
+
<li>You may run into networking issues when using Docker-based environments. These are Homebridge-specific issues, not HBUP-specific ones. You can access the <a target="_blank" href="https://github.com/hjdhjd/homebridge-unifi-protect/blob/main/docs/Troubleshooting.md">Troubleshooting</a> documentation for more information.</li>
|
|
43
|
+
</ul>
|
|
44
|
+
</blockquote>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="text-center">
|
|
29
47
|
<br>
|
|
30
|
-
<button type="button" class="btn btn-primary" id="firstRun">
|
|
48
|
+
<button type="button" class="btn btn-primary" id="firstRun">Configure Plugin →</button>
|
|
31
49
|
<br>
|
|
32
50
|
To optimize performance and responsiveness, please make this plugin a <a target="_blank" href="https://github.com/homebridge/homebridge/wiki/Child-Bridges">child bridge</a> once you've completed configuration.
|
|
33
51
|
</div>
|
|
@@ -61,10 +79,10 @@
|
|
|
61
79
|
<td id="deviceStatsTable">
|
|
62
80
|
<table class="table table-sm table-borderless border-bottom m-0 p-0">
|
|
63
81
|
<tr id="deviceStatsHeader">
|
|
64
|
-
<th class="m-0 p-0" style="width: 30%;"><
|
|
65
|
-
<th class="m-0 p-0 w-25"><
|
|
66
|
-
<th class="m-0 p-0" style="width: 20%;"><
|
|
67
|
-
<th class="m-0 p-0 w-25"><
|
|
82
|
+
<th class="m-0 p-0" style="width: 30%;"><b>Model</b></th>
|
|
83
|
+
<th class="m-0 p-0 w-25"><b>IP Address</b></th>
|
|
84
|
+
<th class="m-0 p-0" style="width: 20%;"><b>MAC Address</b></th>
|
|
85
|
+
<th class="m-0 p-0 w-25"><b>Status</b></th>
|
|
68
86
|
</tr>
|
|
69
87
|
<tr>
|
|
70
88
|
<td id="device_model" class="m-0 p-0"></td>
|
|
@@ -83,15 +101,16 @@
|
|
|
83
101
|
</div>
|
|
84
102
|
<div id="pageSupport" class="mt-4" style="display: none;">
|
|
85
103
|
<h5>Introduction</h5>
|
|
86
|
-
<p class="px-4">I hope you enjoy
|
|
104
|
+
<p class="px-4">I hope you enjoy this plugin as much as I enjoy developing it. All my projects are labors of love. If you'd like to show your appreciation - <a target="_blank" href="https://github.com/hjdhjd/homebridge-unifi-protect">star this project on GitHub</A> and do some good in your community, either financially or with your time: a food bank, an animal shelter (two of my passions), or whatever resonates with you that can give something back to the world around you. If you're looking for a couple of my faves: <a target="_blank" href="https://wck.org/donate">World Central Kitchen</a> and <a target="_blank" href="https://bestfriends.org/donate">Best Friends</a>.</p>
|
|
87
105
|
|
|
88
106
|
<div class="px-4">
|
|
89
|
-
|
|
107
|
+
Plugins by <a target="_blank" href="https://github.com/hjdhjd">HJD</a>:
|
|
90
108
|
|
|
91
109
|
<ul dir="auto">
|
|
92
|
-
<li><a target="_blank" href="https://github.com/hjdhjd/homebridge-
|
|
93
|
-
<li><a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo">homebridge-ratgdo: Ratgdo (non-myQ Liftmaster and Chamberlain) garage door and gate opener support for HomeKit</a></li>
|
|
110
|
+
<li><a target="_blank" href="https://github.com/hjdhjd/homebridge-hunter-hydrawise">homebridge-hunter-hydrawise: Hunter Hydrawise integration for HomeKit.</a></li>
|
|
111
|
+
<li><a target="_blank" href="https://github.com/hjdhjd/homebridge-ratgdo">homebridge-ratgdo: Ratgdo (non-myQ Liftmaster and Chamberlain) garage door and gate opener support for HomeKit</a></li>
|
|
94
112
|
<li><a target="_blank" href="https://github.com/hjdhjd/homebridge-unifi-access">homebridge-unifi-access: HomeKit integration for the UniFi Access ecosystem</a></li>
|
|
113
|
+
<li><a target="_blank" href="https://github.com/hjdhjd/homebridge-unifi-protect">homebridge-unifi-protect: Complete HomeKit integration for the entire UniFi Protect ecosystem</a></li>
|
|
95
114
|
</ul>
|
|
96
115
|
</div>
|
|
97
116
|
|
|
@@ -111,7 +130,7 @@
|
|
|
111
130
|
</li>
|
|
112
131
|
<li>
|
|
113
132
|
<b><a target="_blank" href="https://github.com/hjdhjd/homebridge-unifi-protect/blob/main/docs/Troubleshooting.md">Troubleshooting</a>
|
|
114
|
-
: running into login problems or streaming issues? Give this a read before looking anywhere else.</b>
|
|
133
|
+
: running into login problems, network problems, or streaming issues? Give this a read before looking anywhere else.</b>
|
|
115
134
|
</li>
|
|
116
135
|
<li>
|
|
117
136
|
<a target="_blank" href="https://github.com/hjdhjd/homebridge-unifi-protect/blob/main/docs/Changelog.md">Changelog</a>: changes and release history of this plugin, starting with v3.0.
|
|
@@ -159,15 +178,17 @@
|
|
|
159
178
|
</li>
|
|
160
179
|
</ul>
|
|
161
180
|
</div>
|
|
162
|
-
<
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
181
|
+
<script type="module">
|
|
182
|
+
|
|
183
|
+
/* Copyright(C) 2017-2024, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
184
|
+
*
|
|
185
|
+
* Plugin webUI script loader.
|
|
186
|
+
*/
|
|
187
|
+
"use strict";
|
|
168
188
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
189
|
+
// Ensure we load the webUI dynamically so it isn't cached on each load.
|
|
190
|
+
const script = document.createElement('script');
|
|
191
|
+
script.src = "./ui.mjs?v=" + Date.now().toString();
|
|
192
|
+
script.type = "module";
|
|
193
|
+
document.body.appendChild(script);
|
|
173
194
|
</script>
|