Files
remote-rig/firmware
Joshua King f6a25fc324
Build (Dev) / build (push) Failing after 10s
CI/CD / lint-and-typecheck (push) Successful in 7s
CI/CD / test (push) Successful in 7s
CI/CD / build (push) Failing after 9s
CI/CD / deploy (push) Has been skipped
firmware: fix C6 filesystem provisioning (LittleFS) + ESP-01S env
The C6 never loaded its /config.json, so it fell back to defaults
(SSID RemoteRig, empty password) and couldn't join Wi-Fi. Two bugs:

- Data file was named esp32-config.json but the firmware reads
  /config.json → renamed to config.json.
- Firmware used SPIFFS while pioarduino's uploadfs builds a LittleFS
  image; the SPIFFS mount then reformatted it empty. Switch the C6 to
  LittleFS (matches the toolchain default and the ESP-01S).

Also:
- log loaded ssid/broker/camera_id on config load (not the password)
- platformio.ini: land the ESP-01S env retarget (board d1_mini ->
  esp01_1m, dout, upload_speed 115200) that was missed in 403e1d9
- committed config.json keeps wifi_password blank; the real value is
  flashed to the device, not stored in git

Verified: C6 loads config and associates (got a DHCP lease). MQTT to
the broker is a separate network issue (hub IP / subnet).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 19:28:17 -04:00
..

RemoteRig — Dual-Board Camera Node Firmware

Platform: PlatformIO (esp8266-camera + esp32-mqtt) MQTT Contract: docs/MQTT_CONTRACT.md Hardware: hardware/README.md

Architecture

Each camera node uses two boards connected via UART — zero network switching:

┌─────────────────────┐     UART      ┌─────────────────────┐
│   ESP8266 D1 Mini   │  TX──────→RX  │   ESP32 Dev Board   │
│   (Camera Bridge)   │  RX←──────TX  │   (MQTT Bridge)      │
│                     │    115200     │                      │
│  STA → GoPro AP     │    8N1        │  STA → Travel Router │
│  HTTP → 10.5.5.1    │               │  MQTT → 10.60.1.56│
│  Start/stop/status  │               │  Hub registration   │
└─────────────────────┘               └──────────────────────┘
Board Job Network Protocol
ESP8266 Camera control GoPro AP only (10.5.5.1) HTTP → UART JSON
ESP32 Hub relay Travel router only (10.60.1.x) UART JSON → MQTT

Quick Start

pip install platformio
cd firmware

# Build both
pio run -e esp8266-camera
pio run -e esp32-mqtt

# Upload to boards (connect one at a time via USB)
pio run -e esp8266-camera --target upload
pio run -e esp32-mqtt --target upload

# Upload configs (each board needs its own)
# ESP8266: copy esp8266-config.json to data/config.json, then:
pio run -e esp8266-camera --target uploadfs
# ESP32: copy esp32-config.json to data/config.json, then:
pio run -e esp32-mqtt --target uploadfs

UART Protocol (ESP8266 ↔ ESP32)

JSON-per-line at 115200 8N1. GPIO16 on both boards.

Direction Type Format Purpose
ESP8266 → ESP32 status {"type":"status","battery_raw":217,...} Camera poll result
ESP8266 → ESP32 ack {"type":"ack","cmd":"start_recording"} Command confirmation
ESP8266 → ESP32 pong {"type":"pong","uptime_ms":12345} Ping response
ESP8266 → ESP32 error {"type":"error","msg":"camera unreachable"} Error report
ESP32 → ESP8266 cmd {"type":"cmd","command":"start_recording"} Hub command
ESP32 → ESP8266 cmd {"type":"cmd","command":"ping"} Link health check

Configuration

ESP8266 (data/esp8266-config.json)

Key Default Description
camera_ssid "GOPRO-BP-" GoPro Wi-Fi AP name
camera_password "goprohero" GoPro Wi-Fi password
camera_ip "10.5.5.1" Camera IP (change for Akaso to 192.168.1.1)
poll_interval_sec 30 How often to poll camera

ESP32 (data/esp32-config.json)

Key Default Description
wifi_ssid "RemoteRig" Travel router SSID
wifi_password "" Travel router password
mqtt_broker "10.60.1.56" Pi Zero 2 W IP
mqtt_port 1883 Mosquitto port
camera_id "" Assigned by hub on first announce (leave empty)
heartbeat_interval_sec 60 MQTT heartbeat frequency

Wiring

ESP8266 D1 Mini          ESP32 Dev Board
┌────────────┐           ┌────────────┐
│            │           │            │
│  TX (GPIO1)│──────────→│ RX (GPIO16)│
│  RX (GPIO3)│←──────────│ TX (GPIO17)│
│  GND       │───────────│ GND        │
│  3.3V      │           │ 3.3V       │
│            │           │            │
└────────────┘           └────────────┘
         │                      │
         └────────┬─────────────┘
                  │
           LiPo → 3.3V Buck
           (shared power)

Boot Sequence

  1. ESP8266: Connect to GoPro AP → wait for UART commands
  2. ESP32: Connect to travel router → connect MQTT → announce if new
  3. ESP8266: Poll camera every 30s → send status over UART
  4. ESP32: Receive status → publish MQTT
  5. Hub → MQTT command → ESP32 → UART → ESP8266 → HTTP → GoPro

Camera Compatibility

Camera camera_ip Protocol Status
GoPro Hero 3 10.5.5.1 HTTP GET /bacpac/SH Full support
Akaso Brave 7 192.168.1.1 Varies 🔬 Set camera_ip, test

For non-GoPro cameras: only the ESP8266 firmware needs changes — the ESP32 stays the same.

LED Status (ESP8266)

LED Meaning
Solid on Connected to camera AP, camera responding
Slow blink (500ms) Connected to AP but camera not responding
Off Wi-Fi disconnected

Troubleshooting

Symptom Check
No UART communication Verify TX→RX crossover. Both boards at 115200. Shared GND.
ESP8266 can't connect GoPro must be ON with Wi-Fi enabled. Default password: goprohero
ESP32 can't connect MQTT systemctl status mosquitto on Pi. Port 1883 open.
Camera never registers Watch ESP32 serial for "Announced" message. Check hub logs.