# RemoteRig — Dual-Board Camera Node Firmware > **Platform:** PlatformIO (esp8266-camera + esp32-mqtt) > **MQTT Contract:** [docs/MQTT_CONTRACT.md](../docs/MQTT_CONTRACT.md) > **Hardware:** [hardware/README.md](../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 ```bash 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. |