Appearance
About this article
- Audience: Operators and integrators who need config paths, layer env contracts, and script entry points without reading firmware source
- Goal: After reading, you can locate device config, apply Edge AI layers, run deploy and verification scripts, and probe health through the proxy
- Type: Reference
Summary
Shadow configuration splits between the baked edge app bundle image, cumulative Edge AI layer env files, and durable paths under /data/config/. Deploy and layer scripts live in [repo-root]/oak-vms-firmware/scripts/; soak and fleet automation extend into [repo-root]/cost-sentinel/ and [repo-root]/tools/. Use the proxy on port 8788 for post-change verification—not repeated oakctl operations on running fleet devices.
Prerequisites
- SSH:
root@<device-ip>withYOUR_DEVICE_PASSWORD - Proxy:
export PHANTOM_PROXY=https://<phantom-proxy>:8788 - Repo checkout at
[repo-root]withoak-vms-firmware/andcost-sentinel/trees - One shadow role label (
site-role-a,site-role-b) for contract checks
Configuration paths
| Location | Purpose |
|---|---|
oak-vms-firmware/oakapp.toml | App ID, entrypoint, build steps; small RF-DETR models baked to /app/models/ |
oak-vms-firmware/config/depthai_v3_layers/*.env | Layer0–5 source env; merged cumulatively on apply |
/data/config/depthai_v3_layer.env | Active layer stack on device (durable) |
/app-storage/config/depthai_v3_layer.env | Writable config mirror used during apply |
/data/config/shadow_peer.{crt,key} | Hermes mesh peer TLS material |
/data/config/phantom_vision_endpoint.json | Phantom Vision agent endpoint config |
/etc/oak-agent/profile.env | Host-side tracker env passed into container process.env |
<recordings>/.h265_status | Recorder health: version, storage, encode stats, justified_ok |
<recordings>/recent_manifest.jsonl | Rolling chunk index (~60 s segments, stride metadata) |
Model bundling: Small RF-DETR weights ship in the image. Large .dlc files (RF-DETR variants, monocular depth) land in /data/models/ via push script. Avoid [[additional_mounts]] on RVC4—the sandbox blocks extra bind mounts; use /app-storage and /data instead.
bash
./scripts/push_device_models.sh <device-ip> YOUR_DEVICE_PASSWORDEdge AI layers
Layers stack capabilities from encode-only through full perception. The apply script rsyncs the selected layer file and copies the merged result to device config paths.
| Layer alias | Adds |
|---|---|
layer0 / layer0_baseline | Encode-only baseline |
layer1 / layer1_rfdetr | RF-DETR detection |
layer2 / layer2_tracker | Object tracker (default canary) |
layer3 / layer3_depth | Monocular depth + spatial fusion |
layer4 / layer4_thermal | Thermal governor |
layer5 / full | All layers |
bash
APPLY_RESTART=1 ./scripts/apply_depthai_v3_layer.sh layer2_tracker <device-ip> YOUR_DEVICE_PASSWORD
APPLY_RESTART=1 ./scripts/apply_depthai_v3_layer.sh layer3_depth <device-ip> YOUR_DEVICE_PASSWORDLayer3 env keys (representative): MONO_DEPTH_MODEL_PATH=/data/models/monocular_depth.dlc, MONO_DEPTH_FPS=8, GHOST_ENABLE_OBJECT_TRACKER=1, RF_DETR_STRIDE_FPS=10.
Overlay edits to a running container are ephemeral. For entrypoint or loader changes, rebuild via Firmware deploy—not hot-patch into merged overlay paths.
Operator scripts
| Script | Role |
|---|---|
scripts/deploy_oakapp.sh | Unlock camera, rsync source, oakctl app build/install/start |
scripts/unlock_camera.sh | Standalone camera unlock (called by deploy) |
scripts/apply_depthai_v3_layer.sh | Rsync layer env; optional restart via APPLY_RESTART=1 |
scripts/push_device_models.sh | Copy .dlc weights to /data/models/ |
scripts/soak_gate.sh | Poll die temp and encoder growth; writes pass marker |
scripts/verify_fleet_contract.py | MQTT schema + ~10 Hz contract over --duration-s |
scripts/tap_shadow_session.py | MQTT tap for manifest and FIFO events |
scripts/automate_shadow_soak.py | Soak watcher with optional --tap, --visual |
scripts/batch_soak_scenarios.py | Matrix soak runner |
scripts/visual_soak_gate.py | Proxy snapshot gate for visual regression |
scripts/setup-external-recordings.sh | Host USB mount helper for /data/ext-recordings |
cost-sentinel/scripts/shadow-prune-recordings.sh | Chunk prune (KEEP_CHUNKS, DRY_RUN=1) |
tools/phantom_vms_readiness_agent.py | Phantom module grades; --hermes-validate |
tools/v3_shadow_orchestrator.py | Full pipeline: --batch, --matrix, --prune-first, --tap |
[repo-root]/test_harness.py | Live MCP scenarios (--mode live-mcp) |
Soak gate example:
bash
./scripts/soak_gate.sh <device-ip> YOUR_DEVICE_PASSWORD 60
python3 ./scripts/verify_fleet_contract.py \
--mqtt-host <phantom-proxy> --device-id site-role-a --duration-s 20Prune example:
bash
KEEP_CHUNKS=30 DRY_RUN=1 bash cost-sentinel/scripts/shadow-prune-recordings.shExternal USB recording relief: scripts/setup-external-recordings.sh plus udev rules (scripts/99-external-recordings.rules.example). See USB extended storage.
Proxy and device CLI
| Surface | Examples |
|---|---|
| Proxy 8788 | GET /fleet/registry, GET /fleet/playback-ready, POST /tools/call?target=<device-ip> |
| MCP tools | get_recording_status, get_device_identity, get_hermes_mesh_status, get_firmware_status |
| A2A | POST /a2a/query (HMAC-signed) |
| Device agent | --health, --check-update, --tool get_firmware_status |
oakctl (limited) | app list, app stop, app start—prefer proxy and SSH for fleet checks |
bash
curl -s "$PHANTOM_PROXY/fleet/registry" | jq .
curl -s -X POST "$PHANTOM_PROXY/tools/call?target=<device-ip>" \
-H "Content-Type: application/json" \
-d '{"tool":"get_recording_status","arguments":{}}' | jq .Full route catalog: API quick reference · API reference.
Next steps
- End-to-end deploy flow: Firmware deploy
- Layer3 depth and fusion gates: Layer3 guide
- Prune, soak, and promotion: Prune & soak
- Automation matrix: Soaks & automation
- MQTT contracts after layer apply: MQTT reference
Operator depth
Live fleet state and harness evidence live in private operator handoff (not published) (private).