@trillboards/edge-sdk 0.2.2 → 0.2.3
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 +147 -2
- package/deploy/docker/Dockerfile.cpu +132 -0
- package/deploy/docker/Dockerfile.cuda +134 -0
- package/deploy/docker/Dockerfile.openvino +131 -0
- package/deploy/docker/README.md +358 -0
- package/deploy/helm/README.md +508 -0
- package/deploy/helm/trillboards-edge/Chart.yaml +19 -0
- package/deploy/helm/trillboards-edge/templates/_helpers.tpl +40 -0
- package/deploy/helm/trillboards-edge/templates/daemonset.yaml +120 -0
- package/deploy/helm/trillboards-edge/templates/service.yaml +15 -0
- package/deploy/helm/trillboards-edge/values.yaml +95 -0
- package/deploy/k8s/daemonset.yaml +144 -0
- package/dist/CommandRouter.d.ts +113 -0
- package/dist/CommandRouter.d.ts.map +1 -0
- package/dist/CommandRouter.js +392 -0
- package/dist/CommandRouter.js.map +1 -0
- package/dist/EdgeAgent.d.ts +6 -1
- package/dist/EdgeAgent.d.ts.map +1 -1
- package/dist/EdgeAgent.js +277 -10
- package/dist/EdgeAgent.js.map +1 -1
- package/dist/cli.js +60 -8
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/demo.d.ts +111 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +483 -0
- package/dist/demo.js.map +1 -0
- package/dist/diagnose.d.ts +59 -0
- package/dist/diagnose.d.ts.map +1 -0
- package/dist/diagnose.js +651 -0
- package/dist/diagnose.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +19 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +364 -0
- package/dist/init.js.map +1 -0
- package/dist/mcp-server.d.ts +27 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +1264 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/status.d.ts +11 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +343 -0
- package/dist/status.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Docker Deployment — Trillboards Edge SDK
|
|
2
|
+
|
|
3
|
+
This guide covers deploying the Trillboards Edge AI agent as a Docker container for DOOH audience sensing.
|
|
4
|
+
|
|
5
|
+
## Image Variants
|
|
6
|
+
|
|
7
|
+
Three pre-built images target different hardware profiles:
|
|
8
|
+
|
|
9
|
+
| Tag | Base Image | Execution Provider | Architecture | Use Case |
|
|
10
|
+
|-----|-----------|-------------------|--------------|----------|
|
|
11
|
+
| `latest` | `node:20-slim` | CPU (WASM) | `linux/amd64`, `linux/arm64` | Generic Linux devices, ARM SBCs, Raspberry Pi 4+ |
|
|
12
|
+
| `cuda` | `nvidia/cuda:12.3.2-runtime-ubuntu22.04` | NVIDIA CUDA | `linux/amd64` | NVIDIA Jetson, GPU-equipped signage players |
|
|
13
|
+
| `openvino` | `openvino/ubuntu22_runtime:2024.0.0` | Intel OpenVINO | `linux/amd64` | Backpackster, Intel NUC, mini-PCs with Intel HD 620+ |
|
|
14
|
+
|
|
15
|
+
## Registry Locations
|
|
16
|
+
|
|
17
|
+
Images are published to two registries. Use whichever is reachable from your deployment environment.
|
|
18
|
+
|
|
19
|
+
**GitHub Container Registry (public):**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
docker pull ghcr.io/trillboards/edge-sdk:latest
|
|
23
|
+
docker pull ghcr.io/trillboards/edge-sdk:cuda
|
|
24
|
+
docker pull ghcr.io/trillboards/edge-sdk:openvino
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**AWS ECR (private, for production fleet):**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
aws ecr get-login-password --region us-east-1 | \
|
|
31
|
+
docker login --username AWS --password-stdin 975050306809.dkr.ecr.us-east-1.amazonaws.com
|
|
32
|
+
|
|
33
|
+
docker pull 975050306809.dkr.ecr.us-east-1.amazonaws.com/trillboards-edge-sdk:latest
|
|
34
|
+
docker pull 975050306809.dkr.ecr.us-east-1.amazonaws.com/trillboards-edge-sdk:cuda
|
|
35
|
+
docker pull 975050306809.dkr.ecr.us-east-1.amazonaws.com/trillboards-edge-sdk:openvino
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
docker run -d \
|
|
42
|
+
--name trillboards-edge \
|
|
43
|
+
-e DEVICE_TOKEN=your_device_token_here \
|
|
44
|
+
-p 9090:9090 \
|
|
45
|
+
ghcr.io/trillboards/edge-sdk:latest
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Obtain your `DEVICE_TOKEN` from the Trillboards dashboard under **Devices > Add Device**.
|
|
49
|
+
|
|
50
|
+
## Environment Variables
|
|
51
|
+
|
|
52
|
+
All configuration is driven through environment variables. The container entrypoint generates a config JSON from these at startup.
|
|
53
|
+
|
|
54
|
+
| Variable | Default | Description |
|
|
55
|
+
|----------|---------|-------------|
|
|
56
|
+
| `DEVICE_TOKEN` | *(required)* | Authentication token for backend API registration. Get this from your Trillboards dashboard. |
|
|
57
|
+
| `API_BASE_URL` | `https://api.trillboards.com` | Backend API endpoint. Override for staging or self-hosted deployments. |
|
|
58
|
+
| `CAMERA_ENABLED` | `false` | Enable camera capture for face detection. Requires `/dev/video*` device passthrough. |
|
|
59
|
+
| `AUDIO_ENABLED` | `false` | Enable audio capture for ambient classification (YAMNet). Requires ALSA/PulseAudio access. |
|
|
60
|
+
| `KIOSK_ENABLED` | `false` | Launch a headless Chromium browser pointing to the Trillboards screen player. |
|
|
61
|
+
| `EXECUTION_PROVIDER` | `cpu` (CPU image), `cuda` (CUDA image), `openvino` (OpenVINO image) | ONNX Runtime execution provider. One of: `cpu`, `cuda`, `openvino`, `directml`. |
|
|
62
|
+
| `STATUS_PORT` | `9090` | HTTP port for the local status server (`/status`, `/health`, `/metrics`). |
|
|
63
|
+
| `LOG_LEVEL` | `info` | Logging verbosity. One of: `debug`, `info`, `warn`, `error`. |
|
|
64
|
+
| `MODELS_DIR` | `/app/models` | Directory containing ONNX model files (`blazeface.onnx`, `yamnet.onnx`). |
|
|
65
|
+
| `DATA_DIR` | `/app/data` | Persistence directory for signal buffer, device identity, and federated learning state. |
|
|
66
|
+
| `SCREEN_ID` | *(empty)* | Override the screen identifier. If empty, the agent registers automatically with the backend. |
|
|
67
|
+
| `VENUE_TYPE` | *(empty)* | Venue classification string (e.g., `retail`, `transit`, `office`). Used for contextual audience grading. |
|
|
68
|
+
|
|
69
|
+
## docker-compose Example
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
version: "3.8"
|
|
73
|
+
|
|
74
|
+
services:
|
|
75
|
+
trillboards-edge:
|
|
76
|
+
image: ghcr.io/trillboards/edge-sdk:latest
|
|
77
|
+
container_name: trillboards-edge
|
|
78
|
+
restart: unless-stopped
|
|
79
|
+
environment:
|
|
80
|
+
DEVICE_TOKEN: "${DEVICE_TOKEN}"
|
|
81
|
+
API_BASE_URL: "https://api.trillboards.com"
|
|
82
|
+
CAMERA_ENABLED: "true"
|
|
83
|
+
AUDIO_ENABLED: "true"
|
|
84
|
+
KIOSK_ENABLED: "false"
|
|
85
|
+
EXECUTION_PROVIDER: "cpu"
|
|
86
|
+
LOG_LEVEL: "info"
|
|
87
|
+
ports:
|
|
88
|
+
- "9090:9090"
|
|
89
|
+
volumes:
|
|
90
|
+
# Persist signal buffer and device identity across restarts
|
|
91
|
+
- trillboards-data:/app/data
|
|
92
|
+
# Persist downloaded models to avoid re-downloading on restart
|
|
93
|
+
- trillboards-models:/app/models
|
|
94
|
+
# Camera device passthrough (Linux only)
|
|
95
|
+
- /dev:/dev:ro
|
|
96
|
+
devices:
|
|
97
|
+
- /dev/video0:/dev/video0
|
|
98
|
+
healthcheck:
|
|
99
|
+
test: ["CMD", "curl", "-f", "http://localhost:9090/health"]
|
|
100
|
+
interval: 30s
|
|
101
|
+
timeout: 5s
|
|
102
|
+
start_period: 30s
|
|
103
|
+
retries: 3
|
|
104
|
+
|
|
105
|
+
volumes:
|
|
106
|
+
trillboards-data:
|
|
107
|
+
trillboards-models:
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Start the stack:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
DEVICE_TOKEN=your_token docker compose up -d
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## GPU Passthrough (NVIDIA CUDA)
|
|
117
|
+
|
|
118
|
+
The CUDA image requires the NVIDIA Container Toolkit.
|
|
119
|
+
|
|
120
|
+
**Install the runtime:**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Ubuntu/Debian
|
|
124
|
+
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
|
|
125
|
+
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
|
|
126
|
+
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
|
|
127
|
+
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
|
|
128
|
+
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
|
129
|
+
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
|
|
130
|
+
sudo nvidia-ctk runtime configure --runtime=docker
|
|
131
|
+
sudo systemctl restart docker
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Run with GPU access:**
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
docker run -d \
|
|
138
|
+
--name trillboards-edge-cuda \
|
|
139
|
+
--gpus all \
|
|
140
|
+
-e DEVICE_TOKEN=your_token \
|
|
141
|
+
-e CAMERA_ENABLED=true \
|
|
142
|
+
-p 9090:9090 \
|
|
143
|
+
-v trillboards-data:/app/data \
|
|
144
|
+
-v trillboards-models:/app/models \
|
|
145
|
+
ghcr.io/trillboards/edge-sdk:cuda
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**docker-compose with GPU:**
|
|
149
|
+
|
|
150
|
+
```yaml
|
|
151
|
+
services:
|
|
152
|
+
trillboards-edge:
|
|
153
|
+
image: ghcr.io/trillboards/edge-sdk:cuda
|
|
154
|
+
environment:
|
|
155
|
+
DEVICE_TOKEN: "${DEVICE_TOKEN}"
|
|
156
|
+
CAMERA_ENABLED: "true"
|
|
157
|
+
deploy:
|
|
158
|
+
resources:
|
|
159
|
+
reservations:
|
|
160
|
+
devices:
|
|
161
|
+
- driver: nvidia
|
|
162
|
+
count: 1
|
|
163
|
+
capabilities: [gpu]
|
|
164
|
+
ports:
|
|
165
|
+
- "9090:9090"
|
|
166
|
+
volumes:
|
|
167
|
+
- trillboards-data:/app/data
|
|
168
|
+
- trillboards-models:/app/models
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The CUDA image sets `NVIDIA_VISIBLE_DEVICES=all` and `NVIDIA_DRIVER_CAPABILITIES=compute,utility` automatically.
|
|
172
|
+
|
|
173
|
+
## Volume Mounts
|
|
174
|
+
|
|
175
|
+
Two directories should be persisted across container restarts:
|
|
176
|
+
|
|
177
|
+
| Mount Point | Purpose | Contents |
|
|
178
|
+
|-------------|---------|----------|
|
|
179
|
+
| `/app/models` | ONNX model files | `blazeface.onnx`, `yamnet.onnx`, and any OTA-updated models |
|
|
180
|
+
| `/app/data` | Agent persistent state | `signal_buffer.db` (SQLite signal buffer), device identity fingerprint, federated learning gradients |
|
|
181
|
+
|
|
182
|
+
Default models (`blazeface.onnx` and `yamnet.onnx`) are downloaded at image build time from `https://models.trillboards.com/`. If you mount an empty volume, the agent will operate without models until they are downloaded or placed manually.
|
|
183
|
+
|
|
184
|
+
**Pre-populating models on the host:**
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
mkdir -p /opt/trillboards/models
|
|
188
|
+
curl -o /opt/trillboards/models/blazeface.onnx https://models.trillboards.com/blazeface_128x128.onnx
|
|
189
|
+
curl -o /opt/trillboards/models/yamnet.onnx https://models.trillboards.com/yamnet_classification.onnx
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Then mount as a bind volume:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
docker run -d \
|
|
196
|
+
-e DEVICE_TOKEN=your_token \
|
|
197
|
+
-v /opt/trillboards/models:/app/models \
|
|
198
|
+
-v /opt/trillboards/data:/app/data \
|
|
199
|
+
ghcr.io/trillboards/edge-sdk:latest
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Health Check Configuration
|
|
203
|
+
|
|
204
|
+
The container includes a built-in `HEALTHCHECK` that probes the local status server:
|
|
205
|
+
|
|
206
|
+
```dockerfile
|
|
207
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
208
|
+
CMD curl -f http://localhost:9090/health || exit 1
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The `/health` endpoint returns:
|
|
212
|
+
- **200 OK** with `{"status":"ok"}` when all subsystems are healthy
|
|
213
|
+
- **503 Service Unavailable** with `{"status":"degraded","failed":["CAMERA","SOCKET"]}` when one or more subsystems are in an error state
|
|
214
|
+
|
|
215
|
+
Docker reports the container as `healthy`, `unhealthy`, or `starting` based on this probe.
|
|
216
|
+
|
|
217
|
+
To verify manually:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
docker inspect --format='{{.State.Health.Status}}' trillboards-edge
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Building Custom Images
|
|
224
|
+
|
|
225
|
+
All Dockerfiles use multi-stage builds. The build context must be the monorepo root (`trillboards-edge-sdk/`).
|
|
226
|
+
|
|
227
|
+
**CPU image:**
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
cd trillboards-edge-sdk
|
|
231
|
+
docker build -f packages/edge-sdk/deploy/docker/Dockerfile.cpu \
|
|
232
|
+
-t trillboards/edge-sdk:latest .
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**CUDA image:**
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
cd trillboards-edge-sdk
|
|
239
|
+
docker build -f packages/edge-sdk/deploy/docker/Dockerfile.cuda \
|
|
240
|
+
-t trillboards/edge-sdk:cuda .
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**OpenVINO image:**
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
cd trillboards-edge-sdk
|
|
247
|
+
docker build -f packages/edge-sdk/deploy/docker/Dockerfile.openvino \
|
|
248
|
+
-t trillboards/edge-sdk:openvino .
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Build Arguments
|
|
252
|
+
|
|
253
|
+
The Dockerfiles do not expose build arguments by default. To customize the build (for example, to pin a specific Node.js version or add additional system packages), edit the relevant Dockerfile directly.
|
|
254
|
+
|
|
255
|
+
### Multi-Architecture Builds (CPU Image Only)
|
|
256
|
+
|
|
257
|
+
The CPU image supports `linux/amd64` and `linux/arm64` via Docker Buildx:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
docker buildx create --use
|
|
261
|
+
docker buildx build \
|
|
262
|
+
--platform linux/amd64,linux/arm64 \
|
|
263
|
+
-f packages/edge-sdk/deploy/docker/Dockerfile.cpu \
|
|
264
|
+
-t ghcr.io/trillboards/edge-sdk:latest \
|
|
265
|
+
--push .
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The CUDA and OpenVINO images are `linux/amd64` only due to base image constraints.
|
|
269
|
+
|
|
270
|
+
## Camera Device Passthrough
|
|
271
|
+
|
|
272
|
+
For face detection, the container needs access to the host camera device.
|
|
273
|
+
|
|
274
|
+
**USB camera on Linux:**
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
docker run -d \
|
|
278
|
+
--device /dev/video0:/dev/video0 \
|
|
279
|
+
-e DEVICE_TOKEN=your_token \
|
|
280
|
+
-e CAMERA_ENABLED=true \
|
|
281
|
+
ghcr.io/trillboards/edge-sdk:latest
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Multiple cameras:**
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
docker run -d \
|
|
288
|
+
--device /dev/video0 \
|
|
289
|
+
--device /dev/video2 \
|
|
290
|
+
-e DEVICE_TOKEN=your_token \
|
|
291
|
+
-e CAMERA_ENABLED=true \
|
|
292
|
+
ghcr.io/trillboards/edge-sdk:latest
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Privileged mode (not recommended, but required for some RTSP setups):**
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
docker run -d \
|
|
299
|
+
--privileged \
|
|
300
|
+
-e DEVICE_TOKEN=your_token \
|
|
301
|
+
-e CAMERA_ENABLED=true \
|
|
302
|
+
ghcr.io/trillboards/edge-sdk:latest
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Networking
|
|
306
|
+
|
|
307
|
+
The container exposes a single port:
|
|
308
|
+
|
|
309
|
+
| Port | Protocol | Endpoint | Purpose |
|
|
310
|
+
|------|----------|----------|---------|
|
|
311
|
+
| 9090 | HTTP | `/status`, `/health`, `/metrics` | Local status server for monitoring, health checks, and Prometheus scraping |
|
|
312
|
+
|
|
313
|
+
Outbound connectivity is required to:
|
|
314
|
+
- `api.trillboards.com:443` (HTTPS) -- REST API and Socket.io
|
|
315
|
+
- `models.trillboards.com:443` (HTTPS) -- OTA model downloads (optional, only during model updates)
|
|
316
|
+
|
|
317
|
+
## Logging
|
|
318
|
+
|
|
319
|
+
Logs are written to stdout/stderr in structured format:
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
[2026-03-16T14:30:00.000Z] [INFO] Starting Trillboards Edge Agent v0.2.2
|
|
323
|
+
[2026-03-16T14:30:00.050Z] [INFO] Platform adapter loaded: linux
|
|
324
|
+
[2026-03-16T14:30:00.100Z] [INFO] Device fingerprint: abc123def456
|
|
325
|
+
[2026-03-16T14:30:00.150Z] [INFO] Capability tier: TIER_2 (...)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Use `LOG_LEVEL=debug` for verbose output during troubleshooting. In production, `info` is sufficient.
|
|
329
|
+
|
|
330
|
+
View logs:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
docker logs -f trillboards-edge
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Troubleshooting
|
|
337
|
+
|
|
338
|
+
**Container exits immediately:**
|
|
339
|
+
- Check that `DEVICE_TOKEN` is set and valid. The agent throws an error at startup if the token is empty.
|
|
340
|
+
- Verify API connectivity: `docker run --rm ghcr.io/trillboards/edge-sdk:latest curl -s https://api.trillboards.com/health/live`
|
|
341
|
+
|
|
342
|
+
**Health check fails:**
|
|
343
|
+
- The status server takes up to 30 seconds to start (matching the `start_period` in the health check).
|
|
344
|
+
- Check logs for initialization errors: `docker logs trillboards-edge`
|
|
345
|
+
|
|
346
|
+
**Camera not detected:**
|
|
347
|
+
- Verify the host device exists: `ls -la /dev/video*`
|
|
348
|
+
- Pass the device explicitly: `--device /dev/video0`
|
|
349
|
+
- Check permissions inside the container: `docker exec trillboards-edge ls -la /dev/video0`
|
|
350
|
+
|
|
351
|
+
**CUDA not available:**
|
|
352
|
+
- Verify the NVIDIA runtime is installed: `docker run --rm --gpus all nvidia/cuda:12.3.2-runtime-ubuntu22.04 nvidia-smi`
|
|
353
|
+
- Ensure you are using the `cuda` tag, not `latest`
|
|
354
|
+
|
|
355
|
+
**Models not found:**
|
|
356
|
+
- Models are downloaded at image build time. If the build had no network access, models will be missing.
|
|
357
|
+
- Mount a volume with pre-downloaded models at `/app/models`
|
|
358
|
+
- Or download inside the container: `docker exec trillboards-edge node -e "..." ` (see Dockerfile for the download script)
|