9 Commits

Author SHA1 Message Date
Joshua King ee947485d1 firmware(esp-01s): real GoPro Hero 3 status read (was the shutter bug)
Build (Dev) / build (push) Successful in 10s
CI / quality (push) Successful in 10s
CI / quality (pull_request) Successful in 10s
Validated against a Hero 3 Silver:
- fetchStatus() now GETs the status endpoint /camera/se (was /bacpac/SH?p=%01,
  which *started recording* every poll), at the correct host 10.5.5.9.
- Read the response from the stream, not getString(): the blob is binary and
  starts with 0x00, which truncated the Arduino String to empty.
- Offsets: recording = byte 29 (confirmed by not-recording vs recording diff),
  battery_raw = byte 19 (drains with charge; calibrate on the hub),
  video_remaining = bytes 25-26 (provisional).
- Default config set to this camera (goprosilver-1 / 10.5.5.9); per-camera
  values can still be overridden at runtime via set_config.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 15:21:14 -04:00
Joshua King f261fa0f55 firmware: store real wifi_password in config.json
Build (Dev) / build (push) Failing after 10s
CI/CD / lint-and-typecheck (push) Successful in 8s
CI/CD / test (push) Failing after 0s
CI/CD / build (push) Has been skipped
CI/CD / deploy (push) Has been skipped
Per maintainer decision: this is a private repo and the closed
travel-router Wi-Fi password is low-sensitivity, so keep the real
value in the tracked config for reproducible uploadfs provisioning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 07:49:44 -04:00
Joshua King b0062f1373 net: re-address hub network 10.60.1.0/24 -> 192.168.8.0/24
CI/CD / lint-and-typecheck (push) Successful in 9s
CI/CD / test (push) Successful in 7s
CI/CD / build (push) Failing after 1m21s
CI/CD / deploy (push) Has been skipped
Build (Dev) / build (push) Failing after 5m1s
The project was designed around a 10.60.1.0/24 travel-router network,
but the actual RemoteRig router uses 192.168.8.0/24 (the C6 associates
and gets 192.168.8.x; hub confirmed at 192.168.8.56). Replace the
network prefix everywhere (last octet preserved; GoPro 10.5.5.1 left
alone).

- scripts/setup-pi.sh: static IP 192.168.8.56/24, gateway 192.168.8.1,
  deploy/health command examples updated
- esp32-mqtt-bridge.cpp: default mqtt_broker -> 192.168.8.56
- firmware/data/config.json: broker -> 192.168.8.56 (wifi_password kept
  blank in git; real value flashed to the device only)
- docs (CONTEXT, MQTT_CONTRACT, READMEs, wireframes): gateway/hub/DHCP
  and example IPs re-addressed for consistency

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 07:47:57 -04:00
Joshua King f6a25fc324 firmware: fix C6 filesystem provisioning (LittleFS) + ESP-01S env
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
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
Joshua King cefb7ef52c firmware: battery calibration + full RGB STAT LED (C6)
Build (Dev) / build (push) Failing after 10s
CI/CD / lint-and-typecheck (push) Successful in 8s
CI/CD / test (push) Successful in 8s
CI/CD / build (push) Failing after 9s
CI/CD / deploy (push) Has been skipped
Battery calibration:
- two-point linear cal (bat_raw_min->0%, bat_raw_max->100%) of the
  GoPro offset-57 raw byte, persisted in SPIFFS config
- publish battery_pct in MQTT status only when calibrated (omit
  otherwise, per MQTT_CONTRACT); OLED shows % when calibrated, raw
  until then
- set_battery_cal MQTT command: explicit {raw_min,raw_max} or
  capture-current {point:"full"|"empty"} for field calibration

RGB STAT LED:
- drive D0/D1/D2 (R/G/B) with health colors instead of the single
  green channel: red=offline, magenta=wifi-but-no-hub,
  yellow=hub-but-no-camera, green=healthy; blue during boot
- RGB_COMMON_ANODE polarity flag; this module is common-anode

Verified on hardware: boots, OLED ok, RGB shows correct colors
(blue->red on the bench).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:33:36 -04:00
Hermes c5cbeabd92 feat: add v3 hardware case and update hub network
CI/CD / lint-and-typecheck (pull_request) Failing after 14m12s
CI/CD / test (pull_request) Has been cancelled
CI/CD / build (pull_request) Has been cancelled
CI/CD / deploy (pull_request) Has been cancelled
2026-05-22 16:58:11 -04:00
Hermes b3d4226b1c feat: dual-board architecture — ESP8266 camera bridge + ESP32 MQTT bridge
Build (Dev) / build (push) Failing after 1s
CI/CD / lint-and-typecheck (push) Failing after 0s
CI/CD / test (push) Has been skipped
CI/CD / build (push) Has been skipped
CI/CD / deploy (push) Has been skipped
Complete rewrite of firmware into two dedicated boards per camera node:

ESP8266 (Camera Bridge):
- Connects ONLY to GoPro AP — polls status, sends over UART
- Zero network switching, zero MQTT
- HTTP GET /bacpac/SH for status, start/stop
- JSON-per-line UART protocol to ESP32

ESP32 (MQTT Bridge):
- Connects ONLY to travel router — MQTT to Pi hub
- Reads status from ESP8266 over UART2 (RX16/TX17)
- Auto-registration, heartbeat, command forwarding
- Zero camera communication

UART Protocol: JSON-per-line at 115200 8N1
  ESP8266→ESP32: status/ack/pong/error
  ESP32→ESP8266: cmd (start_recording/stop_recording/ping)

Hardware updates:
- BOM now includes both boards (~4/node)
- 3D case has stacked dual-board compartment
- UART wire channel between board recesses
- Shared 3.3V power rail for both boards
2026-05-22 00:49:06 +00:00
Hermes 324402f268 feat: add ESP8266 support + Akaso camera compatibility config
CI/CD / lint-and-typecheck (push) Failing after 0s
CI/CD / test (push) Has been skipped
CI/CD / build (push) Has been skipped
Build (Dev) / build (push) Failing after 8s
CI/CD / deploy (push) Has been skipped
- Unified firmware for ESP32 (dual-STA) and ESP8266 (time-shared STA)
- ESP8266: alternates between GoPro AP and travel router per poll cycle
- PlatformIO dual-target: esp32dev + esp8266dev (d1_mini)
- camera_ip config field for Akaso/non-GoPro cameras
- LittleFS support for ESP8266 (replaces SPIFFS)
- Camera compatibility table (GoPro H3/H4, Akaso)
- LED polarity handled per-platform (ESP8266 active-low)

ESP8266 time-sharing adds ~4s latency per 30s cycle — invisible at poll rate.
2026-05-22 00:28:48 +00:00
Hermes d419dfe519 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
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
2026-05-21 21:54:05 +00:00