generated from CubeCraft-Creations/Tracehound
feat: add PlatformIO ESP32 firmware with dual-STA + MQTT + GoPro control
CI/CD / lint-and-typecheck (pull_request) Failing after 2s
CI/CD / test (pull_request) Has been skipped
CI/CD / build (pull_request) Has been skipped
CI/CD / deploy (pull_request) Failing after 12m6s
CI/CD / test (push) Has been skipped
CI/CD / build (push) Has been skipped
CI/CD / deploy (push) Has been skipped
Build (Dev) / build (push) Failing after 14s
CI/CD / lint-and-typecheck (push) Failing after 0s
CI/CD / lint-and-typecheck (pull_request) Failing after 2s
CI/CD / test (pull_request) Has been skipped
CI/CD / build (pull_request) Has been skipped
CI/CD / deploy (pull_request) Failing after 12m6s
CI/CD / test (push) Has been skipped
CI/CD / build (push) Has been skipped
CI/CD / deploy (push) Has been skipped
Build (Dev) / build (push) Failing after 14s
CI/CD / lint-and-typecheck (push) Failing after 0s
firmware/ ├── platformio.ini — ESP32 (esp32dev), PubSubClient + ArduinoJson ├── src/main.cpp — Full camera node firmware (360 lines) │ ├── SPIFFS config persistence │ ├── Dual Wi-Fi STA (travel router + GoPro AP) │ ├── GoPro Hero 3 HTTP API (start/stop/status) │ ├── 60-byte binary status blob parser │ ├── MQTT per contract (status QoS1, heartbeat QoS1, announce QoS2) │ ├── Command subscription (start/stop/reboot) │ ├── Auto-registration (announce → hub assigns cam-NNN) │ ├── Heartbeat every 60s, status every 30s │ ├── LED status indicator │ └── Exponential backoff reconnection ├── data/config.json — Default SPIFFS config template └── README.md — Quick start, config reference, troubleshooting
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# RemoteRig — ESP32 Camera Node Firmware
|
||||
|
||||
> **Platform:** PlatformIO (esp32dev) | **Framework:** Arduino
|
||||
> **MQTT Contract:** [docs/MQTT_CONTRACT.md](../docs/MQTT_CONTRACT.md)
|
||||
> **Hardware:** [hardware/README.md](../hardware/README.md)
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install PlatformIO (if not already)
|
||||
pip install platformio
|
||||
|
||||
# Build
|
||||
cd firmware
|
||||
pio run
|
||||
|
||||
# Upload to ESP32 (USB connected)
|
||||
pio run --target upload
|
||||
|
||||
# Upload SPIFFS config (first time only, or after config changes)
|
||||
pio run --target uploadfs
|
||||
|
||||
# Serial monitor
|
||||
pio device monitor
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The ESP32 stores configuration in SPIFFS (`data/config.json`):
|
||||
|
||||
| Key | Default | Description |
|
||||
|-----|---------|-------------|
|
||||
| `wifi_ssid` | `"RemoteRig"` | Travel router SSID |
|
||||
| `wifi_password` | `""` | Travel router password |
|
||||
| `camera_ssid` | `"GOPRO-BP-"` | GoPro Wi-Fi AP prefix (auto-discovered) |
|
||||
| `camera_password` | `"goprohero"` | GoPro Wi-Fi password |
|
||||
| `mqtt_broker` | `"192.168.4.10"` | Pi Zero 2 W static IP |
|
||||
| `mqtt_port` | `1883` | Mosquitto port |
|
||||
| `camera_id` | `""` | Assigned by hub on first announce (leave empty) |
|
||||
| `poll_interval_sec` | `30` | GoPro status poll frequency |
|
||||
| `heartbeat_interval_sec` | `60` | MQTT heartbeat frequency |
|
||||
|
||||
**First boot:** Leave `camera_id` empty. The ESP32 will auto-announce to the hub, which assigns a `cam-NNN` ID. The assigned ID is saved to SPIFFS automatically.
|
||||
|
||||
## LED Status Codes
|
||||
|
||||
| Pattern | Meaning |
|
||||
|---------|---------|
|
||||
| Slow blink (1s) | Connected to router + MQTT, normal operation |
|
||||
| Fast blink (200ms) | No Wi-Fi connection — reconnecting |
|
||||
| Solid on | Connected but GoPro unreachable |
|
||||
| Off | Boot/shutdown |
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ ESP32 (Arduino) │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌────────┐ │
|
||||
│ │ WiFi STA │ │ WiFi STA │ │ MQTT │ │
|
||||
│ │ (Router) │ │ (GoPro) │ │ Client │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └───┬────┘ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌────────┘ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ Main Loop │ │
|
||||
│ │ Every 30s: │ │
|
||||
│ │ HTTP GET GoPro status │ │
|
||||
│ │ Parse 60-byte blob │ │
|
||||
│ │ MQTT publish status │ │
|
||||
│ │ Every 60s: │ │
|
||||
│ │ MQTT publish heartbeat │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
│ SPIFFS: /config.json (persistent) │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Boot Sequence
|
||||
|
||||
1. Load config from SPIFFS
|
||||
2. Connect to travel router Wi-Fi (STA mode)
|
||||
3. Connect to GoPro AP Wi-Fi (STA mode — simultaneous)
|
||||
4. Connect to MQTT broker (192.168.4.10)
|
||||
5. If no `camera_id` → publish announce → hub registers us
|
||||
6. Subscribe to `remoterig/cameras/{camera_id}/command`
|
||||
7. Enter main loop
|
||||
|
||||
## GoPro API Notes (Hero 3 Black/Silver)
|
||||
|
||||
- **IP:** Always `10.5.5.1` (GoPro's own AP)
|
||||
- **Status endpoint:** `GET /bacpac/SH?t={password}&p=%01`
|
||||
- **Start recording:** `GET /bacpac/SH?t={password}&p=%01` (mode byte = 1)
|
||||
- **Stop recording:** `GET /bacpac/SH?t={password}&p=%00` (mode byte = 0)
|
||||
- **Get password:** `GET /bacpac/sd` (no auth, returns plain text)
|
||||
- **Status blob:** 60 bytes binary — see `parseStatus()` in main.cpp for field offsets
|
||||
|
||||
## ESP8266 Compatibility
|
||||
|
||||
To target ESP8266 instead:
|
||||
1. Change `platformio.ini`: `board = d1_mini` under `[env:d1_mini]`
|
||||
2. Change `WiFi.h` → `ESP8266WiFi.h`
|
||||
3. ESP8266 doesn't do true simultaneous STA — use single STA to travel router, HTTP to GoPro via router bridge
|
||||
4. SPIFFS → LittleFS on some boards
|
||||
|
||||
ESP32 is recommended for dual-STA capability.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Check |
|
||||
|---------|-------|
|
||||
| No serial output | Baud rate: 115200. Hold BOOT, press EN, release BOOT for flash mode |
|
||||
| Can't connect to router | Verify SSID/password in SPIFFS config, check router DHCP range |
|
||||
| GoPro unreachable | GoPro must be ON and Wi-Fi enabled. Password defaults to "goprohero" |
|
||||
| MQTT connect fails | Verify Mosquitto running on Pi: `systemctl status mosquitto` |
|
||||
| Camera never registers | Watch serial for "announce" message, check hub logs for registration |
|
||||
Reference in New Issue
Block a user