Progress Log
Pi Rover Agent — First Comms Established
Pi Rover Agent — First Comms Established
Date: 2026-04-12 Type: Build Log
Context
The Convex backend (schema, mutations, queries) and the Next.js control center were already fully built out — rover_status heartbeat, rover_commands queue, missions lifecycle, diagnostics logging, and captures ingestion. What was missing was actual Python code on the Raspberry Pi to call those APIs. This session created the Pi-side rover agent and verified end-to-end communication with the Convex backend.
What Changed
Built a complete Python rover agent in pi/ (6 files) that runs on the Pi and communicates with Convex over HTTP. Uses mock sensor data so the full pipeline can be tested without hardware.
Architecture:
convex_client.py— Thin HTTP wrapper around the Convex REST API (POST /api/mutationand/api/querywith{path, args}body format). No Convex Python SDK needed — justrequests.sensors.py— Abstraction layer with mock mode (default). GPS does a random walk near Catskills coords, battery slowly drains from 8.4V, CPU temp drifts up. SetMOCK_SENSORS=0to use real hardware (stubs exist but raise NotImplementedError).command_loop.py— Background thread that heartbeats every 3s and polls for pending commands every 3s. Dispatches commands to registered handler functions.mission_controller.py— Full mission lifecycle: preflight diagnostics (GPS, battery, camera, I2C, disk, WiFi) →missions:start→ capture loop (every 15s, up to 6 captures) →missions:complete. Handles abort via stop command.config.py— Convex URL and env var overrides.main.py— Entry point that wires everything together, registers command handlers, runs startup diagnostics, and waits for shutdown.
Key discovery: The Convex HTTP API format is POST /api/mutation with {"path": "rover:heartbeat", "args": {...}} in the body — NOT /api/mutation/rover:heartbeat in the URL (that returns 404).
Verified working:
- Heartbeat → dashboard sees rover online with battery, GPS, WiFi, CPU, disk, uptime
- Preflight diagnostics → appear in diagnostics page
- Command poll → picks up pending commands, acks, executes, reports completion
- Mission start → registers in Convex, triggers auto weather snapshot
- Capture ingestion → metadata logged (no real images yet)
- First cold-start Convex call takes ~14s (typical), subsequent calls are fast
Cleanup performed: Aborted a stuck in_progress mission and cleared stale pending commands that were left from a previous dashboard test.
Files Modified
pi/convex_client.py— Convex HTTP API client with typed methods for heartbeat, commands, missions, captures, diagnosticspi/sensors.py— Mock sensor layer (GPS random walk, battery drain, CPU temp drift)pi/command_loop.py— Heartbeat + command polling background threadpi/mission_controller.py— Mission lifecycle orchestrator with preflight checkspi/config.py— Configuration constants with env var overridespi/main.py— Entry point, wiring, signal handling
All files deployed to Pi at ~/rover/ via scp.
Key Takeaways
- Convex HTTP API body format:
{"path": "module:function", "args": {...}}— the path goes in the JSON body, not the URL - The Pi venv at
~/rover/venvalready hadrequestsinstalled (from adafruit deps), so no new packages needed - Mock sensors drift realistically enough to see movement on the dashboard GPS and battery drain over time
- The command queue approach works well — dashboard sends commands, Pi polls and executes asynchronously
- Not yet set up as a systemd service — currently manual
python3 main.pystart
