node-red-contrib-homekit-bridged 2.0.0-dev.4 → 2.0.0-dev.7

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.
Files changed (125) hide show
  1. package/build/lib/HAPHostNode.js +183 -141
  2. package/build/lib/HAPServiceNode.js +199 -172
  3. package/build/lib/HAPServiceNode2.js +207 -172
  4. package/build/lib/NRCHKBError.js +23 -2
  5. package/build/lib/PairingQRCode.js +62 -0
  6. package/build/lib/Storage.js +157 -92
  7. package/build/lib/api.js +654 -288
  8. package/build/lib/camera/CameraControl.js +125 -0
  9. package/build/lib/camera/CameraDelegate.js +507 -0
  10. package/build/lib/camera/MP4StreamingServer.js +159 -0
  11. package/build/lib/hap/HAPCharacteristic.js +25 -4
  12. package/build/lib/hap/HAPService.js +25 -4
  13. package/build/lib/hap/eve-app/EveCharacteristics.js +124 -81
  14. package/build/lib/hap/eve-app/EveServices.js +50 -17
  15. package/build/lib/hap/hap-nodejs.js +32 -0
  16. package/build/lib/migration/HomeKitService2Migration.js +34 -0
  17. package/build/lib/migration/NodeMigration.js +75 -0
  18. package/build/lib/types/AccessoryInformationType.js +15 -1
  19. package/build/lib/types/CameraConfigType.js +15 -1
  20. package/build/lib/types/CustomCharacteristicType.js +15 -1
  21. package/build/lib/types/HAPHostConfigType.js +15 -1
  22. package/build/lib/types/HAPHostNodeType.js +15 -1
  23. package/build/lib/types/HAPService2ConfigType.js +15 -1
  24. package/build/lib/types/HAPService2NodeType.js +15 -1
  25. package/build/lib/types/HAPServiceConfigType.js +15 -1
  26. package/build/lib/types/HAPServiceNodeType.js +15 -1
  27. package/build/lib/types/HAPStatusConfigType.js +15 -1
  28. package/build/lib/types/HAPStatusNodeType.js +15 -1
  29. package/build/lib/types/HostType.js +28 -7
  30. package/build/lib/types/NodeType.js +15 -1
  31. package/build/lib/types/PublishTimersType.js +15 -1
  32. package/build/lib/types/UniFiControllerConfigType.js +16 -0
  33. package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.js +28 -7
  34. package/build/lib/types/hap-nodejs/HapCategories.js +64 -43
  35. package/build/lib/types/storage/SerializedHostType.js +15 -1
  36. package/build/lib/types/storage/StorageType.js +34 -10
  37. package/build/lib/unifi/ProtectDiscovery.js +80 -0
  38. package/build/lib/utils/AccessoryUtils.js +152 -110
  39. package/build/lib/utils/BridgeUtils.js +82 -39
  40. package/build/lib/utils/CharacteristicUtils.js +5 -49
  41. package/build/lib/utils/CharacteristicUtils2.js +5 -49
  42. package/build/lib/utils/CharacteristicUtilsBase.js +81 -0
  43. package/build/lib/utils/NodeStatusUtils.js +89 -40
  44. package/build/lib/utils/ServiceUtils.js +434 -373
  45. package/build/lib/utils/ServiceUtils2.js +514 -307
  46. package/build/lib/utils/index.js +10 -11
  47. package/build/nodes/bridge.html +184 -166
  48. package/build/nodes/bridge.js +27 -9
  49. package/build/nodes/locales/en-US/node-red-contrib-homekit-bridged.json +22 -0
  50. package/build/nodes/nrchkb.html +1601 -88
  51. package/build/nodes/nrchkb.js +66 -88
  52. package/build/nodes/plugin-instance.html +499 -0
  53. package/build/nodes/plugin-instance.js +46 -0
  54. package/build/nodes/service.html +517 -299
  55. package/build/nodes/service.js +5 -6
  56. package/build/nodes/service2.html +1683 -460
  57. package/build/nodes/service2.js +5 -8
  58. package/build/nodes/standalone.html +187 -174
  59. package/build/nodes/standalone.js +27 -9
  60. package/build/nodes/status.html +51 -18
  61. package/build/nodes/status.js +47 -40
  62. package/build/nodes/unifi-controller.html +92 -0
  63. package/build/nodes/unifi-controller.js +20 -0
  64. package/build/plugins/embedded/homebridge-camera-ffmpeg/index.js +479 -0
  65. package/build/plugins/embedded/homebridge-unifi-protect/index.js +521 -0
  66. package/build/plugins/embedded/index.js +58 -0
  67. package/build/plugins/nrchkb-homekit-plugins.js +17 -0
  68. package/build/plugins/registry/index.js +203 -0
  69. package/build/plugins/registry/types.js +16 -0
  70. package/build/scripts/migrate-homekit-service-flows.js +47 -0
  71. package/examples/demo/01 - ALL Demos single import.json +1885 -1885
  72. package/examples/demo/02 - Air Purifier.json +279 -279
  73. package/examples/demo/03 - Air Quality sensor with Battery.json +254 -254
  74. package/examples/demo/04 - Dimmable Bulb.json +172 -172
  75. package/examples/demo/05 - Color Bulb (HSV).json +195 -195
  76. package/examples/demo/06 - Fan (simple, 3 speeds).json +240 -240
  77. package/examples/demo/07 - Fan (with speed, oscillate, rotation direction).json +175 -175
  78. package/examples/demo/08 - CO2 detector.json +224 -224
  79. package/examples/demo/09 - CO (carbon monoxide) example.json +255 -255
  80. package/examples/demo/10 - Door window contact sensor.json +234 -234
  81. package/examples/demos (advanced)/01 - Television with inputs and speaker.json +541 -541
  82. package/examples/switch/01 - Plain Switch.json +178 -178
  83. package/package.json +95 -84
  84. package/build/lib/HAPHostNode.d.ts +0 -1
  85. package/build/lib/HAPServiceNode.d.ts +0 -1
  86. package/build/lib/HAPServiceNode2.d.ts +0 -1
  87. package/build/lib/NRCHKBError.d.ts +0 -3
  88. package/build/lib/Storage.d.ts +0 -30
  89. package/build/lib/api.d.ts +0 -1
  90. package/build/lib/hap/HAPCharacteristic.d.ts +0 -9
  91. package/build/lib/hap/HAPService.d.ts +0 -6
  92. package/build/lib/hap/eve-app/EveCharacteristics.d.ts +0 -20
  93. package/build/lib/hap/eve-app/EveServices.d.ts +0 -5
  94. package/build/lib/types/AccessoryInformationType.d.ts +0 -11
  95. package/build/lib/types/CameraConfigType.d.ts +0 -24
  96. package/build/lib/types/CustomCharacteristicType.d.ts +0 -6
  97. package/build/lib/types/HAPHostConfigType.d.ts +0 -22
  98. package/build/lib/types/HAPHostNodeType.d.ts +0 -14
  99. package/build/lib/types/HAPService2ConfigType.d.ts +0 -6
  100. package/build/lib/types/HAPService2NodeType.d.ts +0 -7
  101. package/build/lib/types/HAPServiceConfigType.d.ts +0 -26
  102. package/build/lib/types/HAPServiceNodeType.d.ts +0 -38
  103. package/build/lib/types/HAPStatusConfigType.d.ts +0 -5
  104. package/build/lib/types/HAPStatusNodeType.d.ts +0 -12
  105. package/build/lib/types/HostType.d.ts +0 -5
  106. package/build/lib/types/NodeType.d.ts +0 -3
  107. package/build/lib/types/PublishTimersType.d.ts +0 -4
  108. package/build/lib/types/hap-nodejs/HapAdaptiveLightingControllerMode.d.ts +0 -5
  109. package/build/lib/types/hap-nodejs/HapCategories.d.ts +0 -41
  110. package/build/lib/types/storage/SerializedHostType.d.ts +0 -5
  111. package/build/lib/types/storage/StorageType.d.ts +0 -8
  112. package/build/lib/utils/AccessoryUtils.d.ts +0 -1
  113. package/build/lib/utils/BridgeUtils.d.ts +0 -1
  114. package/build/lib/utils/CharacteristicUtils.d.ts +0 -1
  115. package/build/lib/utils/CharacteristicUtils2.d.ts +0 -1
  116. package/build/lib/utils/NodeStatusUtils.d.ts +0 -17
  117. package/build/lib/utils/ServiceUtils.d.ts +0 -1
  118. package/build/lib/utils/ServiceUtils2.d.ts +0 -1
  119. package/build/lib/utils/index.d.ts +0 -1
  120. package/build/nodes/bridge.d.ts +0 -1
  121. package/build/nodes/nrchkb.d.ts +0 -1
  122. package/build/nodes/service.d.ts +0 -1
  123. package/build/nodes/service2.d.ts +0 -1
  124. package/build/nodes/standalone.d.ts +0 -1
  125. package/build/nodes/status.d.ts +0 -1
