Skip to content

Commit c923383

Browse files
authored
docs: Comprehensive examples and API documentation improvements (#39)
* docs: Clarify multi-log API and add multi_flight_export example IMPROVEMENTS: 1. New Example: multi_flight_export.rs - Demonstrates how to export ALL flights from a BBL file - Shows proper use of parse_bbl_file_all_logs() - Displays flight numbering and automatic suffixing 2. Updated Examples/README.md - Added quick-start section with usage for both single/multi-flight cases - Clear explanation of when to use each example - API pattern guide showing correct usage - Common mistakes section with dos/don'ts - Flight numbering table explaining suffixes 3. Updated csv_export.rs Comments - Added prominent note about multi-log handling - Reference to multi_flight_export example - Clarified that this exports only first flight 4. Enhanced CRATE_USAGE.md - Added warning section about parse_bbl_file() vs parse_bbl_file_all_logs() - Renamed sections for clarity (Single-flight, Multi-flight) - Best practices: Handle both cases with parse_bbl_file_all_logs() - New Flight Numbering section with detailed explanation - Suffix rules documentation - Production code recommendation This addresses the issue where users might accidentally use parse_bbl_file() on multi-flight files and only export the first flight. The new example and documentation make the distinction clear. * docs: Remove export_demo duplication in examples/README.md Consolidated duplicate content: - Removed brief 3-line description of export_demo (lines 72-77) - Replaced with single cross-reference to the comprehensive section below - Comprehensive section (Features, Usage, Example Output, Implementation Notes) remains intact at line 148+ - Anchor #export_demo-example correctly links from line 73 Improves readability and reduces redundancy while maintaining complete documentation. * docs: Remove csv_export duplication in examples/README.md Consolidated duplicate documentation: - Removed redundant csv_export block from 'Additional Export Examples' section - Replaced with single cross-reference to comprehensive entry in 'Available Examples' - Anchor links correctly reference sections above - Reduces file length by 11 lines while maintaining complete documentation Improves readability by centralizing example documentation. * docs: Clarify CLI vs Library API in examples/README.md Addressed ambiguity about bbl_parser CLI tool usage: Changes: 1. Removed confusing CLI fallback references from gpx_export and event_export - Deleted: 'Use CLI: bbl_parser --gps flight.BBL' - Deleted: 'Use CLI: bbl_parser --event flight.BBL' 2. Added new 'CLI Tool vs Library Examples' section explaining: - What the CLI binary is (src/main.rs in the crate) - When to use CLI (command-line processing, batch operations) - When to use library API (Rust integration, programmatic access) - How to build/install the CLI - Relationship between library, examples, and CLI This clarifies that: - bbl_parser CLI is part of the crate (not separate tool) - It's a convenience wrapper on the library API - Readers should choose based on their use case - Examples focus on library integration patterns * docs: Correct GPS and Event export implementation status Fixed inaccurate documentation: Test Results (BTFL_KWONGKAN_10inch_0326_00_Filter.BBL): - gpx_export: ✅ Successfully exported 833 GPS coordinates - Includes home position, elevation, timestamps - Valid GPX format with proper structure - event_export: ✅ Successfully exported 5 events - Includes sync beep, flight mode, disarm, log end - Proper timestamp collection Documentation Updates: - gpx_export status: ⏳ Partial → ✅ Fully functional - event_export status: ⏳ Partial → ✅ Fully functional - multi_export status: ⏳ Partial → ✅ Production Ready - export_demo status: ⏳ Partial → ✅ Production Ready - Removed misleading footnote about parser enhancement needed - Updated implementation status table GPS and Event data collection are fully functional in the parser module. No parser enhancements are needed. * docs: Update multi_export status to fully functional - Changed multi_export status from 'Fully functional for CSV, ⏳ GPS/Event pending' to '✅ Fully functional - Exports all available formats' - Aligns with verified GPS and Event export functionality * refactor: Simplify output logic in multi_flight_export.rs - Removed unused 'suffix' variable - Simplified conditional output with direct if/else branches - Clearer output messages: - Single flight: '✓ Exported' - Multiple flights: '✓ Exported as .NN.csv' - Reduces code complexity and improves readability * docs: Add status indicator to export_demo section - Added status line after Usage examples (line 171) - Consistent with gpx_export, event_export, and multi_export examples - Status: '✅ Fully functional - Exports all formats (CSV, GPX, events) with comprehensive logging' - Improves visual consistency and clarity across all example sections * fix: Add language identifiers to fenced code blocks - Added 'text' language identifier to multi_flight_export example output (line 42) - Added 'text' language identifier to export_demo example output (line 176) - Improves syntax highlighting and markdown linting compliance - All code blocks now properly labeled: bash, rust, or text
1 parent ec21e39 commit c923383

4 files changed

Lines changed: 376 additions & 96 deletions

File tree

CRATE_USAGE.md

Lines changed: 138 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,25 @@
22

33
Focused guidance for using the bbl_parser Rust crate.
44

5+
## ⚠️ Important: Understanding Log Numbers and Flight Suffixes
6+
7+
A single BBL file can contain **multiple flight sessions** (separated by LOG_END events). The crate handles this with two different parsing functions:
8+
9+
| Function | Returns | Use Case | Output |
10+
|----------|---------|----------|--------|
11+
| `parse_bbl_file()` | First log only | Single-flight files or when you only need the first flight | No suffix (e.g., `flight.csv`) |
12+
| `parse_bbl_file_all_logs()` | **All logs** | Multi-flight files or when you need all flights | With suffixes (e.g., `flight.01.csv`, `flight.02.csv`) |
13+
14+
**⚠️ Common mistake:** Using `parse_bbl_file()` on a multi-flight file will only export the first flight!
15+
516
## Table of Contents
617
- [Installation](#installation)
718
- [Cargo features](#cargo-features)
8-
- [Basic usage](#basic-usage)
9-
- [Multi-log processing](#multi-log-processing)
19+
- [Single-flight usage](#single-flight-usage)
20+
- [Multi-flight usage](#multi-flight-usage)
1021
- [Parsing from memory](#parsing-from-memory)
1122
- [Export functionality](#export-functionality)
23+
- [Flight numbering](#flight-numbering)
1224
- [Examples](#examples)
1325
- [Notes](#notes)
1426

@@ -31,7 +43,9 @@ bbl_parser = { path = "path/to/bbl_parser" }
3143

3244
If you only need the parser types and functions, the defaults are fine.
3345

34-
## Basic usage
46+
## Single-flight usage
47+
48+
For BBL files containing a single flight:
3549

3650
```rust
3751
use bbl_parser::{parse_bbl_file, ExportOptions};
@@ -40,27 +54,53 @@ use std::path::Path;
4054
fn main() -> anyhow::Result<()> {
4155
let log = parse_bbl_file(Path::new("flight.BBL"), ExportOptions::default(), false)?;
4256
println!("firmware: {}", log.header.firmware_revision);
43-
println!("frames: {}", log.sample_frames.len());
57+
println!("frames: {}", log.stats.total_frames);
4458
Ok(())
4559
}
4660
```
4761

4862
Key outputs on the BBLLog:
4963
- `header`: configuration and metadata
50-
- `sample_frames`: decoded I/P/S/G/H/E frames
64+
- `frames`: decoded flight data frames
5165
- `event_frames`: flight events (when present)
5266
- `gps_track`: GPS coordinates (when present)
67+
- `log_number` / `total_logs`: Current log number and total (useful to know if multi-log)
68+
69+
## Multi-flight usage
5370

54-
## Multi-log processing
71+
**For files with multiple flight sessions, ALWAYS use `parse_bbl_file_all_logs()`:**
5572

5673
```rust
5774
use bbl_parser::{parse_bbl_file_all_logs, ExportOptions};
5875
use std::path::Path;
5976

6077
fn main() -> anyhow::Result<()> {
6178
let logs = parse_bbl_file_all_logs(Path::new("multi_flight.BBL"), ExportOptions::default(), false)?;
79+
6280
for log in logs {
63-
println!("log {} of {} -> frames {}", log.log_number, log.total_logs, log.sample_frames.len());
81+
println!("Flight {}/{}", log.log_number, log.total_logs);
82+
println!(" Frames: {}", log.stats.total_frames);
83+
println!(" Firmware: {}", log.header.firmware_revision);
84+
}
85+
Ok(())
86+
}
87+
```
88+
89+
### Best Practice: Handle Both Cases
90+
91+
To write robust code that works with any BBL file:
92+
93+
```rust
94+
use bbl_parser::{parse_bbl_file_all_logs, ExportOptions};
95+
use std::path::Path;
96+
97+
fn main() -> anyhow::Result<()> {
98+
let logs = parse_bbl_file_all_logs(Path::new("flight.BBL"), ExportOptions::default(), false)?;
99+
100+
// This works whether the file has 1 flight or many
101+
for log in logs {
102+
println!("Flight {}/{}: {} frames", log.log_number, log.total_logs, log.stats.total_frames);
103+
// Process this flight
64104
}
65105
Ok(())
66106
}
@@ -69,26 +109,32 @@ fn main() -> anyhow::Result<()> {
69109
## Parsing from memory
70110

71111
```rust
72-
use bbl_parser::{parse_bbl_bytes, ExportOptions};
112+
use bbl_parser::{parse_bbl_bytes, parse_bbl_bytes_all_logs, ExportOptions};
73113

74114
fn main() -> anyhow::Result<()> {
75115
let bytes = std::fs::read("flight.BBL")?;
116+
117+
// Single flight (first only):
76118
let log = parse_bbl_bytes(&bytes, ExportOptions::default(), false)?;
77-
println!("frames: {}", log.sample_frames.len());
119+
120+
// All flights:
121+
let logs = parse_bbl_bytes_all_logs(&bytes, ExportOptions::default(), false)?;
122+
123+
println!("frames: {}", log.stats.total_frames);
78124
Ok(())
79125
}
80126
```
81127

82128
## Export functionality
83129

84-
The crate now provides full export capabilities for CSV, GPX, and Event data formats.
130+
The crate provides full export capabilities for CSV, GPX, and Event data formats.
85131

86132
### CSV Export
87133

88134
Export parsed log data to CSV files (flight data + headers):
89135

90136
```rust
91-
use bbl_parser::{parse_bbl_file, export_to_csv, ExportOptions};
137+
use bbl_parser::{parse_bbl_file_all_logs, export_to_csv, ExportOptions};
92138
use std::path::Path;
93139

94140
fn main() -> anyhow::Result<()> {
@@ -100,23 +146,30 @@ fn main() -> anyhow::Result<()> {
100146
force_export: false,
101147
};
102148

103-
let log = parse_bbl_file(Path::new("flight.BBL"), export_opts.clone(), false)?;
104-
export_to_csv(&log, Path::new("flight.BBL"), &export_opts)?;
149+
// Export all logs from the file (handles both single and multi-log files)
150+
let logs = parse_bbl_file_all_logs(Path::new("flight.BBL"), export_opts.clone(), false)?;
151+
for log in logs {
152+
export_to_csv(&log, Path::new("flight.BBL"), &export_opts)?;
153+
}
105154
println!("CSV exported successfully");
106155
Ok(())
107156
}
108157
```
109158

110-
This creates two files:
111-
- `flight.csv` - Main flight data with blackbox_decode compatible format
112-
- `flight.headers.csv` - Complete header information
159+
This creates two files per flight:
160+
- `flight.csv` or `flight.01.csv`, `flight.02.csv`, etc. - Main flight data with blackbox_decode compatible format
161+
- `flight.headers.csv` or `flight.01.headers.csv`, `flight.02.headers.csv`, etc. - Complete header information
162+
163+
**Flight Number Suffixes:**
164+
- Single flight: No suffix (e.g., `flight.csv`)
165+
- Multiple flights: Zero-padded 2-digit suffix (e.g., `flight.01.csv`, `flight.02.csv`, `flight.03.csv`)
113166

114167
### GPX Export
115168

116169
Export GPS data to GPX format for mapping applications:
117170

118171
```rust
119-
use bbl_parser::{parse_bbl_file, export_to_gpx, ExportOptions};
172+
use bbl_parser::{parse_bbl_file_all_logs, export_to_gpx, ExportOptions};
120173
use std::path::Path;
121174

122175
fn main() -> anyhow::Result<()> {
@@ -128,10 +181,11 @@ fn main() -> anyhow::Result<()> {
128181
force_export: false,
129182
};
130183

131-
let log = parse_bbl_file(Path::new("flight.BBL"), export_opts.clone(), false)?;
184+
let logs = parse_bbl_file_all_logs(Path::new("flight.BBL"), export_opts.clone(), false)?;
132185

133-
if !log.gps_coordinates.is_empty() {
134-
export_to_gpx(
186+
for log in logs {
187+
if !log.gps_coordinates.is_empty() {
188+
export_to_gpx(
135189
Path::new("flight.BBL"),
136190
0, // log index
137191
log.total_logs,
@@ -216,14 +270,75 @@ fn main() -> anyhow::Result<()> {
216270
}
217271
```
218272

273+
## Flight Numbering
274+
275+
Understanding how the crate handles flight numbers is critical for proper export handling:
276+
277+
### What Causes Multiple Flights?
278+
279+
A single BBL file contains multiple flights when the flight controller logs multiple sessions without restarting, typically separated by `LOG_END` events. Examples:
280+
- Same drone, multiple flights in one session
281+
- Interrupted logging (pause and resume)
282+
- Extended flight with logging that resets internal counters
283+
284+
### Flight Number Behavior
285+
286+
| Scenario | Log Number | Total Logs | Output File | Notes |
287+
|----------|-----------|-----------|------------|-------|
288+
| Single flight | 1 | 1 | `flight.csv` | No suffix when only one log |
289+
| 3 flights in file, export 1st | 1 | 3 | `flight.csv` | Using `parse_bbl_file()` only |
290+
| 3 flights in file, export all | 1, 2, 3 | 3 | `flight.01.csv`, `flight.02.csv`, `flight.03.csv` | Using `parse_bbl_file_all_logs()` |
291+
292+
### Accessing Flight Information
293+
294+
```rust
295+
use bbl_parser::{parse_bbl_file_all_logs, ExportOptions};
296+
use std::path::Path;
297+
298+
fn main() -> anyhow::Result<()> {
299+
let logs = parse_bbl_file_all_logs(
300+
Path::new("flight.BBL"),
301+
ExportOptions::default(),
302+
false
303+
)?;
304+
305+
for log in logs {
306+
println!("Flight {}/{}", log.log_number, log.total_logs);
307+
println!(" Frames: {}", log.stats.total_frames);
308+
println!(" Firmware: {}", log.header.firmware_revision);
309+
310+
// The export_to_csv function automatically adds the proper suffix
311+
// based on log.log_number and log.total_logs
312+
}
313+
Ok(())
314+
}
315+
```
316+
317+
### Suffix Rules
318+
319+
- **No suffix** if `total_logs == 1` (e.g., `flight.csv`)
320+
- **Suffix** if `total_logs > 1` (e.g., `flight.01.csv`, `flight.02.csv`)
321+
- **Format**: Zero-padded 2-digit number (`.01`, `.02`, ... `.99`)
322+
- **Automatic**: The `export_to_csv()`, `export_to_gpx()`, and `export_to_event()` functions handle suffixing automatically
323+
219324
For runnable examples with complete code and output, see [examples/README.md](./examples/README.md).
220325

221326
## Examples
222327

223-
Run the crate example that demonstrates multi-firmware support and PID extraction:
328+
### Quick Start Examples
329+
330+
**Export single flight (or first flight only):**
331+
```bash
332+
cargo run --example csv_export -- flight.BBL ./output
333+
```
334+
335+
**Export all flights with proper numbering:**
336+
```bash
337+
cargo run --example multi_flight_export -- flight.BBL ./output
338+
```
224339

340+
**Complete parsing and data access:**
225341
```bash
226-
cargo build --example bbl_crate_test
227342
cargo run --example bbl_crate_test -- flight.BBL
228343
```
229344

@@ -234,3 +349,4 @@ More details: [examples/README.md](./examples/README.md)
234349
- API is evolving while the project is WIP; names and structures may change.
235350
- CSV field order and naming follow blackbox-tools to maximize compatibility.
236351
- For CLI usage and high-level overview, see the main [README](./README.md).
352+
- **Always use `parse_bbl_file_all_logs()` in production code** to ensure all flights are processed correctly.

0 commit comments

Comments
 (0)