@trillboards/edge-sdk 0.2.4 → 0.2.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.
- 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 -5
- 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-service.ps1 +6 -1
- 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 +557 -0
- package/dist/CloudSensingManager.d.ts.map +1 -0
- package/dist/CloudSensingManager.js +1267 -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 +266 -0
- package/dist/autoSense.d.ts.map +1 -0
- package/dist/autoSense.js +606 -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 +526 -27
- 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 +15 -13
- 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 +25 -87
- 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 +284 -0
- package/dist/localSensing.d.ts.map +1 -0
- package/dist/localSensing.js +512 -0
- package/dist/localSensing.js.map +1 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +3 -1
- package/dist/mcp-server.js.map +1 -1
- package/dist/modelIntegrity.d.ts +80 -0
- package/dist/modelIntegrity.d.ts.map +1 -0
- package/dist/modelIntegrity.js +194 -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 +86 -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,456 @@
|
|
|
1
|
+
[CmdletBinding()]
|
|
2
|
+
param(
|
|
3
|
+
[switch]$SmokeTest
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference = 'Stop'
|
|
7
|
+
Set-StrictMode -Version Latest
|
|
8
|
+
|
|
9
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
10
|
+
Add-Type -AssemblyName System.Drawing
|
|
11
|
+
[System.Windows.Forms.Application]::EnableVisualStyles()
|
|
12
|
+
|
|
13
|
+
$BinDir = $PSScriptRoot
|
|
14
|
+
$Pairer = Join-Path $BinDir 'trillboards-pair.cmd'
|
|
15
|
+
$StateDir = Join-Path $env:LOCALAPPDATA 'Trillboards'
|
|
16
|
+
$StatePath = Join-Path $StateDir 'setup-progress.json'
|
|
17
|
+
$LogDir = Join-Path $StateDir 'logs'
|
|
18
|
+
$SetupLogPath = Join-Path $LogDir 'setup-app.log'
|
|
19
|
+
$LocalAiSetup = Join-Path $BinDir 'setup-litertlm.ps1'
|
|
20
|
+
$script:LastStage = 'welcome'
|
|
21
|
+
$script:SetupStarted = $false
|
|
22
|
+
$script:PortalUrl = 'https://trillboards.com/earner/screens'
|
|
23
|
+
$script:PairProcess = $null
|
|
24
|
+
$script:SetupMutex = $null
|
|
25
|
+
$StepNames = @('Welcome', 'Account', 'Recorder', 'Cameras', 'Local AI', 'Ready')
|
|
26
|
+
$StepLabels = New-Object System.Collections.Generic.List[System.Windows.Forms.Label]
|
|
27
|
+
|
|
28
|
+
function New-Label {
|
|
29
|
+
param([string]$Text, [float]$Size = 10, [System.Drawing.FontStyle]$Style = [System.Drawing.FontStyle]::Regular)
|
|
30
|
+
$label = New-Object System.Windows.Forms.Label
|
|
31
|
+
$label.Text = $Text
|
|
32
|
+
$label.Font = New-Object System.Drawing.Font('Segoe UI', $Size, $Style)
|
|
33
|
+
$label.AutoSize = $false
|
|
34
|
+
$label.BackColor = [System.Drawing.Color]::Transparent
|
|
35
|
+
return $label
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function Get-StateValue {
|
|
39
|
+
param($State, [string]$Name)
|
|
40
|
+
if ($null -eq $State) { return $null }
|
|
41
|
+
$property = $State.PSObject.Properties[$Name]
|
|
42
|
+
if ($null -eq $property) { return $null }
|
|
43
|
+
return $property.Value
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function Get-StepIndex([string]$Stage) {
|
|
47
|
+
switch ($Stage) {
|
|
48
|
+
{ $_ -in @('waiting_for_account', 'account_attention') } { return 1 }
|
|
49
|
+
{ $_ -in @('account_connected', 'discovering') } { return 2 }
|
|
50
|
+
'devices_found' { return 3 }
|
|
51
|
+
'validating' { return 3 }
|
|
52
|
+
'cameras_created' { return 4 }
|
|
53
|
+
{ $_ -in @('local_ai', 'local_ai_error', 'starting_service') } { return 4 }
|
|
54
|
+
'ready' { return 5 }
|
|
55
|
+
default { return 0 }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function Get-ProgressValue([string]$Stage, $State) {
|
|
60
|
+
switch ($Stage) {
|
|
61
|
+
'waiting_for_account' { return 18 }
|
|
62
|
+
'account_attention' { return 18 }
|
|
63
|
+
'account_connected' { return 30 }
|
|
64
|
+
'discovering' { return 42 }
|
|
65
|
+
'devices_found' { return 50 }
|
|
66
|
+
'validating' { return 68 }
|
|
67
|
+
'cameras_created' { return 80 }
|
|
68
|
+
'local_ai' {
|
|
69
|
+
$localPercent = Get-StateValue $State 'localAiProgressPercent'
|
|
70
|
+
if ($null -ne $localPercent) {
|
|
71
|
+
return 84 + [Math]::Floor(([Math]::Max(0, [Math]::Min(100, [int]$localPercent))) * 0.14)
|
|
72
|
+
}
|
|
73
|
+
return 84
|
|
74
|
+
}
|
|
75
|
+
'local_ai_error' { return 95 }
|
|
76
|
+
'starting_service' { return 82 }
|
|
77
|
+
'ready' { return 100 }
|
|
78
|
+
default { return 8 }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function Update-Steps([int]$Active, [bool]$CompleteActive = $false) {
|
|
83
|
+
for ($index = 0; $index -lt $StepLabels.Count; $index++) {
|
|
84
|
+
$label = $StepLabels[$index]
|
|
85
|
+
$completed = $index -lt $Active -or ($CompleteActive -and $index -eq $Active)
|
|
86
|
+
$prefix = if ($completed) { [string][char]0x2713 } else { [string]($index + 1) }
|
|
87
|
+
$label.Text = "$prefix $($StepNames[$index])"
|
|
88
|
+
$label.ForeColor = if ($index -le $Active) { [System.Drawing.Color]::FromArgb(30, 43, 49) } else { [System.Drawing.Color]::FromArgb(104, 119, 127) }
|
|
89
|
+
$style = if ($index -eq $Active) { [System.Drawing.FontStyle]::Bold } else { [System.Drawing.FontStyle]::Regular }
|
|
90
|
+
$label.Font = New-Object System.Drawing.Font('Segoe UI', 10, $style)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function Format-ByteCount($Value) {
|
|
95
|
+
if ($null -eq $Value) { return $null }
|
|
96
|
+
$bytes = [double]$Value
|
|
97
|
+
if ($bytes -ge 1GB) { return ('{0:N2} GB' -f ($bytes / 1GB)) }
|
|
98
|
+
if ($bytes -ge 1MB) { return ('{0:N0} MB' -f ($bytes / 1MB)) }
|
|
99
|
+
return ('{0:N0} KB' -f ($bytes / 1KB))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
$Form = New-Object System.Windows.Forms.Form
|
|
103
|
+
$Form.Text = 'Trillboards CCTV Setup'
|
|
104
|
+
$Form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
|
|
105
|
+
$Form.ClientSize = New-Object System.Drawing.Size(760, 540)
|
|
106
|
+
$Form.MinimumSize = New-Object System.Drawing.Size(700, 520)
|
|
107
|
+
$Form.BackColor = [System.Drawing.Color]::White
|
|
108
|
+
$Form.MaximizeBox = $false
|
|
109
|
+
|
|
110
|
+
$Sidebar = New-Object System.Windows.Forms.Panel
|
|
111
|
+
$Sidebar.Dock = [System.Windows.Forms.DockStyle]::Left
|
|
112
|
+
$Sidebar.Width = 190
|
|
113
|
+
$Sidebar.BackColor = [System.Drawing.Color]::FromArgb(238, 243, 245)
|
|
114
|
+
$Form.Controls.Add($Sidebar)
|
|
115
|
+
|
|
116
|
+
$Brand = New-Label -Text 'Trillboards' -Size 12 -Style ([System.Drawing.FontStyle]::Bold)
|
|
117
|
+
$Brand.Location = New-Object System.Drawing.Point(24, 28)
|
|
118
|
+
$Brand.Size = New-Object System.Drawing.Size(145, 28)
|
|
119
|
+
$Sidebar.Controls.Add($Brand)
|
|
120
|
+
|
|
121
|
+
for ($index = 0; $index -lt $StepNames.Count; $index++) {
|
|
122
|
+
$step = New-Label -Text "$($index + 1) $($StepNames[$index])" -Size 10
|
|
123
|
+
$step.Location = New-Object System.Drawing.Point(24, (92 + ($index * 48)))
|
|
124
|
+
$step.Size = New-Object System.Drawing.Size(150, 28)
|
|
125
|
+
$Sidebar.Controls.Add($step)
|
|
126
|
+
$StepLabels.Add($step)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
$Eyebrow = New-Label -Text 'CUSTOMER SETUP' -Size 9 -Style ([System.Drawing.FontStyle]::Bold)
|
|
130
|
+
$Eyebrow.ForeColor = [System.Drawing.Color]::FromArgb(0, 112, 153)
|
|
131
|
+
$Eyebrow.Location = New-Object System.Drawing.Point(236, 48)
|
|
132
|
+
$Eyebrow.Size = New-Object System.Drawing.Size(450, 22)
|
|
133
|
+
$Form.Controls.Add($Eyebrow)
|
|
134
|
+
|
|
135
|
+
$Headline = New-Label -Text '' -Size 21 -Style ([System.Drawing.FontStyle]::Bold)
|
|
136
|
+
$Headline.Location = New-Object System.Drawing.Point(232, 76)
|
|
137
|
+
$Headline.Size = New-Object System.Drawing.Size(475, 70)
|
|
138
|
+
$Form.Controls.Add($Headline)
|
|
139
|
+
|
|
140
|
+
$Detail = New-Label -Text '' -Size 11
|
|
141
|
+
$Detail.ForeColor = [System.Drawing.Color]::FromArgb(96, 113, 122)
|
|
142
|
+
$Detail.Location = New-Object System.Drawing.Point(236, 150)
|
|
143
|
+
$Detail.Size = New-Object System.Drawing.Size(465, 74)
|
|
144
|
+
$Form.Controls.Add($Detail)
|
|
145
|
+
|
|
146
|
+
$StatusBox = New-Object System.Windows.Forms.Panel
|
|
147
|
+
$StatusBox.Location = New-Object System.Drawing.Point(236, 242)
|
|
148
|
+
$StatusBox.Size = New-Object System.Drawing.Size(465, 70)
|
|
149
|
+
$StatusBox.BackColor = [System.Drawing.Color]::FromArgb(245, 248, 249)
|
|
150
|
+
$StatusBox.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle
|
|
151
|
+
$Form.Controls.Add($StatusBox)
|
|
152
|
+
|
|
153
|
+
$StatusValue = New-Label -Text '' -Size 17 -Style ([System.Drawing.FontStyle]::Bold)
|
|
154
|
+
$StatusValue.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
|
|
155
|
+
$StatusValue.Dock = [System.Windows.Forms.DockStyle]::Fill
|
|
156
|
+
$StatusBox.Controls.Add($StatusValue)
|
|
157
|
+
|
|
158
|
+
$Metric = New-Label -Text '' -Size 9
|
|
159
|
+
$Metric.ForeColor = [System.Drawing.Color]::FromArgb(96, 113, 122)
|
|
160
|
+
$Metric.Location = New-Object System.Drawing.Point(236, 330)
|
|
161
|
+
$Metric.Size = New-Object System.Drawing.Size(465, 24)
|
|
162
|
+
$Form.Controls.Add($Metric)
|
|
163
|
+
|
|
164
|
+
$Progress = New-Object System.Windows.Forms.ProgressBar
|
|
165
|
+
$Progress.Location = New-Object System.Drawing.Point(236, 364)
|
|
166
|
+
$Progress.Size = New-Object System.Drawing.Size(465, 10)
|
|
167
|
+
$Progress.Minimum = 0
|
|
168
|
+
$Progress.Maximum = 100
|
|
169
|
+
$Form.Controls.Add($Progress)
|
|
170
|
+
|
|
171
|
+
$Privacy = New-Label -Text 'Camera credentials stay on this computer. Cloud inference is off by default.' -Size 8.5
|
|
172
|
+
$Privacy.ForeColor = [System.Drawing.Color]::FromArgb(96, 113, 122)
|
|
173
|
+
$Privacy.Location = New-Object System.Drawing.Point(236, 468)
|
|
174
|
+
$Privacy.Size = New-Object System.Drawing.Size(300, 40)
|
|
175
|
+
$Form.Controls.Add($Privacy)
|
|
176
|
+
|
|
177
|
+
$Action = New-Object System.Windows.Forms.Button
|
|
178
|
+
$Action.Text = 'Start setup'
|
|
179
|
+
$Action.Font = New-Object System.Drawing.Font('Segoe UI', 10, [System.Drawing.FontStyle]::Bold)
|
|
180
|
+
$Action.Location = New-Object System.Drawing.Point(562, 466)
|
|
181
|
+
$Action.Size = New-Object System.Drawing.Size(139, 42)
|
|
182
|
+
$Action.BackColor = [System.Drawing.Color]::FromArgb(0, 127, 174)
|
|
183
|
+
$Action.ForeColor = [System.Drawing.Color]::White
|
|
184
|
+
$Action.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
|
|
185
|
+
$Action.FlatAppearance.BorderSize = 0
|
|
186
|
+
$Form.Controls.Add($Action)
|
|
187
|
+
|
|
188
|
+
function Show-Welcome {
|
|
189
|
+
$script:LastStage = 'welcome'
|
|
190
|
+
$Headline.Text = 'Set up this computer for CCTV'
|
|
191
|
+
$Detail.Text = 'Connect your Trillboards account, find your recorder, and verify every camera before screens are created.'
|
|
192
|
+
$StatusValue.Text = 'About 5 minutes'
|
|
193
|
+
$Metric.Text = 'Keep this computer and the recorder on the same network.'
|
|
194
|
+
$Progress.Value = 0
|
|
195
|
+
$Action.Text = 'Start setup'
|
|
196
|
+
$Action.Enabled = $true
|
|
197
|
+
Update-Steps 0
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function Show-LocalError([string]$Title, [string]$Message) {
|
|
201
|
+
$script:LastStage = 'error'
|
|
202
|
+
$Headline.Text = $Title
|
|
203
|
+
$Detail.Text = $Message
|
|
204
|
+
$StatusValue.Text = 'Setup stopped'
|
|
205
|
+
$Metric.Text = 'Details are saved in logs\setup-app.log.'
|
|
206
|
+
$Progress.Value = 0
|
|
207
|
+
$Action.Text = 'Try again'
|
|
208
|
+
$Action.Enabled = $true
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function Start-Setup {
|
|
212
|
+
if (-not (Test-Path $Pairer)) {
|
|
213
|
+
Show-LocalError 'Setup app is incomplete' 'Reinstall the Trillboards CCTV connector, then try again.'
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
Stop-SetupProcess
|
|
217
|
+
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
|
|
218
|
+
Remove-Item $StatePath -Force -ErrorAction SilentlyContinue
|
|
219
|
+
Add-Content -Path $SetupLogPath -Value "`r`n[$([DateTime]::Now.ToString('o'))] Starting Trillboards CCTV Setup"
|
|
220
|
+
$Headline.Text = 'Starting camera setup'
|
|
221
|
+
$Detail.Text = 'Connecting securely to Trillboards.'
|
|
222
|
+
$StatusValue.Text = 'Please wait'
|
|
223
|
+
$Metric.Text = 'No Terminal or command window is required.'
|
|
224
|
+
$Progress.Value = 8
|
|
225
|
+
$Action.Enabled = $false
|
|
226
|
+
$script:LastStage = 'starting'
|
|
227
|
+
$script:SetupStarted = $true
|
|
228
|
+
|
|
229
|
+
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
230
|
+
$startInfo.FileName = $env:ComSpec
|
|
231
|
+
$startInfo.Arguments = ('/d /s /c ""{0}" --setup --status-file "{1}" >> "{2}" 2>&1"' -f $Pairer, $StatePath, $SetupLogPath)
|
|
232
|
+
$startInfo.UseShellExecute = $false
|
|
233
|
+
$startInfo.CreateNoWindow = $true
|
|
234
|
+
$startInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
|
|
235
|
+
try {
|
|
236
|
+
$script:PairProcess = [System.Diagnostics.Process]::Start($startInfo)
|
|
237
|
+
} catch {
|
|
238
|
+
Show-LocalError 'Could not start setup' 'Reinstall the Trillboards CCTV connector, then try again.'
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function Start-LocalAiSetup {
|
|
243
|
+
if (-not (Test-Path $LocalAiSetup)) {
|
|
244
|
+
Show-LocalError 'Local AI setup is incomplete' 'Reinstall the Trillboards CCTV connector, then try again.'
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
$Headline.Text = 'Preparing local AI'
|
|
248
|
+
$Detail.Text = 'Restarting the local AI installed with Trillboards. Your paired cameras will not be recreated.'
|
|
249
|
+
$StatusValue.Text = 'Starting local AI'
|
|
250
|
+
$Metric.Text = 'Cloud inference remains off.'
|
|
251
|
+
$Progress.Value = 82
|
|
252
|
+
$Action.Text = 'Working...'
|
|
253
|
+
$Action.Enabled = $false
|
|
254
|
+
$script:LastStage = 'local_ai'
|
|
255
|
+
|
|
256
|
+
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
257
|
+
$startInfo.FileName = 'powershell.exe'
|
|
258
|
+
$startInfo.Arguments = ('-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File "{0}" -RequireBundledModel -ProgressPath "{1}"' -f $LocalAiSetup, $StatePath)
|
|
259
|
+
$startInfo.UseShellExecute = $false
|
|
260
|
+
$startInfo.CreateNoWindow = $true
|
|
261
|
+
$startInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
|
|
262
|
+
try {
|
|
263
|
+
[void][System.Diagnostics.Process]::Start($startInfo)
|
|
264
|
+
} catch {
|
|
265
|
+
Show-LocalError 'Could not start local AI' 'Reinstall the Trillboards CCTV connector, then try again.'
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function Stop-SetupProcess {
|
|
270
|
+
$process = $script:PairProcess
|
|
271
|
+
$script:PairProcess = $null
|
|
272
|
+
if ($null -eq $process) { return }
|
|
273
|
+
try {
|
|
274
|
+
if (-not $process.HasExited) {
|
|
275
|
+
$taskkill = Join-Path $env:SystemRoot 'System32\taskkill.exe'
|
|
276
|
+
& $taskkill /PID $process.Id /T /F | Out-Null
|
|
277
|
+
[void]$process.WaitForExit(5000)
|
|
278
|
+
}
|
|
279
|
+
} catch {
|
|
280
|
+
try {
|
|
281
|
+
if (-not $process.HasExited) { $process.Kill() }
|
|
282
|
+
} catch {
|
|
283
|
+
# The process may have exited between checks.
|
|
284
|
+
}
|
|
285
|
+
} finally {
|
|
286
|
+
$process.Dispose()
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function Render-State($State) {
|
|
291
|
+
$stage = [string](Get-StateValue $State 'stage')
|
|
292
|
+
if (-not $stage) { return }
|
|
293
|
+
$script:LastStage = $stage
|
|
294
|
+
$url = Get-StateValue $State 'portalUrl'
|
|
295
|
+
if ($url) { $script:PortalUrl = [string]$url }
|
|
296
|
+
$Headline.Text = [string](Get-StateValue $State 'title')
|
|
297
|
+
$Detail.Text = [string](Get-StateValue $State 'message')
|
|
298
|
+
$cameraCount = Get-StateValue $State 'cameraCount'
|
|
299
|
+
$validated = Get-StateValue $State 'validatedFeeds'
|
|
300
|
+
$devices = Get-StateValue $State 'devicesFound'
|
|
301
|
+
$rejected = Get-StateValue $State 'rejectedFeeds'
|
|
302
|
+
$localAiPhase = [string](Get-StateValue $State 'localAiPhase')
|
|
303
|
+
$localAiPercent = Get-StateValue $State 'localAiProgressPercent'
|
|
304
|
+
$localAiDownloaded = Get-StateValue $State 'localAiDownloadedBytes'
|
|
305
|
+
$localAiTotal = Get-StateValue $State 'localAiTotalBytes'
|
|
306
|
+
|
|
307
|
+
if ($stage -in @('waiting_for_account', 'account_attention')) {
|
|
308
|
+
$StatusValue.Text = [string](Get-StateValue $State 'displayCode')
|
|
309
|
+
} elseif ($stage -eq 'ready') {
|
|
310
|
+
$StatusValue.Text = 'Setup complete'
|
|
311
|
+
} elseif ($stage -eq 'local_ai_error') {
|
|
312
|
+
$StatusValue.Text = 'Local AI needs attention'
|
|
313
|
+
} elseif ($stage -eq 'starting_service') {
|
|
314
|
+
$StatusValue.Text = 'Starting Trillboards'
|
|
315
|
+
} elseif ($stage -eq 'local_ai') {
|
|
316
|
+
switch ($localAiPhase) {
|
|
317
|
+
'installing_model' {
|
|
318
|
+
$StatusValue.Text = if ($null -ne $localAiPercent) { "Installing Gemma - $localAiPercent%" } else { 'Installing Gemma' }
|
|
319
|
+
}
|
|
320
|
+
'starting_service' { $StatusValue.Text = 'Starting local AI' }
|
|
321
|
+
'verifying' { $StatusValue.Text = 'Checking local AI' }
|
|
322
|
+
default { $StatusValue.Text = 'Installing local AI' }
|
|
323
|
+
}
|
|
324
|
+
} elseif ($cameraCount -and [int]$cameraCount -gt 0) {
|
|
325
|
+
$StatusValue.Text = "$cameraCount camera$(if ([int]$cameraCount -eq 1) { '' } else { 's' })"
|
|
326
|
+
} elseif ($validated -and [int]$validated -gt 0) {
|
|
327
|
+
$StatusValue.Text = "$validated feed$(if ([int]$validated -eq 1) { '' } else { 's' }) ready"
|
|
328
|
+
} elseif ($null -ne $devices) {
|
|
329
|
+
$StatusValue.Text = "$devices device$(if ([int]$devices -eq 1) { '' } else { 's' }) found"
|
|
330
|
+
} elseif ($stage -eq 'error') {
|
|
331
|
+
$StatusValue.Text = 'Setup stopped'
|
|
332
|
+
} else {
|
|
333
|
+
$StatusValue.Text = 'In progress'
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if ($stage -eq 'local_ai' -and $localAiPhase -eq 'installing_model' -and $null -ne $localAiTotal) {
|
|
337
|
+
$totalText = Format-ByteCount $localAiTotal
|
|
338
|
+
$Metric.Text = if ($totalText) { "Installing the $totalText model included with Trillboards. Cloud inference remains off." } else { 'Installing the included model. Cloud inference remains off.' }
|
|
339
|
+
} elseif ($stage -eq 'local_ai_error') {
|
|
340
|
+
$Metric.Text = 'Camera pairing is saved. Retry only the local AI step.'
|
|
341
|
+
} elseif ($rejected -and [int]$rejected -gt 0) {
|
|
342
|
+
$Metric.Text = "$rejected black or unavailable input$(if ([int]$rejected -eq 1) { ' was' } else { 's were' }) ignored."
|
|
343
|
+
} elseif ($stage -eq 'account_attention') {
|
|
344
|
+
$Metric.Text = 'No cameras were added. It is safe to switch accounts.'
|
|
345
|
+
} elseif ($stage -eq 'local_ai') {
|
|
346
|
+
$Metric.Text = 'The included model stays on this computer; cloud inference remains off.'
|
|
347
|
+
} elseif ($stage -eq 'ready') {
|
|
348
|
+
$Metric.Text = 'Trillboards starts automatically when this computer logs in.'
|
|
349
|
+
} elseif ($stage -eq 'error') {
|
|
350
|
+
$Metric.Text = 'Details are saved in logs\setup-app.log.'
|
|
351
|
+
} else {
|
|
352
|
+
$Metric.Text = 'Camera credentials stay encrypted on this computer.'
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
$Progress.Value = [Math]::Max(0, [Math]::Min(100, (Get-ProgressValue $stage $State)))
|
|
356
|
+
Update-Steps (Get-StepIndex $stage) ($stage -eq 'ready')
|
|
357
|
+
switch ($stage) {
|
|
358
|
+
'waiting_for_account' { $Action.Text = 'Open Trillboards'; $Action.Enabled = $true }
|
|
359
|
+
'account_attention' { $Action.Text = 'Switch account'; $Action.Enabled = $true }
|
|
360
|
+
'local_ai_error' { $Action.Text = 'Retry local AI'; $Action.Enabled = $true }
|
|
361
|
+
'ready' { $Action.Text = 'View cameras'; $Action.Enabled = $true }
|
|
362
|
+
'error' { $Action.Text = 'Try again'; $Action.Enabled = $true }
|
|
363
|
+
default { $Action.Text = 'Working...'; $Action.Enabled = $false }
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
$Action.Add_Click({
|
|
368
|
+
switch ($script:LastStage) {
|
|
369
|
+
'waiting_for_account' { Start-Process $script:PortalUrl }
|
|
370
|
+
'account_attention' { Start-Process $script:PortalUrl }
|
|
371
|
+
'local_ai_error' { Start-LocalAiSetup }
|
|
372
|
+
'ready' {
|
|
373
|
+
Start-Process 'https://trillboards.com/earner/screens'
|
|
374
|
+
$Form.Close()
|
|
375
|
+
}
|
|
376
|
+
'error' { Start-Setup }
|
|
377
|
+
'welcome' { Start-Setup }
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
$Form.Add_FormClosing({
|
|
382
|
+
Stop-SetupProcess
|
|
383
|
+
if ($null -ne $script:SetupMutex) {
|
|
384
|
+
try { $script:SetupMutex.ReleaseMutex() } catch { }
|
|
385
|
+
$script:SetupMutex.Dispose()
|
|
386
|
+
$script:SetupMutex = $null
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
$Timer = New-Object System.Windows.Forms.Timer
|
|
391
|
+
$Timer.Interval = 500
|
|
392
|
+
$Timer.Add_Tick({
|
|
393
|
+
if ($script:SetupStarted -and (Test-Path $StatePath)) {
|
|
394
|
+
try {
|
|
395
|
+
$state = Get-Content -Raw -Path $StatePath | ConvertFrom-Json
|
|
396
|
+
Render-State $state
|
|
397
|
+
} catch {
|
|
398
|
+
# Atomic writer means this is uncommon; retry on the next tick.
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if ($null -ne $script:PairProcess -and $script:PairProcess.HasExited) {
|
|
402
|
+
$exitCode = $script:PairProcess.ExitCode
|
|
403
|
+
$script:PairProcess.Dispose()
|
|
404
|
+
$script:PairProcess = $null
|
|
405
|
+
if ($exitCode -ne 0 -and $script:LastStage -notin @('local_ai', 'local_ai_error', 'ready', 'error')) {
|
|
406
|
+
Show-LocalError 'Setup stopped before finishing' "The camera setup helper exited with code $exitCode. Try again; if it repeats, send setup-app.log to Trillboards support."
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
})
|
|
410
|
+
Show-Welcome
|
|
411
|
+
if ($SmokeTest) {
|
|
412
|
+
if ($StepLabels.Count -ne 6 -or $Form.Controls.Count -lt 8 -or $Action.Text -ne 'Start setup') {
|
|
413
|
+
throw 'Windows setup UI did not construct its expected controls.'
|
|
414
|
+
}
|
|
415
|
+
$smokeStartInfo = New-Object System.Diagnostics.ProcessStartInfo
|
|
416
|
+
$smokeStartInfo.FileName = $env:ComSpec
|
|
417
|
+
$smokeStartInfo.Arguments = '/d /s /c "ping -n 120 127.0.0.1 >nul"'
|
|
418
|
+
$smokeStartInfo.UseShellExecute = $false
|
|
419
|
+
$smokeStartInfo.CreateNoWindow = $true
|
|
420
|
+
$script:PairProcess = [System.Diagnostics.Process]::Start($smokeStartInfo)
|
|
421
|
+
$smokeParentId = $script:PairProcess.Id
|
|
422
|
+
$smokeChildIds = @()
|
|
423
|
+
for ($attempt = 0; $attempt -lt 20 -and $smokeChildIds.Count -eq 0; $attempt++) {
|
|
424
|
+
Start-Sleep -Milliseconds 100
|
|
425
|
+
$smokeChildIds = @(Get-CimInstance Win32_Process -Filter "ParentProcessId = $smokeParentId" | Select-Object -ExpandProperty ProcessId)
|
|
426
|
+
}
|
|
427
|
+
Stop-SetupProcess
|
|
428
|
+
if ($smokeChildIds.Count -eq 0) {
|
|
429
|
+
throw 'Windows setup cancellation smoke test did not create its child process.'
|
|
430
|
+
}
|
|
431
|
+
$trackedIds = @($smokeParentId) + $smokeChildIds
|
|
432
|
+
$leftRunning = @($trackedIds)
|
|
433
|
+
for ($attempt = 0; $attempt -lt 20 -and $leftRunning.Count -gt 0; $attempt++) {
|
|
434
|
+
$leftRunning = @($trackedIds | Where-Object { Get-Process -Id $_ -ErrorAction SilentlyContinue })
|
|
435
|
+
if ($leftRunning.Count -gt 0) { Start-Sleep -Milliseconds 100 }
|
|
436
|
+
}
|
|
437
|
+
if ($leftRunning.Count -gt 0) {
|
|
438
|
+
throw "Windows setup cancellation left process IDs running: $($leftRunning -join ', ')"
|
|
439
|
+
}
|
|
440
|
+
Write-Host 'Trillboards CCTV Setup Windows Forms smoke test passed.'
|
|
441
|
+
$Form.Dispose()
|
|
442
|
+
exit 0
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
$createdNew = $false
|
|
446
|
+
$script:SetupMutex = New-Object System.Threading.Mutex($true, 'Local\TrillboardsCctvSetup', [ref]$createdNew)
|
|
447
|
+
if (-not $createdNew) {
|
|
448
|
+
$script:SetupMutex.Dispose()
|
|
449
|
+
$script:SetupMutex = $null
|
|
450
|
+
$Form.Dispose()
|
|
451
|
+
exit 0
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
$Timer.Start()
|
|
455
|
+
[void]$Form.ShowDialog()
|
|
456
|
+
$Timer.Stop()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Option Explicit
|
|
2
|
+
|
|
3
|
+
Dim fso, shell, scriptDir, powerShellScript, command
|
|
4
|
+
Set fso = CreateObject("Scripting.FileSystemObject")
|
|
5
|
+
Set shell = CreateObject("WScript.Shell")
|
|
6
|
+
|
|
7
|
+
scriptDir = fso.GetParentFolderName(WScript.ScriptFullName)
|
|
8
|
+
powerShellScript = fso.BuildPath(scriptDir, "trillboards-setup.ps1")
|
|
9
|
+
command = "powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File """ & powerShellScript & """"
|
|
10
|
+
|
|
11
|
+
' Window style 0 prevents a console flash; the PowerShell process displays only
|
|
12
|
+
' the Windows Forms customer setup application.
|
|
13
|
+
shell.Run command, 0, False
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AudienceAnalyzeClient — POSTs a JPEG frame to the cloud VLM endpoint
|
|
3
|
+
* `POST {apiBaseUrl}/v2/earner/audience-analyze`.
|
|
4
|
+
*
|
|
5
|
+
* This is the ONE genuinely-new piece for cloud sensing: it replaces the
|
|
6
|
+
* edge-cloud Gemini-direct path. The cloud VLM does the inference; the edge
|
|
7
|
+
* only grabs a frame and ships it.
|
|
8
|
+
*
|
|
9
|
+
* Wire contract mirrors the Android agent-core `FrameCaptureManager.sendToApi`:
|
|
10
|
+
* - body: JSON `{ fingerprint?, screenId?, imageBase64, capturedAt, ... }`
|
|
11
|
+
* - headers required by `middleware/deviceRequestAuth.js`:
|
|
12
|
+
* X-Device-Token — the per-screen device token
|
|
13
|
+
* X-Trillboard-Device-Token — alias header (back-compat)
|
|
14
|
+
* X-Device-Timestamp — epoch ms (replay skew window)
|
|
15
|
+
* X-Device-Nonce — unique per request (replay guard)
|
|
16
|
+
*
|
|
17
|
+
* Uses Node's built-in http/https (no extra dependency) so it works inside a
|
|
18
|
+
* self-contained binary and is trivially mockable in tests.
|
|
19
|
+
*/
|
|
20
|
+
export interface AudienceAnalyzeClientOptions {
|
|
21
|
+
/** Base URL, e.g. https://api.trillboards.com (no trailing slash needed). */
|
|
22
|
+
apiBaseUrl: string;
|
|
23
|
+
/** Device token for X-Device-Token (one feed = one token). */
|
|
24
|
+
deviceToken: string;
|
|
25
|
+
/** Screen this client posts for (one feed = one screen). Optional. */
|
|
26
|
+
screenId?: string;
|
|
27
|
+
/** Device fingerprint, sent in the body for legacy correlation. Optional. */
|
|
28
|
+
fingerprint?: string;
|
|
29
|
+
/** Request timeout in ms. Default: 30000. */
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
/** Image width sent in the body metadata. Optional. */
|
|
32
|
+
imageWidth?: number;
|
|
33
|
+
/** Image height sent in the body metadata. Optional. */
|
|
34
|
+
imageHeight?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface AudienceAnalyzeRequest {
|
|
37
|
+
/** Raw JPEG bytes for this frame. */
|
|
38
|
+
jpeg: Buffer;
|
|
39
|
+
/** Capture timestamp (epoch ms). Default: Date.now(). */
|
|
40
|
+
capturedAt?: number;
|
|
41
|
+
/** Capture mode hint forwarded to the cloud. Optional. */
|
|
42
|
+
captureMode?: string;
|
|
43
|
+
/** Extra body fields merged into the payload (e.g. per_face_observations). */
|
|
44
|
+
extra?: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
export interface AudienceAnalyzeResponse {
|
|
47
|
+
/** HTTP status code. */
|
|
48
|
+
statusCode: number;
|
|
49
|
+
/** Whether the POST succeeded (2xx). */
|
|
50
|
+
ok: boolean;
|
|
51
|
+
/** Parsed JSON body (or null if the body was not valid JSON). */
|
|
52
|
+
body: Record<string, unknown> | null;
|
|
53
|
+
/** Raw response text. */
|
|
54
|
+
rawBody: string;
|
|
55
|
+
}
|
|
56
|
+
export type CameraHealthState = 'never_started' | 'starting' | 'open' | 'failed' | 'closed';
|
|
57
|
+
export type CameraHealthFailureClass = 'rtsp_auth' | 'rtsp_unreachable' | 'rtsp_timeout' | 'nvr_busy' | 'no_frames' | 'decode_error';
|
|
58
|
+
export type CameraSensingState = 'idle' | 'analyzing' | 'active' | 'waiting_for_capacity' | 'unavailable';
|
|
59
|
+
export interface CameraHealthReport {
|
|
60
|
+
state: CameraHealthState;
|
|
61
|
+
lastFrameAtMs?: number;
|
|
62
|
+
retryCount?: number;
|
|
63
|
+
lastFailureClass?: CameraHealthFailureClass;
|
|
64
|
+
lastFailureMessage?: string;
|
|
65
|
+
/** AI/inference state, deliberately separate from RTSP/video health. */
|
|
66
|
+
sensingState?: CameraSensingState;
|
|
67
|
+
/** Authenticated attestation that the connector decoded a local frame. */
|
|
68
|
+
captureProof?: 'decoded_frame';
|
|
69
|
+
}
|
|
70
|
+
/** Minimal injectable HTTP transport — lets tests stub the network entirely. */
|
|
71
|
+
export interface HttpPoster {
|
|
72
|
+
(url: string, options: {
|
|
73
|
+
method: string;
|
|
74
|
+
headers: Record<string, string>;
|
|
75
|
+
timeoutMs: number;
|
|
76
|
+
}, body: string): Promise<{
|
|
77
|
+
statusCode: number;
|
|
78
|
+
body: string;
|
|
79
|
+
}>;
|
|
80
|
+
}
|
|
81
|
+
export declare class AudienceAnalyzeClient {
|
|
82
|
+
private readonly endpoint;
|
|
83
|
+
private readonly deviceToken;
|
|
84
|
+
private readonly screenId?;
|
|
85
|
+
private readonly fingerprint?;
|
|
86
|
+
private readonly timeoutMs;
|
|
87
|
+
private readonly imageWidth?;
|
|
88
|
+
private readonly imageHeight?;
|
|
89
|
+
private readonly poster;
|
|
90
|
+
constructor(options: AudienceAnalyzeClientOptions, poster?: HttpPoster);
|
|
91
|
+
/** The resolved POST URL (exposed for assertions / logging). */
|
|
92
|
+
getEndpoint(): string;
|
|
93
|
+
private authHeaders;
|
|
94
|
+
/**
|
|
95
|
+
* POST a JPEG frame for cloud audience analysis. Returns the parsed response.
|
|
96
|
+
*/
|
|
97
|
+
analyze(request: AudienceAnalyzeRequest): Promise<AudienceAnalyzeResponse>;
|
|
98
|
+
/**
|
|
99
|
+
* POST a PRE-ANALYZED structured result (computed ON-DEVICE by
|
|
100
|
+
* LiteRtVlmProvider) to the same audience-analyze endpoint. The server detects
|
|
101
|
+
* `preAnalyzed`, SKIPS the cloud VLM, and ingests the result directly —
|
|
102
|
+
* forcing provenance `local_connector` server-side so it drives the
|
|
103
|
+
* operator's Sense-Anything routes but is gated out of the sold bidstream.
|
|
104
|
+
* Same device-token auth + replay guard as analyze().
|
|
105
|
+
*
|
|
106
|
+
* EVIDENCE FRAME (optional): when `jpeg` (raw bytes) or `imageBase64` (already
|
|
107
|
+
* base64) is supplied, the SAME JPEG the on-device VLM analyzed is included as
|
|
108
|
+
* `imageBase64` ALONGSIDE `preAnalyzed`. The server uploads it and attaches it
|
|
109
|
+
* to any alert the result fires. The caller decides WHETHER to attach it — the
|
|
110
|
+
* connector only sends a frame for alert-worthy observations (see
|
|
111
|
+
* localSensing.ts), so this method just forwards what it's given. When neither
|
|
112
|
+
* is passed, NO `imageBase64` is sent (results-only, privacy-preserving
|
|
113
|
+
* default for empty/uninteresting scenes).
|
|
114
|
+
*/
|
|
115
|
+
analyzePreAnalyzed(preAnalyzed: Record<string, unknown>, request?: {
|
|
116
|
+
capturedAt?: number;
|
|
117
|
+
captureMode?: string;
|
|
118
|
+
extra?: Record<string, unknown>;
|
|
119
|
+
/** Raw JPEG bytes of the analyzed frame — encoded to base64 and sent as `imageBase64`. */
|
|
120
|
+
jpeg?: Buffer;
|
|
121
|
+
/** Pre-encoded base64 JPEG of the analyzed frame (alternative to `jpeg`). */
|
|
122
|
+
imageBase64?: string;
|
|
123
|
+
}): Promise<AudienceAnalyzeResponse>;
|
|
124
|
+
/**
|
|
125
|
+
* POST a FRAMELESS camera-health beacon. This is used when the connector can
|
|
126
|
+
* pair but cannot open the RTSP stream, so the portal can show "Camera login
|
|
127
|
+
* failed" / "not reachable" instead of looking like the connector is absent.
|
|
128
|
+
*/
|
|
129
|
+
reportCameraHealth(cameraHealth: CameraHealthReport): Promise<AudienceAnalyzeResponse>;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Default transport using Node's built-in http/https. No third-party deps so it
|
|
133
|
+
* survives bundling into a single self-contained binary.
|
|
134
|
+
*/
|
|
135
|
+
export declare const defaultHttpPoster: HttpPoster;
|
|
136
|
+
//# sourceMappingURL=AudienceAnalyzeClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudienceAnalyzeClient.d.ts","sourceRoot":"","sources":["../src/AudienceAnalyzeClient.ts"],"names":[],"mappings":"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"}
|