@trillboards/edge-sdk 0.2.1 → 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 +5 -4
package/README.md
CHANGED
|
@@ -59,10 +59,17 @@ await agent.start();
|
|
|
59
59
|
|
|
60
60
|
| Command | Description |
|
|
61
61
|
|---------|-------------|
|
|
62
|
+
| `trillboards-edge demo` | Try it instantly -- synthetic audience sensing with a live terminal dashboard. No token, camera, or models required. |
|
|
63
|
+
| `trillboards-edge init` | Interactive setup wizard -- prompts for token, platform, camera, audio, kiosk, models, and execution provider |
|
|
62
64
|
| `trillboards-edge start [--config path]` | Start the edge agent |
|
|
65
|
+
| `trillboards-edge status [--host h] [--port p] [--json] [--watch]` | Query the agent status endpoint and display a formatted dashboard |
|
|
66
|
+
| `trillboards-edge diagnose [--json]` | Run 10 system diagnostic checks (Node.js, platform, memory, CPU, disk, camera, models, API, GPU, network) |
|
|
67
|
+
| `trillboards-edge mcp` | Start the MCP server for AI agent integration (Claude Desktop, Cursor) |
|
|
63
68
|
| `trillboards-edge download-models [--dir path]` | Download ONNX models (BlazeFace, YAMNet) |
|
|
64
69
|
| `trillboards-edge version` | Print SDK version |
|
|
65
70
|
|
|
71
|
+
See [docs/CLI.md](../../docs/CLI.md) for the full CLI reference with all flags and configuration details.
|
|
72
|
+
|
|
66
73
|
## Capability Tiers
|
|
67
74
|
|
|
68
75
|
The SDK auto-detects device capabilities and adjusts inference accordingly:
|
|
@@ -95,10 +102,137 @@ This is the umbrella package. For fine-grained control, install sub-packages ind
|
|
|
95
102
|
| [@trillboards/edge-platform-linux](https://www.npmjs.com/package/@trillboards/edge-platform-linux) | V4L2 camera, PulseAudio, systemd, kiosk mode |
|
|
96
103
|
| [@trillboards/edge-platform-windows](https://www.npmjs.com/package/@trillboards/edge-platform-windows) | DirectShow, RTSP IP cameras, WASAPI audio |
|
|
97
104
|
|
|
105
|
+
## MCP Server (AI Agent Integration)
|
|
106
|
+
|
|
107
|
+
The SDK includes a built-in MCP (Model Context Protocol) server that allows
|
|
108
|
+
AI agents to discover, configure, and diagnose edge devices.
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
trillboards-edge mcp
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The server communicates over stdio using JSON-RPC 2.0 and talks to the running
|
|
115
|
+
edge agent's StatusServer on `localhost:9090`.
|
|
116
|
+
|
|
117
|
+
**7 tools available:** `get-device-status`, `get-audience-live`,
|
|
118
|
+
`configure-sensing`, `run-benchmark`, `diagnose-hardware`, `list-models`,
|
|
119
|
+
`get-buffer-stats`.
|
|
120
|
+
|
|
121
|
+
**Claude Desktop config** (`claude_desktop_config.json`):
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"trillboards-edge": {
|
|
127
|
+
"command": "npx",
|
|
128
|
+
"args": ["-y", "@trillboards/edge-sdk", "mcp"],
|
|
129
|
+
"env": { "EDGE_STATUS_PORT": "9090" }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Cursor config** (`.cursor/mcp.json`):
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"mcpServers": {
|
|
140
|
+
"trillboards-edge": {
|
|
141
|
+
"command": "npx",
|
|
142
|
+
"args": ["-y", "@trillboards/edge-sdk", "mcp"]
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
See [docs/MCP.md](../../docs/MCP.md) for the full MCP server reference.
|
|
149
|
+
|
|
150
|
+
## Status Endpoint
|
|
151
|
+
|
|
152
|
+
When the edge agent is running, it exposes an HTTP status server (default port
|
|
153
|
+
9090) with three endpoints:
|
|
154
|
+
|
|
155
|
+
| Endpoint | Method | Description |
|
|
156
|
+
|----------|--------|-------------|
|
|
157
|
+
| `/status` | GET | Full JSON status payload (device, sensing, subsystems, buffer) |
|
|
158
|
+
| `/health` | GET | Health check -- returns 200 if healthy, 503 if degraded |
|
|
159
|
+
| `/metrics` | GET | Prometheus-format metrics for scraping |
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
curl http://localhost:9090/status # Full status JSON
|
|
163
|
+
curl http://localhost:9090/health # Health check
|
|
164
|
+
curl http://localhost:9090/metrics # Prometheus metrics
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Query from the CLI:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
trillboards-edge status # Formatted dashboard
|
|
171
|
+
trillboards-edge status --watch # Refresh every 5s
|
|
172
|
+
trillboards-edge status --host 192.168.1.50 # Remote device
|
|
173
|
+
trillboards-edge status --json # Raw JSON
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
See [docs/STATUS_API.md](../../docs/STATUS_API.md) for the full status API reference.
|
|
177
|
+
|
|
178
|
+
## Docker Deployment
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# CPU (default)
|
|
182
|
+
docker run -d \
|
|
183
|
+
--name trillboards-edge \
|
|
184
|
+
-e DEVICE_TOKEN=your-token \
|
|
185
|
+
-p 9090:9090 \
|
|
186
|
+
--device /dev/video0:/dev/video0 \
|
|
187
|
+
trillboards/edge-sdk:latest
|
|
188
|
+
|
|
189
|
+
# NVIDIA GPU
|
|
190
|
+
docker run -d \
|
|
191
|
+
--name trillboards-edge \
|
|
192
|
+
--gpus all \
|
|
193
|
+
-e DEVICE_TOKEN=your-token \
|
|
194
|
+
-p 9090:9090 \
|
|
195
|
+
--device /dev/video0:/dev/video0 \
|
|
196
|
+
trillboards/edge-sdk:cuda
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**docker-compose:**
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
services:
|
|
203
|
+
edge-agent:
|
|
204
|
+
image: trillboards/edge-sdk:latest
|
|
205
|
+
restart: unless-stopped
|
|
206
|
+
environment:
|
|
207
|
+
- DEVICE_TOKEN=${DEVICE_TOKEN}
|
|
208
|
+
ports:
|
|
209
|
+
- "9090:9090"
|
|
210
|
+
devices:
|
|
211
|
+
- /dev/video0:/dev/video0
|
|
212
|
+
volumes:
|
|
213
|
+
- ./models:/app/models
|
|
214
|
+
healthcheck:
|
|
215
|
+
test: ["CMD", "curl", "-f", "http://localhost:9090/health"]
|
|
216
|
+
interval: 30s
|
|
217
|
+
timeout: 5s
|
|
218
|
+
retries: 3
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The `create-trillboards-edge` scaffolding tool can generate a complete Docker or
|
|
222
|
+
Kubernetes project for you:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
npx create-trillboards-edge my-deploy --template docker
|
|
226
|
+
npx create-trillboards-edge fleet --template kubernetes
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
See [deploy/docker/README.md](../../deploy/docker/README.md) and
|
|
230
|
+
[deploy/helm/README.md](../../deploy/helm/README.md) for full deployment guides.
|
|
231
|
+
|
|
98
232
|
## Platform Support
|
|
99
233
|
|
|
100
|
-
- **Linux**
|
|
101
|
-
- **Windows**
|
|
234
|
+
- **Linux** -- Ubuntu 20.04+, Debian 11+, Raspberry Pi OS (ARM64)
|
|
235
|
+
- **Windows** -- Windows 10/11 (x64)
|
|
102
236
|
|
|
103
237
|
## Get a Device Token
|
|
104
238
|
|
|
@@ -108,6 +242,17 @@ npx @trillboards/ads-sdk init
|
|
|
108
242
|
|
|
109
243
|
Or register via the [Trillboards API](https://api.trillboards.com/developer).
|
|
110
244
|
|
|
245
|
+
## Documentation
|
|
246
|
+
|
|
247
|
+
| Document | Description |
|
|
248
|
+
|----------|-------------|
|
|
249
|
+
| [docs/CLI.md](../../docs/CLI.md) | Full CLI reference with all commands, flags, and configuration |
|
|
250
|
+
| [docs/MCP.md](../../docs/MCP.md) | MCP server reference for AI agent integration |
|
|
251
|
+
| [docs/STATUS_API.md](../../docs/STATUS_API.md) | Status endpoint API reference |
|
|
252
|
+
| [deploy/docker/README.md](../../deploy/docker/README.md) | Docker deployment guide |
|
|
253
|
+
| [deploy/helm/README.md](../../deploy/helm/README.md) | Helm chart deployment guide |
|
|
254
|
+
| [create-trillboards-edge](../../../create-trillboards-edge/README.md) | Project scaffolding tool |
|
|
255
|
+
|
|
111
256
|
## License
|
|
112
257
|
|
|
113
258
|
MIT
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Trillboards Edge AI SDK — CPU-only container
|
|
2
|
+
# Usage: docker build -f Dockerfile.cpu -t trillboards/edge-sdk:latest ../../
|
|
3
|
+
# Run: docker run -e DEVICE_TOKEN=xxx trillboards/edge-sdk:latest
|
|
4
|
+
|
|
5
|
+
FROM node:20-slim AS builder
|
|
6
|
+
|
|
7
|
+
WORKDIR /build
|
|
8
|
+
|
|
9
|
+
# Copy workspace package files first for layer caching
|
|
10
|
+
COPY package.json package-lock.json* ./
|
|
11
|
+
COPY packages/edge-core/package.json packages/edge-core/
|
|
12
|
+
COPY packages/edge-sensing/package.json packages/edge-sensing/
|
|
13
|
+
COPY packages/edge-federated/package.json packages/edge-federated/
|
|
14
|
+
COPY packages/edge-ads/package.json packages/edge-ads/
|
|
15
|
+
COPY packages/edge-cloud/package.json packages/edge-cloud/
|
|
16
|
+
COPY packages/edge-sdk/package.json packages/edge-sdk/
|
|
17
|
+
COPY packages/edge-platform-linux/package.json packages/edge-platform-linux/
|
|
18
|
+
|
|
19
|
+
# Install all dependencies
|
|
20
|
+
RUN npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps
|
|
21
|
+
|
|
22
|
+
# Copy source and build
|
|
23
|
+
COPY . .
|
|
24
|
+
RUN npm run build --workspaces --if-present
|
|
25
|
+
|
|
26
|
+
# ─── Production image ─────────────────────────────────────────────────────
|
|
27
|
+
FROM node:20-slim
|
|
28
|
+
|
|
29
|
+
LABEL maintainer="Trillboards <engineering@trillboards.com>"
|
|
30
|
+
LABEL description="Trillboards Edge AI SDK — CPU-only container for DOOH audience sensing"
|
|
31
|
+
|
|
32
|
+
# Install runtime dependencies for camera/audio (optional — headless works without)
|
|
33
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
34
|
+
libv4l-dev \
|
|
35
|
+
libasound2 \
|
|
36
|
+
ca-certificates \
|
|
37
|
+
curl \
|
|
38
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
39
|
+
|
|
40
|
+
WORKDIR /app
|
|
41
|
+
|
|
42
|
+
# Copy built packages
|
|
43
|
+
COPY --from=builder /build/packages/edge-core/dist packages/edge-core/dist
|
|
44
|
+
COPY --from=builder /build/packages/edge-core/package.json packages/edge-core/
|
|
45
|
+
COPY --from=builder /build/packages/edge-sensing/dist packages/edge-sensing/dist
|
|
46
|
+
COPY --from=builder /build/packages/edge-sensing/package.json packages/edge-sensing/
|
|
47
|
+
COPY --from=builder /build/packages/edge-federated/dist packages/edge-federated/dist
|
|
48
|
+
COPY --from=builder /build/packages/edge-federated/package.json packages/edge-federated/
|
|
49
|
+
COPY --from=builder /build/packages/edge-ads/dist packages/edge-ads/dist
|
|
50
|
+
COPY --from=builder /build/packages/edge-ads/package.json packages/edge-ads/
|
|
51
|
+
COPY --from=builder /build/packages/edge-cloud/dist packages/edge-cloud/dist
|
|
52
|
+
COPY --from=builder /build/packages/edge-cloud/package.json packages/edge-cloud/
|
|
53
|
+
COPY --from=builder /build/packages/edge-sdk/dist packages/edge-sdk/dist
|
|
54
|
+
COPY --from=builder /build/packages/edge-sdk/package.json packages/edge-sdk/
|
|
55
|
+
COPY --from=builder /build/packages/edge-platform-linux/dist packages/edge-platform-linux/dist
|
|
56
|
+
COPY --from=builder /build/packages/edge-platform-linux/package.json packages/edge-platform-linux/
|
|
57
|
+
|
|
58
|
+
# Copy configs directory
|
|
59
|
+
COPY --from=builder /build/packages/edge-sdk/configs packages/edge-sdk/configs
|
|
60
|
+
|
|
61
|
+
# Install production dependencies only
|
|
62
|
+
COPY --from=builder /build/package.json /build/package-lock.json* ./
|
|
63
|
+
RUN npm ci --legacy-peer-deps --omit=dev 2>/dev/null || npm install --legacy-peer-deps --omit=dev
|
|
64
|
+
|
|
65
|
+
# Create models directory
|
|
66
|
+
RUN mkdir -p /app/models /app/data
|
|
67
|
+
|
|
68
|
+
# Download default models at build time
|
|
69
|
+
RUN node -e " \
|
|
70
|
+
const https = require('https'); \
|
|
71
|
+
const fs = require('fs'); \
|
|
72
|
+
const models = { \
|
|
73
|
+
'blazeface.onnx': 'https://models.trillboards.com/blazeface_128x128.onnx', \
|
|
74
|
+
'yamnet.onnx': 'https://models.trillboards.com/yamnet_classification.onnx', \
|
|
75
|
+
}; \
|
|
76
|
+
Object.entries(models).forEach(([name, url]) => { \
|
|
77
|
+
console.log('Downloading ' + name + '...'); \
|
|
78
|
+
const file = fs.createWriteStream('/app/models/' + name); \
|
|
79
|
+
https.get(url, (res) => { \
|
|
80
|
+
if (res.statusCode === 301 || res.statusCode === 302) { \
|
|
81
|
+
https.get(res.headers.location, (r) => r.pipe(file)); \
|
|
82
|
+
} else { \
|
|
83
|
+
res.pipe(file); \
|
|
84
|
+
} \
|
|
85
|
+
}); \
|
|
86
|
+
}); \
|
|
87
|
+
" 2>/dev/null || echo "Model download skipped (build-time network may be unavailable)"
|
|
88
|
+
|
|
89
|
+
# Environment variables with defaults
|
|
90
|
+
ENV NODE_ENV=production
|
|
91
|
+
ENV DEVICE_TOKEN=""
|
|
92
|
+
ENV SCREEN_ID=""
|
|
93
|
+
ENV VENUE_TYPE=""
|
|
94
|
+
ENV API_BASE_URL="https://api.trillboards.com"
|
|
95
|
+
ENV CAMERA_ENABLED="false"
|
|
96
|
+
ENV AUDIO_ENABLED="false"
|
|
97
|
+
ENV KIOSK_ENABLED="false"
|
|
98
|
+
ENV MODELS_DIR="/app/models"
|
|
99
|
+
ENV DATA_DIR="/app/data"
|
|
100
|
+
ENV EXECUTION_PROVIDER="cpu"
|
|
101
|
+
ENV STATUS_PORT="9090"
|
|
102
|
+
ENV LOG_LEVEL="info"
|
|
103
|
+
|
|
104
|
+
# Expose status server port
|
|
105
|
+
EXPOSE 9090
|
|
106
|
+
|
|
107
|
+
# Health check against the local status endpoint
|
|
108
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
109
|
+
CMD curl -f http://localhost:9090/health || exit 1
|
|
110
|
+
|
|
111
|
+
# Generate config from env vars and start
|
|
112
|
+
ENTRYPOINT ["/bin/sh", "-c", "\
|
|
113
|
+
echo '{}' | node -e \" \
|
|
114
|
+
const cfg = { \
|
|
115
|
+
apiBaseUrl: process.env.API_BASE_URL, \
|
|
116
|
+
deviceToken: process.env.DEVICE_TOKEN, \
|
|
117
|
+
screenId: process.env.SCREEN_ID || undefined, \
|
|
118
|
+
venueType: process.env.VENUE_TYPE || undefined, \
|
|
119
|
+
platform: 'linux', \
|
|
120
|
+
camera: { enabled: process.env.CAMERA_ENABLED === 'true' }, \
|
|
121
|
+
audio: { enabled: process.env.AUDIO_ENABLED === 'true' }, \
|
|
122
|
+
models: { dir: process.env.MODELS_DIR, executionProvider: process.env.EXECUTION_PROVIDER }, \
|
|
123
|
+
kiosk: { enabled: process.env.KIOSK_ENABLED === 'true' }, \
|
|
124
|
+
cloud: { enabled: false }, \
|
|
125
|
+
federated: { enabled: true }, \
|
|
126
|
+
dataDir: process.env.DATA_DIR, \
|
|
127
|
+
logLevel: process.env.LOG_LEVEL, \
|
|
128
|
+
}; \
|
|
129
|
+
require('fs').writeFileSync('/app/config.json', JSON.stringify(cfg, null, 2)); \
|
|
130
|
+
\" && \
|
|
131
|
+
node packages/edge-sdk/dist/cli.js start --config /app/config.json \
|
|
132
|
+
"]
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Trillboards Edge AI SDK — NVIDIA CUDA container
|
|
2
|
+
# Usage: docker build -f Dockerfile.cuda -t trillboards/edge-sdk:cuda ../../
|
|
3
|
+
# Run: docker run --gpus all -e DEVICE_TOKEN=xxx trillboards/edge-sdk:cuda
|
|
4
|
+
|
|
5
|
+
FROM nvidia/cuda:12.3.2-runtime-ubuntu22.04 AS base
|
|
6
|
+
|
|
7
|
+
# Install Node.js 20
|
|
8
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
9
|
+
curl \
|
|
10
|
+
ca-certificates \
|
|
11
|
+
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
|
12
|
+
&& apt-get install -y nodejs \
|
|
13
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
14
|
+
|
|
15
|
+
# ─── Builder stage ─────────────────────────────────────────────────────────
|
|
16
|
+
FROM base AS builder
|
|
17
|
+
|
|
18
|
+
WORKDIR /build
|
|
19
|
+
|
|
20
|
+
COPY package.json package-lock.json* ./
|
|
21
|
+
COPY packages/edge-core/package.json packages/edge-core/
|
|
22
|
+
COPY packages/edge-sensing/package.json packages/edge-sensing/
|
|
23
|
+
COPY packages/edge-federated/package.json packages/edge-federated/
|
|
24
|
+
COPY packages/edge-ads/package.json packages/edge-ads/
|
|
25
|
+
COPY packages/edge-cloud/package.json packages/edge-cloud/
|
|
26
|
+
COPY packages/edge-sdk/package.json packages/edge-sdk/
|
|
27
|
+
COPY packages/edge-platform-linux/package.json packages/edge-platform-linux/
|
|
28
|
+
|
|
29
|
+
RUN npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps
|
|
30
|
+
|
|
31
|
+
COPY . .
|
|
32
|
+
RUN npm run build --workspaces --if-present
|
|
33
|
+
|
|
34
|
+
# ─── Production image ─────────────────────────────────────────────────────
|
|
35
|
+
FROM base
|
|
36
|
+
|
|
37
|
+
LABEL maintainer="Trillboards <engineering@trillboards.com>"
|
|
38
|
+
LABEL description="Trillboards Edge AI SDK — NVIDIA CUDA container for GPU-accelerated audience sensing"
|
|
39
|
+
|
|
40
|
+
# Install runtime dependencies
|
|
41
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
42
|
+
libv4l-dev \
|
|
43
|
+
libasound2 \
|
|
44
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
45
|
+
|
|
46
|
+
WORKDIR /app
|
|
47
|
+
|
|
48
|
+
# Copy built packages
|
|
49
|
+
COPY --from=builder /build/packages/edge-core/dist packages/edge-core/dist
|
|
50
|
+
COPY --from=builder /build/packages/edge-core/package.json packages/edge-core/
|
|
51
|
+
COPY --from=builder /build/packages/edge-sensing/dist packages/edge-sensing/dist
|
|
52
|
+
COPY --from=builder /build/packages/edge-sensing/package.json packages/edge-sensing/
|
|
53
|
+
COPY --from=builder /build/packages/edge-federated/dist packages/edge-federated/dist
|
|
54
|
+
COPY --from=builder /build/packages/edge-federated/package.json packages/edge-federated/
|
|
55
|
+
COPY --from=builder /build/packages/edge-ads/dist packages/edge-ads/dist
|
|
56
|
+
COPY --from=builder /build/packages/edge-ads/package.json packages/edge-ads/
|
|
57
|
+
COPY --from=builder /build/packages/edge-cloud/dist packages/edge-cloud/dist
|
|
58
|
+
COPY --from=builder /build/packages/edge-cloud/package.json packages/edge-cloud/
|
|
59
|
+
COPY --from=builder /build/packages/edge-sdk/dist packages/edge-sdk/dist
|
|
60
|
+
COPY --from=builder /build/packages/edge-sdk/package.json packages/edge-sdk/
|
|
61
|
+
COPY --from=builder /build/packages/edge-platform-linux/dist packages/edge-platform-linux/dist
|
|
62
|
+
COPY --from=builder /build/packages/edge-platform-linux/package.json packages/edge-platform-linux/
|
|
63
|
+
|
|
64
|
+
COPY --from=builder /build/packages/edge-sdk/configs packages/edge-sdk/configs
|
|
65
|
+
COPY --from=builder /build/package.json /build/package-lock.json* ./
|
|
66
|
+
RUN npm ci --legacy-peer-deps --omit=dev 2>/dev/null || npm install --legacy-peer-deps --omit=dev
|
|
67
|
+
|
|
68
|
+
RUN mkdir -p /app/models /app/data
|
|
69
|
+
|
|
70
|
+
# Download default models
|
|
71
|
+
RUN node -e " \
|
|
72
|
+
const https = require('https'); \
|
|
73
|
+
const fs = require('fs'); \
|
|
74
|
+
const models = { \
|
|
75
|
+
'blazeface.onnx': 'https://models.trillboards.com/blazeface_128x128.onnx', \
|
|
76
|
+
'yamnet.onnx': 'https://models.trillboards.com/yamnet_classification.onnx', \
|
|
77
|
+
}; \
|
|
78
|
+
Object.entries(models).forEach(([name, url]) => { \
|
|
79
|
+
console.log('Downloading ' + name + '...'); \
|
|
80
|
+
const file = fs.createWriteStream('/app/models/' + name); \
|
|
81
|
+
https.get(url, (res) => { \
|
|
82
|
+
if (res.statusCode === 301 || res.statusCode === 302) { \
|
|
83
|
+
https.get(res.headers.location, (r) => r.pipe(file)); \
|
|
84
|
+
} else { \
|
|
85
|
+
res.pipe(file); \
|
|
86
|
+
} \
|
|
87
|
+
}); \
|
|
88
|
+
}); \
|
|
89
|
+
" 2>/dev/null || echo "Model download skipped"
|
|
90
|
+
|
|
91
|
+
ENV NODE_ENV=production
|
|
92
|
+
ENV DEVICE_TOKEN=""
|
|
93
|
+
ENV SCREEN_ID=""
|
|
94
|
+
ENV VENUE_TYPE=""
|
|
95
|
+
ENV API_BASE_URL="https://api.trillboards.com"
|
|
96
|
+
ENV CAMERA_ENABLED="false"
|
|
97
|
+
ENV AUDIO_ENABLED="false"
|
|
98
|
+
ENV KIOSK_ENABLED="false"
|
|
99
|
+
ENV MODELS_DIR="/app/models"
|
|
100
|
+
ENV DATA_DIR="/app/data"
|
|
101
|
+
ENV EXECUTION_PROVIDER="cuda"
|
|
102
|
+
ENV STATUS_PORT="9090"
|
|
103
|
+
ENV LOG_LEVEL="info"
|
|
104
|
+
|
|
105
|
+
# NVIDIA runtime configuration
|
|
106
|
+
ENV NVIDIA_VISIBLE_DEVICES=all
|
|
107
|
+
ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility
|
|
108
|
+
|
|
109
|
+
EXPOSE 9090
|
|
110
|
+
|
|
111
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
112
|
+
CMD curl -f http://localhost:9090/health || exit 1
|
|
113
|
+
|
|
114
|
+
ENTRYPOINT ["/bin/sh", "-c", "\
|
|
115
|
+
echo '{}' | node -e \" \
|
|
116
|
+
const cfg = { \
|
|
117
|
+
apiBaseUrl: process.env.API_BASE_URL, \
|
|
118
|
+
deviceToken: process.env.DEVICE_TOKEN, \
|
|
119
|
+
screenId: process.env.SCREEN_ID || undefined, \
|
|
120
|
+
venueType: process.env.VENUE_TYPE || undefined, \
|
|
121
|
+
platform: 'linux', \
|
|
122
|
+
camera: { enabled: process.env.CAMERA_ENABLED === 'true' }, \
|
|
123
|
+
audio: { enabled: process.env.AUDIO_ENABLED === 'true' }, \
|
|
124
|
+
models: { dir: process.env.MODELS_DIR, executionProvider: process.env.EXECUTION_PROVIDER }, \
|
|
125
|
+
kiosk: { enabled: process.env.KIOSK_ENABLED === 'true' }, \
|
|
126
|
+
cloud: { enabled: false }, \
|
|
127
|
+
federated: { enabled: true }, \
|
|
128
|
+
dataDir: process.env.DATA_DIR, \
|
|
129
|
+
logLevel: process.env.LOG_LEVEL, \
|
|
130
|
+
}; \
|
|
131
|
+
require('fs').writeFileSync('/app/config.json', JSON.stringify(cfg, null, 2)); \
|
|
132
|
+
\" && \
|
|
133
|
+
node packages/edge-sdk/dist/cli.js start --config /app/config.json \
|
|
134
|
+
"]
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Trillboards Edge AI SDK — Intel OpenVINO container
|
|
2
|
+
# Usage: docker build -f Dockerfile.openvino -t trillboards/edge-sdk:openvino ../../
|
|
3
|
+
# Run: docker run -e DEVICE_TOKEN=xxx trillboards/edge-sdk:openvino
|
|
4
|
+
# Optimized for Intel HD 620+ GPUs (Backpackster, NUC, mini-PCs)
|
|
5
|
+
|
|
6
|
+
FROM openvino/ubuntu22_runtime:2024.0.0 AS base
|
|
7
|
+
|
|
8
|
+
USER root
|
|
9
|
+
|
|
10
|
+
# Install Node.js 20
|
|
11
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
12
|
+
curl \
|
|
13
|
+
ca-certificates \
|
|
14
|
+
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
|
15
|
+
&& apt-get install -y nodejs \
|
|
16
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
17
|
+
|
|
18
|
+
# ─── Builder stage ─────────────────────────────────────────────────────────
|
|
19
|
+
FROM base AS builder
|
|
20
|
+
|
|
21
|
+
WORKDIR /build
|
|
22
|
+
|
|
23
|
+
COPY package.json package-lock.json* ./
|
|
24
|
+
COPY packages/edge-core/package.json packages/edge-core/
|
|
25
|
+
COPY packages/edge-sensing/package.json packages/edge-sensing/
|
|
26
|
+
COPY packages/edge-federated/package.json packages/edge-federated/
|
|
27
|
+
COPY packages/edge-ads/package.json packages/edge-ads/
|
|
28
|
+
COPY packages/edge-cloud/package.json packages/edge-cloud/
|
|
29
|
+
COPY packages/edge-sdk/package.json packages/edge-sdk/
|
|
30
|
+
COPY packages/edge-platform-linux/package.json packages/edge-platform-linux/
|
|
31
|
+
|
|
32
|
+
RUN npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps
|
|
33
|
+
|
|
34
|
+
COPY . .
|
|
35
|
+
RUN npm run build --workspaces --if-present
|
|
36
|
+
|
|
37
|
+
# ─── Production image ─────────────────────────────────────────────────────
|
|
38
|
+
FROM base
|
|
39
|
+
|
|
40
|
+
LABEL maintainer="Trillboards <engineering@trillboards.com>"
|
|
41
|
+
LABEL description="Trillboards Edge AI SDK — Intel OpenVINO container for accelerated inference"
|
|
42
|
+
|
|
43
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
44
|
+
libv4l-dev \
|
|
45
|
+
libasound2 \
|
|
46
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
47
|
+
|
|
48
|
+
WORKDIR /app
|
|
49
|
+
|
|
50
|
+
COPY --from=builder /build/packages/edge-core/dist packages/edge-core/dist
|
|
51
|
+
COPY --from=builder /build/packages/edge-core/package.json packages/edge-core/
|
|
52
|
+
COPY --from=builder /build/packages/edge-sensing/dist packages/edge-sensing/dist
|
|
53
|
+
COPY --from=builder /build/packages/edge-sensing/package.json packages/edge-sensing/
|
|
54
|
+
COPY --from=builder /build/packages/edge-federated/dist packages/edge-federated/dist
|
|
55
|
+
COPY --from=builder /build/packages/edge-federated/package.json packages/edge-federated/
|
|
56
|
+
COPY --from=builder /build/packages/edge-ads/dist packages/edge-ads/dist
|
|
57
|
+
COPY --from=builder /build/packages/edge-ads/package.json packages/edge-ads/
|
|
58
|
+
COPY --from=builder /build/packages/edge-cloud/dist packages/edge-cloud/dist
|
|
59
|
+
COPY --from=builder /build/packages/edge-cloud/package.json packages/edge-cloud/
|
|
60
|
+
COPY --from=builder /build/packages/edge-sdk/dist packages/edge-sdk/dist
|
|
61
|
+
COPY --from=builder /build/packages/edge-sdk/package.json packages/edge-sdk/
|
|
62
|
+
COPY --from=builder /build/packages/edge-platform-linux/dist packages/edge-platform-linux/dist
|
|
63
|
+
COPY --from=builder /build/packages/edge-platform-linux/package.json packages/edge-platform-linux/
|
|
64
|
+
|
|
65
|
+
COPY --from=builder /build/packages/edge-sdk/configs packages/edge-sdk/configs
|
|
66
|
+
COPY --from=builder /build/package.json /build/package-lock.json* ./
|
|
67
|
+
RUN npm ci --legacy-peer-deps --omit=dev 2>/dev/null || npm install --legacy-peer-deps --omit=dev
|
|
68
|
+
|
|
69
|
+
RUN mkdir -p /app/models /app/data
|
|
70
|
+
|
|
71
|
+
RUN node -e " \
|
|
72
|
+
const https = require('https'); \
|
|
73
|
+
const fs = require('fs'); \
|
|
74
|
+
const models = { \
|
|
75
|
+
'blazeface.onnx': 'https://models.trillboards.com/blazeface_128x128.onnx', \
|
|
76
|
+
'yamnet.onnx': 'https://models.trillboards.com/yamnet_classification.onnx', \
|
|
77
|
+
}; \
|
|
78
|
+
Object.entries(models).forEach(([name, url]) => { \
|
|
79
|
+
console.log('Downloading ' + name + '...'); \
|
|
80
|
+
const file = fs.createWriteStream('/app/models/' + name); \
|
|
81
|
+
https.get(url, (res) => { \
|
|
82
|
+
if (res.statusCode === 301 || res.statusCode === 302) { \
|
|
83
|
+
https.get(res.headers.location, (r) => r.pipe(file)); \
|
|
84
|
+
} else { \
|
|
85
|
+
res.pipe(file); \
|
|
86
|
+
} \
|
|
87
|
+
}); \
|
|
88
|
+
}); \
|
|
89
|
+
" 2>/dev/null || echo "Model download skipped"
|
|
90
|
+
|
|
91
|
+
ENV NODE_ENV=production
|
|
92
|
+
ENV DEVICE_TOKEN=""
|
|
93
|
+
ENV SCREEN_ID=""
|
|
94
|
+
ENV VENUE_TYPE=""
|
|
95
|
+
ENV API_BASE_URL="https://api.trillboards.com"
|
|
96
|
+
ENV CAMERA_ENABLED="false"
|
|
97
|
+
ENV AUDIO_ENABLED="false"
|
|
98
|
+
ENV KIOSK_ENABLED="false"
|
|
99
|
+
ENV MODELS_DIR="/app/models"
|
|
100
|
+
ENV DATA_DIR="/app/data"
|
|
101
|
+
ENV EXECUTION_PROVIDER="openvino"
|
|
102
|
+
ENV STATUS_PORT="9090"
|
|
103
|
+
ENV LOG_LEVEL="info"
|
|
104
|
+
|
|
105
|
+
EXPOSE 9090
|
|
106
|
+
|
|
107
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
108
|
+
CMD curl -f http://localhost:9090/health || exit 1
|
|
109
|
+
|
|
110
|
+
ENTRYPOINT ["/bin/sh", "-c", "\
|
|
111
|
+
source /opt/intel/openvino/setupvars.sh && \
|
|
112
|
+
echo '{}' | node -e \" \
|
|
113
|
+
const cfg = { \
|
|
114
|
+
apiBaseUrl: process.env.API_BASE_URL, \
|
|
115
|
+
deviceToken: process.env.DEVICE_TOKEN, \
|
|
116
|
+
screenId: process.env.SCREEN_ID || undefined, \
|
|
117
|
+
venueType: process.env.VENUE_TYPE || undefined, \
|
|
118
|
+
platform: 'linux', \
|
|
119
|
+
camera: { enabled: process.env.CAMERA_ENABLED === 'true' }, \
|
|
120
|
+
audio: { enabled: process.env.AUDIO_ENABLED === 'true' }, \
|
|
121
|
+
models: { dir: process.env.MODELS_DIR, executionProvider: process.env.EXECUTION_PROVIDER }, \
|
|
122
|
+
kiosk: { enabled: process.env.KIOSK_ENABLED === 'true' }, \
|
|
123
|
+
cloud: { enabled: false }, \
|
|
124
|
+
federated: { enabled: true }, \
|
|
125
|
+
dataDir: process.env.DATA_DIR, \
|
|
126
|
+
logLevel: process.env.LOG_LEVEL, \
|
|
127
|
+
}; \
|
|
128
|
+
require('fs').writeFileSync('/app/config.json', JSON.stringify(cfg, null, 2)); \
|
|
129
|
+
\" && \
|
|
130
|
+
node packages/edge-sdk/dist/cli.js start --config /app/config.json \
|
|
131
|
+
"]
|