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>
This commit is contained in:
Joshua King
2026-06-05 15:21:14 -04:00
parent f03dbb056d
commit ee947485d1
2 changed files with 30 additions and 17 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
{
"camera_ssid": "GOPRO-BP-",
"camera_password": "goprohero",
"camera_ip": "10.5.5.1",
"camera_ssid": "goprosilver-1",
"camera_password": "Bzyeatn421",
"camera_ip": "10.5.5.9",
"poll_interval_sec": 30
}
+27 -14
View File
@@ -41,9 +41,11 @@
// ────────────────────────────────────────────
struct Config {
String camera_ssid = "GOPRO-BP-";
String camera_password = "goprohero";
String camera_ip = "10.5.5.1";
// Defaults validated against a GoPro Hero 3 Silver. Per-camera values can
// be overridden at runtime via the set_config command (no reflash).
String camera_ssid = "goprosilver-1";
String camera_password = "Bzyeatn421";
String camera_ip = "10.5.5.9"; // Hero 3 HTTP API host (not .1)
int poll_interval_sec = 30;
} cfg;
@@ -95,27 +97,38 @@ struct CamStatus {
CamStatus fetchStatus() {
CamStatus s;
String url = "http://" + cfg.camera_ip +
"/bacpac/SH?t=" + cfg.camera_password + "&p=%01";
// READ status — must NOT be the shutter endpoint. Hero 3 status blob
// (validated on a Hero 3 Silver, ~31 bytes):
// [29] recording flag (0 idle / 1 recording) — confirmed
// [19] battery level (raw; drains with charge) — calibrate on the hub
// [25..26] video-remaining (provisional)
// The body is binary and starts with 0x00, so read the stream directly —
// Arduino String truncates at the first null byte.
String url = "http://" + cfg.camera_ip + "/camera/se?t=" + cfg.camera_password;
HTTPClient http;
http.useHTTP10(true);
http.begin(goproClient, url);
http.setTimeout(5000);
int code = http.GET();
if (code != 200) { http.end(); return s; }
String raw = http.getString();
uint8_t buf[40] = {0};
WiFiClient* stream = http.getStreamPtr();
size_t n = 0;
unsigned long t0 = millis();
while (n < sizeof(buf) && millis() - t0 < 1500) {
if (stream && stream->available()) buf[n++] = (uint8_t)stream->read();
else delay(5);
}
http.end();
if (raw.length() < 58) return s;
if (n < 30) return s;
const uint8_t* buf = (const uint8_t*)raw.c_str();
s.valid = true;
s.valid = true;
s.recording = (buf[29] == 1);
s.battery_raw = buf[19];
s.video_remaining_sec = buf[25] | (buf[26] << 8);
s.recording = (buf[29] == 1);
s.battery_raw = buf[57];
return s;
}