@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.
Files changed (200) hide show
  1. package/README.md +4 -3
  2. package/deploy/docker/Dockerfile.cloud-sense +117 -0
  3. package/deploy/docker/Dockerfile.cpu +30 -21
  4. package/deploy/docker/Dockerfile.cuda +30 -21
  5. package/deploy/docker/Dockerfile.openvino +30 -20
  6. package/deploy/docker/README.md +9 -4
  7. package/deploy/docker/connector-entrypoint.sh +122 -0
  8. package/deploy/helm/README.md +1 -1
  9. package/deploy/k8s/daemonset.yaml +1 -1
  10. package/deploy/macos/README.md +161 -0
  11. package/deploy/macos/TrillboardsSetupApp.m +603 -0
  12. package/deploy/macos/build-macos-pkg.sh +588 -0
  13. package/deploy/macos/com.trillboards.edge.plist +62 -0
  14. package/deploy/macos/com.trillboards.litertlm.plist +45 -0
  15. package/deploy/macos/pair.command +519 -0
  16. package/deploy/macos/scripts/ensure-litertlm.sh +62 -0
  17. package/deploy/macos/scripts/postinstall +153 -0
  18. package/deploy/macos/scripts/setup-litertlm.sh +272 -0
  19. package/deploy/macos/test-install-pair.sh +383 -0
  20. package/deploy/macos/test-setup-litertlm-reinstall.sh +109 -0
  21. package/deploy/systemd/install.sh +25 -15
  22. package/deploy/systemd/trillboards-edge.service +4 -1
  23. package/deploy/windows/README.md +70 -0
  24. package/deploy/windows/build-windows.ps1 +225 -0
  25. package/deploy/windows/bundle-windows-installer.ps1 +153 -0
  26. package/deploy/windows/check-feeds.js +26 -0
  27. package/deploy/windows/e2e/fixtures/person.jpg +0 -0
  28. package/deploy/windows/e2e/test-local-sense.ps1 +185 -0
  29. package/deploy/windows/install-update.ps1 +101 -0
  30. package/deploy/windows/installer.nsi +138 -0
  31. package/deploy/windows/register-litertlm-task.ps1 +42 -0
  32. package/deploy/windows/register-task.ps1 +44 -0
  33. package/deploy/windows/run-connector.ps1 +69 -0
  34. package/deploy/windows/setup-litertlm.ps1 +361 -0
  35. package/deploy/windows/stop-existing.ps1 +72 -0
  36. package/deploy/windows/trillboards-edge-task.vbs +25 -0
  37. package/deploy/windows/trillboards-edge.cmd +33 -0
  38. package/deploy/windows/trillboards-pair.cmd +276 -0
  39. package/deploy/windows/trillboards-setup.ps1 +456 -0
  40. package/deploy/windows/trillboards-setup.vbs +13 -0
  41. package/dist/AudienceAnalyzeClient.d.ts +136 -0
  42. package/dist/AudienceAnalyzeClient.d.ts.map +1 -0
  43. package/dist/AudienceAnalyzeClient.js +246 -0
  44. package/dist/AudienceAnalyzeClient.js.map +1 -0
  45. package/dist/ChannelProber.d.ts +150 -0
  46. package/dist/ChannelProber.d.ts.map +1 -0
  47. package/dist/ChannelProber.js +887 -0
  48. package/dist/ChannelProber.js.map +1 -0
  49. package/dist/CloudEscalationPolicy.d.ts +143 -0
  50. package/dist/CloudEscalationPolicy.d.ts.map +1 -0
  51. package/dist/CloudEscalationPolicy.js +137 -0
  52. package/dist/CloudEscalationPolicy.js.map +1 -0
  53. package/dist/CloudSensingManager.d.ts +533 -0
  54. package/dist/CloudSensingManager.d.ts.map +1 -0
  55. package/dist/CloudSensingManager.js +1254 -0
  56. package/dist/CloudSensingManager.js.map +1 -0
  57. package/dist/DiscoveryReportClient.d.ts +66 -0
  58. package/dist/DiscoveryReportClient.d.ts.map +1 -0
  59. package/dist/DiscoveryReportClient.js +85 -0
  60. package/dist/DiscoveryReportClient.js.map +1 -0
  61. package/dist/EdgeAgent.d.ts +12 -2
  62. package/dist/EdgeAgent.d.ts.map +1 -1
  63. package/dist/EdgeAgent.js +122 -65
  64. package/dist/EdgeAgent.js.map +1 -1
  65. package/dist/LiteRtVlmProvider.d.ts +193 -0
  66. package/dist/LiteRtVlmProvider.d.ts.map +1 -0
  67. package/dist/LiteRtVlmProvider.js +436 -0
  68. package/dist/LiteRtVlmProvider.js.map +1 -0
  69. package/dist/MosaicSource.d.ts +108 -0
  70. package/dist/MosaicSource.d.ts.map +1 -0
  71. package/dist/MosaicSource.js +274 -0
  72. package/dist/MosaicSource.js.map +1 -0
  73. package/dist/OnvifClient.d.ts +83 -0
  74. package/dist/OnvifClient.d.ts.map +1 -0
  75. package/dist/OnvifClient.js +209 -0
  76. package/dist/OnvifClient.js.map +1 -0
  77. package/dist/PairClient.d.ts +106 -0
  78. package/dist/PairClient.d.ts.map +1 -0
  79. package/dist/PairClient.js +186 -0
  80. package/dist/PairClient.js.map +1 -0
  81. package/dist/RecorderAddressRecovery.d.ts +53 -0
  82. package/dist/RecorderAddressRecovery.d.ts.map +1 -0
  83. package/dist/RecorderAddressRecovery.js +359 -0
  84. package/dist/RecorderAddressRecovery.js.map +1 -0
  85. package/dist/SceneChangeDetector.d.ts +291 -0
  86. package/dist/SceneChangeDetector.d.ts.map +1 -0
  87. package/dist/SceneChangeDetector.js +682 -0
  88. package/dist/SceneChangeDetector.js.map +1 -0
  89. package/dist/SensingProfileClient.d.ts +59 -0
  90. package/dist/SensingProfileClient.d.ts.map +1 -0
  91. package/dist/SensingProfileClient.js +78 -0
  92. package/dist/SensingProfileClient.js.map +1 -0
  93. package/dist/SetupSessionClient.d.ts +114 -0
  94. package/dist/SetupSessionClient.d.ts.map +1 -0
  95. package/dist/SetupSessionClient.js +95 -0
  96. package/dist/SetupSessionClient.js.map +1 -0
  97. package/dist/VlmAdmissionGate.d.ts +126 -0
  98. package/dist/VlmAdmissionGate.d.ts.map +1 -0
  99. package/dist/VlmAdmissionGate.js +166 -0
  100. package/dist/VlmAdmissionGate.js.map +1 -0
  101. package/dist/autoSense.d.ts +216 -0
  102. package/dist/autoSense.d.ts.map +1 -0
  103. package/dist/autoSense.js +521 -0
  104. package/dist/autoSense.js.map +1 -0
  105. package/dist/cli.d.ts +27 -1
  106. package/dist/cli.d.ts.map +1 -1
  107. package/dist/cli.js +511 -21
  108. package/dist/cli.js.map +1 -1
  109. package/dist/combinedSense.d.ts +128 -0
  110. package/dist/combinedSense.d.ts.map +1 -0
  111. package/dist/combinedSense.js +261 -0
  112. package/dist/combinedSense.js.map +1 -0
  113. package/dist/config.d.ts +351 -0
  114. package/dist/config.d.ts.map +1 -1
  115. package/dist/config.js +99 -2
  116. package/dist/config.js.map +1 -1
  117. package/dist/connectorCadence.d.ts +135 -0
  118. package/dist/connectorCadence.d.ts.map +1 -0
  119. package/dist/connectorCadence.js +151 -0
  120. package/dist/connectorCadence.js.map +1 -0
  121. package/dist/dataDir.d.ts +33 -0
  122. package/dist/dataDir.d.ts.map +1 -0
  123. package/dist/dataDir.js +76 -0
  124. package/dist/dataDir.js.map +1 -0
  125. package/dist/deployedCadence.d.ts +167 -0
  126. package/dist/deployedCadence.d.ts.map +1 -0
  127. package/dist/deployedCadence.js +209 -0
  128. package/dist/deployedCadence.js.map +1 -0
  129. package/dist/deployedCadenceSource.d.ts +48 -0
  130. package/dist/deployedCadenceSource.d.ts.map +1 -0
  131. package/dist/deployedCadenceSource.js +74 -0
  132. package/dist/deployedCadenceSource.js.map +1 -0
  133. package/dist/diagnose.d.ts +1 -1
  134. package/dist/diagnose.d.ts.map +1 -1
  135. package/dist/diagnose.js +13 -12
  136. package/dist/diagnose.js.map +1 -1
  137. package/dist/discovery.d.ts +131 -0
  138. package/dist/discovery.d.ts.map +1 -0
  139. package/dist/discovery.js +499 -0
  140. package/dist/discovery.js.map +1 -0
  141. package/dist/gemmaModelOta.d.ts +118 -0
  142. package/dist/gemmaModelOta.d.ts.map +1 -0
  143. package/dist/gemmaModelOta.js +291 -0
  144. package/dist/gemmaModelOta.js.map +1 -0
  145. package/dist/index.d.ts +16 -1
  146. package/dist/index.d.ts.map +1 -1
  147. package/dist/index.js +40 -1
  148. package/dist/index.js.map +1 -1
  149. package/dist/init.d.ts.map +1 -1
  150. package/dist/init.js +41 -18
  151. package/dist/init.js.map +1 -1
  152. package/dist/keepAwake.d.ts +33 -0
  153. package/dist/keepAwake.d.ts.map +1 -0
  154. package/dist/keepAwake.js +54 -0
  155. package/dist/keepAwake.js.map +1 -0
  156. package/dist/legacyRecorderProfile.d.ts +20 -0
  157. package/dist/legacyRecorderProfile.d.ts.map +1 -0
  158. package/dist/legacyRecorderProfile.js +27 -0
  159. package/dist/legacyRecorderProfile.js.map +1 -0
  160. package/dist/localInferenceSchema.d.ts +132 -0
  161. package/dist/localInferenceSchema.d.ts.map +1 -0
  162. package/dist/localInferenceSchema.js +274 -0
  163. package/dist/localInferenceSchema.js.map +1 -0
  164. package/dist/localSenseE2eHarness.d.ts +101 -0
  165. package/dist/localSenseE2eHarness.d.ts.map +1 -0
  166. package/dist/localSenseE2eHarness.js +279 -0
  167. package/dist/localSenseE2eHarness.js.map +1 -0
  168. package/dist/localSensing.d.ts +268 -0
  169. package/dist/localSensing.d.ts.map +1 -0
  170. package/dist/localSensing.js +492 -0
  171. package/dist/localSensing.js.map +1 -0
  172. package/dist/modelIntegrity.d.ts +59 -0
  173. package/dist/modelIntegrity.d.ts.map +1 -0
  174. package/dist/modelIntegrity.js +165 -0
  175. package/dist/modelIntegrity.js.map +1 -0
  176. package/dist/pairVerify.d.ts +100 -0
  177. package/dist/pairVerify.d.ts.map +1 -0
  178. package/dist/pairVerify.js +296 -0
  179. package/dist/pairVerify.js.map +1 -0
  180. package/dist/qrScanner.d.ts +33 -0
  181. package/dist/qrScanner.d.ts.map +1 -0
  182. package/dist/qrScanner.js +103 -0
  183. package/dist/qrScanner.js.map +1 -0
  184. package/dist/runtimePaths.d.ts +10 -0
  185. package/dist/runtimePaths.d.ts.map +1 -0
  186. package/dist/runtimePaths.js +79 -0
  187. package/dist/runtimePaths.js.map +1 -0
  188. package/dist/sensingRunMode.d.ts +68 -0
  189. package/dist/sensingRunMode.d.ts.map +1 -0
  190. package/dist/sensingRunMode.js +346 -0
  191. package/dist/sensingRunMode.js.map +1 -0
  192. package/dist/setupMode.d.ts +98 -0
  193. package/dist/setupMode.d.ts.map +1 -0
  194. package/dist/setupMode.js +828 -0
  195. package/dist/setupMode.js.map +1 -0
  196. package/dist/setupProgress.d.ts +31 -0
  197. package/dist/setupProgress.d.ts.map +1 -0
  198. package/dist/setupProgress.js +173 -0
  199. package/dist/setupProgress.js.map +1 -0
  200. package/package.json +13 -4
