Appearance
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]withYOUR_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.pyfor 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 countReview 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.shVerify: 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_PASSWORDDeploy 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_streak0recent_chunks≥ 1 withjustified: true- Person class 0 detections (RF-DETR precomp)
- Non-null fingerprint; peer sidecar on 8777
- SSH:
ghost_coreactive, manifest showsjustified=true,.h265_statusstorage 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_healthOK - 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/healthandget_recording_status.
See Common issues and Recovery.
Next steps
- First operator tasks — contract verification and Phantom readiness
- Firmware deploy — Edge AI layers after baseline
- API quick reference — fleet and MCP routes
- ONVIF MVP camera — full WS-Discovery / Media2 / Events contract
Operator depth
Live fleet state, soak history, harness evidence, ONVIF sub IDs, and exact promote decisions live in private operator handoff (not published) (private).