node-red-contrib-homekit-bridged 2.0.0-dev.1 → 2.0.0-dev.10
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/build/lib/HAPHostNode.js +185 -146
- package/build/lib/HAPServiceNode.js +200 -177
- package/build/lib/HAPServiceNode2.js +208 -177
- package/build/lib/NRCHKBError.js +23 -2
- package/build/lib/PairingQRCode.js +62 -0
- package/build/lib/Storage.js +152 -90
- package/build/lib/api.js +654 -290
- package/build/lib/camera/CameraControl.js +125 -0
- package/build/lib/camera/CameraDelegate.js +507 -0
- package/build/lib/camera/MP4StreamingServer.js +159 -0
- package/build/lib/hap/HAPCharacteristic.js +25 -4
- package/build/lib/hap/HAPService.js +25 -4
- package/build/lib/hap/eve-app/EveCharacteristics.js +124 -81
- package/build/lib/hap/eve-app/EveServices.js +50 -17
- package/build/lib/hap/hap-nodejs.js +32 -0
- package/build/lib/migration/HomeKitService2Migration.js +34 -0
- package/build/lib/migration/NodeMigration.js +75 -0
- package/build/lib/types/AccessoryInformationType.js +15 -1
- package/build/lib/types/CameraConfigType.js +15 -1
- package/build/lib/types/CustomCharacteristicType.js +15 -1
- package/build/lib/types/HAPHostConfigType.js +15 -1
- package/build/lib/types/HAPHostNodeType.js +15 -1
- package/build/lib/types/HAPService2ConfigType.js +15 -1
- package/build/lib/types/HAPService2NodeType.js +15 -1
- package/build/lib/types/HAPServiceConfigType.js +15 -1
- package/build/lib/types/HAPServiceNodeType.js +15 -1
- package/build/lib/types/HAPStatusConfigType.js +15 -1
- package/build/lib/types/HAPStatusNodeType.js +15 -1
- package/build/lib/types/HostType.js +28 -7
- package/build/lib/types/NodeType.js +15 -1
- package/build/lib/types/PublishTimersType.js +15 -1
- package/build/lib/types/UniFiControllerConfigType.js +16 -0
- package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.js +28 -7
- package/build/lib/types/hap-nodejs/HapCategories.js +64 -43
- package/build/lib/types/storage/SerializedHostType.js +15 -1
- package/build/lib/types/storage/StorageType.js +34 -10
- package/build/lib/unifi/ProtectDiscovery.js +80 -0
- package/build/lib/utils/AccessoryUtils.js +152 -112
- package/build/lib/utils/BridgeUtils.js +95 -39
- package/build/lib/utils/CharacteristicUtils.js +5 -49
- package/build/lib/utils/CharacteristicUtils2.js +5 -49
- package/build/lib/utils/CharacteristicUtilsBase.js +81 -0
- package/build/lib/utils/NodeStatusUtils.js +89 -40
- package/build/lib/utils/ServiceUtils.js +433 -368
- package/build/lib/utils/ServiceUtils2.js +519 -304
- package/build/lib/utils/index.js +11 -12
- package/build/nodes/bridge.html +206 -168
- package/build/nodes/bridge.js +27 -9
- package/build/nodes/locales/en-US/node-red-contrib-homekit-bridged.json +22 -0
- package/build/nodes/nrchkb.html +1753 -117
- package/build/nodes/nrchkb.js +66 -88
- package/build/nodes/plugin-instance.html +509 -0
- package/build/nodes/plugin-instance.js +46 -0
- package/build/nodes/service.html +557 -306
- package/build/nodes/service.js +5 -6
- package/build/nodes/service2.html +1735 -455
- package/build/nodes/service2.js +5 -8
- package/build/nodes/standalone.html +208 -176
- package/build/nodes/standalone.js +27 -9
- package/build/nodes/status.html +51 -18
- package/build/nodes/status.js +47 -41
- package/build/nodes/unifi-controller.html +92 -0
- package/build/nodes/unifi-controller.js +20 -0
- package/build/plugins/embedded/homebridge-camera-ffmpeg/index.js +479 -0
- package/build/plugins/embedded/homebridge-unifi-protect/index.js +521 -0
- package/build/plugins/embedded/index.js +58 -0
- package/build/plugins/nrchkb-homekit-plugins.js +17 -0
- package/build/plugins/registry/index.js +203 -0
- package/build/plugins/registry/types.js +16 -0
- package/build/scripts/migrate-homekit-service-flows.js +47 -0
- package/examples/demo/01 - ALL Demos single import.json +1885 -1885
- package/examples/demo/02 - Air Purifier.json +279 -279
- package/examples/demo/03 - Air Quality sensor with Battery.json +254 -254
- package/examples/demo/04 - Dimmable Bulb.json +172 -172
- package/examples/demo/05 - Color Bulb (HSV).json +195 -195
- package/examples/demo/06 - Fan (simple, 3 speeds).json +240 -240
- package/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json +175 -175
- package/examples/demo/08 - CO2 detector.json +224 -224
- package/examples/demo/09 - CO (carbon monoxide) example.json +255 -255
- package/examples/demo/10 - Door window contact sensor.json +234 -234
- package/examples/demos (advanced)/01 - Television with inputs and speaker.json +541 -541
- package/examples/switch/01 - Plain Switch.json +178 -178
- package/package.json +95 -82
- package/build/lib/HAPHostNode.d.ts +0 -1
- package/build/lib/HAPServiceNode.d.ts +0 -1
- package/build/lib/HAPServiceNode2.d.ts +0 -1
- package/build/lib/NRCHKBError.d.ts +0 -3
- package/build/lib/Storage.d.ts +0 -30
- package/build/lib/api.d.ts +0 -1
- package/build/lib/hap/HAPCharacteristic.d.ts +0 -9
- package/build/lib/hap/HAPService.d.ts +0 -6
- package/build/lib/hap/eve-app/EveCharacteristics.d.ts +0 -20
- package/build/lib/hap/eve-app/EveServices.d.ts +0 -5
- package/build/lib/types/AccessoryInformationType.d.ts +0 -11
- package/build/lib/types/CameraConfigType.d.ts +0 -24
- package/build/lib/types/CustomCharacteristicType.d.ts +0 -6
- package/build/lib/types/HAPHostConfigType.d.ts +0 -22
- package/build/lib/types/HAPHostNodeType.d.ts +0 -14
- package/build/lib/types/HAPService2ConfigType.d.ts +0 -6
- package/build/lib/types/HAPService2NodeType.d.ts +0 -7
- package/build/lib/types/HAPServiceConfigType.d.ts +0 -26
- package/build/lib/types/HAPServiceNodeType.d.ts +0 -38
- package/build/lib/types/HAPStatusConfigType.d.ts +0 -5
- package/build/lib/types/HAPStatusNodeType.d.ts +0 -12
- package/build/lib/types/HostType.d.ts +0 -5
- package/build/lib/types/NodeType.d.ts +0 -3
- package/build/lib/types/PublishTimersType.d.ts +0 -4
- package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.d.ts +0 -5
- package/build/lib/types/hap-nodejs/HapCategories.d.ts +0 -41
- package/build/lib/types/storage/SerializedHostType.d.ts +0 -5
- package/build/lib/types/storage/StorageType.d.ts +0 -8
- package/build/lib/utils/AccessoryUtils.d.ts +0 -1
- package/build/lib/utils/BridgeUtils.d.ts +0 -1
- package/build/lib/utils/CharacteristicUtils.d.ts +0 -1
- package/build/lib/utils/CharacteristicUtils2.d.ts +0 -1
- package/build/lib/utils/NodeStatusUtils.d.ts +0 -17
- package/build/lib/utils/ServiceUtils.d.ts +0 -1
- package/build/lib/utils/ServiceUtils2.d.ts +0 -1
- package/build/lib/utils/index.d.ts +0 -1
- package/build/nodes/bridge.d.ts +0 -1
- package/build/nodes/nrchkb.d.ts +0 -1
- package/build/nodes/service.d.ts +0 -1
- package/build/nodes/service2.d.ts +0 -1
- package/build/nodes/standalone.d.ts +0 -1
- package/build/nodes/status.d.ts +0 -1
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var homebridge_unifi_protect_exports = {};
|
|
30
|
+
__export(homebridge_unifi_protect_exports, {
|
|
31
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID: () => HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID,
|
|
32
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME: () => HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME,
|
|
33
|
+
attachHomebridgeUniFiProtectPlugin: () => attachHomebridgeUniFiProtectPlugin,
|
|
34
|
+
createHomebridgeUniFiProtectCleanup: () => createHomebridgeUniFiProtectCleanup,
|
|
35
|
+
createHomebridgeUniFiProtectPluginEntry: () => createHomebridgeUniFiProtectPluginEntry,
|
|
36
|
+
ensureHomebridgePlatformAccessoryShape: () => ensureHomebridgePlatformAccessoryShape,
|
|
37
|
+
homebridgeUniFiProtectPluginFactory: () => homebridgeUniFiProtectPluginFactory,
|
|
38
|
+
homebridgeUniFiProtectPluginMetadata: () => homebridgeUniFiProtectPluginMetadata,
|
|
39
|
+
registerHomebridgeUniFiProtectPlugin: () => registerHomebridgeUniFiProtectPlugin
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(homebridge_unifi_protect_exports);
|
|
42
|
+
var import_hap_nodejs = require("@homebridge/hap-nodejs");
|
|
43
|
+
var import_logger = require("@nrchkb/logger");
|
|
44
|
+
var import_registry = require("../../registry");
|
|
45
|
+
const HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME = "homebridge-unifi-protect";
|
|
46
|
+
const HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID = (0, import_registry.normalizePluginId)(
|
|
47
|
+
"node-red-contrib-homekit-bridged",
|
|
48
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME
|
|
49
|
+
);
|
|
50
|
+
const requirePackageJson = (packageName) => {
|
|
51
|
+
try {
|
|
52
|
+
return require(`${packageName}/package.json`);
|
|
53
|
+
} catch (_) {
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const upstreamPackage = requirePackageJson("homebridge-unifi-protect");
|
|
58
|
+
const toName = (value) => typeof value === "string" ? value : value?.name ?? "";
|
|
59
|
+
const upstreamAuthor = toName(upstreamPackage.author);
|
|
60
|
+
const upstreamContributors = upstreamPackage.contributors?.map(toName).filter(Boolean) ?? [];
|
|
61
|
+
const importEsm = (specifier) => {
|
|
62
|
+
const importer = new Function("specifier", "return import(specifier)");
|
|
63
|
+
return importer(specifier);
|
|
64
|
+
};
|
|
65
|
+
const ensureHomebridgePlatformAccessoryShape = (accessory, bridged) => {
|
|
66
|
+
const platformAccessory = accessory;
|
|
67
|
+
platformAccessory._associatedHAPAccessory ??= {};
|
|
68
|
+
platformAccessory._associatedHAPAccessory.bridged = bridged;
|
|
69
|
+
};
|
|
70
|
+
const createHomebridgeLogger = () => {
|
|
71
|
+
const log = (0, import_logger.logger)("NRCHKB", "HomebridgeUniFiProtect");
|
|
72
|
+
const write = (level) => (message, ...parameters) => {
|
|
73
|
+
const suffix = parameters.length ? ` ${parameters.join(" ")}` : "";
|
|
74
|
+
const text = `${message}${suffix}`;
|
|
75
|
+
if (level === "error") {
|
|
76
|
+
log.error(text);
|
|
77
|
+
} else {
|
|
78
|
+
log.debug(text);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
debug: write("debug"),
|
|
83
|
+
info: write("info"),
|
|
84
|
+
warn: write("warn"),
|
|
85
|
+
error: write("error"),
|
|
86
|
+
success: write("info"),
|
|
87
|
+
log: write("info")
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
const getControllerNode = (context) => {
|
|
91
|
+
const controllerId = context.config.controller;
|
|
92
|
+
if (!controllerId || !context.RED) {
|
|
93
|
+
throw new Error("UniFi Protect controller is not configured.");
|
|
94
|
+
}
|
|
95
|
+
const controller = context.RED.nodes.getNode(controllerId);
|
|
96
|
+
if (!controller) {
|
|
97
|
+
throw new Error(`UniFi controller "${controllerId}" was not found.`);
|
|
98
|
+
}
|
|
99
|
+
if ((controller.application ?? "protect") !== "protect") {
|
|
100
|
+
throw new Error(
|
|
101
|
+
"Selected UniFi controller is not a Protect controller."
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
if (!controller.address || !controller.credentials?.username || !controller.credentials.password) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
"UniFi Protect controller address, username, and password are required."
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return controller;
|
|
110
|
+
};
|
|
111
|
+
const getSelectedCamera = (context) => {
|
|
112
|
+
const camera = context.config.camera?.trim();
|
|
113
|
+
if (!camera) {
|
|
114
|
+
throw new Error("Select a UniFi Protect camera before deploying.");
|
|
115
|
+
}
|
|
116
|
+
return camera;
|
|
117
|
+
};
|
|
118
|
+
const splitFeatureOptions = (value) => (value ?? "").split(/\r?\n/).map((entry) => entry.trim()).filter(Boolean);
|
|
119
|
+
const buildFeatureOptions = (config) => {
|
|
120
|
+
const options = splitFeatureOptions(config.featureOptions);
|
|
121
|
+
if (config.audio === false) {
|
|
122
|
+
options.push("Disable.Audio");
|
|
123
|
+
}
|
|
124
|
+
if (config.twoWayAudio === false) {
|
|
125
|
+
options.push("Disable.Audio.TwoWay");
|
|
126
|
+
}
|
|
127
|
+
if (config.twoWayAudioDirect === true) {
|
|
128
|
+
options.push("Enable.Audio.TwoWay.Direct");
|
|
129
|
+
}
|
|
130
|
+
if (config.hksv === false) {
|
|
131
|
+
options.push("Disable.Video.HKSV");
|
|
132
|
+
}
|
|
133
|
+
if (config.hksvRecordingSwitch === true) {
|
|
134
|
+
options.push("Enable.Video.HKSV.Recording.Switch");
|
|
135
|
+
}
|
|
136
|
+
if (config.motionSwitch === true) {
|
|
137
|
+
options.push("Enable.Motion.Switch");
|
|
138
|
+
}
|
|
139
|
+
if (config.motionTrigger === true) {
|
|
140
|
+
options.push("Enable.Motion.Trigger");
|
|
141
|
+
}
|
|
142
|
+
if (config.occupancySensor === true) {
|
|
143
|
+
options.push("Enable.Motion.OccupancySensor");
|
|
144
|
+
}
|
|
145
|
+
if (config.doorbellTrigger === true) {
|
|
146
|
+
options.push("Enable.Doorbell.Trigger");
|
|
147
|
+
}
|
|
148
|
+
return options;
|
|
149
|
+
};
|
|
150
|
+
const createHomebridgeApiShim = async (context) => {
|
|
151
|
+
const hap = await import("@homebridge/hap-nodejs");
|
|
152
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
153
|
+
const PlatformAccessoryShim = class extends hap.Accessory {
|
|
154
|
+
constructor(displayName, uuid) {
|
|
155
|
+
super(displayName, uuid);
|
|
156
|
+
this.context ??= {};
|
|
157
|
+
ensureHomebridgePlatformAccessoryShape(this, true);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
const api = {
|
|
161
|
+
hap,
|
|
162
|
+
platformAccessory: PlatformAccessoryShim,
|
|
163
|
+
on: (event, handler) => {
|
|
164
|
+
const eventHandlers = handlers.get(event) ?? [];
|
|
165
|
+
eventHandlers.push(handler);
|
|
166
|
+
handlers.set(event, eventHandlers);
|
|
167
|
+
},
|
|
168
|
+
registerPlatformAccessories: (_pluginName, _platformName, accessories) => {
|
|
169
|
+
accessories.forEach((accessory) => {
|
|
170
|
+
ensureHomebridgePlatformAccessoryShape(accessory, true);
|
|
171
|
+
if (!context.accessory.services.includes(accessory)) {
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
},
|
|
175
|
+
unregisterPlatformAccessories: () => void 0,
|
|
176
|
+
updatePlatformAccessories: () => void 0,
|
|
177
|
+
publishExternalAccessories: (_pluginName, accessories) => {
|
|
178
|
+
accessories.forEach((accessory) => {
|
|
179
|
+
ensureHomebridgePlatformAccessoryShape(accessory, false);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
return {
|
|
184
|
+
api,
|
|
185
|
+
emit: (event) => {
|
|
186
|
+
;
|
|
187
|
+
(handlers.get(event) ?? []).forEach((handler) => handler());
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
const configureSelectedCameraOnly = (context, platform) => {
|
|
192
|
+
const selectedCamera = getSelectedCamera(context).toLowerCase();
|
|
193
|
+
context.accessory.context ??= {};
|
|
194
|
+
ensureHomebridgePlatformAccessoryShape(context.accessory, true);
|
|
195
|
+
platform.accessories = [context.accessory];
|
|
196
|
+
platform.controllers.forEach((controller) => {
|
|
197
|
+
controller.addHomeKitDevice = (device) => {
|
|
198
|
+
const deviceMac = device.mac?.toLowerCase();
|
|
199
|
+
const deviceId = device.id?.toLowerCase();
|
|
200
|
+
if (!selectedCamera || selectedCamera !== deviceMac && selectedCamera !== deviceId) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
context.accessory.context ??= {};
|
|
204
|
+
context.accessory.context.mac = device.mac;
|
|
205
|
+
if (controller.ufp?.mac) {
|
|
206
|
+
context.accessory.context.nvr = controller.ufp.mac;
|
|
207
|
+
}
|
|
208
|
+
const accessoryUuid = context.accessory.UUID;
|
|
209
|
+
if (!controller.configuredDevices.has(accessoryUuid)) {
|
|
210
|
+
controller.addProtectDevice(context.accessory, device);
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
controller.events?.emit("updateEvent", {
|
|
214
|
+
header: {
|
|
215
|
+
action: "update",
|
|
216
|
+
hbupBootstrap: true,
|
|
217
|
+
id: device.id,
|
|
218
|
+
modelKey: device.modelKey
|
|
219
|
+
},
|
|
220
|
+
payload: device
|
|
221
|
+
});
|
|
222
|
+
return true;
|
|
223
|
+
};
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
const guardPlatformLaunch = (platform) => {
|
|
227
|
+
platform.launchControllers = async () => {
|
|
228
|
+
try {
|
|
229
|
+
if (platform.codecSupport && !await platform.codecSupport.probe()) {
|
|
230
|
+
platform.log?.error(
|
|
231
|
+
"Homebridge UniFi Protect requires a working FFmpeg executable."
|
|
232
|
+
);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
await Promise.all(
|
|
236
|
+
platform.controllers.map(async (controller) => {
|
|
237
|
+
try {
|
|
238
|
+
const login = controller.login;
|
|
239
|
+
await login?.call(controller);
|
|
240
|
+
} catch (error) {
|
|
241
|
+
platform.log?.error(
|
|
242
|
+
"Unable to start UniFi Protect controller: %s",
|
|
243
|
+
error
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
platform.log?.error("Unable to launch UniFi Protect: %s", error);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
const createHomebridgeUniFiProtectCleanup = (platform, emit) => {
|
|
254
|
+
let closed = false;
|
|
255
|
+
return () => {
|
|
256
|
+
if (closed) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
closed = true;
|
|
260
|
+
emit("shutdown");
|
|
261
|
+
platform.controllers.forEach((controller) => {
|
|
262
|
+
controller.configuredDevices.forEach((device) => {
|
|
263
|
+
try {
|
|
264
|
+
device.cleanup?.();
|
|
265
|
+
} catch (_) {
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
try {
|
|
269
|
+
controller.disconnect();
|
|
270
|
+
} catch (_) {
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
controller.ufpApi?.logout?.();
|
|
274
|
+
} catch (_) {
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
};
|
|
279
|
+
const homebridgeUniFiProtectPluginMetadata = {
|
|
280
|
+
id: HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID,
|
|
281
|
+
packageName: "node-red-contrib-homekit-bridged",
|
|
282
|
+
pluginName: HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME,
|
|
283
|
+
displayName: "Homebridge UniFi Protect",
|
|
284
|
+
author: "NRCHKB",
|
|
285
|
+
version: "1.0.0",
|
|
286
|
+
description: "Adds a selected UniFi Protect camera using Homebridge UniFi Protect runtime behavior.",
|
|
287
|
+
attachment: "config-node",
|
|
288
|
+
license: "Apache-2.0",
|
|
289
|
+
capabilities: {
|
|
290
|
+
camera: true,
|
|
291
|
+
snapshots: true,
|
|
292
|
+
liveVideo: true,
|
|
293
|
+
audio: true,
|
|
294
|
+
twoWayAudio: true,
|
|
295
|
+
secureVideo: true,
|
|
296
|
+
experimental: ["twoWayAudio", "secureVideo"]
|
|
297
|
+
},
|
|
298
|
+
prerequisites: {
|
|
299
|
+
serviceNames: ["Camera"]
|
|
300
|
+
},
|
|
301
|
+
serviceNames: ["Camera"],
|
|
302
|
+
multipleInstances: false,
|
|
303
|
+
upstream: {
|
|
304
|
+
packageName: "homebridge-unifi-protect",
|
|
305
|
+
packageVersion: upstreamPackage.version,
|
|
306
|
+
projectName: "Homebridge UniFi Protect",
|
|
307
|
+
repoUrl: "https://github.com/hjdhjd/homebridge-unifi-protect",
|
|
308
|
+
license: upstreamPackage.license,
|
|
309
|
+
authors: upstreamAuthor ? [upstreamAuthor] : [],
|
|
310
|
+
contributors: upstreamContributors,
|
|
311
|
+
disclaimer: "Original authors and contributors are credited for the upstream Homebridge plugin. NRCHKB owns and supports this embedded integration."
|
|
312
|
+
},
|
|
313
|
+
editor: {
|
|
314
|
+
defaultConfig: {
|
|
315
|
+
controller: "",
|
|
316
|
+
camera: "",
|
|
317
|
+
videoProcessor: "",
|
|
318
|
+
verboseFfmpeg: false,
|
|
319
|
+
audio: true,
|
|
320
|
+
twoWayAudio: true,
|
|
321
|
+
twoWayAudioDirect: false,
|
|
322
|
+
hksv: true,
|
|
323
|
+
hksvRecordingSwitch: false,
|
|
324
|
+
motionSwitch: false,
|
|
325
|
+
motionTrigger: false,
|
|
326
|
+
occupancySensor: false,
|
|
327
|
+
doorbellTrigger: false,
|
|
328
|
+
featureOptions: ""
|
|
329
|
+
},
|
|
330
|
+
sections: [
|
|
331
|
+
{
|
|
332
|
+
title: "Controller",
|
|
333
|
+
fields: [
|
|
334
|
+
{
|
|
335
|
+
path: "controller",
|
|
336
|
+
label: "UniFi Controller",
|
|
337
|
+
type: "config-node",
|
|
338
|
+
icon: "fa-server",
|
|
339
|
+
configNodeType: "homekit-unifi-controller"
|
|
340
|
+
}
|
|
341
|
+
]
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
title: "Camera",
|
|
345
|
+
fields: [
|
|
346
|
+
{
|
|
347
|
+
path: "camera",
|
|
348
|
+
label: "Camera",
|
|
349
|
+
type: "dynamic-select",
|
|
350
|
+
icon: "fa-video-camera",
|
|
351
|
+
optionsUrl: "nrchkb/unifi/controllers/{controller}/protect/cameras",
|
|
352
|
+
optionsDependsOn: "controller"
|
|
353
|
+
}
|
|
354
|
+
]
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
title: "Streaming & Audio",
|
|
358
|
+
fields: [
|
|
359
|
+
{
|
|
360
|
+
path: "videoProcessor",
|
|
361
|
+
label: "FFmpeg Location",
|
|
362
|
+
type: "text",
|
|
363
|
+
icon: "fa-terminal"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
path: "verboseFfmpeg",
|
|
367
|
+
label: "Verbose FFmpeg",
|
|
368
|
+
type: "checkbox",
|
|
369
|
+
icon: "fa-bug",
|
|
370
|
+
default: false
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
path: "audio",
|
|
374
|
+
label: "Audio",
|
|
375
|
+
type: "checkbox",
|
|
376
|
+
icon: "fa-headphones",
|
|
377
|
+
default: true
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
path: "twoWayAudio",
|
|
381
|
+
label: "Two-Way Audio",
|
|
382
|
+
type: "checkbox",
|
|
383
|
+
icon: "fa-microphone",
|
|
384
|
+
default: true
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
path: "twoWayAudioDirect",
|
|
388
|
+
label: "Direct Two-Way Audio",
|
|
389
|
+
type: "checkbox",
|
|
390
|
+
icon: "fa-microphone",
|
|
391
|
+
default: false
|
|
392
|
+
}
|
|
393
|
+
]
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
title: "Recording / HKSV",
|
|
397
|
+
fields: [
|
|
398
|
+
{
|
|
399
|
+
path: "hksv",
|
|
400
|
+
label: "HomeKit Secure Video",
|
|
401
|
+
type: "checkbox",
|
|
402
|
+
icon: "fa-video-camera",
|
|
403
|
+
default: true
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
path: "hksvRecordingSwitch",
|
|
407
|
+
label: "Recording Switch",
|
|
408
|
+
type: "checkbox",
|
|
409
|
+
icon: "fa-toggle-on",
|
|
410
|
+
default: false
|
|
411
|
+
}
|
|
412
|
+
]
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
title: "Advanced",
|
|
416
|
+
fields: [
|
|
417
|
+
{
|
|
418
|
+
path: "motionSwitch",
|
|
419
|
+
label: "Motion Switch",
|
|
420
|
+
type: "checkbox",
|
|
421
|
+
icon: "fa-toggle-on",
|
|
422
|
+
default: false
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
path: "motionTrigger",
|
|
426
|
+
label: "Motion Trigger",
|
|
427
|
+
type: "checkbox",
|
|
428
|
+
icon: "fa-bell",
|
|
429
|
+
default: false
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
path: "occupancySensor",
|
|
433
|
+
label: "Occupancy Sensor",
|
|
434
|
+
type: "checkbox",
|
|
435
|
+
icon: "fa-street-view",
|
|
436
|
+
default: false
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
path: "doorbellTrigger",
|
|
440
|
+
label: "Doorbell Trigger",
|
|
441
|
+
type: "checkbox",
|
|
442
|
+
icon: "fa-bell-o",
|
|
443
|
+
default: false
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
path: "featureOptions",
|
|
447
|
+
label: "Feature Options",
|
|
448
|
+
type: "textarea",
|
|
449
|
+
icon: "fa-list",
|
|
450
|
+
placeholder: "One Homebridge UniFi Protect feature option per line"
|
|
451
|
+
}
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
]
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
const attachHomebridgeUniFiProtectPlugin = async (context) => {
|
|
458
|
+
getSelectedCamera(context);
|
|
459
|
+
const controller = getControllerNode(context);
|
|
460
|
+
const module2 = await importEsm(
|
|
461
|
+
"homebridge-unifi-protect/dist/protect-platform.js"
|
|
462
|
+
);
|
|
463
|
+
const { api, emit } = await createHomebridgeApiShim(context);
|
|
464
|
+
const hbupConfig = {
|
|
465
|
+
controllers: [
|
|
466
|
+
{
|
|
467
|
+
address: controller.address,
|
|
468
|
+
username: controller.credentials?.username,
|
|
469
|
+
password: controller.credentials?.password,
|
|
470
|
+
name: controller.name,
|
|
471
|
+
overrideAddress: controller.overrideAddress
|
|
472
|
+
}
|
|
473
|
+
],
|
|
474
|
+
options: buildFeatureOptions(context.config),
|
|
475
|
+
verboseFfmpeg: context.config.verboseFfmpeg === true,
|
|
476
|
+
videoProcessor: context.config.videoProcessor || void 0
|
|
477
|
+
};
|
|
478
|
+
const platform = new module2.ProtectPlatform(
|
|
479
|
+
createHomebridgeLogger(),
|
|
480
|
+
hbupConfig,
|
|
481
|
+
api
|
|
482
|
+
);
|
|
483
|
+
configureSelectedCameraOnly(context, platform);
|
|
484
|
+
guardPlatformLaunch(platform);
|
|
485
|
+
emit("didFinishLaunching");
|
|
486
|
+
context.node?.on(
|
|
487
|
+
"close",
|
|
488
|
+
createHomebridgeUniFiProtectCleanup(platform, emit)
|
|
489
|
+
);
|
|
490
|
+
return context.accessory.getService(import_hap_nodejs.Service.CameraRTPStreamManagement) ?? context.accessory.addService(
|
|
491
|
+
import_hap_nodejs.Service.CameraRTPStreamManagement,
|
|
492
|
+
context.serviceInformation.name
|
|
493
|
+
);
|
|
494
|
+
};
|
|
495
|
+
const homebridgeUniFiProtectPluginFactory = {
|
|
496
|
+
attach: attachHomebridgeUniFiProtectPlugin
|
|
497
|
+
};
|
|
498
|
+
const registerHomebridgeUniFiProtectPlugin = () => (0, import_registry.registerPlugin)(
|
|
499
|
+
homebridgeUniFiProtectPluginMetadata,
|
|
500
|
+
homebridgeUniFiProtectPluginFactory
|
|
501
|
+
);
|
|
502
|
+
const createHomebridgeUniFiProtectPluginEntry = (config) => ({
|
|
503
|
+
id: HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID,
|
|
504
|
+
automatic: false,
|
|
505
|
+
modified: true,
|
|
506
|
+
config: {
|
|
507
|
+
...config
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
511
|
+
0 && (module.exports = {
|
|
512
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID,
|
|
513
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME,
|
|
514
|
+
attachHomebridgeUniFiProtectPlugin,
|
|
515
|
+
createHomebridgeUniFiProtectCleanup,
|
|
516
|
+
createHomebridgeUniFiProtectPluginEntry,
|
|
517
|
+
ensureHomebridgePlatformAccessoryShape,
|
|
518
|
+
homebridgeUniFiProtectPluginFactory,
|
|
519
|
+
homebridgeUniFiProtectPluginMetadata,
|
|
520
|
+
registerHomebridgeUniFiProtectPlugin
|
|
521
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var embedded_exports = {};
|
|
20
|
+
__export(embedded_exports, {
|
|
21
|
+
HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID: () => import_homebridge_camera_ffmpeg2.HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID,
|
|
22
|
+
HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME: () => import_homebridge_camera_ffmpeg2.HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME,
|
|
23
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID: () => import_homebridge_unifi_protect2.HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID,
|
|
24
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME: () => import_homebridge_unifi_protect2.HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME,
|
|
25
|
+
createAutomaticHomebridgeCameraFfmpegPluginEntry: () => import_homebridge_camera_ffmpeg2.createAutomaticHomebridgeCameraFfmpegPluginEntry,
|
|
26
|
+
createHomebridgeUniFiProtectCleanup: () => import_homebridge_unifi_protect2.createHomebridgeUniFiProtectCleanup,
|
|
27
|
+
createHomebridgeUniFiProtectPluginEntry: () => import_homebridge_unifi_protect2.createHomebridgeUniFiProtectPluginEntry,
|
|
28
|
+
ensureHomebridgePlatformAccessoryShape: () => import_homebridge_unifi_protect2.ensureHomebridgePlatformAccessoryShape,
|
|
29
|
+
mapLegacyCameraConfigToPluginConfig: () => import_homebridge_camera_ffmpeg2.mapLegacyCameraConfigToPluginConfig,
|
|
30
|
+
registerEmbeddedPlugins: () => registerEmbeddedPlugins
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(embedded_exports);
|
|
33
|
+
var import_registry = require("../registry");
|
|
34
|
+
var import_homebridge_camera_ffmpeg = require("./homebridge-camera-ffmpeg");
|
|
35
|
+
var import_homebridge_unifi_protect = require("./homebridge-unifi-protect");
|
|
36
|
+
var import_homebridge_camera_ffmpeg2 = require("./homebridge-camera-ffmpeg");
|
|
37
|
+
var import_homebridge_unifi_protect2 = require("./homebridge-unifi-protect");
|
|
38
|
+
const registerEmbeddedPlugins = () => {
|
|
39
|
+
if (!(0, import_registry.getPlugin)(import_homebridge_camera_ffmpeg.HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID)) {
|
|
40
|
+
(0, import_homebridge_camera_ffmpeg.registerHomebridgeCameraFfmpegPlugin)();
|
|
41
|
+
}
|
|
42
|
+
if (!(0, import_registry.getPlugin)(import_homebridge_unifi_protect.HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID)) {
|
|
43
|
+
(0, import_homebridge_unifi_protect.registerHomebridgeUniFiProtectPlugin)();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID,
|
|
49
|
+
HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME,
|
|
50
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_ID,
|
|
51
|
+
HOMEBRIDGE_UNIFI_PROTECT_PLUGIN_NAME,
|
|
52
|
+
createAutomaticHomebridgeCameraFfmpegPluginEntry,
|
|
53
|
+
createHomebridgeUniFiProtectCleanup,
|
|
54
|
+
createHomebridgeUniFiProtectPluginEntry,
|
|
55
|
+
ensureHomebridgePlatformAccessoryShape,
|
|
56
|
+
mapLegacyCameraConfigToPluginConfig,
|
|
57
|
+
registerEmbeddedPlugins
|
|
58
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_homebridge_camera_ffmpeg = require("./embedded/homebridge-camera-ffmpeg");
|
|
3
|
+
var import_homebridge_unifi_protect = require("./embedded/homebridge-unifi-protect");
|
|
4
|
+
var import_registry = require("./registry");
|
|
5
|
+
module.exports = (RED) => {
|
|
6
|
+
const plugins = RED.plugins;
|
|
7
|
+
plugins?.registerPlugin?.(import_homebridge_camera_ffmpeg.homebridgeCameraFfmpegPluginMetadata.id, {
|
|
8
|
+
type: import_registry.NRCHKB_NODE_RED_PLUGIN_TYPE,
|
|
9
|
+
metadata: import_homebridge_camera_ffmpeg.homebridgeCameraFfmpegPluginMetadata,
|
|
10
|
+
factory: import_homebridge_camera_ffmpeg.homebridgeCameraFfmpegPluginFactory
|
|
11
|
+
});
|
|
12
|
+
plugins?.registerPlugin?.(import_homebridge_unifi_protect.homebridgeUniFiProtectPluginMetadata.id, {
|
|
13
|
+
type: import_registry.NRCHKB_NODE_RED_PLUGIN_TYPE,
|
|
14
|
+
metadata: import_homebridge_unifi_protect.homebridgeUniFiProtectPluginMetadata,
|
|
15
|
+
factory: import_homebridge_unifi_protect.homebridgeUniFiProtectPluginFactory
|
|
16
|
+
});
|
|
17
|
+
};
|