Progress Log

Control Center: Telemetry, Missions, Rover Live, and Pi API

April 12, 202609:34Build Log

Control Center: Telemetry, Missions, Rover Live, and Pi API

Date: 2026-04-12 Type: Build Log

Context

The Tick Slayer 3000 app had parts tracking, blog, and build docs — but no way to interact with or monitor the rover itself. The goal was to define the data schema for missions, telemetry, and diagnostics from the app side first, so the Pi software knows exactly what to send. This also establishes the command/control layer for remote operation.

What Changed

Convex Schema — 6 new tables

  • missions — session-level records: route name, status (planned/in_progress/completed/aborted), start/end timestamps, GPS positions, battery start/end, weather, notes
  • captures — per-stop data: GPS lat/lon, battery voltage, image storage ID, filename, timestamp. Indexed by mission + time
  • diagnostics — pre-flight checks and runtime events: type (camera/gps/i2c/battery/disk_space/wifi/general), pass/warning/fail status, message, numeric value
  • tick_counts — manual post-session tick logging: count, temperature, humidity, time of day, cloth condition, notes
  • rover_status — singleton heartbeat from Pi: position, battery, WiFi signal, disk free, CPU temp, GPS satellites, state (idle/running/returning/error/offline), uptime. Dashboard considers rover "offline" if lastSeen > 30s
  • rover_commands — command queue (dashboard writes, Pi polls): start_mission, stop, return_home, take_photo, pause, resume. Lifecycle: pending → acknowledged → completed/failed

Convex Functions

  • convex/missions.ts — list, get, getByMissionId, start (Pi calls), complete (Pi calls), update (admin), remove
  • convex/captures.ts — listByMission, get, ingest (Pi upload script), generateUploadUrl (for image storage)
  • convex/diagnostics.ts — listByMission, listRecent, log (Pi calls)
  • convex/tickCounts.ts — listByMission, listAll, create (admin), update
  • convex/rover.ts — heartbeat (Pi), getCurrent (dashboard), sendCommand (admin), pendingCommands (Pi polls), ackCommand (Pi), completeCommand (Pi), recentCommands (dashboard)

Control Center UI — 5 pages

  • /control-center — Dashboard with Rover Live panel (pulsing online indicator, 6-item telemetry grid, state badge, command buttons, recent command history), stats cards, latest mission summary, recent diagnostics
  • /control-center/missions — Table listing all missions with date, route, status, capture count, duration, battery, GPS start
  • /control-center/missions/[id] — Single scrollable view (no tabs, user preference): live panel for active missions, 5 stat cards, battery drain sparkline from capture data, mission metadata, GPS track as coordinate chips, tick count cards, unified activity timeline with filter chips (All/Captures/Diagnostics/Commands/Status)
  • /control-center/diagnostics — All diagnostics across missions with pass/warn/fail counts and color-coded table
  • /control-center/tick-log — All tick counts with summary stats (total, sessions, avg per session), linked back to parent missions

Sidebar Navigation

Added "Control Center" as a collapsible group with sub-items: Dashboard, Missions, Diagnostics, Tick Log. Uses the Gauge icon.

Documentation

  • Guide 9: Pi ↔ Dashboard API Integration (docs/articles/build-09-pi-api-integration.md) — Complete reference for the Pi-side developer: every Convex mutation/query with Python examples, schema reference tables, data flow diagram, offline queue pattern, command lifecycle, and CLI testing commands
  • Registered in article-index.ts under the Software category

Seed Data

  • seed:seedMission — Creates a completed "Backyard Perimeter" mission with 8 captures (GPS track around a yard), 6 pre-flight diagnostics (5 pass, 1 WiFi warning), and a tick count (3 ticks: 2 deer, 1 lone star)
  • seed:seedRoverStatus — Creates an idle rover heartbeat with realistic telemetry values

Files Modified

  • convex/schema.ts — Added missions, captures, diagnostics, tick_counts, rover_status, rover_commands tables with indexes
  • convex/missions.ts — New: mission CRUD + Pi lifecycle mutations
  • convex/captures.ts — New: capture queries + Pi ingest mutation + file upload URL
  • convex/diagnostics.ts — New: diagnostic queries + Pi log mutation
  • convex/tickCounts.ts — New: tick count CRUD (admin-gated writes)
  • convex/rover.ts — New: heartbeat, command queue, status queries
  • convex/seed.ts — Added seedMission and seedRoverStatus mutations
  • src/components/app-sidebar.tsx — Added Control Center collapsible nav group
  • src/app/control-center/page.tsx — New: dashboard with Rover Live panel
  • src/app/control-center/missions/page.tsx — New: missions list
  • src/app/control-center/missions/[id]/page.tsx — New: mission detail with timeline
  • src/app/control-center/diagnostics/page.tsx — New: standalone diagnostics view
  • src/app/control-center/tick-log/page.tsx — New: tick log with trend stats
  • src/app/docs/article-index.ts — Registered Guide 9 under Software category
  • docs/articles/build-09-pi-api-integration.md — New: full Pi API integration guide

Key Takeaways

  • App-first schema design — Building the dashboard and API before the Pi software means the data contract is well-defined. The Pi just needs to call the documented mutations
  • Rover Live uses a singleton patternrover_status has one row that gets upserted on every heartbeat, not an append-only log. The 30-second timeout for "online" detection is simple and effective
  • Command queue is pull-based — The Pi polls pendingCommands every ~3 seconds. No WebSocket or push needed since the Pi already heartbeats on that interval
  • Mission detail is one view, filterable — User explicitly didn't want tabs. The unified activity timeline interleaves captures, diagnostics, commands, and status events chronologically with filter chips
  • Offline queue pattern — Captures always save locally first (image + JSON sidecar), then try to upload. Failed uploads stay queued for the next sync cycle
  • Tick counts are manual — Camera can't see the underside of the cloth, so tick counting is a human step: flip cloth after mission, count, log from dashboard
  • Deployed to production — Convex prod + Vercel prod + seeded with sample data. Live at tickslayer3000.com/control-center