Skip to content

Public-safe docs: Examples use placeholders. Live fleet IDs, credentials, telemetry snapshots, harness evidence, and session chronology are maintained in operator-controlled handoff repositories — not on the public web.

About this article

  • Audience: Operators resetting the firmware tree or re-baking both shadows from source for a known-good baseline
  • Goal: After reading, you can prep a clean source tree, prune storage, deploy both shadows, verify justified recording + registry + ONVIF MVP path through the Phantom proxy, and confirm a minimal live baseline before layer promotion
  • Type: How-to

Summary

A clean bake rebuilds the edge app image from source and installs it on each shadow. Use this for full fleet resets—not overlay hot-patches. Validate justified recording, registry health, peer mesh, and the ONVIF MVP (WS-Discovery + RF-DETR events c=0) with minimal features enabled before layering depth, thermal, or cloud integrations. This is the foundation for production soak gates and mass transit safety scenarios.

Prerequisites

  • Phantom host stack running (MQTT 1883, proxy 8788)
  • SSH access: root@[device-ip] with YOUR_DEVICE_PASSWORD
  • Shadows: shadow-canary (site-role-a) and shadow-secondary (site-role-b)
  • export PHANTOM_PROXY=https://[phantom-proxy]:8788
  • Tools in [repo-root]/oak-vms-firmware/: scripts/deploy_oakapp.sh, cost-sentinel/scripts/shadow-prune-recordings.sh, tools/v3_shadow_orchestrator.py
  • (Optional but recommended for ONVIF MVP) ONVIF client or vms_cli.py for WS-Discovery / GetStreamUri / Events pull

See Full Stack Onboarding and First Operator Tasks.

1. Prep a clean source tree

bash
cd [repo-root]/oak-vms-firmware
find . -name '*.bak*' -delete
rm -rf test-results/ logs/ build/ build-test/ __pycache__
rm -f *.oakapp harness_results*.json
git status --porcelain | wc -l   # expect low count

Review git clean -fdx --dry-run before a forced clean. Keep models/ and src/ intact. This ensures a reproducible bake without stale artifacts.

2. Prune storage

bash
cd [repo-root]
DRY_RUN=1 bash cost-sentinel/scripts/shadow-prune-recordings.sh
KEEP_CHUNKS=30 bash cost-sentinel/scripts/shadow-prune-recordings.sh

Verify: storage_health is OK or WARNING, not CRITICAL. See Prune and soak.

3. Clean bake both shadows

bash
cd [repo-root]/oak-vms-firmware
./scripts/deploy_oakapp.sh [device-ip-canary] YOUR_DEVICE_PASSWORD
./scripts/deploy_oakapp.sh [device-ip-secondary] YOUR_DEVICE_PASSWORD

Deploy unlocks the camera, syncs source, builds, installs, and starts the app. Verify through SSH and the proxy—not repeated oakctl on running fleet shadows. Start minimal: encode, registry, MQTT, peer mesh, RF-DETR only (precomp authority).

4. Verify through the proxy (core surfaces + ONVIF MVP)

Wait 60+ seconds for the first justified chunk, then:

bash
curl -s "$PHANTOM_PROXY/fleet/registry" | jq .
curl -s "$PHANTOM_PROXY/fleet/health" | jq .
curl -s "$PHANTOM_PROXY/fleet/playback-ready?shadow=site-role-a&limit=3" | jq .

curl -s -X POST "$PHANTOM_PROXY/tools/call?target=[device-ip-canary]" \
  -H "Content-Type: application/json" \
  -d '{"tool":"get_recording_status","arguments":{}}' | jq .

curl -s -X POST "$PHANTOM_PROXY/tools/call?target=[device-ip-canary]" \
  -H "Content-Type: application/json" \
  -d '{"tool":"get_latest_dets","arguments":{}}' | jq .

Verify core:

  • Both roles in registry
  • encode_fail_streak 0
  • recent_chunks ≥ 1 with justified: true
  • Person class 0 detections (RF-DETR precomp)
  • Non-null fingerprint; peer sidecar on 8777
  • SSH: ghost_core active, manifest shows justified=true, .h265_status storage OK

ONVIF MVP verification (WS-Discovery / Device / Media2 / Events c=0): Use proxy MCP or vms_cli / standalone onvif client against the shadow RTSP/ONVIF port (typically 8554 after deploy). Expect:

  • WS-Discovery ProbeMatch (Profile S/T + NVT)
  • GetDeviceInfo, GetProfiles (H.265 3840/30 encoder)
  • SetVideoEncoderConfig mutates depthai_v3_layer (AF/H265/RF-DETR)
  • Events PullPoint for person (RF-DETR c=0) + GetStreamUri 8554

See ONVIF MVP reference and First operator tasks for exact one-liners and expected 7/7 + 4/4 gate.

Full routes: API quick reference.

5. Restart proxy (if stale) and run soak gate

If registry or MQTT is stale, restart the Phantom proxy per your host stack (systemd, pm2, or manual), then:

bash
curl -s "$PHANTOM_PROXY/health"
curl -s "$PHANTOM_PROXY/fleet/registry" | jq '.shadows | length'

Run a minimal soak after proxy checks pass:

bash
cd [repo-root]/oak-vms-firmware
python3 tools/v3_shadow_orchestrator.py \
  --batch --scenarios normal_short,playback \
  --prune-first --tap --visual \
  --batch-id fresh-start-$(date +%s)

Verify: soak gate PASS on both shadows. Artifacts land under v3-runs/ in [operator-artifacts].

Success gate

Ready for layer promotion when each shadow has:

  • Two or more new justified 60s chunks
  • Live certificate fingerprint in registry and device identity
  • MQTT at ~10 Hz with person class 0 detections (precomp sacred)
  • Active peer mesh and storage_health OK
  • ONVIF MVP surfaces responding (WS-Discovery + Events c=0) if validating camera path

Troubleshooting

  • Bake fails on host SSH or docker context → check YOUR_DEVICE_PASSWORD, network to [device-ip], and that entrypoint + oakapp.toml are in tree.
  • No justified chunks → confirm thermal mit, storage not CRITICAL, and orchestrator --prune-first.
  • ONVIF no discovery / no person events → verify depthai_v3_layer has RF-DETR c=0, camera unlocked, and proxy MCP forwards Events.
  • Stale registry/MQTT → restart proxy; re-check /fleet/health and get_recording_status.

See Common issues and Recovery.

Next steps

Operator depth

Live fleet state, soak history, harness evidence, ONVIF sub IDs, and exact promote decisions live in private operator handoff (not published) (private).