generated from CubeCraft-Creations/Tracehound
d419dfe519
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
RemoteRig — ESP32 Camera Node Firmware
Platform: PlatformIO (esp32dev) | Framework: Arduino MQTT Contract: docs/MQTT_CONTRACT.md Hardware: hardware/README.md
Quick Start
# 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
- Load config from SPIFFS
- Connect to travel router Wi-Fi (STA mode)
- Connect to GoPro AP Wi-Fi (STA mode — simultaneous)
- Connect to MQTT broker (192.168.4.10)
- If no
camera_id→ publish announce → hub registers us - Subscribe to
remoterig/cameras/{camera_id}/command - 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:
- Change
platformio.ini:board = d1_miniunder[env:d1_mini] - Change
WiFi.h→ESP8266WiFi.h - ESP8266 doesn't do true simultaneous STA — use single STA to travel router, HTTP to GoPro via router bridge
- 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 |