Cross-platform (macOS + Linux) C++17 CLI that extracts a Betaflight FC's blackbox log in one command: auto-detect the serial port, read craft_name over the Betaflight CLI, send `msc` to reboot into USB mass storage, wait for the volume to mount, copy btfl_all.bbl to <craft_name>_<YYYYMMDD>_<HHMMSS>.bbl, and eject. Native throughout (termios serial, getmntinfo/proc-mounts mount detection, DiskArbitration/umount eject); the only subprocess is the Linux udisksctl eject fallback. Includes CMake/ctest build, unit tests for the pure logic (naming, craft_name parsing, mount diff, serial via pty, CLI parsing), README with a manual hardware integration procedure, and design/plan docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
79 lines
2.5 KiB
Markdown
79 lines
2.5 KiB
Markdown
# bfebbx — Betaflight Extract Blackbox
|
|
|
|
Extract a Betaflight flight controller's blackbox log to a timestamped,
|
|
craft-named file in a single command. macOS and Linux.
|
|
|
|
## What it does
|
|
|
|
1. Auto-detects the FC's serial port.
|
|
2. Reads `craft_name` over the Betaflight CLI.
|
|
3. Sends `msc` to reboot the FC into USB mass-storage mode.
|
|
4. Waits for the storage volume to mount, then copies `btfl_all.bbl` to
|
|
`<craft_name>_<YYYYMMDD>_<HHMMSS>.bbl`.
|
|
5. Ejects the volume.
|
|
|
|
## Build
|
|
|
|
```bash
|
|
cmake -S . -B build
|
|
cmake --build build
|
|
ctest --test-dir build # run unit tests
|
|
```
|
|
|
|
The binary is `build/bfebbx`.
|
|
|
|
Requirements: a C++17 compiler and CMake ≥ 3.16. No third-party libraries.
|
|
macOS links the system DiskArbitration/CoreFoundation frameworks.
|
|
|
|
## Usage
|
|
|
|
```
|
|
bfebbx [--port PORT] [--output DIR] [--craft-name NAME] [--timeout SEC] [-v]
|
|
```
|
|
|
|
| Flag | Default | Meaning |
|
|
|------|---------|---------|
|
|
| `--port` | auto-detect | Serial device (e.g. `/dev/tty.usbmodem1101`). |
|
|
| `--output` | current dir | Directory for the extracted `.bbl`. |
|
|
| `--craft-name` | read from FC | Override / fallback craft name. |
|
|
| `--timeout` | 30 | Seconds to wait for the storage volume. |
|
|
| `-v` | off | Verbose progress on stderr. |
|
|
|
|
### Exit codes
|
|
|
|
| Code | Meaning |
|
|
|------|---------|
|
|
| 0 | Success |
|
|
| 2 | No candidate serial port |
|
|
| 3 | Multiple candidate ports (pass `--port`) |
|
|
| 4 | Serial open / handshake failure |
|
|
| 5 | Storage volume did not appear before timeout |
|
|
| 6 | `btfl_all.bbl` not found on the volume |
|
|
| 7 | Copy failed |
|
|
| 8 | Destination file already exists |
|
|
| 64 | Usage error |
|
|
|
|
## Manual integration test (requires a real FC)
|
|
|
|
The pure logic is unit-tested. The serial handshake and eject need hardware:
|
|
|
|
1. Flash/confirm a Betaflight FC with blackbox logs on onboard flash.
|
|
2. Connect it via USB. Confirm the port appears: `ls /dev/tty.usbmodem*`
|
|
(macOS) or `ls /dev/ttyACM*` (Linux).
|
|
3. Run `./build/bfebbx -v` in an empty directory.
|
|
4. Verify:
|
|
- The craft name is read and printed.
|
|
- The FC re-enumerates as a USB drive.
|
|
- A file `<craft_name>_<date>_<time>.bbl` is written and matches the size
|
|
of `btfl_all.bbl` on the drive.
|
|
- The volume is ejected (no longer in `/Volumes` on macOS / `/proc/mounts`
|
|
on Linux).
|
|
5. Re-run in the same directory within the same second is not required; the
|
|
timestamp differs each run, so collisions are not expected. To exercise the
|
|
overwrite guard, `--craft-name X` twice within one second and confirm exit
|
|
code 8.
|
|
|
|
## Design
|
|
|
|
See `docs/superpowers/specs/2026-07-22-bfebbx-design.md`.
|