@trillboards/edge-sdk 0.2.3 → 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 +122 -65
- 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,106 @@
|
|
|
1
|
+
import { type HttpPoster } from './AudienceAnalyzeClient';
|
|
2
|
+
import type { EdgeAgentConfig, MosaicTile } from './config';
|
|
3
|
+
/**
|
|
4
|
+
* PairClient — exchanges a short-TTL claim code for the connector's full
|
|
5
|
+
* config via `POST {apiBaseUrl}/v2/earner/cameras/pair`.
|
|
6
|
+
*
|
|
7
|
+
* This is the security conduit for the one-click installer: the device token
|
|
8
|
+
* is NEVER baked into the downloadable binary. Instead the operator generates
|
|
9
|
+
* a claim code in the portal (bound to the camera screens they just
|
|
10
|
+
* provisioned), the installer asks for that code once on first run, and this
|
|
11
|
+
* client trades it for `{ apiBaseUrl, cloudSensing, cameras: [{ screenId,
|
|
12
|
+
* deviceToken, rtspUrl? }] }` — which is written verbatim to
|
|
13
|
+
* trillboards.config.json.
|
|
14
|
+
*
|
|
15
|
+
* The claim code IS the credential, so the request carries NO device-token
|
|
16
|
+
* headers (mirrors the unauthenticated, rate-limited
|
|
17
|
+
* `POST /v2/mdm/enrollment/device` enrollment endpoint). Uses the same
|
|
18
|
+
* built-in-http poster as AudienceAnalyzeClient (no extra dep → survives
|
|
19
|
+
* bundling into a self-contained binary; trivially mockable in tests).
|
|
20
|
+
*/
|
|
21
|
+
export interface PairClientOptions {
|
|
22
|
+
/** Base URL, e.g. https://api.trillboards.com (no trailing slash needed). */
|
|
23
|
+
apiBaseUrl: string;
|
|
24
|
+
/** Request timeout in ms. Default: 30000. */
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface PairRequest {
|
|
28
|
+
/** The claim code from the portal (with or without the XXXX-XXXX dash). */
|
|
29
|
+
claimCode: string;
|
|
30
|
+
/** Stable per-host fingerprint, sent for correlation/audit. Optional. */
|
|
31
|
+
deviceFingerprint?: string;
|
|
32
|
+
/** Connector version string, for server-side compat checks. Optional. */
|
|
33
|
+
connectorVersion?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The config the server returns for a valid claim code — exactly the shape the
|
|
37
|
+
* connector persists to trillboards.config.json and then runs `cloud-sense`
|
|
38
|
+
* against. `rtspUrl` is OPTIONAL per camera: the portal MAY deliver it
|
|
39
|
+
* (stored encrypted) or the operator enters it locally so credentials never
|
|
40
|
+
* leave the venue.
|
|
41
|
+
*/
|
|
42
|
+
export interface PairedConfig {
|
|
43
|
+
apiBaseUrl: string;
|
|
44
|
+
cloudSensing: {
|
|
45
|
+
enabled: true;
|
|
46
|
+
periodicIntervalMs?: number;
|
|
47
|
+
faceTriggeredIntervalMs?: number;
|
|
48
|
+
jpegQuality?: number;
|
|
49
|
+
feedStaggerMs?: number;
|
|
50
|
+
maxFeedStaggerMs?: number;
|
|
51
|
+
cameraHealthFailureGraceCount?: number;
|
|
52
|
+
};
|
|
53
|
+
cameras: Array<{
|
|
54
|
+
name: string;
|
|
55
|
+
screenId: string;
|
|
56
|
+
deviceToken: string;
|
|
57
|
+
rtspUrl?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Mosaic tiling (carve one composite/quad RTSP into per-screen tiles).
|
|
60
|
+
* `id` marks a SOURCE feed (carries the rtspUrl); `sourceFeedId` points a
|
|
61
|
+
* tile at that source so it shares the single RTSP pull; `tile` is the crop
|
|
62
|
+
* rect (source pixels). All optional — absent for whole-frame feeds. These
|
|
63
|
+
* MUST survive pairing or a DVR-mosaic feed can't be split into N screens.
|
|
64
|
+
*/
|
|
65
|
+
id?: string;
|
|
66
|
+
sourceFeedId?: string;
|
|
67
|
+
tile?: MosaicTile;
|
|
68
|
+
width?: number;
|
|
69
|
+
height?: number;
|
|
70
|
+
fps?: number;
|
|
71
|
+
transport?: 'tcp' | 'udp';
|
|
72
|
+
}>;
|
|
73
|
+
}
|
|
74
|
+
export interface PairResponse {
|
|
75
|
+
/** HTTP status code. */
|
|
76
|
+
statusCode: number;
|
|
77
|
+
/** Whether pairing succeeded (2xx with a usable config). */
|
|
78
|
+
ok: boolean;
|
|
79
|
+
/** The connector config to persist, when ok. */
|
|
80
|
+
config: PairedConfig | null;
|
|
81
|
+
/** Server error code/message when not ok (e.g. INVALID_CODE, EXPIRED_CODE). */
|
|
82
|
+
error?: string;
|
|
83
|
+
/** Raw response text. */
|
|
84
|
+
rawBody: string;
|
|
85
|
+
}
|
|
86
|
+
/** Normalize a user-entered claim code: strip spaces/dashes, upper-case. */
|
|
87
|
+
export declare function normalizeClaimCode(code: string): string;
|
|
88
|
+
export declare class PairClient {
|
|
89
|
+
private readonly endpoint;
|
|
90
|
+
private readonly timeoutMs;
|
|
91
|
+
private readonly poster;
|
|
92
|
+
constructor(options: PairClientOptions, poster?: HttpPoster);
|
|
93
|
+
/** The resolved POST URL (exposed for assertions / logging). */
|
|
94
|
+
getEndpoint(): string;
|
|
95
|
+
/** Exchange a claim code for the connector config. */
|
|
96
|
+
pair(request: PairRequest): Promise<PairResponse>;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Validate + shape the server payload into a PairedConfig. Accepts either the
|
|
100
|
+
* config at the top level or nested under `config`. Requires at least one
|
|
101
|
+
* camera with a screenId + deviceToken (rtspUrl optional — creds-local mode).
|
|
102
|
+
*/
|
|
103
|
+
export declare function extractPairedConfig(body: Record<string, unknown> | null): PairedConfig | null;
|
|
104
|
+
/** Build the EdgeAgentConfig-compatible object written to disk after pairing. */
|
|
105
|
+
export declare function pairedConfigToFile(config: PairedConfig): Partial<EdgeAgentConfig>;
|
|
106
|
+
//# sourceMappingURL=PairClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PairClient.d.ts","sourceRoot":"","sources":["../src/PairClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE5D;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE;QACZ,OAAO,EAAE,IAAI,CAAC;QACd,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,uBAAuB,CAAC,EAAE,MAAM,CAAC;QACjC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,6BAA6B,CAAC,EAAE,MAAM,CAAC;KACxC,CAAC;IACF,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB;;;;;;WAMG;QACH,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,UAAU,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;KAC3B,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,EAAE,EAAE,OAAO,CAAC;IACZ,gDAAgD;IAChD,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,UAAU;IAU3D,gEAAgE;IAChE,WAAW,IAAI,MAAM;IAIrB,sDAAsD;IAChD,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAwDxD;AAoBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACnC,YAAY,GAAG,IAAI,CA8DrB;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAqBjF"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PairClient = void 0;
|
|
4
|
+
exports.normalizeClaimCode = normalizeClaimCode;
|
|
5
|
+
exports.extractPairedConfig = extractPairedConfig;
|
|
6
|
+
exports.pairedConfigToFile = pairedConfigToFile;
|
|
7
|
+
const AudienceAnalyzeClient_1 = require("./AudienceAnalyzeClient");
|
|
8
|
+
/** Normalize a user-entered claim code: strip spaces/dashes, upper-case. */
|
|
9
|
+
function normalizeClaimCode(code) {
|
|
10
|
+
return String(code || '')
|
|
11
|
+
.replace(/[\s-]+/g, '')
|
|
12
|
+
.toUpperCase();
|
|
13
|
+
}
|
|
14
|
+
class PairClient {
|
|
15
|
+
constructor(options, poster) {
|
|
16
|
+
if (!options.apiBaseUrl) {
|
|
17
|
+
throw new Error('apiBaseUrl is required for PairClient');
|
|
18
|
+
}
|
|
19
|
+
const base = options.apiBaseUrl.replace(/\/+$/, '');
|
|
20
|
+
this.endpoint = `${base}/v2/earner/cameras/pair`;
|
|
21
|
+
this.timeoutMs = options.timeoutMs ?? 30000;
|
|
22
|
+
this.poster = poster ?? AudienceAnalyzeClient_1.defaultHttpPoster;
|
|
23
|
+
}
|
|
24
|
+
/** The resolved POST URL (exposed for assertions / logging). */
|
|
25
|
+
getEndpoint() {
|
|
26
|
+
return this.endpoint;
|
|
27
|
+
}
|
|
28
|
+
/** Exchange a claim code for the connector config. */
|
|
29
|
+
async pair(request) {
|
|
30
|
+
const claimCode = normalizeClaimCode(request?.claimCode);
|
|
31
|
+
if (!claimCode) {
|
|
32
|
+
throw new Error('pair() requires a non-empty claimCode');
|
|
33
|
+
}
|
|
34
|
+
const payload = {
|
|
35
|
+
claimCode,
|
|
36
|
+
...(request.deviceFingerprint ? { deviceFingerprint: request.deviceFingerprint } : {}),
|
|
37
|
+
...(request.connectorVersion ? { connectorVersion: request.connectorVersion } : {}),
|
|
38
|
+
};
|
|
39
|
+
const result = await this.poster(this.endpoint, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
42
|
+
timeoutMs: this.timeoutMs,
|
|
43
|
+
}, JSON.stringify(payload));
|
|
44
|
+
let parsed = null;
|
|
45
|
+
try {
|
|
46
|
+
parsed = result.body ? JSON.parse(result.body) : null;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
parsed = null;
|
|
50
|
+
}
|
|
51
|
+
const ok = result.statusCode >= 200 && result.statusCode < 300;
|
|
52
|
+
if (!ok) {
|
|
53
|
+
return {
|
|
54
|
+
statusCode: result.statusCode,
|
|
55
|
+
ok: false,
|
|
56
|
+
config: null,
|
|
57
|
+
error: (parsed && parsed.error) ||
|
|
58
|
+
(parsed && parsed.message) ||
|
|
59
|
+
`pair failed (HTTP ${result.statusCode})`,
|
|
60
|
+
rawBody: result.body,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const config = extractPairedConfig(parsed);
|
|
64
|
+
if (!config) {
|
|
65
|
+
return {
|
|
66
|
+
statusCode: result.statusCode,
|
|
67
|
+
ok: false,
|
|
68
|
+
config: null,
|
|
69
|
+
error: 'pair response did not contain a usable camera config',
|
|
70
|
+
rawBody: result.body,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { statusCode: result.statusCode, ok: true, config, rawBody: result.body };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.PairClient = PairClient;
|
|
77
|
+
/**
|
|
78
|
+
* Sanitize a mosaic tile rectangle (source pixels) → { x, y, w, h } with
|
|
79
|
+
* non-negative integer offsets + positive integer dimensions, or null when the
|
|
80
|
+
* shape is absent/invalid. Mirrors the server-side cameraClaimCodeService
|
|
81
|
+
* sanitizeTile so a malformed rect never reaches the connector's ffmpeg crop.
|
|
82
|
+
*/
|
|
83
|
+
function sanitizeTile(tile) {
|
|
84
|
+
if (!tile || typeof tile !== 'object')
|
|
85
|
+
return null;
|
|
86
|
+
const t = tile;
|
|
87
|
+
const x = Math.trunc(Number(t.x));
|
|
88
|
+
const y = Math.trunc(Number(t.y));
|
|
89
|
+
const w = Math.trunc(Number(t.w));
|
|
90
|
+
const h = Math.trunc(Number(t.h));
|
|
91
|
+
if (![x, y, w, h].every(Number.isFinite))
|
|
92
|
+
return null;
|
|
93
|
+
if (x < 0 || y < 0 || w <= 0 || h <= 0)
|
|
94
|
+
return null;
|
|
95
|
+
return { x, y, w, h };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validate + shape the server payload into a PairedConfig. Accepts either the
|
|
99
|
+
* config at the top level or nested under `config`. Requires at least one
|
|
100
|
+
* camera with a screenId + deviceToken (rtspUrl optional — creds-local mode).
|
|
101
|
+
*/
|
|
102
|
+
function extractPairedConfig(body) {
|
|
103
|
+
if (!body)
|
|
104
|
+
return null;
|
|
105
|
+
const src = (body.config && typeof body.config === 'object'
|
|
106
|
+
? body.config
|
|
107
|
+
: body);
|
|
108
|
+
const rawCameras = Array.isArray(src.cameras) ? src.cameras : [];
|
|
109
|
+
const cameras = rawCameras
|
|
110
|
+
.map((c) => (c && typeof c === 'object' ? c : null))
|
|
111
|
+
.filter((c) => !!c && !!c.screenId && !!c.deviceToken)
|
|
112
|
+
.map((c) => {
|
|
113
|
+
// Re-sanitize the tile defensively: the connector feeds these coords
|
|
114
|
+
// straight into the ffmpeg crop filter, so a malformed rect from any
|
|
115
|
+
// source must never reach it (mirrors the server-side sanitizeTile).
|
|
116
|
+
const tile = sanitizeTile(c.tile);
|
|
117
|
+
return {
|
|
118
|
+
name: String(c.name || c.screenId),
|
|
119
|
+
screenId: String(c.screenId),
|
|
120
|
+
deviceToken: String(c.deviceToken),
|
|
121
|
+
...(c.rtspUrl ? { rtspUrl: String(c.rtspUrl) } : {}),
|
|
122
|
+
// Mosaic tiling: carry the source link + crop so a composite/quad feed
|
|
123
|
+
// can be carved into per-tile screens (config.ts resolveConfig groups
|
|
124
|
+
// tiles by sourceFeedId and inherits the source's single RTSP pull).
|
|
125
|
+
...(c.id ? { id: String(c.id) } : {}),
|
|
126
|
+
...(c.sourceFeedId ? { sourceFeedId: String(c.sourceFeedId) } : {}),
|
|
127
|
+
...(tile ? { tile } : {}),
|
|
128
|
+
...(typeof c.width === 'number' ? { width: c.width } : {}),
|
|
129
|
+
...(typeof c.height === 'number' ? { height: c.height } : {}),
|
|
130
|
+
...(typeof c.fps === 'number' ? { fps: c.fps } : {}),
|
|
131
|
+
...(c.transport === 'udp' || c.transport === 'tcp'
|
|
132
|
+
? { transport: c.transport }
|
|
133
|
+
: {}),
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
if (cameras.length === 0)
|
|
137
|
+
return null;
|
|
138
|
+
const cs = (src.cloudSensing && typeof src.cloudSensing === 'object'
|
|
139
|
+
? src.cloudSensing
|
|
140
|
+
: {});
|
|
141
|
+
return {
|
|
142
|
+
apiBaseUrl: String(src.apiBaseUrl || 'https://api.trillboards.com'),
|
|
143
|
+
cloudSensing: {
|
|
144
|
+
enabled: true,
|
|
145
|
+
...(typeof cs.periodicIntervalMs === 'number'
|
|
146
|
+
? { periodicIntervalMs: cs.periodicIntervalMs }
|
|
147
|
+
: {}),
|
|
148
|
+
...(typeof cs.faceTriggeredIntervalMs === 'number'
|
|
149
|
+
? { faceTriggeredIntervalMs: cs.faceTriggeredIntervalMs }
|
|
150
|
+
: {}),
|
|
151
|
+
...(typeof cs.jpegQuality === 'number' ? { jpegQuality: cs.jpegQuality } : {}),
|
|
152
|
+
...(typeof cs.feedStaggerMs === 'number' ? { feedStaggerMs: cs.feedStaggerMs } : {}),
|
|
153
|
+
...(typeof cs.maxFeedStaggerMs === 'number'
|
|
154
|
+
? { maxFeedStaggerMs: cs.maxFeedStaggerMs }
|
|
155
|
+
: {}),
|
|
156
|
+
...(typeof cs.cameraHealthFailureGraceCount === 'number'
|
|
157
|
+
? { cameraHealthFailureGraceCount: cs.cameraHealthFailureGraceCount }
|
|
158
|
+
: {}),
|
|
159
|
+
},
|
|
160
|
+
cameras,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/** Build the EdgeAgentConfig-compatible object written to disk after pairing. */
|
|
164
|
+
function pairedConfigToFile(config) {
|
|
165
|
+
return {
|
|
166
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
167
|
+
cloudSensing: config.cloudSensing,
|
|
168
|
+
cameras: config.cameras.map((c) => ({
|
|
169
|
+
name: c.name,
|
|
170
|
+
screenId: c.screenId,
|
|
171
|
+
deviceToken: c.deviceToken,
|
|
172
|
+
rtspUrl: c.rtspUrl || '',
|
|
173
|
+
// Mosaic tiling — persist the source link + crop so loadConfig/resolveConfig
|
|
174
|
+
// can reconstitute the tile feeds (a tile inherits its source's rtspUrl via
|
|
175
|
+
// the id→rtspUrl map). A tile's own rtspUrl stays '' (inherited on load).
|
|
176
|
+
...(c.id ? { id: c.id } : {}),
|
|
177
|
+
...(c.sourceFeedId ? { sourceFeedId: c.sourceFeedId } : {}),
|
|
178
|
+
...(c.tile ? { tile: c.tile } : {}),
|
|
179
|
+
...(c.width ? { width: c.width } : {}),
|
|
180
|
+
...(c.height ? { height: c.height } : {}),
|
|
181
|
+
...(c.fps ? { fps: c.fps } : {}),
|
|
182
|
+
...(c.transport ? { transport: c.transport } : {}),
|
|
183
|
+
})),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=PairClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PairClient.js","sourceRoot":"","sources":["../src/PairClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { EdgeAgentConfig, CameraFeedConfig } from './config';
|
|
2
|
+
import type { ResolvedFeed } from './CloudSensingManager';
|
|
3
|
+
import { discoverOnvifHosts, sweepLanForRecorders, type OnvifHost } from './discovery';
|
|
4
|
+
export interface RecorderAddressRecoveryOptions {
|
|
5
|
+
configPath?: string;
|
|
6
|
+
log?: (message: string) => void;
|
|
7
|
+
cooldownMs?: number;
|
|
8
|
+
now?: () => number;
|
|
9
|
+
discover?: typeof discoverOnvifHosts;
|
|
10
|
+
sweep?: typeof sweepLanForRecorders;
|
|
11
|
+
validateStream?: (url: string, feed: CameraFeedConfig) => Promise<boolean>;
|
|
12
|
+
matchSerial?: (candidate: OnvifHost, expectedSerial: string, credentials: {
|
|
13
|
+
username: string;
|
|
14
|
+
password: string;
|
|
15
|
+
}) => Promise<boolean>;
|
|
16
|
+
lookupMac?: (host: string) => Promise<string | null>;
|
|
17
|
+
}
|
|
18
|
+
export declare function normalizeMacAddress(value: string): string | null;
|
|
19
|
+
/** Read one already-contacted LAN host from the operating system's neighbor table. */
|
|
20
|
+
export declare function lookupMacAddress(host: string): Promise<string | null>;
|
|
21
|
+
/** Replace only the host, preserving credentials, port, path, query, and RTSPS. */
|
|
22
|
+
export declare function rewriteStreamHost(streamUrl: string, host: string): string;
|
|
23
|
+
export declare function shouldAttemptRecorderAddressRecovery(error: unknown): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Finds a recorder again after DHCP changes its address.
|
|
26
|
+
*
|
|
27
|
+
* Recovery is deliberately conservative: the MAC address must match before
|
|
28
|
+
* credentials are used. An ONVIF serial is then verified when setup captured
|
|
29
|
+
* one; otherwise an existing channel recipe validates the matched recorder.
|
|
30
|
+
* Credentials are never tried against an unmatched LAN device.
|
|
31
|
+
*/
|
|
32
|
+
export declare class RecorderAddressRecovery {
|
|
33
|
+
private readonly groups;
|
|
34
|
+
private readonly currentHost;
|
|
35
|
+
private readonly inFlight;
|
|
36
|
+
private readonly lastFailedAt;
|
|
37
|
+
private readonly configPath?;
|
|
38
|
+
private readonly log;
|
|
39
|
+
private readonly cooldownMs;
|
|
40
|
+
private readonly now;
|
|
41
|
+
private readonly discover;
|
|
42
|
+
private readonly sweep;
|
|
43
|
+
private readonly validateStream;
|
|
44
|
+
private readonly matchSerial;
|
|
45
|
+
private readonly lookupMac;
|
|
46
|
+
constructor(config: EdgeAgentConfig, options?: RecorderAddressRecoveryOptions);
|
|
47
|
+
canRecover(feed: ResolvedFeed): boolean;
|
|
48
|
+
recover(feed: ResolvedFeed, currentUrl: string, error: unknown): Promise<string | null>;
|
|
49
|
+
private findCurrentHost;
|
|
50
|
+
private updateGroupUrls;
|
|
51
|
+
private persistGroupUrls;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=RecorderAddressRecovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecorderAddressRecovery.d.ts","sourceRoot":"","sources":["../src/RecorderAddressRecovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAoB,MAAM,UAAU,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAavF,MAAM,WAAW,8BAA8B;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,kBAAkB,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,oBAAoB,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CACZ,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAChD,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACtD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAShE;AAaD,sFAAsF;AACtF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoB3E;AA4BD,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIzE;AAED,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG5E;AAuCD;;;;;;;GAOG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAC3D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA4B;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4D;IAC3F,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6D;IACzF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2D;gBAEzE,MAAM,EAAE,eAAe,EAAE,OAAO,GAAE,8BAAmC;IA4BjF,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO;IAMjC,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YAwC/E,eAAe;IAmD7B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,gBAAgB;CAuCzB"}
|