@@ -0,0 +1,101 @@
1
+ <#
2
+ Validates a staged connector, stops the running copy, swaps bin/lib, registers
3
+ the new hidden task, and restores the previous runnable version on failure.
4
+ #>
5
+ [CmdletBinding()]
6
+ param(
7
+ [Parameter(Mandatory = $true)][string]$InstallDir,
8
+ [Parameter(Mandatory = $true)][string]$StagingDir
9
+ )
10
+
11
+ $ErrorActionPreference = "Stop"
12
+ $previousDir = Join-Path $InstallDir ".previous"
13
+ $parts = @("bin", "lib")
14
+ $movedPrevious = New-Object System.Collections.Generic.List[string]
15
+ $movedStaged = New-Object System.Collections.Generic.List[string]
16
+
17
+ function Assert-ConnectorVersion([string]$Root) {
18
+ $node = Join-Path $Root "bin\node.exe"
19
+ $cli = Join-Path $Root "lib\edge-sdk\dist\cli.js"
20
+ if (-not (Test-Path $node) -or -not (Test-Path $cli)) {
21
+ throw "The staged connector is incomplete."
22
+ }
23
+
24
+ $oldPath = $env:PATH
25
+ $oldNodePath = $env:NODE_PATH
26
+ try {
27
+ $env:PATH = "$(Join-Path $Root 'bin');$oldPath"
28
+ $env:NODE_PATH = Join-Path $Root "lib\node_modules"
29
+ $version = (& $node $cli version 2>&1 | Out-String).Trim()
30
+ if ($LASTEXITCODE -ne 0 -or $version -notmatch 'edge-sdk v') {
31
+ throw "Connector version check failed: $version"
32
+ }
33
+ Write-Host "Validated $version"
34
+ } finally {
35
+ $env:PATH = $oldPath
36
+ $env:NODE_PATH = $oldNodePath
37
+ }
38
+ }
39
+
40
+ function Register-Connector([string]$Root) {
41
+ $register = Join-Path $Root "bin\register-task.ps1"
42
+ & $register -InstallDir $InstallDir -Mode "auto-sense"
43
+ if ($LASTEXITCODE -ne 0) { throw "Scheduled-task registration failed." }
44
+ }
45
+
46
+ try {
47
+ Assert-ConnectorVersion $StagingDir
48
+ & (Join-Path $StagingDir "bin\stop-existing.ps1") -InstallDir $InstallDir
49
+
50
+ if (Test-Path $previousDir) { Remove-Item -Recurse -Force $previousDir }
51
+ New-Item -ItemType Directory -Force -Path $InstallDir, $previousDir | Out-Null
52
+
53
+ foreach ($part in $parts) {
54
+ $active = Join-Path $InstallDir $part
55
+ if (Test-Path $active) {
56
+ Move-Item -LiteralPath $active -Destination (Join-Path $previousDir $part)
57
+ $movedPrevious.Add($part)
58
+ }
59
+ }
60
+ foreach ($part in $parts) {
61
+ $staged = Join-Path $StagingDir $part
62
+ if (-not (Test-Path $staged)) { throw "Staged connector is missing $part." }
63
+ Move-Item -LiteralPath $staged -Destination (Join-Path $InstallDir $part)
64
+ $movedStaged.Add($part)
65
+ }
66
+
67
+ Assert-ConnectorVersion $InstallDir
68
+ Register-Connector $InstallDir
69
+ if (Test-Path (Join-Path $InstallDir "trillboards.config.json")) {
70
+ Start-ScheduledTask -TaskName "TrillboardsEdge" -ErrorAction Stop
71
+ }
72
+
73
+ Remove-Item -Recurse -Force $previousDir -ErrorAction SilentlyContinue
74
+ Remove-Item -Recurse -Force $StagingDir -ErrorAction SilentlyContinue
75
+ Write-Host "Trillboards Edge update installed successfully."
76
+ } catch {
77
+ $failure = $_
78
+ try {
79
+ $stopScript = Join-Path $InstallDir "bin\stop-existing.ps1"
80
+ if (Test-Path $stopScript) { & $stopScript -InstallDir $InstallDir }
81
+ } catch {}
82
+
83
+ foreach ($part in $movedStaged) {
84
+ Remove-Item -Recurse -Force (Join-Path $InstallDir $part) -ErrorAction SilentlyContinue
85
+ }
86
+ foreach ($part in $movedPrevious) {
87
+ $backup = Join-Path $previousDir $part
88
+ if (Test-Path $backup) {
89
+ Move-Item -LiteralPath $backup -Destination (Join-Path $InstallDir $part)
90
+ }
91
+ }
92
+ if ($movedPrevious.Count -gt 0) {
93
+ try {
94
+ Register-Connector $InstallDir
95
+ if (Test-Path (Join-Path $InstallDir "trillboards.config.json")) {
96
+ Start-ScheduledTask -TaskName "TrillboardsEdge" -ErrorAction SilentlyContinue
97
+ }
98
+ } catch {}
99
+ }
100
+ throw "Trillboards Edge update failed and the previous version was restored: $($failure.Exception.Message)"
101
+ }
@@ -0,0 +1,138 @@
1
+ ; installer.nsi — Trillboards Edge on-device (local-sense) CCTV connector (Windows).
2
+ ; Per-user, no-admin install (RequestExecutionLevel user) that mirrors the
3
+ ; home-domain macOS .pkg: lays down the self-contained tree under
4
+ ; %LOCALAPPDATA%\Trillboards\edge, registers a per-user Scheduled Task that
5
+ ; runs local-first auto-sense at logon, installs the model supplied by the outer
6
+ ; signed customer package, verifies local AI, then opens first-run pairing.
7
+ ;
8
+ ; The release workflow Authenticode-signs and verifies the finished executable
9
+ ; with Azure Trusted Signing before publishing it to the customer CDN.
10
+ ;
11
+ ; Driven by build-windows.ps1 with:
12
+ ; makensis /DPAYLOAD_DIR=<stage>\Trillboards\edge /DAPP_VERSION=<ver> /DOUT_FILE=<exe> installer.nsi
13
+
14
+ !ifndef PAYLOAD_DIR
15
+ !error "PAYLOAD_DIR not defined (pass /DPAYLOAD_DIR=...)"
16
+ !endif
17
+ !ifndef APP_VERSION
18
+ !define APP_VERSION "0.0.0"
19
+ !endif
20
+ !ifndef OUT_FILE
21
+ !define OUT_FILE "TrillboardsEdgeSetup.exe"
22
+ !endif
23
+
24
+ !define APP_NAME "Trillboards Edge - CCTV Connector"
25
+ !define TASK_NAME "TrillboardsEdge"
26
+ !define LITERT_TASK_NAME "TrillboardsLiteRtLm"
27
+
28
+ Var ModelSource
29
+
30
+ Name "${APP_NAME}"
31
+ OutFile "${OUT_FILE}"
32
+ Unicode True
33
+ RequestExecutionLevel user ; per-user, no admin/UAC
34
+ InstallDir "$LOCALAPPDATA\Trillboards\edge"
35
+ SetCompressor /SOLID lzma
36
+ ShowInstDetails show
37
+ BrandingText "Trillboards"
38
+
39
+ !include "MUI2.nsh"
40
+ !include "FileFunc.nsh"
41
+
42
+ !define MUI_ABORTWARNING
43
+ !define MUI_WELCOMEPAGE_TITLE "Connect your camera to Trillboards"
44
+ !define MUI_WELCOMEPAGE_TEXT "This installs the Trillboards camera connector and private local AI included with it. Camera pairing opens after both are installed and verified. Cloud inference stays off unless explicitly enabled."
45
+ !insertmacro MUI_PAGE_WELCOME
46
+ !insertmacro MUI_PAGE_INSTFILES
47
+
48
+ ; Finish page: launch the native Windows Forms setup app through wscript. The
49
+ ; setup engine and its cmd wrapper run with CreateNoWindow, so no console flashes.
50
+ !define MUI_FINISHPAGE_RUN "$INSTDIR\bin\trillboards-setup.vbs"
51
+ !define MUI_FINISHPAGE_RUN_TEXT "Set up my CCTV cameras now"
52
+ !define MUI_FINISHPAGE_TEXT "The connector and private local AI are installed. Continue in the Trillboards CCTV Setup app to pair your cameras."
53
+ !insertmacro MUI_PAGE_FINISH
54
+
55
+ !insertmacro MUI_UNPAGE_CONFIRM
56
+ !insertmacro MUI_UNPAGE_INSTFILES
57
+ !insertmacro MUI_LANGUAGE "English"
58
+
59
+ Function .onInit
60
+ ; The SFX launcher supplies a process-scoped environment value so paths with
61
+ ; spaces are unambiguous. Keep the command-line option as an engineering and
62
+ ; recovery fallback.
63
+ ReadEnvStr $ModelSource "TRILLBOARDS_BUNDLED_MODEL_PATH"
64
+ ${If} $ModelSource == ""
65
+ ${GetParameters} $0
66
+ ${GetOptions} $0 "/MODEL_SOURCE=" $ModelSource
67
+ ${EndIf}
68
+ ${If} $ModelSource == ""
69
+ MessageBox MB_ICONSTOP|MB_OK "This installer is missing its included local AI model. Download the complete Trillboards CCTV installer and try again."
70
+ Abort
71
+ ${EndIf}
72
+ FunctionEnd
73
+
74
+ Section "Install"
75
+ ; Copy and validate beside the live install first. install-update.ps1 then
76
+ ; stops the task, swaps bin/lib atomically, verifies again, and restores the
77
+ ; previous runnable version if registration fails. The root-level camera
78
+ ; config is never moved or overwritten.
79
+ RMDir /r "$INSTDIR\.update-staging"
80
+ SetOutPath "$INSTDIR\.update-staging"
81
+ File /r "${PAYLOAD_DIR}\*"
82
+
83
+ InitPluginsDir
84
+ File /oname=$PLUGINSDIR\install-update.ps1 "${PAYLOAD_DIR}\bin\install-update.ps1"
85
+ DetailPrint "Validating and updating the background connector..."
86
+ nsExec::ExecToLog 'powershell -NoProfile -ExecutionPolicy Bypass -File "$PLUGINSDIR\install-update.ps1" -InstallDir "$INSTDIR" -StagingDir "$INSTDIR\.update-staging"'
87
+ Pop $0
88
+ ${If} $0 != 0
89
+ MessageBox MB_ICONSTOP|MB_OK "Trillboards CCTV setup could not be updated safely. Your previous connector was restored. Please retry the installer."
90
+ Abort
91
+ ${EndIf}
92
+ SetOutPath "$INSTDIR"
93
+
94
+ ; The outer signed self-extractor passes its checksum-pinned model here. This
95
+ ; is synchronous and required: pairing is never offered while AI is absent or
96
+ ; still downloading in the background.
97
+ ${IfNot} ${FileExists} "$ModelSource"
98
+ MessageBox MB_ICONSTOP|MB_OK "The local AI model included with this installer could not be found. Download a fresh Trillboards CCTV installer."
99
+ Abort
100
+ ${EndIf}
101
+ DetailPrint "Installing and verifying private local AI..."
102
+ nsExec::ExecToLog '"$WINDIR\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -ExecutionPolicy Bypass -File "$INSTDIR\bin\setup-litertlm.ps1" -BundledModelPath "$ModelSource" -RequireBundledModel'
103
+ Pop $0
104
+ ${If} $0 != 0
105
+ MessageBox MB_ICONSTOP|MB_OK "Private local AI could not be installed. Camera pairing has not started. Download a fresh installer or contact Trillboards support."
106
+ Abort
107
+ ${EndIf}
108
+ DetailPrint "Private local AI is installed and healthy."
109
+
110
+ ; Start Menu shortcuts.
111
+ CreateDirectory "$SMPROGRAMS\Trillboards"
112
+ CreateShortcut "$SMPROGRAMS\Trillboards\Trillboards CCTV Setup.lnk" "$WINDIR\System32\wscript.exe" '$\"$INSTDIR\bin\trillboards-setup.vbs$\"'
113
+ CreateShortcut "$SMPROGRAMS\Trillboards\Uninstall Trillboards Edge.lnk" "$INSTDIR\uninstall.exe"
114
+
115
+ ; Uninstaller + Add/Remove Programs entry (per-user hive).
116
+ WriteUninstaller "$INSTDIR\uninstall.exe"
117
+ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\TrillboardsEdge" "DisplayName" "${APP_NAME}"
118
+ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\TrillboardsEdge" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
119
+ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\TrillboardsEdge" "DisplayVersion" "${APP_VERSION}"
120
+ WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\TrillboardsEdge" "Publisher" "Trillboards"
121
+ WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\TrillboardsEdge" "NoModify" 1
122
+ WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\TrillboardsEdge" "NoRepair" 1
123
+ SectionEnd
124
+
125
+ Section "Uninstall"
126
+ ; Stop + remove the background tasks (connector + litert-lm serve).
127
+ nsExec::ExecToLog 'powershell -NoProfile -ExecutionPolicy Bypass -File "$INSTDIR\bin\stop-existing.ps1" -InstallDir "$INSTDIR"'
128
+ nsExec::ExecToLog 'schtasks /End /TN "${TASK_NAME}"'
129
+ nsExec::ExecToLog 'schtasks /Delete /F /TN "${TASK_NAME}"'
130
+ nsExec::ExecToLog 'schtasks /End /TN "${LITERT_TASK_NAME}"'
131
+ nsExec::ExecToLog 'schtasks /Delete /F /TN "${LITERT_TASK_NAME}"'
132
+ Delete "$SMPROGRAMS\Trillboards\Pair a camera.lnk"
133
+ Delete "$SMPROGRAMS\Trillboards\Trillboards CCTV Setup.lnk"
134
+ Delete "$SMPROGRAMS\Trillboards\Uninstall Trillboards Edge.lnk"
135
+ RMDir "$SMPROGRAMS\Trillboards"
136
+ RMDir /r "$INSTDIR"
137
+ DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\TrillboardsEdge"
138
+ SectionEnd
@@ -0,0 +1,42 @@
1
+ <#
2
+ register-litertlm-task.ps1 — register the per-user Scheduled Task that runs the
3
+ LiteRT-LM on-device VLM server (Gemma 4 E2B) at logon, with crash-restart.
4
+ Per-user + Interactive logon type → NO admin/UAC (mirrors the macOS
5
+ com.trillboards.litertlm LaunchAgent: KeepAlive=true + ThrottleInterval=30).
6
+ The connector's LiteRtVlmProvider talks to the OpenAI-compatible endpoint on
7
+ 127.0.0.1:<Port>. Invoked by setup-litertlm.ps1.
8
+ #>
9
+ param(
10
+ [Parameter(Mandatory = $true)][string]$LitertLmPath,
11
+ [string]$Port = "9379"
12
+ )
13
+ $ErrorActionPreference = "Stop"
14
+
15
+ $TaskName = "TrillboardsLiteRtLm"
16
+ $UserId = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
17
+ # litert-lm serve --host 127.0.0.1 --port <port> (loopback only — the connector
18
+ # is local; never expose the model server off-box).
19
+ $argument = 'serve --host 127.0.0.1 --port ' + $Port
20
+ $Action = New-ScheduledTaskAction -Execute $LitertLmPath -Argument $argument
21
+ $Trigger = New-ScheduledTaskTrigger -AtLogOn -User $UserId
22
+ # RestartCount/Interval == the plist's ThrottleInterval crash-loop guard (e.g.
23
+ # while the ~2.4 GB model is still importing on first run); Zero time limit ==
24
+ # the always-on KeepAlive serve endpoint.
25
+ $Settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) `
26
+ -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable `
27
+ -ExecutionTimeLimit ([TimeSpan]::Zero)
28
+ $Principal = New-ScheduledTaskPrincipal -UserId $UserId -LogonType Interactive -RunLevel Limited
29
+
30
+ Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
31
+ Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Settings $Settings `
32
+ -Principal $Principal -Description "Trillboards LiteRT-LM - on-device Gemma VLM server (:$Port)" | Out-Null
33
+
34
+ $registered = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
35
+ if (-not $registered) {
36
+ Write-Error "Scheduled task '$TaskName' did NOT register (Get-ScheduledTask found nothing)."
37
+ exit 1
38
+ }
39
+
40
+ # Start it now (don't wait for the next logon) so first-run sensing has a server.
41
+ Start-ScheduledTask -TaskName $TaskName
42
+ Write-Host "Registered scheduled task '$TaskName' (litert-lm serve on :$Port, restarts on failure)."
@@ -0,0 +1,44 @@
1
+ <#
2
+ register-task.ps1 — register the per-user Scheduled Task that runs the
3
+ Trillboards local-first connector at logon (with crash-restart). Per-user +
4
+ Interactive logon type so NO admin/UAC is required (mirrors the home-domain,
5
+ no-sudo macOS LaunchAgent). Invoked by the NSIS installer post-copy.
6
+ #>
7
+ param(
8
+ [Parameter(Mandatory = $true)][string]$InstallDir,
9
+ # Default to auto-sense: use on-device Gemma (LiteRT-LM) and wait locally while
10
+ # the model is provisioning. cloud-sense remains an explicit operator choice.
11
+ [ValidateSet("auto-sense", "local-sense", "cloud-sense")][string]$Mode = "auto-sense"
12
+ )
13
+ $ErrorActionPreference = "Stop"
14
+
15
+ $TaskName = "TrillboardsEdge"
16
+ $UserId = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
17
+ $taskHost = Join-Path $InstallDir "bin\trillboards-edge-task.vbs"
18
+ $wscript = Join-Path $env:WINDIR "System32\wscript.exe"
19
+
20
+ # wscript owns the task lifetime, launches the connector with window style 0,
21
+ # waits for it, and returns its exit code. Task Scheduler can therefore restart
22
+ # crashes without exposing cmd.exe or PowerShell to the customer.
23
+ $argument = '"' + $taskHost + '" "' + $Mode + '"'
24
+ $Action = New-ScheduledTaskAction -Execute $wscript -Argument $argument -WorkingDirectory $InstallDir
25
+ $Trigger = New-ScheduledTaskTrigger -AtLogOn -User $UserId
26
+ $Settings = New-ScheduledTaskSettingsSet -RestartCount 99 -RestartInterval (New-TimeSpan -Minutes 1) `
27
+ -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable `
28
+ -ExecutionTimeLimit ([TimeSpan]::Zero) # no time limit — sensing runs continuously
29
+ $Principal = New-ScheduledTaskPrincipal -UserId $UserId -LogonType Interactive -RunLevel Limited
30
+
31
+ Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
32
+ Register-ScheduledTask -TaskName $TaskName -Action $Action -Trigger $Trigger -Settings $Settings `
33
+ -Principal $Principal -Description "Trillboards Edge - CCTV $Mode connector" | Out-Null
34
+
35
+ # VERIFY the registration landed instead of trusting Register-ScheduledTask's
36
+ # silence — a silently-missing task is exactly how a real 16-camera install
37
+ # ended up paired with zero frames (the pairing helper then claimed success).
38
+ # Callers (installer.nsi, trillboards-pair.cmd's self-repair) branch on our
39
+ # exit code, so fail LOUDLY here.
40
+ $registered = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
41
+ if (-not $registered) {
42
+ throw "Scheduled task '$TaskName' did NOT register (Get-ScheduledTask found nothing)."
43
+ }
44
+ Write-Host "Registered scheduled task '$TaskName' (runs $Mode at logon, restarts on failure)."
@@ -0,0 +1,69 @@
1
+ <#
2
+ Hidden connector supervisor. It merges stdout/stderr into one pipe and owns
3
+ the log file, allowing size-based rotation while the connector runs 24/7.
4
+ #>
5
+ [CmdletBinding()]
6
+ param(
7
+ [Parameter(Mandatory = $true)][string]$InstallDir,
8
+ [ValidateSet("auto-sense", "local-sense", "cloud-sense")][string]$Mode = "auto-sense"
9
+ )
10
+
11
+ $ErrorActionPreference = "Stop"
12
+ $logDir = Join-Path $InstallDir "logs"
13
+ $logPath = Join-Path $logDir "connector.log"
14
+ $launcher = Join-Path $InstallDir "bin\trillboards-edge.cmd"
15
+ $configPath = Join-Path $InstallDir "trillboards.config.json"
16
+ $maxLogBytes = 5MB
17
+ New-Item -ItemType Directory -Force -Path $logDir | Out-Null
18
+
19
+ function Move-ConnectorLogs {
20
+ if (Test-Path "$logPath.3") { Remove-Item -Force "$logPath.3" }
21
+ for ($index = 2; $index -ge 1; $index--) {
22
+ $source = "$logPath.$index"
23
+ $target = "$logPath.$($index + 1)"
24
+ if (Test-Path $source) { Move-Item -Force $source $target }
25
+ }
26
+ if (Test-Path $logPath) { Move-Item -Force $logPath "$logPath.1" }
27
+ }
28
+
29
+ if ((Test-Path $logPath) -and (Get-Item $logPath).Length -ge $maxLogBytes) {
30
+ Move-ConnectorLogs
31
+ }
32
+
33
+ $writer = $null
34
+ $process = $null
35
+ try {
36
+ $writer = New-Object System.IO.StreamWriter($logPath, $true, (New-Object System.Text.UTF8Encoding($false)))
37
+ $writer.AutoFlush = $true
38
+
39
+ $startInfo = New-Object System.Diagnostics.ProcessStartInfo
40
+ $startInfo.FileName = $env:ComSpec
41
+ $startInfo.Arguments = '/d /s /c ""' + $launcher + '" ' + $Mode + ' --config "' + $configPath + '" 2>&1"'
42
+ $startInfo.WorkingDirectory = $InstallDir
43
+ $startInfo.UseShellExecute = $false
44
+ $startInfo.CreateNoWindow = $true
45
+ $startInfo.RedirectStandardOutput = $true
46
+
47
+ $process = New-Object System.Diagnostics.Process
48
+ $process.StartInfo = $startInfo
49
+ if (-not $process.Start()) { throw "The Trillboards connector did not start." }
50
+
51
+ while (-not $process.StandardOutput.EndOfStream) {
52
+ $line = $process.StandardOutput.ReadLine()
53
+ if ($null -eq $line) { continue }
54
+ $writer.WriteLine($line)
55
+ if ($writer.BaseStream.Length -ge $maxLogBytes) {
56
+ $writer.Dispose()
57
+ $writer = $null
58
+ Move-ConnectorLogs
59
+ $writer = New-Object System.IO.StreamWriter($logPath, $true, (New-Object System.Text.UTF8Encoding($false)))
60
+ $writer.AutoFlush = $true
61
+ }
62
+ }
63
+
64
+ $process.WaitForExit()
65
+ exit $process.ExitCode
66
+ } finally {
67
+ if ($null -ne $writer) { $writer.Dispose() }
68
+ if ($null -ne $process) { $process.Dispose() }
69
+ }