@@ -1,44 +1,51 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const hap_nodejs_1 = require("@homebridge/hap-nodejs");
4
- const logger_1 = require("@nrchkb/logger");
5
- const NodeStatusUtils_1 = require("../lib/utils/NodeStatusUtils");
6
- const log = (0, logger_1.logger)('NRCHKB', 'HAPStatusNode');
2
+ var import_hap_nodejs = require("@homebridge/hap-nodejs");
3
+ var import_logger = require("@nrchkb/logger");
4
+ var import_NodeStatusUtils = require("../lib/utils/NodeStatusUtils");
5
+ const log = (0, import_logger.logger)("NRCHKB", "HAPStatusNode");
7
6
  module.exports = (RED) => {
8
- log.debug('Registering homekit-status type');
9
- RED.nodes.registerType('homekit-status', function (config) {
10
- this.config = config;
11
- RED.nodes.createNode(this, config);
12
- this.nodeStatusUtils = new NodeStatusUtils_1.NodeStatusUtils(this);
13
- try {
14
- this.serviceNode = RED.nodes.getNode(this.config.serviceNodeId);
7
+ log.debug("Registering homekit-status type");
8
+ RED.nodes.registerType(
9
+ "homekit-status",
10
+ function(config) {
11
+ this.config = config;
12
+ RED.nodes.createNode(this, config);
13
+ this.nodeStatusUtils = new import_NodeStatusUtils.NodeStatusUtils(this);
14
+ try {
15
+ this.serviceNode = RED.nodes.getNode(
16
+ this.config.serviceNodeId
17
+ );
18
+ } catch (error) {
19
+ log.error(error);
20
+ }
21
+ this.on("input", (_) => {
22
+ if (this.serviceNode) {
23
+ this.nodeStatusUtils.setStatus(
24
+ {
25
+ fill: "green",
26
+ shape: "dot",
27
+ text: "Done"
28
+ },
29
+ 3e3
30
+ );
31
+ const serializedService = import_hap_nodejs.Service.serialize(
32
+ this.serviceNode.service
33
+ );
34
+ this.send({
35
+ payload: serializedService
36
+ });
37
+ } else {
38
+ this.nodeStatusUtils.setStatus({
39
+ fill: "red",
40
+ shape: "dot",
41
+ text: "Check your config"
42
+ });
15
43
  }
16
- catch (error) {
17
- log.error(error);
18
- }
19
- this.on('input', (_) => {
20
- if (this.serviceNode) {
21
- this.nodeStatusUtils.setStatus({
22
- fill: 'green',
23
- shape: 'dot',
24
- text: 'Done'
25
- }, 3000);
26
- const serializedService = hap_nodejs_1.Service.serialize(this.serviceNode.service);
27
- this.send({
28
- payload: serializedService
29
- });
30
- }
31
- else {
32
- this.nodeStatusUtils.setStatus({
33
- fill: 'red',
34
- shape: 'dot',
35
- text: 'Check your config'
36
- });
37
- }
38
- });
39
- this.on('close', (_, done) => {
40
- this.serviceNode = undefined;
41
- done();
42
- });
43
- });
44
+ });
45
+ this.on("close", (_, done) => {
46
+ this.serviceNode = void 0;
47
+ done();
48
+ });
49
+ }
50
+ );
44
51
  };
@@ -0,0 +1,92 @@
1
+ <script data-template-name="homekit-unifi-controller" type="text/x-red">
2
+ <div class="nrchkb-editor">
3
+ <details class="nrchkb-section" open>
4
+ <summary><i class="fa fa-server"></i> UniFi Controller</summary>
5
+ <div class="nrchkb-section-body">
6
+ <div class="form-row">
7
+ <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
8
+ <input type="text" id="node-config-input-name" placeholder="UniFi Protect">
9
+ </div>
10
+ <div class="form-row">
11
+ <label for="node-config-input-application"><i class="fa fa-cubes"></i> Application</label>
12
+ <select id="node-config-input-application">
13
+ <option value="protect" selected>Protect</option>
14
+ </select>
15
+ </div>
16
+ <div class="form-row">
17
+ <label for="node-config-input-address"><i class="fa fa-globe"></i> Address</label>
18
+ <input type="text" id="node-config-input-address" placeholder="192.168.1.1">
19
+ </div>
20
+ <div class="form-row">
21
+ <label for="node-config-input-username"><i class="fa fa-user"></i> Username</label>
22
+ <input type="text" id="node-config-input-username">
23
+ </div>
24
+ <div class="form-row">
25
+ <label for="node-config-input-password"><i class="fa fa-lock"></i> Password</label>
26
+ <input type="password" id="node-config-input-password">
27
+ </div>
28
+ <div class="form-row">
29
+ <label for="node-config-input-overrideAddress"><i class="fa fa-random"></i> Override Address</label>
30
+ <input type="text" id="node-config-input-overrideAddress" placeholder="Optional livestream address">
31
+ </div>
32
+ <div class="form-row nrchkb-checkbox-row">
33
+ <label class="nrchkb-checkbox-label" for="node-config-input-allowSelfSigned">
34
+ <input type="checkbox" id="node-config-input-allowSelfSigned">
35
+ <span><i class="fa fa-certificate"></i> Allow self-signed certificates</span>
36
+ </label>
37
+ </div>
38
+ </div>
39
+ </details>
40
+ </div>
41
+ </script>
42
+
43
+ <script data-help-name="homekit-unifi-controller" type="text/markdown">
44
+ # UniFi Controller
45
+
46
+ Stores connection details for UniFi application integrations. Protect is supported now; the generic node name leaves room for future Access or Network integrations.
47
+
48
+ > [!IMPORTANT]
49
+ > Use a dedicated local UniFi account with the minimum permissions needed to read Protect camera data.
50
+
51
+ > [!WARNING]
52
+ > Allow self-signed certificates only for controllers you administer and trust on your local network.
53
+ </script>
54
+
55
+ <script type="text/javascript">
56
+ RED.nodes.registerType('homekit-unifi-controller', {
57
+ category: 'config',
58
+ defaults: {
59
+ name: {
60
+ value: '',
61
+ },
62
+ application: {
63
+ value: 'protect',
64
+ required: true,
65
+ },
66
+ address: {
67
+ value: '',
68
+ required: true,
69
+ },
70
+ allowSelfSigned: {
71
+ value: false,
72
+ },
73
+ overrideAddress: {
74
+ value: '',
75
+ },
76
+ },
77
+ credentials: {
78
+ username: {
79
+ type: 'text',
80
+ },
81
+ password: {
82
+ type: 'password',
83
+ },
84
+ },
85
+ label: function () {
86
+ return this.name || this.address || 'UniFi Controller'
87
+ },
88
+ onadd: function () {
89
+ applyDefaultNodeDocumentation(this, 'homekit-unifi-controller')
90
+ },
91
+ })
92
+ </script>
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var import_logger = require("@nrchkb/logger");
3
+ const log = (0, import_logger.logger)("NRCHKB", "UniFiController");
4
+ module.exports = (RED) => {
5
+ const init = function(config) {
6
+ RED.nodes.createNode(this, config);
7
+ this.name = config.name;
8
+ this.address = config.address;
9
+ this.application = config.application ?? "protect";
10
+ this.allowSelfSigned = config.allowSelfSigned === true;
11
+ this.overrideAddress = config.overrideAddress;
12
+ };
13
+ log.debug("Registering homekit-unifi-controller type");
14
+ RED.nodes.registerType("homekit-unifi-controller", init, {
15
+ credentials: {
16
+ username: { type: "text" },
17
+ password: { type: "password" }
18
+ }
19
+ });
20
+ };
@@ -0,0 +1,479 @@
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_camera_ffmpeg_exports = {};
30
+ __export(homebridge_camera_ffmpeg_exports, {
31
+ HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID: () => HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID,
32
+ HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME: () => HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME,
33
+ createAutomaticHomebridgeCameraFfmpegPluginEntry: () => createAutomaticHomebridgeCameraFfmpegPluginEntry,
34
+ homebridgeCameraFfmpegPluginFactory: () => homebridgeCameraFfmpegPluginFactory,
35
+ homebridgeCameraFfmpegPluginMetadata: () => homebridgeCameraFfmpegPluginMetadata,
36
+ mapLegacyCameraConfigToPluginConfig: () => mapLegacyCameraConfigToPluginConfig,
37
+ registerHomebridgeCameraFfmpegPlugin: () => registerHomebridgeCameraFfmpegPlugin
38
+ });
39
+ module.exports = __toCommonJS(homebridge_camera_ffmpeg_exports);
40
+ var import_hap_nodejs = require("@homebridge/hap-nodejs");
41
+ var import_logger = require("@nrchkb/logger");
42
+ var import_registry = require("../../registry");
43
+ const HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME = "homebridge-camera-ffmpeg";
44
+ const HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID = (0, import_registry.normalizePluginId)(
45
+ "node-red-contrib-homekit-bridged",
46
+ HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME
47
+ );
48
+ const requirePackageJson = (packageName) => {
49
+ try {
50
+ return require(`${packageName}/package.json`);
51
+ } catch (_) {
52
+ return {};
53
+ }
54
+ };
55
+ const upstreamPackage = requirePackageJson(
56
+ "@homebridge-plugins/homebridge-camera-ffmpeg"
57
+ );
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 toBoolean = (value) => {
62
+ if (typeof value === "boolean") {
63
+ return value;
64
+ }
65
+ if (typeof value === "string") {
66
+ return value.trim().toLowerCase() === "true";
67
+ }
68
+ return Boolean(value);
69
+ };
70
+ const importEsm = (specifier) => {
71
+ const importer = new Function("specifier", "return import(specifier)");
72
+ return importer(specifier);
73
+ };
74
+ const createHomebridgeLogger = () => {
75
+ const log = (0, import_logger.logger)("NRCHKB", "HomebridgeCameraFFmpeg");
76
+ const write = (level) => (message, ...parameters) => {
77
+ const suffix = parameters.length ? ` ${parameters.join(" ")}` : "";
78
+ const text = `${message}${suffix}`;
79
+ if (level === "debug") {
80
+ log.debug(text);
81
+ } else if (level === "error") {
82
+ log.error(text);
83
+ } else {
84
+ log.debug(text);
85
+ }
86
+ };
87
+ return {
88
+ debug: write("debug"),
89
+ info: write("info"),
90
+ warn: write("warn"),
91
+ error: write("error"),
92
+ success: write("info"),
93
+ log: write("info")
94
+ };
95
+ };
96
+ const createHomebridgeApiShim = () => ({
97
+ on: (_event, _handler) => {
98
+ }
99
+ });
100
+ const getCameraConfig = (context) => ({
101
+ name: context.config.camera?.name ?? context.serviceInformation.name,
102
+ manufacturer: context.config.camera?.manufacturer ?? context.serviceInformation.config.manufacturer,
103
+ model: context.config.camera?.model ?? context.serviceInformation.config.model,
104
+ serialNumber: context.config.camera?.serialNumber ?? context.serviceInformation.config.serialNo,
105
+ firmwareRevision: context.config.camera?.firmwareRevision ?? context.serviceInformation.config.firmwareRev,
106
+ motion: context.config.camera?.motion,
107
+ doorbell: context.config.camera?.doorbell,
108
+ switches: context.config.camera?.switches,
109
+ motionTimeout: context.config.camera?.motionTimeout,
110
+ motionDoorbell: context.config.camera?.motionDoorbell,
111
+ videoConfig: {
112
+ ...context.config.camera?.videoConfig
113
+ }
114
+ });
115
+ const mapLegacyCameraConfigToPluginConfig = (config) => ({
116
+ videoProcessor: config.cameraConfigVideoProcessor || "ffmpeg",
117
+ camera: {
118
+ name: config.name,
119
+ manufacturer: config.manufacturer,
120
+ model: config.model,
121
+ serialNumber: config.serialNo,
122
+ firmwareRevision: config.firmwareRev,
123
+ videoConfig: {
124
+ source: config.cameraConfigSource,
125
+ stillImageSource: config.cameraConfigStillImageSource,
126
+ maxStreams: config.cameraConfigMaxStreams,
127
+ maxWidth: config.cameraConfigMaxWidth,
128
+ maxHeight: config.cameraConfigMaxHeight,
129
+ maxFPS: config.cameraConfigMaxFPS,
130
+ maxBitrate: config.cameraConfigMaxBitrate,
131
+ vcodec: config.cameraConfigVideoCodec,
132
+ audio: toBoolean(config.cameraConfigAudio),
133
+ returnAudioTarget: config.cameraConfigReturnAudioTarget,
134
+ packetSize: config.cameraConfigPacketSize,
135
+ forceMax: toBoolean(config.cameraConfigForceMax),
136
+ mapvideo: config.cameraConfigMapVideo,
137
+ mapaudio: config.cameraConfigMapAudio,
138
+ videoFilter: config.cameraConfigVideoFilter,
139
+ encoderOptions: config.cameraConfigAdditionalCommandLine,
140
+ debug: toBoolean(config.cameraConfigDebug),
141
+ debugReturn: toBoolean(config.cameraConfigDebugReturn),
142
+ recording: toBoolean(config.cameraConfigRecording),
143
+ prebuffer: toBoolean(config.cameraConfigPrebuffer)
144
+ }
145
+ }
146
+ });
147
+ const createAutomaticHomebridgeCameraFfmpegPluginEntry = (config) => ({
148
+ id: HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID,
149
+ automatic: true,
150
+ modified: false,
151
+ config: mapLegacyCameraConfigToPluginConfig(config)
152
+ });
153
+ const homebridgeCameraFfmpegPluginMetadata = {
154
+ id: HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID,
155
+ packageName: "node-red-contrib-homekit-bridged",
156
+ pluginName: HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME,
157
+ displayName: "Homebridge Camera FFmpeg",
158
+ author: "NRCHKB",
159
+ version: "1.0.0",
160
+ description: "Adds FFmpeg-backed HomeKit camera snapshots, live video, audio, and experimental recording features.",
161
+ attachment: "inline",
162
+ license: "Apache-2.0",
163
+ capabilities: {
164
+ camera: true,
165
+ snapshots: true,
166
+ liveVideo: true,
167
+ audio: true,
168
+ twoWayAudio: true,
169
+ secureVideo: true,
170
+ experimental: ["twoWayAudio", "secureVideo"]
171
+ },
172
+ prerequisites: {
173
+ serviceNames: ["Camera"]
174
+ },
175
+ multipleInstances: false,
176
+ upstream: {
177
+ packageName: "@homebridge-plugins/homebridge-camera-ffmpeg",
178
+ packageVersion: upstreamPackage.version,
179
+ projectName: "Homebridge Camera FFmpeg",
180
+ repoUrl: "https://github.com/homebridge-plugins/homebridge-camera-ffmpeg",
181
+ license: upstreamPackage.license,
182
+ authors: upstreamAuthor ? [upstreamAuthor] : [],
183
+ contributors: upstreamContributors,
184
+ disclaimer: "Original authors and contributors are credited for the upstream Homebridge plugin. NRCHKB owns and supports this embedded integration."
185
+ },
186
+ editor: {
187
+ defaultConfig: {
188
+ videoProcessor: "ffmpeg",
189
+ camera: {
190
+ videoConfig: {
191
+ source: "",
192
+ stillImageSource: "",
193
+ maxStreams: 2,
194
+ maxWidth: 1280,
195
+ maxHeight: 720,
196
+ maxFPS: 10,
197
+ maxBitrate: 300,
198
+ vcodec: "libx264",
199
+ audio: false,
200
+ returnAudioTarget: "",
201
+ packetSize: 1316,
202
+ forceMax: false,
203
+ mapvideo: "0:0",
204
+ mapaudio: "0:1",
205
+ videoFilter: "scale=1280:720",
206
+ encoderOptions: "-tune zerolatency",
207
+ debug: false,
208
+ debugReturn: false,
209
+ recording: true,
210
+ prebuffer: true
211
+ }
212
+ }
213
+ },
214
+ sections: [
215
+ {
216
+ title: "FFmpeg",
217
+ description: "Configure the command arguments used for HomeKit camera snapshots and live video.",
218
+ fields: [
219
+ {
220
+ path: "videoProcessor",
221
+ label: "Video Processor",
222
+ type: "text",
223
+ icon: "fa-terminal",
224
+ placeholder: "ffmpeg",
225
+ default: "ffmpeg"
226
+ },
227
+ {
228
+ path: "camera.videoConfig.source",
229
+ label: "Source",
230
+ type: "text",
231
+ icon: "fa-sign-in"
232
+ },
233
+ {
234
+ path: "camera.videoConfig.stillImageSource",
235
+ label: "Still Image Source",
236
+ type: "text",
237
+ icon: "fa-picture-o"
238
+ },
239
+ {
240
+ path: "camera.videoConfig.maxStreams",
241
+ label: "Max Streams",
242
+ type: "number",
243
+ icon: "fa-random",
244
+ default: 2
245
+ },
246
+ {
247
+ path: "camera.videoConfig.maxWidth",
248
+ label: "Max Width",
249
+ type: "number",
250
+ icon: "fa-arrows-h",
251
+ default: 1280
252
+ },
253
+ {
254
+ path: "camera.videoConfig.maxHeight",
255
+ label: "Max Height",
256
+ type: "number",
257
+ icon: "fa-arrows-v",
258
+ default: 720
259
+ },
260
+ {
261
+ path: "camera.videoConfig.maxFPS",
262
+ label: "Max FPS",
263
+ type: "number",
264
+ icon: "fa-clock-o",
265
+ default: 10
266
+ },
267
+ {
268
+ path: "camera.videoConfig.maxBitrate",
269
+ label: "Max Bitrate",
270
+ type: "number",
271
+ icon: "fa-tachometer",
272
+ default: 300
273
+ },
274
+ {
275
+ path: "camera.videoConfig.vcodec",
276
+ label: "Video Codec",
277
+ type: "text",
278
+ icon: "fa-film",
279
+ default: "libx264"
280
+ },
281
+ {
282
+ path: "camera.videoConfig.audio",
283
+ label: "Audio",
284
+ type: "checkbox",
285
+ icon: "fa-headphones",
286
+ default: false
287
+ },
288
+ {
289
+ path: "camera.videoConfig.returnAudioTarget",
290
+ label: "Return Audio Target",
291
+ type: "text",
292
+ icon: "fa-microphone"
293
+ },
294
+ {
295
+ path: "camera.videoConfig.packetSize",
296
+ label: "Packet Size",
297
+ type: "number",
298
+ icon: "fa-archive",
299
+ default: 1316
300
+ },
301
+ {
302
+ path: "camera.videoConfig.forceMax",
303
+ label: "Force Max",
304
+ type: "checkbox",
305
+ icon: "fa-arrows-alt",
306
+ default: false
307
+ },
308
+ {
309
+ path: "camera.videoConfig.mapvideo",
310
+ label: "Map Video",
311
+ type: "text",
312
+ icon: "fa-film",
313
+ default: "0:0"
314
+ },
315
+ {
316
+ path: "camera.videoConfig.mapaudio",
317
+ label: "Map Audio",
318
+ type: "text",
319
+ icon: "fa-volume-up",
320
+ default: "0:1"
321
+ },
322
+ {
323
+ path: "camera.videoConfig.videoFilter",
324
+ label: "Video Filter",
325
+ type: "text",
326
+ icon: "fa-filter",
327
+ default: "scale=1280:720"
328
+ },
329
+ {
330
+ path: "camera.videoConfig.encoderOptions",
331
+ label: "Additional Command Line",
332
+ type: "text",
333
+ icon: "fa-terminal",
334
+ default: "-tune zerolatency"
335
+ },
336
+ {
337
+ path: "camera.videoConfig.debug",
338
+ label: "Debug",
339
+ type: "checkbox",
340
+ icon: "fa-bug",
341
+ default: false
342
+ },
343
+ {
344
+ path: "camera.videoConfig.debugReturn",
345
+ label: "Debug Return Audio",
346
+ type: "checkbox",
347
+ icon: "fa-bug",
348
+ default: false
349
+ },
350
+ {
351
+ path: "camera.videoConfig.recording",
352
+ label: "Recording",
353
+ type: "checkbox",
354
+ icon: "fa-video-camera",
355
+ default: true
356
+ },
357
+ {
358
+ path: "camera.videoConfig.prebuffer",
359
+ label: "Prebuffer",
360
+ type: "checkbox",
361
+ icon: "fa-clock-o",
362
+ default: true
363
+ }
364
+ ]
365
+ },
366
+ {
367
+ title: "Camera Events",
368
+ description: "Expose HomeKit motion and doorbell helpers supported by Camera FFmpeg.",
369
+ fields: [
370
+ {
371
+ path: "camera.motion",
372
+ label: "Motion Sensor",
373
+ type: "checkbox",
374
+ icon: "fa-bell",
375
+ default: false
376
+ },
377
+ {
378
+ path: "camera.doorbell",
379
+ label: "Doorbell",
380
+ type: "checkbox",
381
+ icon: "fa-bell-o",
382
+ default: false
383
+ },
384
+ {
385
+ path: "camera.switches",
386
+ label: "Trigger Switches",
387
+ type: "checkbox",
388
+ icon: "fa-toggle-on",
389
+ default: false
390
+ },
391
+ {
392
+ path: "camera.motionTimeout",
393
+ label: "Motion Timeout",
394
+ type: "number",
395
+ icon: "fa-clock-o",
396
+ default: 1
397
+ },
398
+ {
399
+ path: "camera.motionDoorbell",
400
+ label: "Motion Rings Doorbell",
401
+ type: "checkbox",
402
+ icon: "fa-bell",
403
+ default: false
404
+ }
405
+ ]
406
+ },
407
+ {
408
+ title: "Camera Identity",
409
+ description: "Optional HomeKit metadata overrides for this camera.",
410
+ fields: [
411
+ {
412
+ path: "camera.manufacturer",
413
+ label: "Manufacturer",
414
+ type: "text",
415
+ icon: "fa-industry"
416
+ },
417
+ {
418
+ path: "camera.model",
419
+ label: "Model",
420
+ type: "text",
421
+ icon: "fa-cube"
422
+ },
423
+ {
424
+ path: "camera.serialNumber",
425
+ label: "Serial Number",
426
+ type: "text",
427
+ icon: "fa-barcode"
428
+ },
429
+ {
430
+ path: "camera.firmwareRevision",
431
+ label: "Firmware Revision",
432
+ type: "text",
433
+ icon: "fa-microchip"
434
+ }
435
+ ]
436
+ }
437
+ ]
438
+ }
439
+ };
440
+ const homebridgeCameraFfmpegPluginFactory = {
441
+ attach: async (context) => {
442
+ const hap = await import("@homebridge/hap-nodejs");
443
+ const module2 = await importEsm(
444
+ "@homebridge-plugins/homebridge-camera-ffmpeg/dist/streamingDelegate.js"
445
+ );
446
+ const delegate = new module2.StreamingDelegate(
447
+ createHomebridgeLogger(),
448
+ getCameraConfig(context),
449
+ createHomebridgeApiShim(),
450
+ hap,
451
+ context.accessory,
452
+ context.config.videoProcessor
453
+ );
454
+ context.accessory.configureController(delegate.controller);
455
+ const service = context.accessory.services.find(
456
+ (candidate) => candidate.UUID === import_hap_nodejs.Service.CameraRTPStreamManagement.UUID
457
+ );
458
+ if (!service) {
459
+ throw new Error(
460
+ "Homebridge Camera FFmpeg did not create a camera stream service."
461
+ );
462
+ }
463
+ return service;
464
+ }
465
+ };
466
+ const registerHomebridgeCameraFfmpegPlugin = () => (0, import_registry.registerPlugin)(
467
+ homebridgeCameraFfmpegPluginMetadata,
468
+ homebridgeCameraFfmpegPluginFactory
469
+ );
470
+ // Annotate the CommonJS export names for ESM import in node:
471
+ 0 && (module.exports = {
472
+ HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_ID,
473
+ HOMEBRIDGE_CAMERA_FFMPEG_PLUGIN_NAME,
474
+ createAutomaticHomebridgeCameraFfmpegPluginEntry,
475
+ homebridgeCameraFfmpegPluginFactory,
476
+ homebridgeCameraFfmpegPluginMetadata,
477
+ mapLegacyCameraConfigToPluginConfig,
478
+ registerHomebridgeCameraFfmpegPlugin
479
+ });