homebridge-unifi-protect 5.5.4 → 6.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 +3 -3
- package/config.schema.json +17 -16
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/protect-camera.d.ts +58 -0
- package/dist/protect-camera.js +367 -246
- package/dist/protect-camera.js.map +1 -1
- package/dist/protect-device.d.ts +48 -0
- package/dist/protect-device.js +189 -0
- package/dist/protect-device.js.map +1 -0
- package/dist/protect-doorbell.d.ts +22 -0
- package/dist/protect-doorbell.js +75 -64
- package/dist/protect-doorbell.js.map +1 -1
- package/dist/protect-ffmpeg-record.d.ts +15 -0
- package/dist/protect-ffmpeg-record.js +48 -34
- package/dist/protect-ffmpeg-record.js.map +1 -1
- package/dist/protect-ffmpeg-stream.d.ts +15 -0
- package/dist/protect-ffmpeg-stream.js +22 -12
- package/dist/protect-ffmpeg-stream.js.map +1 -1
- package/dist/protect-ffmpeg.d.ts +42 -0
- package/dist/protect-ffmpeg.js +49 -58
- package/dist/protect-ffmpeg.js.map +1 -1
- package/dist/protect-light.d.ts +13 -0
- package/dist/protect-light.js +63 -40
- package/dist/protect-light.js.map +1 -1
- package/dist/protect-liveviews.d.ts +17 -0
- package/dist/protect-liveviews.js +117 -101
- package/dist/protect-liveviews.js.map +1 -1
- package/dist/protect-mqtt.d.ts +19 -0
- package/dist/protect-mqtt.js +26 -35
- package/dist/protect-mqtt.js.map +1 -1
- package/dist/protect-nvr-events.d.ts +30 -0
- package/dist/protect-nvr-events.js +168 -431
- package/dist/protect-nvr-events.js.map +1 -1
- package/dist/protect-nvr-systeminfo.d.ts +15 -0
- package/dist/protect-nvr-systeminfo.js +43 -49
- package/dist/protect-nvr-systeminfo.js.map +1 -1
- package/dist/protect-nvr.d.ts +48 -0
- package/dist/protect-nvr.js +327 -359
- package/dist/protect-nvr.js.map +1 -1
- package/dist/protect-options.d.ts +39 -0
- package/dist/protect-options.js +172 -6
- package/dist/protect-options.js.map +1 -1
- package/dist/protect-platform.d.ts +17 -0
- package/dist/protect-platform.js +17 -30
- package/dist/protect-platform.js.map +1 -1
- package/dist/protect-record.d.ts +33 -0
- package/dist/protect-record.js +130 -126
- package/dist/protect-record.js.map +1 -1
- package/dist/protect-rtp.d.ts +29 -0
- package/dist/protect-rtp.js +133 -16
- package/dist/protect-rtp.js.map +1 -1
- package/dist/protect-securitysystem.d.ts +18 -0
- package/dist/protect-securitysystem.js +105 -109
- package/dist/protect-securitysystem.js.map +1 -1
- package/dist/protect-sensor.d.ts +28 -0
- package/dist/protect-sensor.js +79 -97
- package/dist/protect-sensor.js.map +1 -1
- package/dist/protect-stream.d.ts +41 -0
- package/dist/protect-stream.js +298 -156
- package/dist/protect-stream.js.map +1 -1
- package/dist/protect-timeshift.d.ts +30 -0
- package/dist/protect-timeshift.js +65 -48
- package/dist/protect-timeshift.js.map +1 -1
- package/dist/protect-types.d.ts +50 -0
- package/dist/protect-types.js +22 -0
- package/dist/protect-types.js.map +1 -0
- package/dist/protect-viewer.d.ts +17 -0
- package/dist/protect-viewer.js +41 -47
- package/dist/protect-viewer.js.map +1 -1
- package/dist/settings.d.ts +22 -0
- package/dist/settings.js +30 -35
- package/dist/settings.js.map +1 -1
- package/homebridge-ui/public/index.html +715 -0
- package/homebridge-ui/server.js +156 -0
- package/package.json +14 -15
- package/dist/protect-accessory.js +0 -184
- package/dist/protect-accessory.js.map +0 -1
package/dist/protect-nvr.js
CHANGED
|
@@ -1,67 +1,158 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class ProtectNvr {
|
|
1
|
+
import { PLATFORM_NAME, PLUGIN_NAME, PROTECT_CONTROLLER_REFRESH_INTERVAL } from "./settings.js";
|
|
2
|
+
import { ProtectApi } from "unifi-protect";
|
|
3
|
+
import { optionEnabled } from "./protect-options.js";
|
|
4
|
+
import { ProtectCamera } from "./protect-camera.js";
|
|
5
|
+
import { ProtectDoorbell } from "./protect-doorbell.js";
|
|
6
|
+
import { ProtectLight } from "./protect-light.js";
|
|
7
|
+
import { ProtectLiveviews } from "./protect-liveviews.js";
|
|
8
|
+
import { ProtectMqtt } from "./protect-mqtt.js";
|
|
9
|
+
import { ProtectNvrEvents } from "./protect-nvr-events.js";
|
|
10
|
+
import { ProtectNvrSystemInfo } from "./protect-nvr-systeminfo.js";
|
|
11
|
+
import { ProtectSensor } from "./protect-sensor.js";
|
|
12
|
+
import { ProtectViewer } from "./protect-viewer.js";
|
|
13
|
+
import util from "node:util";
|
|
14
|
+
export class ProtectNvr {
|
|
16
15
|
constructor(platform, nvrOptions) {
|
|
17
16
|
this.api = platform.api;
|
|
18
17
|
this.config = nvrOptions;
|
|
19
18
|
this.configuredDevices = {};
|
|
20
|
-
this.debug = platform.debug.bind(platform);
|
|
21
|
-
this.doorbellCount = 0;
|
|
22
19
|
this.isEnabled = false;
|
|
23
20
|
this.hap = this.api.hap;
|
|
24
21
|
this.lastMotion = {};
|
|
25
22
|
this.lastRing = {};
|
|
26
23
|
this.liveviews = null;
|
|
27
|
-
this.
|
|
24
|
+
this.logApiErrors = true;
|
|
28
25
|
this.mqtt = null;
|
|
29
|
-
this.name = nvrOptions.name;
|
|
30
|
-
this.
|
|
31
|
-
this.nvrAddress = nvrOptions.address;
|
|
26
|
+
this.name = nvrOptions.name ?? nvrOptions.address;
|
|
27
|
+
this.nvrOptions = nvrOptions;
|
|
32
28
|
this.platform = platform;
|
|
33
|
-
this.refreshInterval = nvrOptions.refreshInterval;
|
|
34
29
|
this.systemInfo = null;
|
|
30
|
+
this.ufp = {};
|
|
35
31
|
this.unsupportedDevices = {};
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
this.name
|
|
39
|
-
|
|
32
|
+
// Configure our logging.
|
|
33
|
+
this.log = {
|
|
34
|
+
debug: (message, ...parameters) => this.platform.debug(util.format(this.name + ": " + message, ...parameters)),
|
|
35
|
+
error: (message, ...parameters) => this.platform.log.error(util.format(this.name + ": " + message, ...parameters)),
|
|
36
|
+
info: (message, ...parameters) => this.platform.log.info(util.format(this.name + ": " + message, ...parameters)),
|
|
37
|
+
warn: (message, ...parameters) => this.platform.log.warn(util.format(this.name + ": " + message, ...parameters))
|
|
38
|
+
};
|
|
40
39
|
// Validate our Protect address and login information.
|
|
41
40
|
if (!nvrOptions.address || !nvrOptions.username || !nvrOptions.password) {
|
|
42
41
|
return;
|
|
43
42
|
}
|
|
44
43
|
// Initialize our connection to the UniFi Protect API.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
const ufpLog = {
|
|
45
|
+
debug: (message, ...parameters) => this.platform.debug(util.format(message, ...parameters)),
|
|
46
|
+
error: (message, ...parameters) => {
|
|
47
|
+
if (this.logApiErrors) {
|
|
48
|
+
this.platform.log.error(util.format(message, ...parameters));
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
info: (message, ...parameters) => this.platform.log.info(util.format(message, ...parameters)),
|
|
52
|
+
warn: (message, ...parameters) => this.platform.log.warn(util.format(message, ...parameters))
|
|
53
|
+
};
|
|
54
|
+
this.ufpApi = new ProtectApi(ufpLog);
|
|
55
|
+
// Initialize our UniFi Protect realtime event handlers.
|
|
56
|
+
this.events = new ProtectNvrEvents(this);
|
|
57
|
+
// Inform users when we've logged in.
|
|
58
|
+
this.ufpApi.once("login", (success) => {
|
|
59
|
+
// We had login issues.
|
|
60
|
+
if (!success) {
|
|
61
|
+
this.ufpApi.clearLoginCredentials();
|
|
62
|
+
this.log.info("Unable to login to the UniFi Protect API. Ensure your login credentials and Protect controller address are correct.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// We logged in successfully.
|
|
66
|
+
this.platform.log.info("Connected to the UniFi Protect API at %s.", nvrOptions.address);
|
|
67
|
+
void this.ufpUpdate();
|
|
68
|
+
});
|
|
69
|
+
// Once we've connected to the Protect API, we can initialize ourselves.
|
|
70
|
+
this.ufpApi.once("bootstrap", this.ufpStartupHandler.bind(this));
|
|
71
|
+
// Cleanup any remaining streaming sessions on shutdown.
|
|
53
72
|
this.api.on("shutdown" /* APIEvent.SHUTDOWN */, () => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
void ((_a = protectCamera.stream) === null || _a === void 0 ? void 0 : _a.shutdown());
|
|
73
|
+
for (const protectDevice of Object.values(this.configuredDevices)) {
|
|
74
|
+
if (("ufp" in protectDevice) && (protectDevice.ufp.modelKey === "camera")) {
|
|
75
|
+
protectDevice.log.debug("Shutting down all video stream processes.");
|
|
76
|
+
void protectDevice.stream?.shutdown();
|
|
59
77
|
}
|
|
60
78
|
}
|
|
61
79
|
});
|
|
62
80
|
}
|
|
63
|
-
//
|
|
64
|
-
|
|
81
|
+
// Maintain our connection to the UniFi Protect controller. This is only called after we've successfully logged in for the first time at plugin launch.
|
|
82
|
+
async ufpUpdate() {
|
|
83
|
+
// Periodically refresh our bootstrap of the Protect controller to ensure our state always remains in sync in between updates.
|
|
84
|
+
for (;;) {
|
|
85
|
+
// Gently continue to attempt bootstrapping the Protect controller until we're successful.
|
|
86
|
+
// eslint-disable-next-line no-await-in-loop
|
|
87
|
+
if (!(await this.ufpApi.getBootstrap())) {
|
|
88
|
+
// eslint-disable-next-line no-await-in-loop
|
|
89
|
+
await this.sleep(10 * 1000);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
// Sync status and check for any new or removed accessories.
|
|
93
|
+
this.discoverAndSyncAccessories();
|
|
94
|
+
// Refresh the accessory cache.
|
|
95
|
+
this.api.updatePlatformAccessories(this.platform.accessories);
|
|
96
|
+
// Sleep and continue looping.
|
|
97
|
+
// eslint-disable-next-line no-await-in-loop
|
|
98
|
+
await this.sleep(PROTECT_CONTROLLER_REFRESH_INTERVAL * 1000);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Initialize ourselves once we've bootstrapped the Protect controller for the first time.
|
|
102
|
+
ufpStartupHandler(bootstrap) {
|
|
103
|
+
this.ufp = bootstrap.nvr;
|
|
104
|
+
// Assign our name if the user hasn't explicitly specified a preference.
|
|
105
|
+
this.name = this.nvrOptions.name ?? this.ufp.name;
|
|
106
|
+
// This NVR has been disabled. Let the user know that we're done here.
|
|
107
|
+
if (!this.isEnabled && !this.optionEnabled(this.ufp, "Nvr")) {
|
|
108
|
+
this.log.info("Disabling this UniFi Protect controller.");
|
|
109
|
+
this.ufpApi.clearLoginCredentials();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
this.isEnabled = true;
|
|
113
|
+
// Configure any NVR-specific settings.
|
|
114
|
+
void this.configureNvr();
|
|
115
|
+
// Initialize our liveviews.
|
|
116
|
+
this.liveviews = new ProtectLiveviews(this);
|
|
117
|
+
// Initialize our NVR system information.
|
|
118
|
+
this.systemInfo = new ProtectNvrSystemInfo(this);
|
|
119
|
+
// Initialize MQTT, if needed.
|
|
120
|
+
if (!this.mqtt && this.config.mqttUrl) {
|
|
121
|
+
this.mqtt = new ProtectMqtt(this);
|
|
122
|
+
}
|
|
123
|
+
// Inform the user about the devices we see.
|
|
124
|
+
this.log.info("Discovered %s: %s.", this.ufp.modelKey, this.ufpApi.getDeviceName(this.ufp, this.ufp.name, true));
|
|
125
|
+
for (const device of [...bootstrap.cameras, ...bootstrap.lights, ...bootstrap.sensors, ...bootstrap.viewers]) {
|
|
126
|
+
// Filter out any devices that aren't adopted by this Protect controller.
|
|
127
|
+
if (device.isAdoptedByOther || device.isAdopting || !device.isAdopted) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
this.log.info("Discovered %s: %s.", device.modelKey, this.ufpApi.getDeviceName(device, device.name, true));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Configure NVR-specific settings.
|
|
134
|
+
async configureNvr() {
|
|
135
|
+
// Configure the default doorbell message on the NVR.
|
|
136
|
+
await this.configureDefaultDoorbellMessage();
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
// Configure a default doorbell message on the Protect doorbell.
|
|
140
|
+
async configureDefaultDoorbellMessage() {
|
|
141
|
+
const defaultMessage = this.nvrOptions.defaultDoorbellMessage ?? "WELCOME";
|
|
142
|
+
// Set the default message.
|
|
143
|
+
const newUfp = await this.ufpApi.updateDevice(this.ufp, { doorbellSettings: { defaultMessageText: defaultMessage } });
|
|
144
|
+
if (!newUfp) {
|
|
145
|
+
this.log.error("Unable to set the default doorbell message. Please ensure this username has the Administrator role in UniFi Protect.");
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
// Update our internal view of the NVR configuration.
|
|
149
|
+
this.ufp = newUfp;
|
|
150
|
+
// Inform the user.
|
|
151
|
+
this.log.info("Default doorbell message set to: %s.", defaultMessage);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
// Create instances of Protect device types in our plugin.
|
|
155
|
+
addProtectDevice(accessory, device) {
|
|
65
156
|
if (!accessory || !device) {
|
|
66
157
|
return false;
|
|
67
158
|
}
|
|
@@ -69,380 +160,258 @@ class ProtectNvr {
|
|
|
69
160
|
case "camera":
|
|
70
161
|
// We have a UniFi Protect camera or doorbell.
|
|
71
162
|
if (device.featureFlags.hasChime) {
|
|
72
|
-
this.configuredDevices[accessory.UUID] = new
|
|
163
|
+
this.configuredDevices[accessory.UUID] = new ProtectDoorbell(this, device, accessory);
|
|
73
164
|
}
|
|
74
165
|
else {
|
|
75
|
-
this.configuredDevices[accessory.UUID] = new
|
|
166
|
+
this.configuredDevices[accessory.UUID] = new ProtectCamera(this, device, accessory);
|
|
76
167
|
}
|
|
77
168
|
return true;
|
|
78
169
|
break;
|
|
79
170
|
case "light":
|
|
80
171
|
// We have a UniFi Protect light.
|
|
81
|
-
this.configuredDevices[accessory.UUID] = new
|
|
172
|
+
this.configuredDevices[accessory.UUID] = new ProtectLight(this, device, accessory);
|
|
82
173
|
return true;
|
|
83
174
|
break;
|
|
84
175
|
case "sensor":
|
|
85
176
|
// We have a UniFi Protect sensor.
|
|
86
|
-
this.configuredDevices[accessory.UUID] = new
|
|
177
|
+
this.configuredDevices[accessory.UUID] = new ProtectSensor(this, device, accessory);
|
|
87
178
|
return true;
|
|
88
179
|
break;
|
|
89
180
|
case "viewer":
|
|
90
181
|
// We have a UniFi Protect viewer.
|
|
91
|
-
this.configuredDevices[accessory.UUID] = new
|
|
182
|
+
this.configuredDevices[accessory.UUID] = new ProtectViewer(this, device, accessory);
|
|
92
183
|
return true;
|
|
93
184
|
break;
|
|
94
185
|
default:
|
|
95
|
-
this.log.error("
|
|
186
|
+
this.log.error("Unknown device class `%s` detected for ``%s``", device.modelKey, device.name);
|
|
96
187
|
return false;
|
|
97
188
|
}
|
|
98
189
|
}
|
|
99
190
|
// Discover UniFi Protect devices that may have been added to the NVR since we last checked.
|
|
100
191
|
discoverDevices(devices) {
|
|
101
|
-
var _a;
|
|
102
192
|
// Iterate through the list of cameras that Protect has returned and sync them with what we show HomeKit.
|
|
103
|
-
for (const device of devices
|
|
104
|
-
|
|
105
|
-
if (!device.mac || !device.name || device.isAdopting || !device.isAdopted) {
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
// We only support certain devices.
|
|
109
|
-
switch (device.modelKey) {
|
|
110
|
-
case "camera":
|
|
111
|
-
case "light":
|
|
112
|
-
case "sensor":
|
|
113
|
-
case "viewer":
|
|
114
|
-
break;
|
|
115
|
-
default:
|
|
116
|
-
// If we've already informed the user about this one, we're done.
|
|
117
|
-
if (this.unsupportedDevices[device.mac]) {
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
// Notify the user we see this device, but we aren't adding it to HomeKit.
|
|
121
|
-
this.unsupportedDevices[device.mac] = true;
|
|
122
|
-
this.log.info("%s: UniFi Protect device type '%s' is not currently supported, ignoring: %s.", this.nvrApi.getNvrName(), device.modelKey, this.nvrApi.getDeviceName(device));
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
// Exclude or include certain devices based on configuration parameters.
|
|
126
|
-
if (!this.optionEnabled(device)) {
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
// Generate this device's unique identifier.
|
|
130
|
-
const uuid = this.hap.uuid.generate(device.mac);
|
|
131
|
-
let accessory;
|
|
132
|
-
// See if we already know about this accessory or if it's truly new. If it is new, add it to HomeKit.
|
|
133
|
-
if ((accessory = this.platform.accessories.find(x => x.UUID === uuid)) === undefined) {
|
|
134
|
-
accessory = new this.api.platformAccessory(device.name, uuid);
|
|
135
|
-
this.log.info("%s: Adding %s to HomeKit.", this.nvrApi.getFullName(device), device.modelKey);
|
|
136
|
-
// Register this accessory with homebridge and add it to the accessory array so we can track it.
|
|
137
|
-
this.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
|
|
138
|
-
this.platform.accessories.push(accessory);
|
|
139
|
-
}
|
|
140
|
-
// Link the accessory to it's device object and it's hosting NVR.
|
|
141
|
-
accessory.context.device = device;
|
|
142
|
-
accessory.context.nvr = (_a = this.nvrApi.bootstrap) === null || _a === void 0 ? void 0 : _a.nvr.mac;
|
|
143
|
-
// Setup the Protect device if it hasn't been configured yet.
|
|
144
|
-
if (!this.configuredDevices[accessory.UUID]) {
|
|
145
|
-
this.configureDevice(accessory, device);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
// Device-specific periodic reconfiguration. We need to do this to reflect state changes in
|
|
149
|
-
// the Protect NVR (e.g. device settings changes) that we want to catch. Many of the realtime
|
|
150
|
-
// changes are sent through the realtime update API, but a few things aren't, so we deal with that
|
|
151
|
-
// here.
|
|
152
|
-
switch (device.modelKey) {
|
|
153
|
-
case "camera":
|
|
154
|
-
// Check if we have changes to the exposed RTSP streams on our cameras.
|
|
155
|
-
void this.configuredDevices[accessory.UUID].configureVideoStream();
|
|
156
|
-
// Check for changes to the doorbell LCD as well.
|
|
157
|
-
if (device.featureFlags.hasLcdScreen) {
|
|
158
|
-
void this.configuredDevices[accessory.UUID].configureDoorbellLcdSwitch();
|
|
159
|
-
}
|
|
160
|
-
break;
|
|
161
|
-
case "viewer":
|
|
162
|
-
// Sync the viewer state with HomeKit.
|
|
163
|
-
void this.configuredDevices[accessory.UUID].updateDevice();
|
|
164
|
-
break;
|
|
165
|
-
default:
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
193
|
+
for (const device of devices) {
|
|
194
|
+
this.addHomeKitDevice(device);
|
|
169
195
|
}
|
|
170
196
|
return true;
|
|
171
197
|
}
|
|
172
|
-
//
|
|
198
|
+
// Add a newly detected Protect device to HomeKit.
|
|
199
|
+
addHomeKitDevice(device) {
|
|
200
|
+
// If we have no MAC address, name, or this camera isn't being managed by this Protect controller, we're done.
|
|
201
|
+
if (!device || !device.mac || !device.name || device.isAdoptedByOther || !device.isAdopted) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
// We only support certain devices.
|
|
205
|
+
switch (device.modelKey) {
|
|
206
|
+
case "camera":
|
|
207
|
+
case "light":
|
|
208
|
+
case "sensor":
|
|
209
|
+
case "viewer":
|
|
210
|
+
break;
|
|
211
|
+
default:
|
|
212
|
+
// If we've already informed the user about this one, we're done.
|
|
213
|
+
if (this.unsupportedDevices[device.mac]) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
// Notify the user we see this device, but we aren't adding it to HomeKit.
|
|
217
|
+
this.unsupportedDevices[device.mac] = true;
|
|
218
|
+
this.log.info("UniFi Protect device type '%s' is not currently supported, ignoring: %s.", device.modelKey, this.ufpApi.getDeviceName(device));
|
|
219
|
+
return null;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
// Exclude or include certain devices based on configuration parameters.
|
|
223
|
+
if (!this.optionEnabled(device, "Device")) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
// Generate this device's unique identifier.
|
|
227
|
+
const uuid = this.hap.uuid.generate(device.mac);
|
|
228
|
+
let accessory;
|
|
229
|
+
// See if we already know about this accessory or if it's truly new. If it is new, add it to HomeKit.
|
|
230
|
+
if ((accessory = this.platform.accessories.find(x => x.UUID === uuid)) === undefined) {
|
|
231
|
+
accessory = new this.api.platformAccessory(device.name, uuid);
|
|
232
|
+
this.log.info("%s: Adding %s to HomeKit.", this.ufpApi.getFullName(device), device.modelKey);
|
|
233
|
+
// Register this accessory with homebridge and add it to the accessory array so we can track it.
|
|
234
|
+
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
235
|
+
this.platform.accessories.push(accessory);
|
|
236
|
+
this.api.updatePlatformAccessories(this.platform.accessories);
|
|
237
|
+
}
|
|
238
|
+
// Link the accessory to it's device object and it's hosting NVR.
|
|
239
|
+
accessory.context.nvr = this.ufp.mac;
|
|
240
|
+
// Locate our existing Protect device instance, if we have one.
|
|
241
|
+
const protectDevice = this.configuredDevices[accessory.UUID];
|
|
242
|
+
// Setup the Protect device if it hasn't been configured yet.
|
|
243
|
+
if (!protectDevice) {
|
|
244
|
+
this.addProtectDevice(accessory, device);
|
|
245
|
+
}
|
|
246
|
+
return protectDevice;
|
|
247
|
+
}
|
|
248
|
+
// Discover and sync UniFi Protect devices between HomeKit and the Protect controller.
|
|
173
249
|
discoverAndSyncAccessories() {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
this.log.error("%s: Error discovering camera devices.", this.nvrApi.getNvrName());
|
|
250
|
+
if (!this.ufpApi.bootstrap) {
|
|
251
|
+
return false;
|
|
177
252
|
}
|
|
178
|
-
if (this.
|
|
179
|
-
this.log.error("
|
|
253
|
+
if (this.ufpApi.bootstrap.cameras && !this.discoverDevices(this.ufpApi.bootstrap?.cameras)) {
|
|
254
|
+
this.log.error("Error discovering camera devices.");
|
|
180
255
|
}
|
|
181
|
-
if (this.
|
|
182
|
-
this.log.error("
|
|
256
|
+
if (this.ufpApi.bootstrap.lights && !this.discoverDevices(this.ufpApi.bootstrap?.lights)) {
|
|
257
|
+
this.log.error("Error discovering light devices.");
|
|
183
258
|
}
|
|
184
|
-
if (this.
|
|
185
|
-
this.log.error("
|
|
259
|
+
if (this.ufpApi.bootstrap.sensors && !this.discoverDevices(this.ufpApi.bootstrap?.sensors)) {
|
|
260
|
+
this.log.error("Error discovering sensor devices.");
|
|
261
|
+
}
|
|
262
|
+
if (this.ufpApi.bootstrap.viewers && !this.discoverDevices(this.ufpApi.bootstrap?.viewers)) {
|
|
263
|
+
this.log.error("Error discovering viewer devices.");
|
|
186
264
|
}
|
|
187
265
|
// Remove Protect devices that are no longer found on this Protect NVR, but we still have in HomeKit.
|
|
188
266
|
this.cleanupDevices();
|
|
189
267
|
// Configure our liveview-based accessories.
|
|
190
|
-
|
|
191
|
-
//
|
|
192
|
-
(
|
|
268
|
+
this.liveviews?.configureLiveviews();
|
|
269
|
+
// Update our viewer accessories.
|
|
270
|
+
Object.keys(this.configuredDevices)
|
|
271
|
+
.filter(x => this.configuredDevices[x].ufp.modelKey === "viewer")
|
|
272
|
+
.map(x => this.configuredDevices[x].updateDevice());
|
|
193
273
|
return true;
|
|
194
274
|
}
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (!this.refreshInterval) {
|
|
219
|
-
this.refreshInterval = this.config.refreshInterval = settings_1.PROTECT_NVR_UNIFIOS_REFRESH_INTERVAL;
|
|
275
|
+
// Cleanup removed Protect devices from HomeKit.
|
|
276
|
+
cleanupDevices() {
|
|
277
|
+
for (const accessory of this.platform.accessories) {
|
|
278
|
+
const protectDevice = this.configuredDevices[accessory.UUID];
|
|
279
|
+
// Check to see if we have an orphan - where we haven't configured this in the plugin, but the accessory still exists in HomeKit. One example of
|
|
280
|
+
// when this might happen is when Homebridge might be shutdown and a camera removed. When we start back up, the camera still exists in HomeKit but
|
|
281
|
+
// not in Protect. We catch those orphan devices here.
|
|
282
|
+
if (!protectDevice) {
|
|
283
|
+
// We only remove devices if they're on the Protect controller we're interested in.
|
|
284
|
+
if (("nvr" in accessory.context) && accessory.context.nvr !== this.ufp.mac) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
// We only store MAC addresses on devices that exist on the Protect controller. Any other accessories created are ones we created ourselves
|
|
288
|
+
// and are managed elsewhere.
|
|
289
|
+
if (!("mac" in accessory.context)) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
this.log.info("%s: Removing device from HomeKit.", accessory.displayName);
|
|
293
|
+
// Unregister the accessory and delete it's remnants from HomeKit.
|
|
294
|
+
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
295
|
+
this.platform.accessories.splice(this.platform.accessories.indexOf(accessory), 1);
|
|
296
|
+
this.api.updatePlatformAccessories(this.platform.accessories);
|
|
297
|
+
continue;
|
|
220
298
|
}
|
|
221
|
-
|
|
222
|
-
|
|
299
|
+
// If we don't have the Protect bootstrap JSON available, we're done. We need to know what's on the Protect controller in order to determine what
|
|
300
|
+
// to do with the accessories we know about.
|
|
301
|
+
if (!this.ufpApi.bootstrap) {
|
|
302
|
+
continue;
|
|
223
303
|
}
|
|
224
|
-
//
|
|
225
|
-
|
|
226
|
-
|
|
304
|
+
// Check to see if the device still exists on the Protect controller and the user has not chosen to hide it.
|
|
305
|
+
switch (protectDevice.ufp.modelKey) {
|
|
306
|
+
case "camera":
|
|
307
|
+
if (this.ufpApi.bootstrap.cameras.some((x) => x.mac === protectDevice.ufp.mac) && this.optionEnabled(protectDevice.ufp, "Device")) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
case "light":
|
|
312
|
+
if (this.ufpApi.bootstrap.lights.some((x) => x.mac === protectDevice.ufp.mac) && this.optionEnabled(protectDevice.ufp, "Device")) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
case "sensor":
|
|
317
|
+
if (this.ufpApi.bootstrap.sensors.some((x) => x.mac === protectDevice.ufp.mac) && this.optionEnabled(protectDevice.ufp, "Device")) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
break;
|
|
321
|
+
case "viewer":
|
|
322
|
+
if (this.ufpApi.bootstrap.viewers.some((x) => x.mac === protectDevice.ufp.mac) && this.optionEnabled(protectDevice.ufp, "Device")) {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
break;
|
|
326
|
+
default:
|
|
327
|
+
break;
|
|
227
328
|
}
|
|
228
|
-
|
|
329
|
+
// Process the device removal.
|
|
330
|
+
this.removeHomeKitDevice(this.configuredDevices[accessory.UUID]);
|
|
229
331
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
332
|
+
}
|
|
333
|
+
// Cleanup removed Protect devices from HomeKit.
|
|
334
|
+
removeHomeKitDevice(protectDevice) {
|
|
335
|
+
// Sanity check.
|
|
336
|
+
if (!protectDevice) {
|
|
337
|
+
return;
|
|
233
338
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
this.mqtt = new protect_mqtt_1.ProtectMqtt(this);
|
|
339
|
+
// We only remove devices if they're on the Protect controller we're interested in.
|
|
340
|
+
if (protectDevice.accessory.context.nvr !== this.ufp.mac) {
|
|
341
|
+
return;
|
|
238
342
|
}
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
343
|
+
// Package cameras are handled elsewhere.
|
|
344
|
+
if ("packageCamera" in protectDevice.accessory.context) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
// The NVR system information accessory is handled elsewhere.
|
|
348
|
+
if ("systemInfo" in protectDevice.accessory.context) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
// Liveview-centric accessories are handled elsewhere.
|
|
352
|
+
if (("liveview" in protectDevice.accessory.context) || protectDevice.accessory.getService(this.hap.Service.SecuritySystem)) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
// Remove this device.
|
|
356
|
+
this.log.info("%s: Removing %s from HomeKit.", protectDevice.ufp.name ? this.ufpApi.getDeviceName(protectDevice.ufp) : protectDevice.accessory.displayName, protectDevice.ufp.modelKey ? protectDevice.ufp.modelKey : "device");
|
|
357
|
+
const deletingAccessories = [protectDevice.accessory];
|
|
358
|
+
// Check to see if we're removing a camera device that has a package camera as well.
|
|
359
|
+
if (protectDevice.ufp.modelKey === "camera") {
|
|
360
|
+
const protectCamera = protectDevice;
|
|
361
|
+
if (protectCamera && protectCamera.packageCamera) {
|
|
362
|
+
// Ensure we delete the accessory and cleanup after ourselves.
|
|
363
|
+
deletingAccessories.push(protectCamera.packageCamera.accessory);
|
|
364
|
+
this.platform.accessories.splice(this.platform.accessories.indexOf(protectCamera.packageCamera.accessory), 1);
|
|
365
|
+
protectCamera.packageCamera.cleanup();
|
|
366
|
+
protectCamera.packageCamera = null;
|
|
261
367
|
}
|
|
262
368
|
}
|
|
369
|
+
// Cleanup our event handlers.
|
|
370
|
+
protectDevice.cleanup();
|
|
371
|
+
// Unregister the accessory and delete it's remnants from HomeKit and the plugin.
|
|
372
|
+
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, deletingAccessories);
|
|
373
|
+
delete this.configuredDevices[protectDevice.accessory.UUID];
|
|
374
|
+
this.platform.accessories.splice(this.platform.accessories.indexOf(protectDevice.accessory), 1);
|
|
375
|
+
this.api.updatePlatformAccessories(this.platform.accessories);
|
|
263
376
|
}
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
//
|
|
269
|
-
if (!
|
|
377
|
+
// Reauthenticate with the NVR and reset any HKSV timeshift buffers, as needed.
|
|
378
|
+
async resetNvrConnection() {
|
|
379
|
+
// Clear our login credentials.
|
|
380
|
+
this.ufpApi.clearLoginCredentials();
|
|
381
|
+
// Bootstrap the Protect NVR.
|
|
382
|
+
if (!(await this.ufpApi.getBootstrap())) {
|
|
270
383
|
return;
|
|
271
384
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// The NVR system information accessory is handled elsewhere.
|
|
281
|
-
if (("systemInfo" in oldAccessory.context)) {
|
|
282
|
-
continue;
|
|
283
|
-
}
|
|
284
|
-
// Liveview-centric accessories are handled elsewhere.
|
|
285
|
-
if (("liveview" in oldAccessory.context) || oldAccessory.getService(this.hap.Service.SecuritySystem)) {
|
|
385
|
+
// Inform all HKSV-enabled devices that are using a timeshift buffer to reset.
|
|
386
|
+
// protectCamera.hints.timeshift for timeshift buffer enablement.
|
|
387
|
+
//
|
|
388
|
+
for (const accessory of this.platform.accessories) {
|
|
389
|
+
// Retrieve the HBUP object for this device.
|
|
390
|
+
const protectDevice = this.configuredDevices[accessory.UUID];
|
|
391
|
+
// Ensure it's a camera device and that we have HKSV as well as timeshifting enabled.
|
|
392
|
+
if ((protectDevice?.ufp?.modelKey !== "camera") || !protectDevice.hasHksv || !protectDevice.hints.timeshift) {
|
|
286
393
|
continue;
|
|
287
394
|
}
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
switch (oldDevice.modelKey) {
|
|
292
|
-
case "camera":
|
|
293
|
-
if (((_b = this.nvrApi.cameras) === null || _b === void 0 ? void 0 : _b.some((x) => x.mac === oldDevice.mac)) &&
|
|
294
|
-
this.optionEnabled(oldDevice)) {
|
|
295
|
-
continue;
|
|
296
|
-
}
|
|
297
|
-
break;
|
|
298
|
-
case "light":
|
|
299
|
-
if (((_c = this.nvrApi.lights) === null || _c === void 0 ? void 0 : _c.some((x) => x.mac === oldDevice.mac)) &&
|
|
300
|
-
this.optionEnabled(oldDevice)) {
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
break;
|
|
304
|
-
case "sensor":
|
|
305
|
-
if (((_d = this.nvrApi.sensors) === null || _d === void 0 ? void 0 : _d.some((x) => x.mac === oldDevice.mac)) &&
|
|
306
|
-
this.optionEnabled(oldDevice)) {
|
|
307
|
-
continue;
|
|
308
|
-
}
|
|
309
|
-
break;
|
|
310
|
-
case "viewer":
|
|
311
|
-
if (((_e = this.nvrApi.viewers) === null || _e === void 0 ? void 0 : _e.some((x) => x.mac === oldDevice.mac)) &&
|
|
312
|
-
this.optionEnabled(oldDevice)) {
|
|
313
|
-
continue;
|
|
314
|
-
}
|
|
315
|
-
break;
|
|
316
|
-
default:
|
|
317
|
-
break;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
// Decrement our doorbell count.
|
|
321
|
-
if (oldAccessory.getService(this.hap.Service.Doorbell)) {
|
|
322
|
-
this.doorbellCount--;
|
|
323
|
-
}
|
|
324
|
-
// Remove this device.
|
|
325
|
-
this.log.info("%s %s: Removing %s from HomeKit.", this.nvrApi.getNvrName(), oldDevice ? this.nvrApi.getDeviceName(oldDevice) : oldAccessory.displayName, oldDevice ? oldDevice.modelKey : "device");
|
|
326
|
-
// Unregister the accessory and delete it's remnants from HomeKit and the plugin.
|
|
327
|
-
this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [oldAccessory]);
|
|
328
|
-
delete this.configuredDevices[oldAccessory.UUID];
|
|
329
|
-
this.platform.accessories.splice(this.platform.accessories.indexOf(oldAccessory), 1);
|
|
395
|
+
// Restart the timeshift buffer.
|
|
396
|
+
// eslint-disable-next-line no-await-in-loop
|
|
397
|
+
await protectDevice.stream.hksv?.restartTimeshifting();
|
|
330
398
|
}
|
|
331
399
|
}
|
|
332
|
-
// Lookup a device by it's identifier and return
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
// Find the device in our list of accessories.
|
|
338
|
-
const foundDevice = Object.keys(this.configuredDevices).find(x => this.configuredDevices[x].accessory.context.device.id === deviceId);
|
|
339
|
-
return foundDevice ? this.configuredDevices[foundDevice].accessory : undefined;
|
|
400
|
+
// Lookup a device by it's identifier and return it if it exists.
|
|
401
|
+
deviceLookup(deviceId) {
|
|
402
|
+
// Find the device.
|
|
403
|
+
const foundDevice = Object.keys(this.configuredDevices).find(x => (this.configuredDevices[x].ufp).id === deviceId);
|
|
404
|
+
return foundDevice ? this.configuredDevices[foundDevice] : null;
|
|
340
405
|
}
|
|
341
406
|
// Utility function to let us know if a device or feature should be enabled or not.
|
|
342
407
|
optionEnabled(device, option = "", defaultReturnValue = true, address = "", addressOnly = false) {
|
|
343
|
-
|
|
344
|
-
// There are a couple of ways to enable and disable options. The rules of the road are:
|
|
345
|
-
//
|
|
346
|
-
// 1. Explicitly disabling, or enabling an option on the NVR propogates to all the devices
|
|
347
|
-
// that are managed by that NVR. Why might you want to do this? Because...
|
|
348
|
-
//
|
|
349
|
-
// 2. Explicitly disabling, or enabling an option on a device by its MAC address will always
|
|
350
|
-
// override the above. This means that it's possible to disable an option for an NVR,
|
|
351
|
-
// and all the cameras that are managed by it, and then override that behavior on a single
|
|
352
|
-
// camera that it's managing.
|
|
353
|
-
const configOptions = (_a = this.platform) === null || _a === void 0 ? void 0 : _a.configOptions;
|
|
354
|
-
// Nothing configured - we assume the default return value.
|
|
355
|
-
if (!configOptions) {
|
|
356
|
-
return defaultReturnValue;
|
|
357
|
-
}
|
|
358
|
-
// Upper case parameters for easier checks.
|
|
359
|
-
option = option ? option.toUpperCase() : "";
|
|
360
|
-
address = address ? address.toUpperCase() : "";
|
|
361
|
-
const deviceMac = (device === null || device === void 0 ? void 0 : device.mac) ? device.mac.toUpperCase() : "";
|
|
362
|
-
let optionSetting;
|
|
363
|
-
// If we've specified an address parameter - we check for device and address-specific options before
|
|
364
|
-
// anything else.
|
|
365
|
-
if (address && option) {
|
|
366
|
-
// Test for device-specific and address-specific option settings, used together.
|
|
367
|
-
if (deviceMac) {
|
|
368
|
-
optionSetting = option + "." + deviceMac + "." + address;
|
|
369
|
-
// We've explicitly enabled this option for this device and address combination.
|
|
370
|
-
if (configOptions.indexOf("ENABLE." + optionSetting) !== -1) {
|
|
371
|
-
return true;
|
|
372
|
-
}
|
|
373
|
-
// We've explicitly disabled this option for this device and address combination.
|
|
374
|
-
if (configOptions.indexOf("DISABLE." + optionSetting) !== -1) {
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
// Test for address-specific option settings only.
|
|
379
|
-
optionSetting = option + "." + address;
|
|
380
|
-
// We've explicitly enabled this option for this address.
|
|
381
|
-
if (configOptions.indexOf("ENABLE." + optionSetting) !== -1) {
|
|
382
|
-
return true;
|
|
383
|
-
}
|
|
384
|
-
// We've explicitly disabled this option for this address.
|
|
385
|
-
if (configOptions.indexOf("DISABLE." + optionSetting) !== -1) {
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
|
-
// We're only interested in address-specific options.
|
|
389
|
-
if (addressOnly) {
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
// If we've specified a device, check for device-specific options first. Otherwise, we're dealing
|
|
394
|
-
// with an NVR-specific or global option.
|
|
395
|
-
if (deviceMac) {
|
|
396
|
-
// First we test for camera-level option settings.
|
|
397
|
-
// No option specified means we're testing to see if this device should be shown in HomeKit.
|
|
398
|
-
optionSetting = option ? option + "." + deviceMac : deviceMac;
|
|
399
|
-
// We've explicitly enabled this option for this device.
|
|
400
|
-
if (configOptions.indexOf("ENABLE." + optionSetting) !== -1) {
|
|
401
|
-
return true;
|
|
402
|
-
}
|
|
403
|
-
// We've explicitly disabled this option for this device.
|
|
404
|
-
if (configOptions.indexOf("DISABLE." + optionSetting) !== -1) {
|
|
405
|
-
return false;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
// If we don't have a managing device attached, we're done here.
|
|
409
|
-
if (!((_c = (_b = this.nvrApi.bootstrap) === null || _b === void 0 ? void 0 : _b.nvr) === null || _c === void 0 ? void 0 : _c.mac)) {
|
|
410
|
-
return defaultReturnValue;
|
|
411
|
-
}
|
|
412
|
-
// Now we test for NVR-level option settings.
|
|
413
|
-
// No option specified means we're testing to see if this NVR (and it's attached devices) should be shown in HomeKit.
|
|
414
|
-
const nvrMac = this.nvrApi.bootstrap.nvr.mac.toUpperCase();
|
|
415
|
-
optionSetting = option ? option + "." + nvrMac : nvrMac;
|
|
416
|
-
// We've explicitly enabled this option for this NVR and all the devices attached to it.
|
|
417
|
-
if (configOptions.indexOf("ENABLE." + optionSetting) !== -1) {
|
|
418
|
-
return true;
|
|
419
|
-
}
|
|
420
|
-
// We've explicitly disabled this option for this NVR and all the devices attached to it.
|
|
421
|
-
if (configOptions.indexOf("DISABLE." + optionSetting) !== -1) {
|
|
422
|
-
return false;
|
|
423
|
-
}
|
|
424
|
-
// Finally, let's see if we have a global option here.
|
|
425
|
-
// No option means we're done - it's a special case for testing if an NVR or camera should be hidden in HomeKit.
|
|
426
|
-
if (!option) {
|
|
427
|
-
return defaultReturnValue;
|
|
428
|
-
}
|
|
429
|
-
// We've explicitly enabled this globally for all devices.
|
|
430
|
-
if (configOptions.indexOf("ENABLE." + option) !== -1) {
|
|
431
|
-
return true;
|
|
432
|
-
}
|
|
433
|
-
// We've explicitly disabled this globally for all devices.
|
|
434
|
-
if (configOptions.indexOf("DISABLE." + option) !== -1) {
|
|
435
|
-
return false;
|
|
436
|
-
}
|
|
437
|
-
// Nothing special to do - assume the option is defaultReturnValue.
|
|
438
|
-
return defaultReturnValue;
|
|
408
|
+
return optionEnabled(this.platform.configOptions, this.ufp, device, option, defaultReturnValue, address, addressOnly);
|
|
439
409
|
}
|
|
440
410
|
// Utility function to return a configuration parameter for a Protect device.
|
|
441
411
|
optionGet(device, option, address = "") {
|
|
442
|
-
var _a, _b, _c, _d;
|
|
443
412
|
// Using the same rules as we do to test for whether an option is enabled, retrieve options with parameters and
|
|
444
413
|
// return them. If we don't find anything, we return undefined.
|
|
445
|
-
const configOptions =
|
|
414
|
+
const configOptions = this.platform?.configOptions;
|
|
446
415
|
// Nothing configured - we assume there's nothing.
|
|
447
416
|
if (!configOptions || !option) {
|
|
448
417
|
return undefined;
|
|
@@ -450,7 +419,7 @@ class ProtectNvr {
|
|
|
450
419
|
// Upper case parameters for easier checks.
|
|
451
420
|
address = address ? address.toUpperCase() : "";
|
|
452
421
|
option = option.toUpperCase();
|
|
453
|
-
const deviceMac =
|
|
422
|
+
const deviceMac = device?.mac.toUpperCase() ?? null;
|
|
454
423
|
let foundOption;
|
|
455
424
|
let optionSetting;
|
|
456
425
|
// If we've specified an address parameter - we check for device and address-specific options before
|
|
@@ -497,12 +466,12 @@ class ProtectNvr {
|
|
|
497
466
|
}
|
|
498
467
|
}
|
|
499
468
|
// If we don't have a managing device attached, we're done here.
|
|
500
|
-
if (!
|
|
469
|
+
if (!this.ufp.mac) {
|
|
501
470
|
return undefined;
|
|
502
471
|
}
|
|
503
472
|
// Now we test for NVR-level option settings.
|
|
504
473
|
// No option specified means we're testing to see if this NVR (and it's attached devices) should be shown in HomeKit.
|
|
505
|
-
const nvrMac = this.
|
|
474
|
+
const nvrMac = this.ufp.mac.toUpperCase();
|
|
506
475
|
optionSetting = "ENABLE." + option + "." + nvrMac + ".";
|
|
507
476
|
// We've explicitly enabled this option for this NVR and all the devices attached to it.
|
|
508
477
|
if ((foundOption = configOptions.find(x => optionSetting === x.slice(0, optionSetting.length))) !== undefined) {
|
|
@@ -527,5 +496,4 @@ class ProtectNvr {
|
|
|
527
496
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
528
497
|
}
|
|
529
498
|
}
|
|
530
|
-
exports.ProtectNvr = ProtectNvr;
|
|
531
499
|
//# sourceMappingURL=protect-nvr.js.map
|