@trillboards/edge-sdk 0.2.4 → 0.2.6
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 +4 -3
- package/deploy/docker/Dockerfile.cloud-sense +117 -0
- package/deploy/docker/Dockerfile.cpu +30 -21
- package/deploy/docker/Dockerfile.cuda +30 -21
- package/deploy/docker/Dockerfile.openvino +30 -20
- package/deploy/docker/README.md +9 -4
- package/deploy/docker/connector-entrypoint.sh +122 -0
- package/deploy/helm/README.md +1 -1
- package/deploy/k8s/daemonset.yaml +1 -1
- package/deploy/macos/README.md +161 -0
- package/deploy/macos/TrillboardsSetupApp.m +603 -0
- package/deploy/macos/build-macos-pkg.sh +588 -0
- package/deploy/macos/com.trillboards.edge.plist +62 -0
- package/deploy/macos/com.trillboards.litertlm.plist +45 -0
- package/deploy/macos/pair.command +519 -0
- package/deploy/macos/scripts/ensure-litertlm.sh +62 -0
- package/deploy/macos/scripts/postinstall +153 -0
- package/deploy/macos/scripts/setup-litertlm.sh +272 -0
- package/deploy/macos/test-install-pair.sh +383 -0
- package/deploy/macos/test-setup-litertlm-reinstall.sh +109 -0
- package/deploy/systemd/install.sh +25 -15
- package/deploy/systemd/trillboards-edge.service +4 -1
- package/deploy/windows/README.md +70 -0
- package/deploy/windows/build-windows.ps1 +225 -0
- package/deploy/windows/bundle-windows-installer.ps1 +153 -0
- package/deploy/windows/check-feeds.js +26 -0
- package/deploy/windows/e2e/fixtures/person.jpg +0 -0
- package/deploy/windows/e2e/test-local-sense.ps1 +185 -0
- package/deploy/windows/install-update.ps1 +101 -0
- package/deploy/windows/installer.nsi +138 -0
- package/deploy/windows/register-litertlm-task.ps1 +42 -0
- package/deploy/windows/register-task.ps1 +44 -0
- package/deploy/windows/run-connector.ps1 +69 -0
- package/deploy/windows/setup-litertlm.ps1 +361 -0
- package/deploy/windows/stop-existing.ps1 +72 -0
- package/deploy/windows/trillboards-edge-task.vbs +25 -0
- package/deploy/windows/trillboards-edge.cmd +33 -0
- package/deploy/windows/trillboards-pair.cmd +276 -0
- package/deploy/windows/trillboards-setup.ps1 +456 -0
- package/deploy/windows/trillboards-setup.vbs +13 -0
- package/dist/AudienceAnalyzeClient.d.ts +136 -0
- package/dist/AudienceAnalyzeClient.d.ts.map +1 -0
- package/dist/AudienceAnalyzeClient.js +246 -0
- package/dist/AudienceAnalyzeClient.js.map +1 -0
- package/dist/ChannelProber.d.ts +150 -0
- package/dist/ChannelProber.d.ts.map +1 -0
- package/dist/ChannelProber.js +887 -0
- package/dist/ChannelProber.js.map +1 -0
- package/dist/CloudEscalationPolicy.d.ts +143 -0
- package/dist/CloudEscalationPolicy.d.ts.map +1 -0
- package/dist/CloudEscalationPolicy.js +137 -0
- package/dist/CloudEscalationPolicy.js.map +1 -0
- package/dist/CloudSensingManager.d.ts +533 -0
- package/dist/CloudSensingManager.d.ts.map +1 -0
- package/dist/CloudSensingManager.js +1254 -0
- package/dist/CloudSensingManager.js.map +1 -0
- package/dist/DiscoveryReportClient.d.ts +66 -0
- package/dist/DiscoveryReportClient.d.ts.map +1 -0
- package/dist/DiscoveryReportClient.js +85 -0
- package/dist/DiscoveryReportClient.js.map +1 -0
- package/dist/EdgeAgent.d.ts +12 -2
- package/dist/EdgeAgent.d.ts.map +1 -1
- package/dist/EdgeAgent.js +55 -13
- package/dist/EdgeAgent.js.map +1 -1
- package/dist/LiteRtVlmProvider.d.ts +193 -0
- package/dist/LiteRtVlmProvider.d.ts.map +1 -0
- package/dist/LiteRtVlmProvider.js +436 -0
- package/dist/LiteRtVlmProvider.js.map +1 -0
- package/dist/MosaicSource.d.ts +108 -0
- package/dist/MosaicSource.d.ts.map +1 -0
- package/dist/MosaicSource.js +274 -0
- package/dist/MosaicSource.js.map +1 -0
- package/dist/OnvifClient.d.ts +83 -0
- package/dist/OnvifClient.d.ts.map +1 -0
- package/dist/OnvifClient.js +209 -0
- package/dist/OnvifClient.js.map +1 -0
- package/dist/PairClient.d.ts +106 -0
- package/dist/PairClient.d.ts.map +1 -0
- package/dist/PairClient.js +186 -0
- package/dist/PairClient.js.map +1 -0
- package/dist/RecorderAddressRecovery.d.ts +53 -0
- package/dist/RecorderAddressRecovery.d.ts.map +1 -0
- package/dist/RecorderAddressRecovery.js +359 -0
- package/dist/RecorderAddressRecovery.js.map +1 -0
- package/dist/SceneChangeDetector.d.ts +291 -0
- package/dist/SceneChangeDetector.d.ts.map +1 -0
- package/dist/SceneChangeDetector.js +682 -0
- package/dist/SceneChangeDetector.js.map +1 -0
- package/dist/SensingProfileClient.d.ts +59 -0
- package/dist/SensingProfileClient.d.ts.map +1 -0
- package/dist/SensingProfileClient.js +78 -0
- package/dist/SensingProfileClient.js.map +1 -0
- package/dist/SetupSessionClient.d.ts +114 -0
- package/dist/SetupSessionClient.d.ts.map +1 -0
- package/dist/SetupSessionClient.js +95 -0
- package/dist/SetupSessionClient.js.map +1 -0
- package/dist/VlmAdmissionGate.d.ts +126 -0
- package/dist/VlmAdmissionGate.d.ts.map +1 -0
- package/dist/VlmAdmissionGate.js +166 -0
- package/dist/VlmAdmissionGate.js.map +1 -0
- package/dist/autoSense.d.ts +216 -0
- package/dist/autoSense.d.ts.map +1 -0
- package/dist/autoSense.js +521 -0
- package/dist/autoSense.js.map +1 -0
- package/dist/cli.d.ts +27 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +511 -21
- package/dist/cli.js.map +1 -1
- package/dist/combinedSense.d.ts +128 -0
- package/dist/combinedSense.d.ts.map +1 -0
- package/dist/combinedSense.js +261 -0
- package/dist/combinedSense.js.map +1 -0
- package/dist/config.d.ts +351 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +99 -2
- package/dist/config.js.map +1 -1
- package/dist/connectorCadence.d.ts +135 -0
- package/dist/connectorCadence.d.ts.map +1 -0
- package/dist/connectorCadence.js +151 -0
- package/dist/connectorCadence.js.map +1 -0
- package/dist/dataDir.d.ts +33 -0
- package/dist/dataDir.d.ts.map +1 -0
- package/dist/dataDir.js +76 -0
- package/dist/dataDir.js.map +1 -0
- package/dist/deployedCadence.d.ts +167 -0
- package/dist/deployedCadence.d.ts.map +1 -0
- package/dist/deployedCadence.js +209 -0
- package/dist/deployedCadence.js.map +1 -0
- package/dist/deployedCadenceSource.d.ts +48 -0
- package/dist/deployedCadenceSource.d.ts.map +1 -0
- package/dist/deployedCadenceSource.js +74 -0
- package/dist/deployedCadenceSource.js.map +1 -0
- package/dist/diagnose.d.ts +1 -1
- package/dist/diagnose.d.ts.map +1 -1
- package/dist/diagnose.js +13 -12
- package/dist/diagnose.js.map +1 -1
- package/dist/discovery.d.ts +131 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +499 -0
- package/dist/discovery.js.map +1 -0
- package/dist/gemmaModelOta.d.ts +118 -0
- package/dist/gemmaModelOta.d.ts.map +1 -0
- package/dist/gemmaModelOta.js +291 -0
- package/dist/gemmaModelOta.js.map +1 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -1
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +41 -18
- package/dist/init.js.map +1 -1
- package/dist/keepAwake.d.ts +33 -0
- package/dist/keepAwake.d.ts.map +1 -0
- package/dist/keepAwake.js +54 -0
- package/dist/keepAwake.js.map +1 -0
- package/dist/legacyRecorderProfile.d.ts +20 -0
- package/dist/legacyRecorderProfile.d.ts.map +1 -0
- package/dist/legacyRecorderProfile.js +27 -0
- package/dist/legacyRecorderProfile.js.map +1 -0
- package/dist/localInferenceSchema.d.ts +132 -0
- package/dist/localInferenceSchema.d.ts.map +1 -0
- package/dist/localInferenceSchema.js +274 -0
- package/dist/localInferenceSchema.js.map +1 -0
- package/dist/localSenseE2eHarness.d.ts +101 -0
- package/dist/localSenseE2eHarness.d.ts.map +1 -0
- package/dist/localSenseE2eHarness.js +279 -0
- package/dist/localSenseE2eHarness.js.map +1 -0
- package/dist/localSensing.d.ts +268 -0
- package/dist/localSensing.d.ts.map +1 -0
- package/dist/localSensing.js +492 -0
- package/dist/localSensing.js.map +1 -0
- package/dist/modelIntegrity.d.ts +59 -0
- package/dist/modelIntegrity.d.ts.map +1 -0
- package/dist/modelIntegrity.js +165 -0
- package/dist/modelIntegrity.js.map +1 -0
- package/dist/pairVerify.d.ts +100 -0
- package/dist/pairVerify.d.ts.map +1 -0
- package/dist/pairVerify.js +296 -0
- package/dist/pairVerify.js.map +1 -0
- package/dist/qrScanner.d.ts +33 -0
- package/dist/qrScanner.d.ts.map +1 -0
- package/dist/qrScanner.js +103 -0
- package/dist/qrScanner.js.map +1 -0
- package/dist/runtimePaths.d.ts +10 -0
- package/dist/runtimePaths.d.ts.map +1 -0
- package/dist/runtimePaths.js +79 -0
- package/dist/runtimePaths.js.map +1 -0
- package/dist/sensingRunMode.d.ts +68 -0
- package/dist/sensingRunMode.d.ts.map +1 -0
- package/dist/sensingRunMode.js +346 -0
- package/dist/sensingRunMode.js.map +1 -0
- package/dist/setupMode.d.ts +98 -0
- package/dist/setupMode.d.ts.map +1 -0
- package/dist/setupMode.js +828 -0
- package/dist/setupMode.js.map +1 -0
- package/dist/setupProgress.d.ts +31 -0
- package/dist/setupProgress.d.ts.map +1 -0
- package/dist/setupProgress.js +173 -0
- package/dist/setupProgress.js.map +1 -0
- package/package.json +13 -4
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.decodeImageToRgba = decodeImageToRgba;
|
|
40
|
+
exports.decodeQrFromImageBuffer = decodeQrFromImageBuffer;
|
|
41
|
+
exports.decodeClaimCodeFromImageFile = decodeClaimCodeFromImageFile;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const jsqr_1 = __importDefault(require("jsqr"));
|
|
44
|
+
const pngjs_1 = require("pngjs");
|
|
45
|
+
const jpeg = __importStar(require("jpeg-js"));
|
|
46
|
+
const PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47]; // "\x89PNG"
|
|
47
|
+
const JPEG_MAGIC = [0xff, 0xd8, 0xff];
|
|
48
|
+
function startsWith(buf, sig) {
|
|
49
|
+
if (buf.length < sig.length)
|
|
50
|
+
return false;
|
|
51
|
+
for (let i = 0; i < sig.length; i += 1) {
|
|
52
|
+
if (buf[i] !== sig[i])
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Decode a PNG or JPEG buffer to RGBA pixels, or null for an unsupported format
|
|
59
|
+
* (sniffed by magic bytes, not file extension, so a mislabeled file still works).
|
|
60
|
+
*/
|
|
61
|
+
function decodeImageToRgba(buf) {
|
|
62
|
+
if (startsWith(buf, PNG_MAGIC)) {
|
|
63
|
+
const png = pngjs_1.PNG.sync.read(buf); // always RGBA
|
|
64
|
+
return { data: new Uint8ClampedArray(png.data), width: png.width, height: png.height };
|
|
65
|
+
}
|
|
66
|
+
if (startsWith(buf, JPEG_MAGIC)) {
|
|
67
|
+
const img = jpeg.decode(buf, { useTArray: true, formatAsRGBA: true, maxMemoryUsageInMB: 512 });
|
|
68
|
+
return { data: new Uint8ClampedArray(img.data), width: img.width, height: img.height };
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
/** Decode the QR payload from an image buffer, or null if unsupported / no QR found. */
|
|
73
|
+
function decodeQrFromImageBuffer(buf) {
|
|
74
|
+
const img = decodeImageToRgba(buf);
|
|
75
|
+
if (!img)
|
|
76
|
+
return null;
|
|
77
|
+
const result = (0, jsqr_1.default)(img.data, img.width, img.height);
|
|
78
|
+
return result && typeof result.data === 'string' ? result.data : null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Read an image file (a PNG/JPEG screenshot or photo of the portal's claim-code
|
|
82
|
+
* QR) and return the embedded claim code. Throws a clear, owner-facing error for
|
|
83
|
+
* a missing file, an unsupported format, or an image with no QR — so the CLI can
|
|
84
|
+
* print actionable guidance instead of a stack trace.
|
|
85
|
+
*/
|
|
86
|
+
async function decodeClaimCodeFromImageFile(filePath) {
|
|
87
|
+
let buf;
|
|
88
|
+
try {
|
|
89
|
+
buf = await fs.promises.readFile(filePath);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
throw new Error(`could not read image file: ${filePath}`);
|
|
93
|
+
}
|
|
94
|
+
if (!decodeImageToRgba(buf)) {
|
|
95
|
+
throw new Error(`unsupported image format (save the QR as a PNG or JPEG): ${filePath}`);
|
|
96
|
+
}
|
|
97
|
+
const code = decodeQrFromImageBuffer(buf);
|
|
98
|
+
if (!code || !code.trim()) {
|
|
99
|
+
throw new Error(`no QR code found in image: ${filePath}`);
|
|
100
|
+
}
|
|
101
|
+
return code.trim();
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=qrScanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrScanner.js","sourceRoot":"","sources":["../src/qrScanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the FFmpeg binary for connector run modes.
|
|
3
|
+
*
|
|
4
|
+
* macOS LaunchAgents and Windows scheduled tasks can start with a minimal PATH,
|
|
5
|
+
* so the packaged connector should prefer the FFmpeg shipped beside its bundled
|
|
6
|
+
* Node runtime. Operators can still override with an explicit config/CLI path
|
|
7
|
+
* or TRILLBOARDS_FFMPEG.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveFfmpegBinaryPath(...configuredPaths: Array<string | null | undefined>): string;
|
|
10
|
+
//# sourceMappingURL=runtimePaths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimePaths.d.ts","sourceRoot":"","sources":["../src/runtimePaths.ts"],"names":[],"mappings":"AAgBA;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,eAAe,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GACnD,MAAM,CAmBR"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveFfmpegBinaryPath = resolveFfmpegBinaryPath;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const FFMPEG_BINARY = process.platform === 'win32' ? 'ffmpeg.exe' : 'ffmpeg';
|
|
40
|
+
function firstExistingFile(paths) {
|
|
41
|
+
for (const candidate of new Set(paths)) {
|
|
42
|
+
try {
|
|
43
|
+
if (fs.statSync(candidate).isFile())
|
|
44
|
+
return candidate;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// keep looking
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the FFmpeg binary for connector run modes.
|
|
54
|
+
*
|
|
55
|
+
* macOS LaunchAgents and Windows scheduled tasks can start with a minimal PATH,
|
|
56
|
+
* so the packaged connector should prefer the FFmpeg shipped beside its bundled
|
|
57
|
+
* Node runtime. Operators can still override with an explicit config/CLI path
|
|
58
|
+
* or TRILLBOARDS_FFMPEG.
|
|
59
|
+
*/
|
|
60
|
+
function resolveFfmpegBinaryPath(...configuredPaths) {
|
|
61
|
+
for (const configuredPath of configuredPaths) {
|
|
62
|
+
const trimmed = configuredPath?.trim();
|
|
63
|
+
if (trimmed)
|
|
64
|
+
return trimmed;
|
|
65
|
+
}
|
|
66
|
+
const envPath = process.env.TRILLBOARDS_FFMPEG?.trim();
|
|
67
|
+
if (envPath)
|
|
68
|
+
return envPath;
|
|
69
|
+
const bundled = firstExistingFile([
|
|
70
|
+
// Installed connector: edge/bin/node and edge/bin/ffmpeg are siblings.
|
|
71
|
+
path.join(path.dirname(process.execPath), FFMPEG_BINARY),
|
|
72
|
+
// dist/runtimePaths.js in the packaged connector: edge/lib/edge-sdk/dist.
|
|
73
|
+
path.resolve(__dirname, '../../../bin', FFMPEG_BINARY),
|
|
74
|
+
// In-package fallback for future layouts: edge-sdk/dist next to edge-sdk/bin.
|
|
75
|
+
path.resolve(__dirname, '../bin', FFMPEG_BINARY),
|
|
76
|
+
]);
|
|
77
|
+
return bundled || FFMPEG_BINARY;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=runtimePaths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtimePaths.js","sourceRoot":"","sources":["../src/runtimePaths.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,0DAqBC;AA7CD,uCAAyB;AACzB,2CAA6B;AAE7B,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;AAE7E,SAAS,iBAAiB,CAAC,KAAe;IACxC,KAAK,MAAM,SAAS,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE;gBAAE,OAAO,SAAS,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,uBAAuB,CACrC,GAAG,eAAiD;IAEpD,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,cAAc,EAAE,IAAI,EAAE,CAAC;QACvC,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;IAC9B,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IACvD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,OAAO,GAAG,iBAAiB,CAAC;QAChC,uEAAuE;QACvE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;QACxD,0EAA0E;QAC1E,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC;QACtD,8EAA8E;QAC9E,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;KACjD,CAAC,CAAC;IAEH,OAAO,OAAO,IAAI,aAAa,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { CloudSensingManager, type ResolvedFeed } from './CloudSensingManager';
|
|
2
|
+
import type { SharedFrameSource } from './MosaicSource';
|
|
3
|
+
import type { EdgeAgentConfig } from './config';
|
|
4
|
+
/**
|
|
5
|
+
* Optional cross-rail mosaic-pull sharing: the combined `sense` entrypoint passes
|
|
6
|
+
* a `sharedSources` registry so the VLM rail attaches to the SAME SharedFrameSource
|
|
7
|
+
* the on-device ONNX zoo rail uses — one RTSP pull per mosaic source feeds both.
|
|
8
|
+
*/
|
|
9
|
+
export interface SensingManagerOpts {
|
|
10
|
+
sharedSources?: Map<string, SharedFrameSource>;
|
|
11
|
+
/** Persist DHCP-recovered recorder addresses back to this local config. */
|
|
12
|
+
configPath?: string;
|
|
13
|
+
/** Reuse a caller-owned recovery coordinator across shared sensing rails. */
|
|
14
|
+
streamUrlResolver?: (feed: ResolvedFeed, currentUrl: string, error: Error) => Promise<string | null>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The lifecycle surface the auto-sense supervisor drives. `CloudSensingManager`
|
|
18
|
+
* already satisfies it: `start()` opens cameras + runs the capture loops;
|
|
19
|
+
* `stop()` clears the loop timers + closes cameras (a clean teardown that a
|
|
20
|
+
* later `start()` resumes from). Narrowed to just these two so the supervisor
|
|
21
|
+
* can hold either a real manager or a test fake.
|
|
22
|
+
*/
|
|
23
|
+
export interface SensingManager {
|
|
24
|
+
start(): Promise<void>;
|
|
25
|
+
stop(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/** A console-shaped sink so callers can capture/redirect the build-time logs. */
|
|
28
|
+
export interface SensingIo {
|
|
29
|
+
log: (msg: string) => void;
|
|
30
|
+
warn: (msg: string) => void;
|
|
31
|
+
error: (msg: string) => void;
|
|
32
|
+
}
|
|
33
|
+
/** Default sink: the real console (what the CLI entrypoints use). */
|
|
34
|
+
export declare const consoleIo: SensingIo;
|
|
35
|
+
/**
|
|
36
|
+
* The error logged (and `null` returned) when a build is attempted with no
|
|
37
|
+
* camera feeds configured. Exported so the supervisor + CLI surface the SAME
|
|
38
|
+
* message and so tests can assert on it.
|
|
39
|
+
*/
|
|
40
|
+
export declare const NO_FEEDS_MESSAGE: string;
|
|
41
|
+
/**
|
|
42
|
+
* How often the connector prints the one line that answers "why is my
|
|
43
|
+
* 16-camera store only sampling every N seconds?". Long enough not to spam a
|
|
44
|
+
* 24/7 log, short enough that an operator watching an install sees it.
|
|
45
|
+
*/
|
|
46
|
+
export declare const SENSING_HEALTH_LOG_INTERVAL_MS: number;
|
|
47
|
+
/**
|
|
48
|
+
* The operator-facing degradation line. A machine that cannot analyze 16
|
|
49
|
+
* cameras every 30 s is not a bug to hide — it is a capacity fact to state, in
|
|
50
|
+
* the terms an operator can act on: how often each camera is actually looked
|
|
51
|
+
* at, how many analyses/minute this machine sustains, and where the rest went.
|
|
52
|
+
*/
|
|
53
|
+
export declare function formatSensingHealth(health: ReturnType<CloudSensingManager['getSensingHealth']>): string;
|
|
54
|
+
/**
|
|
55
|
+
* Build (but do NOT start) the thin cloud-sensing manager: RTSP frame → POST
|
|
56
|
+
* /v2/earner/audience-analyze (cloud VLM does the inference). Returns `null`
|
|
57
|
+
* after logging NO_FEEDS_MESSAGE when no feeds are configured — the caller
|
|
58
|
+
* decides how to surface that (the CLI + the supervisor both exit 1).
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildCloudSensingManager(config: EdgeAgentConfig, io?: SensingIo, opts?: SensingManagerOpts): CloudSensingManager | null;
|
|
61
|
+
/**
|
|
62
|
+
* Build (but do NOT start) the on-device LOCAL-sensing manager: RTSP frame →
|
|
63
|
+
* LOCAL VLM (LiteRT-LM serving Gemma) → POST the STRUCTURED result as
|
|
64
|
+
* `preAnalyzed` (skips the cloud VLM → no Vertex cost). Returns `null` after
|
|
65
|
+
* logging NO_FEEDS_MESSAGE when no feeds are configured.
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildLocalSensingManager(config: EdgeAgentConfig, io?: SensingIo, opts?: SensingManagerOpts): CloudSensingManager | null;
|
|
68
|
+
//# sourceMappingURL=sensingRunMode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensingRunMode.d.ts","sourceRoot":"","sources":["../src/sensingRunMode.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EAInB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMhD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC/C,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,CAClB,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,KAAK,KACT,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC7B;AA2CD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,qEAAqE;AACrE,eAAO,MAAM,SAAS,EAAE,SAIvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAEgD,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,QAAgB,CAAC;AA4C5D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,GAC1D,MAAM,CAqBR;AAoDD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAE,SAAqB,EACzB,IAAI,CAAC,EAAE,kBAAkB,GACxB,mBAAmB,GAAG,IAAI,CA6D5B;AAqCD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAE,SAAqB,EACzB,IAAI,CAAC,EAAE,kBAAkB,GACxB,mBAAmB,GAAG,IAAI,CAmF5B"}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SENSING_HEALTH_LOG_INTERVAL_MS = exports.NO_FEEDS_MESSAGE = exports.consoleIo = void 0;
|
|
4
|
+
exports.formatSensingHealth = formatSensingHealth;
|
|
5
|
+
exports.buildCloudSensingManager = buildCloudSensingManager;
|
|
6
|
+
exports.buildLocalSensingManager = buildLocalSensingManager;
|
|
7
|
+
const CloudSensingManager_1 = require("./CloudSensingManager");
|
|
8
|
+
const localSensing_1 = require("./localSensing");
|
|
9
|
+
const SensingProfileClient_1 = require("./SensingProfileClient");
|
|
10
|
+
const deployedCadenceSource_1 = require("./deployedCadenceSource");
|
|
11
|
+
const RecorderAddressRecovery_1 = require("./RecorderAddressRecovery");
|
|
12
|
+
/**
|
|
13
|
+
* Shared construction of the cloud- and local-sensing managers.
|
|
14
|
+
*
|
|
15
|
+
* Both the explicit `cloud-sense` / `local-sense` CLI entrypoints AND the
|
|
16
|
+
* `auto-sense` supervisor build their managers through here, so there is exactly
|
|
17
|
+
* ONE place that wires an EdgeAgentConfig → a real `CloudSensingManager` (loops +
|
|
18
|
+
* cadence + event logging). The supervisor starts/stops the SAME real managers
|
|
19
|
+
* the explicit modes use — no parallel sensing implementation.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* One profile client per feed, so the connector can ask what cadence its
|
|
23
|
+
* operator actually deployed. Each feed's device token binds to its own screen,
|
|
24
|
+
* so this is N clients, not one — the same shape local sensing already uses to
|
|
25
|
+
* fetch each screen's custom fields.
|
|
26
|
+
*
|
|
27
|
+
* Returns undefined when nothing can be asked (no feed carries a device token),
|
|
28
|
+
* which leaves the manager on its constructor cadence exactly as before.
|
|
29
|
+
*/
|
|
30
|
+
function cadenceSourceFor(config, feeds, mode) {
|
|
31
|
+
const profileClients = feeds
|
|
32
|
+
.filter((f) => !!f.deviceToken)
|
|
33
|
+
.map((f) => new SensingProfileClient_1.SensingProfileClient({
|
|
34
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
35
|
+
deviceToken: f.deviceToken,
|
|
36
|
+
}));
|
|
37
|
+
return (0, deployedCadenceSource_1.buildDeployedCadenceSource)({
|
|
38
|
+
profileClients,
|
|
39
|
+
mode,
|
|
40
|
+
feedCount: feeds.length,
|
|
41
|
+
monthlyBudgetUsdPerCamera: config.cloudSensing?.monthlyBudgetUsdPerCamera,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const DEFAULT_LITERT_LM_BASE_URL = 'http://localhost:9379';
|
|
45
|
+
const DEFAULT_LITERT_LM_MODEL = 'gemma-4-E2B-it.litertlm';
|
|
46
|
+
/** Default sink: the real console (what the CLI entrypoints use). */
|
|
47
|
+
exports.consoleIo = {
|
|
48
|
+
log: (m) => console.log(m),
|
|
49
|
+
warn: (m) => console.warn(m),
|
|
50
|
+
error: (m) => console.error(m),
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The error logged (and `null` returned) when a build is attempted with no
|
|
54
|
+
* camera feeds configured. Exported so the supervisor + CLI surface the SAME
|
|
55
|
+
* message and so tests can assert on it.
|
|
56
|
+
*/
|
|
57
|
+
exports.NO_FEEDS_MESSAGE = 'No camera feeds configured. Set `cameras: [{ name, screenId, deviceToken, rtspUrl }]` ' +
|
|
58
|
+
'for multi-channel, or `camera.rtspUrl` + `deviceToken` for a single feed.';
|
|
59
|
+
/**
|
|
60
|
+
* How often the connector prints the one line that answers "why is my
|
|
61
|
+
* 16-camera store only sampling every N seconds?". Long enough not to spam a
|
|
62
|
+
* 24/7 log, short enough that an operator watching an install sees it.
|
|
63
|
+
*/
|
|
64
|
+
exports.SENSING_HEALTH_LOG_INTERVAL_MS = 5 * 60 * 1000;
|
|
65
|
+
const CADENCE_CLAMP_WORDING = {
|
|
66
|
+
no_request: '',
|
|
67
|
+
operator_request: '',
|
|
68
|
+
cloud_cost_budget: 'cloud spend budget',
|
|
69
|
+
local_inference_budget: 'this machine\'s single inference slot',
|
|
70
|
+
look_interval: 'the connector never looks that often',
|
|
71
|
+
cadence_ceiling: 'a capture loop cannot run a cadence that slow',
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* The deployed-cadence fragment of the capacity line.
|
|
75
|
+
*
|
|
76
|
+
* `resolveDeployedCadence` exists to make a clamp legible instead of silent, and
|
|
77
|
+
* `getSensingHealth()` duly returns the whole verdict — but this formatter, the
|
|
78
|
+
* ONLY thing in the connector that a human ever reads, dropped it. An operator
|
|
79
|
+
* who set "every 30 seconds" in the portal and is being run at 303 saw a line
|
|
80
|
+
* about analyses/minute and nothing at all about the 10x gap or its reason. A
|
|
81
|
+
* clamp nobody is told about is a silent clamp however carefully the verdict
|
|
82
|
+
* that produced it was modelled.
|
|
83
|
+
*
|
|
84
|
+
* The projected bill rides along whenever the cloud path knows it, clamped or
|
|
85
|
+
* not: "what is this camera costing me" is the other question this number is
|
|
86
|
+
* the only answer to.
|
|
87
|
+
*/
|
|
88
|
+
function formatDeployedCadence(cadence) {
|
|
89
|
+
if (!cadence || cadence.intervalMs === null)
|
|
90
|
+
return [];
|
|
91
|
+
const secs = (ms) => `${(ms / 1000).toFixed(0)}s`;
|
|
92
|
+
const parts = [];
|
|
93
|
+
if (cadence.clamped && cadence.requestedMs !== null) {
|
|
94
|
+
parts.push(`deployed ${secs(cadence.requestedMs)} → running ${secs(cadence.intervalMs)} ` +
|
|
95
|
+
`(${CADENCE_CLAMP_WORDING[cadence.reason] || cadence.reason})`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
parts.push(`deployed cadence ${secs(cadence.intervalMs)}`);
|
|
99
|
+
}
|
|
100
|
+
if (cadence.estimatedMonthlyUsdPerCamera !== null) {
|
|
101
|
+
parts.push(`~$${cadence.estimatedMonthlyUsdPerCamera.toFixed(0)}/camera/month`);
|
|
102
|
+
}
|
|
103
|
+
return parts;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The operator-facing degradation line. A machine that cannot analyze 16
|
|
107
|
+
* cameras every 30 s is not a bug to hide — it is a capacity fact to state, in
|
|
108
|
+
* the terms an operator can act on: how often each camera is actually looked
|
|
109
|
+
* at, how many analyses/minute this machine sustains, and where the rest went.
|
|
110
|
+
*/
|
|
111
|
+
function formatSensingHealth(health) {
|
|
112
|
+
const perCamera = health.effectiveSampleIntervalMs === null
|
|
113
|
+
? 'no analyses yet'
|
|
114
|
+
: `every ${(health.effectiveSampleIntervalMs / 1000).toFixed(0)}s per camera`;
|
|
115
|
+
const parts = [
|
|
116
|
+
`${health.loops} feed${health.loops === 1 ? '' : 's'}`,
|
|
117
|
+
`sampling ${perCamera}`,
|
|
118
|
+
`sustained ${health.analysesPerMinute.toFixed(1)} analyses/min (cap ${health.maxConcurrentAnalyses} concurrent)`,
|
|
119
|
+
];
|
|
120
|
+
if (health.motionSkipped > 0)
|
|
121
|
+
parts.push(`${health.motionSkipped} skipped (no change)`);
|
|
122
|
+
if (health.admissionDenied > 0)
|
|
123
|
+
parts.push(`${health.admissionDenied} deferred (model busy)`);
|
|
124
|
+
parts.push(...formatDeployedCadence(health.deployedCadence));
|
|
125
|
+
// Frames that LEFT the premises for cloud confirmation. Printed whenever
|
|
126
|
+
// escalation is on — including at zero — because "how many frames left" is a
|
|
127
|
+
// question an operator must be able to answer from the log, and an absent
|
|
128
|
+
// line reads as "none" whether or not the feature is even running.
|
|
129
|
+
if (health.cloudEscalationEnabled) {
|
|
130
|
+
parts.push(`${health.cloudEscalated} escalated to cloud (confirming alerts)`);
|
|
131
|
+
}
|
|
132
|
+
return `[sensing] ${parts.join(' · ')}`;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Wire the manager's lifecycle events to the IO sink — identical for both modes
|
|
136
|
+
* except the per-frame "analyzed" line (cloud says `analyze →`, local says
|
|
137
|
+
* `local→preAnalyzed →`).
|
|
138
|
+
*
|
|
139
|
+
* The cascade's per-frame outcomes (`motionSkipped`, `admissionDenied`) are
|
|
140
|
+
* deliberately NOT logged per event: on a saturated 16-camera connector they
|
|
141
|
+
* would be tens of thousands of lines a day and would bury the events that
|
|
142
|
+
* need a human. They stay on the EventEmitter for embedders, and reach the
|
|
143
|
+
* operator as counts on the periodic capacity line below.
|
|
144
|
+
*/
|
|
145
|
+
function wireSensingLogs(manager, io, analyzedLine) {
|
|
146
|
+
manager.on('analyzed', ({ name, response }) => {
|
|
147
|
+
io.log(analyzedLine(name, response));
|
|
148
|
+
});
|
|
149
|
+
manager.on('reconnecting', ({ name, delayMs }) => {
|
|
150
|
+
io.warn(`[${name}] RTSP down — re-opening (next retry in ${delayMs}ms)…`);
|
|
151
|
+
});
|
|
152
|
+
manager.on('reconnected', ({ name }) => {
|
|
153
|
+
io.log(`[${name}] RTSP reconnected — sensing resumed`);
|
|
154
|
+
});
|
|
155
|
+
manager.on('error', ({ name, error }) => {
|
|
156
|
+
io.error(`[${name}] error: ${error.message}`);
|
|
157
|
+
});
|
|
158
|
+
// Periodic capacity line. `unref()` so it can never hold the process open.
|
|
159
|
+
const timer = setInterval(() => {
|
|
160
|
+
if (!manager.isRunning())
|
|
161
|
+
return;
|
|
162
|
+
io.log(formatSensingHealth(manager.getSensingHealth()));
|
|
163
|
+
}, exports.SENSING_HEALTH_LOG_INTERVAL_MS);
|
|
164
|
+
if (typeof timer.unref === 'function')
|
|
165
|
+
timer.unref();
|
|
166
|
+
}
|
|
167
|
+
/** Print the per-feed startup banner (the lines the CLI used to print inline). */
|
|
168
|
+
function logFeedBanner(io, header, feeds) {
|
|
169
|
+
for (const line of header)
|
|
170
|
+
io.log(line);
|
|
171
|
+
io.log(` Feeds: ${feeds.length}`);
|
|
172
|
+
for (const f of feeds) {
|
|
173
|
+
io.log(` - ${f.name}${f.screenId ? ` (screen ${f.screenId})` : ''}`);
|
|
174
|
+
}
|
|
175
|
+
io.log('');
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Build (but do NOT start) the thin cloud-sensing manager: RTSP frame → POST
|
|
179
|
+
* /v2/earner/audience-analyze (cloud VLM does the inference). Returns `null`
|
|
180
|
+
* after logging NO_FEEDS_MESSAGE when no feeds are configured — the caller
|
|
181
|
+
* decides how to surface that (the CLI + the supervisor both exit 1).
|
|
182
|
+
*/
|
|
183
|
+
function buildCloudSensingManager(config, io = exports.consoleIo, opts) {
|
|
184
|
+
const feeds = (0, CloudSensingManager_1.resolveFeeds)(config);
|
|
185
|
+
if (feeds.length === 0) {
|
|
186
|
+
io.error(exports.NO_FEEDS_MESSAGE);
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
logFeedBanner(io, [` API: ${config.apiBaseUrl}`], feeds);
|
|
190
|
+
const addressRecovery = opts?.streamUrlResolver
|
|
191
|
+
? null
|
|
192
|
+
: new RecorderAddressRecovery_1.RecorderAddressRecovery(config, {
|
|
193
|
+
configPath: opts?.configPath,
|
|
194
|
+
log: (message) => io.warn(message),
|
|
195
|
+
});
|
|
196
|
+
const loops = (0, CloudSensingManager_1.buildSensingLoops)(config, {
|
|
197
|
+
sharedSources: opts?.sharedSources,
|
|
198
|
+
streamUrlResolver: (feed, currentUrl, error) => opts?.streamUrlResolver?.(feed, currentUrl, error) ??
|
|
199
|
+
addressRecovery.recover(feed, currentUrl, error),
|
|
200
|
+
});
|
|
201
|
+
const manager = new CloudSensingManager_1.CloudSensingManager({
|
|
202
|
+
loops,
|
|
203
|
+
periodicIntervalMs: config.cloudSensing?.periodicIntervalMs,
|
|
204
|
+
faceTriggeredIntervalMs: config.cloudSensing?.faceTriggeredIntervalMs,
|
|
205
|
+
jpegQuality: config.cloudSensing?.jpegQuality,
|
|
206
|
+
// The cadence the operator deployed from the portal, re-asked on the profile
|
|
207
|
+
// TTL so it reaches a RUNNING connector. Clamped by the cloud spend budget —
|
|
208
|
+
// see deployedCadence. Before this the cloud path made NO config-bearing
|
|
209
|
+
// server call after start(), so a portal cadence change reached it never.
|
|
210
|
+
cadenceSource: cadenceSourceFor(config, feeds, 'cloud'),
|
|
211
|
+
// Thin mode: no local face detector drives face state, so POST on the
|
|
212
|
+
// periodic cadence (the cloud VLM does the inference). Honor an explicit
|
|
213
|
+
// opt-in to face-gating if the operator wires an edge motion gate.
|
|
214
|
+
skipPostWhenNoFaces: config.cloudSensing?.skipPostWhenNoFaces ?? false,
|
|
215
|
+
width: config.camera?.width,
|
|
216
|
+
height: config.camera?.height,
|
|
217
|
+
// Self-recover from RTSP drops (retry forever, bounded exponential backoff).
|
|
218
|
+
reconnectInitialDelayMs: config.cloudSensing?.reconnectInitialDelayMs,
|
|
219
|
+
reconnectMaxDelayMs: config.cloudSensing?.reconnectMaxDelayMs,
|
|
220
|
+
// Phase multi-camera loops apart so one connector does not stampede an NVR.
|
|
221
|
+
feedStaggerMs: config.cloudSensing?.feedStaggerMs,
|
|
222
|
+
maxFeedStaggerMs: config.cloudSensing?.maxFeedStaggerMs,
|
|
223
|
+
cameraHealthFailureGraceCount: config.cloudSensing?.cameraHealthFailureGraceCount,
|
|
224
|
+
// The cloud VLM is genuinely concurrent, so admission stays wide open
|
|
225
|
+
// unless the operator narrows it — no behavior change for cloud sensing.
|
|
226
|
+
maxConcurrentAnalyses: config.cloudSensing?.maxConcurrentAnalyses,
|
|
227
|
+
maxAnalysisInFlightMs: config.cloudSensing?.maxAnalysisInFlightMs,
|
|
228
|
+
admissionRetryDelayMs: config.cloudSensing?.admissionRetryDelayMs,
|
|
229
|
+
// Motion cascade is OPT-IN here: cloud has no single-instance ceiling to
|
|
230
|
+
// relieve, and looking more often would raise the per-call bill instead of
|
|
231
|
+
// throughput. Local sensing enables it by default (see below).
|
|
232
|
+
motionGate: resolveMotionGateOptions(config, false),
|
|
233
|
+
});
|
|
234
|
+
wireSensingLogs(manager, io, (name, response) => `[${name}] analyze → HTTP ${response.statusCode}${response.ok ? '' : ' (NOT OK)'}`);
|
|
235
|
+
return manager;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Resolve the motion-cascade options for a run mode, or `undefined` when the
|
|
239
|
+
* cascade is off. `enabledByDefault` differs by mode; an explicit
|
|
240
|
+
* `cloudSensing.motionGate.enabled` always wins.
|
|
241
|
+
*/
|
|
242
|
+
function resolveMotionGateOptions(config, enabledByDefault) {
|
|
243
|
+
const configured = config.cloudSensing?.motionGate;
|
|
244
|
+
const enabled = configured?.enabled ?? enabledByDefault;
|
|
245
|
+
if (!enabled)
|
|
246
|
+
return undefined;
|
|
247
|
+
return {
|
|
248
|
+
enabled: true,
|
|
249
|
+
...(configured?.scanIntervalMs !== undefined
|
|
250
|
+
? { scanIntervalMs: configured.scanIntervalMs }
|
|
251
|
+
: {}),
|
|
252
|
+
...(configured?.heartbeatIntervalMs !== undefined
|
|
253
|
+
? { heartbeatIntervalMs: configured.heartbeatIntervalMs }
|
|
254
|
+
: {}),
|
|
255
|
+
...(configured?.minAnalyzeIntervalMs !== undefined
|
|
256
|
+
? { minAnalyzeIntervalMs: configured.minAnalyzeIntervalMs }
|
|
257
|
+
: {}),
|
|
258
|
+
...(configured?.frameHeight !== undefined ? { frameHeight: configured.frameHeight } : {}),
|
|
259
|
+
...(configured?.threshold !== undefined ? { threshold: configured.threshold } : {}),
|
|
260
|
+
...(configured?.contourArea !== undefined ? { contourArea: configured.contourArea } : {}),
|
|
261
|
+
...(configured?.lightningThreshold !== undefined
|
|
262
|
+
? { lightningThreshold: configured.lightningThreshold }
|
|
263
|
+
: {}),
|
|
264
|
+
...(configured?.stationaryReanalyzeEvery !== undefined
|
|
265
|
+
? { stationaryReanalyzeEvery: configured.stationaryReanalyzeEvery }
|
|
266
|
+
: {}),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Build (but do NOT start) the on-device LOCAL-sensing manager: RTSP frame →
|
|
271
|
+
* LOCAL VLM (LiteRT-LM serving Gemma) → POST the STRUCTURED result as
|
|
272
|
+
* `preAnalyzed` (skips the cloud VLM → no Vertex cost). Returns `null` after
|
|
273
|
+
* logging NO_FEEDS_MESSAGE when no feeds are configured.
|
|
274
|
+
*/
|
|
275
|
+
function buildLocalSensingManager(config, io = exports.consoleIo, opts) {
|
|
276
|
+
const feeds = (0, CloudSensingManager_1.resolveFeeds)(config);
|
|
277
|
+
if (feeds.length === 0) {
|
|
278
|
+
io.error(exports.NO_FEEDS_MESSAGE);
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
const litertLm = config.localSensing?.litertLmBaseUrl || DEFAULT_LITERT_LM_BASE_URL;
|
|
282
|
+
const model = config.localSensing?.model || DEFAULT_LITERT_LM_MODEL;
|
|
283
|
+
// The delegate is resolved by LiteRtVlmProvider at first inference (it reads
|
|
284
|
+
// /v1/models and prefers the `,gpu` variant) and logged there — the banner
|
|
285
|
+
// reports the POLICY so a pinned 'cpu' is visible at startup.
|
|
286
|
+
const accelerator = config.localSensing?.accelerator || 'auto';
|
|
287
|
+
// State the egress posture at startup, in both directions. "Nothing leaves
|
|
288
|
+
// your premises" is only true of the on-device path, so an operator must see
|
|
289
|
+
// which one they are running BEFORE the first frame, not discover it in a log
|
|
290
|
+
// line an hour later.
|
|
291
|
+
// isCloudEscalationEnabled is the SAME expression LocalSensingClient enforces
|
|
292
|
+
// (it also honors attachEvidenceFrame:false), so this line can never announce
|
|
293
|
+
// an egress posture the connector is not actually running.
|
|
294
|
+
const escalation = config.localSensing?.cloudEscalation;
|
|
295
|
+
const escalationLine = (0, localSensing_1.isCloudEscalationEnabled)(config.localSensing)
|
|
296
|
+
? ` Escalation: ON — a flagged frame is sent to the cloud VLM to confirm an alert ` +
|
|
297
|
+
`(max ${escalation?.maxPerHour ?? 12}/hour per camera)`
|
|
298
|
+
: ' Escalation: off — every frame is analyzed on this machine';
|
|
299
|
+
logFeedBanner(io, [
|
|
300
|
+
` API: ${config.apiBaseUrl}`,
|
|
301
|
+
` LiteRT-LM: ${litertLm} (model ${model}, accelerator ${accelerator})`,
|
|
302
|
+
escalationLine,
|
|
303
|
+
], feeds);
|
|
304
|
+
const addressRecovery = opts?.streamUrlResolver
|
|
305
|
+
? null
|
|
306
|
+
: new RecorderAddressRecovery_1.RecorderAddressRecovery(config, {
|
|
307
|
+
configPath: opts?.configPath,
|
|
308
|
+
log: (message) => io.warn(message),
|
|
309
|
+
});
|
|
310
|
+
const loops = (0, localSensing_1.buildLocalSensingLoops)(config, {
|
|
311
|
+
sharedSources: opts?.sharedSources,
|
|
312
|
+
streamUrlResolver: (feed, currentUrl, error) => opts?.streamUrlResolver?.(feed, currentUrl, error) ??
|
|
313
|
+
addressRecovery.recover(feed, currentUrl, error),
|
|
314
|
+
});
|
|
315
|
+
const manager = new CloudSensingManager_1.CloudSensingManager({
|
|
316
|
+
loops,
|
|
317
|
+
periodicIntervalMs: config.localSensing?.captureIntervalMs ?? config.cloudSensing?.periodicIntervalMs,
|
|
318
|
+
faceTriggeredIntervalMs: config.cloudSensing?.faceTriggeredIntervalMs,
|
|
319
|
+
// Same deployed cadence, clamped instead by the single local inference slot
|
|
320
|
+
// (connectorCadence's measured 7.30 s/frame ceiling) rather than by money.
|
|
321
|
+
cadenceSource: cadenceSourceFor(config, feeds, 'local'),
|
|
322
|
+
// Local inference has no cloud cost → POST every periodic frame.
|
|
323
|
+
skipPostWhenNoFaces: false,
|
|
324
|
+
width: config.camera?.width,
|
|
325
|
+
height: config.camera?.height,
|
|
326
|
+
// Self-recover from RTSP drops (retry forever, bounded exponential backoff).
|
|
327
|
+
reconnectInitialDelayMs: config.cloudSensing?.reconnectInitialDelayMs,
|
|
328
|
+
reconnectMaxDelayMs: config.cloudSensing?.reconnectMaxDelayMs,
|
|
329
|
+
// Same RTSP/NVR friendliness as cloud mode; local VLM only changes analysis.
|
|
330
|
+
feedStaggerMs: config.cloudSensing?.feedStaggerMs,
|
|
331
|
+
maxFeedStaggerMs: config.cloudSensing?.maxFeedStaggerMs,
|
|
332
|
+
cameraHealthFailureGraceCount: config.cloudSensing?.cameraHealthFailureGraceCount,
|
|
333
|
+
// `litert-lm serve` takes ONE conversation at a time. Without this gate N
|
|
334
|
+
// feeds pile onto it, frames age against the provider's 120 s timeout, and
|
|
335
|
+
// each failure burns retries — 16 cameras produce ~17x the work the server
|
|
336
|
+
// can do. One slot, shared by every feed, drop-not-queue.
|
|
337
|
+
maxConcurrentAnalyses: config.cloudSensing?.maxConcurrentAnalyses ?? 1,
|
|
338
|
+
maxAnalysisInFlightMs: config.cloudSensing?.maxAnalysisInFlightMs,
|
|
339
|
+
admissionRetryDelayMs: config.cloudSensing?.admissionRetryDelayMs,
|
|
340
|
+
// …and don't spend that one slot on an empty aisle: the cascade decides.
|
|
341
|
+
motionGate: resolveMotionGateOptions(config, true),
|
|
342
|
+
});
|
|
343
|
+
wireSensingLogs(manager, io, (name, response) => `[${name}] local→preAnalyzed → HTTP ${response.statusCode}${response.ok ? '' : ' (NOT OK)'}`);
|
|
344
|
+
return manager;
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=sensingRunMode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensingRunMode.js","sourceRoot":"","sources":["../src/sensingRunMode.ts"],"names":[],"mappings":"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"}
|