Skip to content

Commit 946ad65

Browse files
committed
feat: improve file naming logic and documentation
- Remove .01 suffix for single log files (cleaner output) - Apply consistent naming across CSV, GPX, and event exports - Update README with clear filename examples for single vs multiple logs - Fix debug output formatting examples with proper field name display - Maintain blackbox_decode compatibility while improving user experience
1 parent c37eee7 commit 946ad65

2 files changed

Lines changed: 49 additions & 20 deletions

File tree

README.md

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ A high-performance Rust library and command-line tool for parsing BBL (Blackbox
2929

3030
Exports blackbox logs to CSV format with blackbox_decode compatibility:
3131

32-
- **`.XX.csv`**: Main flight data file containing I, P, S, G frame data
32+
- **`[.XX].csv`**: Main flight data file containing I, P, S, G frame data
3333
- Field names header row in blackbox_decode compatible order
3434
- Time field labeled as "time (us)" for microsecond precision
3535
- All flight loop data (I frames) and status data (S frames)
3636
- GPS data (G frames) when available
3737
- Time-sorted chronological data rows
38-
- **`.XX.headers.csv`**: Complete header information file
38+
- **`[.XX].headers.csv`**: Complete header information file
3939
- Field,Value format with all configuration parameters
4040
- Frame definitions, system settings, firmware information
4141
- All BBL header metadata for analysis tools
@@ -44,7 +44,7 @@ Exports blackbox logs to CSV format with blackbox_decode compatibility:
4444

4545
Exports GPS data to GPX format for mapping applications:
4646

47-
- **`.gps.gpx`**: GPS track file in standard GPX format
47+
- **`[.XX].gps.gpx`**: GPS track file in standard GPX format
4848
- Geographic coordinates from GPS frames
4949
- Altitude information with proper firmware scaling
5050
- Timestamp data for track visualization
@@ -54,22 +54,36 @@ Exports GPS data to GPX format for mapping applications:
5454

5555
Exports flight events to JSONL format:
5656

57-
- **`.event`**: Flight event data in JSON Lines format
57+
- **`[.XX].event`**: Flight event data in JSON Lines format
5858
- Individual JSON objects per line for streaming compatibility
5959
- Event types based on official Betaflight FlightLogEvent enum
6060
- Includes sync beeps, disarm events, flight mode changes, log boundaries
6161
- Compatible with log analysis tools expecting JSONL format
6262

63-
Where `XX` represents the flight log number (01, 02, 03, etc.) for multiple logs within a single BBL file.
63+
**Filename Logic:**
64+
- **Single log files**: Clean filenames without numbering (`flight_log.csv`, `flight_log.event`, `flight_log.gps.gpx`)
65+
- **Multiple log files**: Numbered sequence for clarity (`flight_log.01.csv`, `flight_log.02.event`, etc.)
6466

6567
**Example files generated:**
68+
69+
*Single log in BBL file:*
70+
```
71+
BTFL_LOG_20250601_121852.csv # Flight data
72+
BTFL_LOG_20250601_121852.headers.csv # Headers
73+
BTFL_LOG_20250601_121852.gps.gpx # GPS track data
74+
BTFL_LOG_20250601_121852.event # Flight events
75+
```
76+
77+
*Multiple logs in BBL file:*
6678
```
6779
BTFL_LOG_20250601_121852.01.csv # Flight data for log 1
6880
BTFL_LOG_20250601_121852.01.headers.csv # Headers for log 1
69-
BTFL_LOG_20250601_121852.gps.gpx # GPS track data
70-
BTFL_LOG_20250601_121852.event # Flight events
81+
BTFL_LOG_20250601_121852.01.gps.gpx # GPS data for log 1
82+
BTFL_LOG_20250601_121852.01.event # Events for log 1
7183
BTFL_LOG_20250601_121852.02.csv # Flight data for log 2
7284
BTFL_LOG_20250601_121852.02.headers.csv # Headers for log 2
85+
BTFL_LOG_20250601_121852.02.gps.gpx # GPS data for log 2
86+
BTFL_LOG_20250601_121852.02.event # Events for log 2
7387
```
7488

7589
## Installation & Usage
@@ -340,8 +354,10 @@ Data ver 2
340354

341355
Additional output when export flags are used:
342356
```
343-
Exported GPS data to: flight_log.gps.gpx # When --gpx used
344-
Exported event data to: flight_log.event # When --event used
357+
Exported headers to: flight_log[.XX].headers.csv
358+
Exported flight data to: flight_log[.XX].csv
359+
Exported GPS data to: flight_log[.XX].gps.gpx # When --gpx used
360+
Exported event data to: flight_log[.XX].event # When --event used
345361
```
346362

347363
### Debug Output
@@ -352,15 +368,15 @@ Debug mode adds frame data tables for detailed analysis:
352368
=== FRAME DATA ===
353369
354370
I-frame data (25 frames):
355-
Index Time(μs) Loop accSmooth[ accSmooth[ gyroADC[0] motor[0] motor[1] ... (40 more fields)
371+
Index Time(μs) Loop accSmooth accSmooth gyroADC[0] motor[0] motor[1] ... (40 more fields)
356372
0 0 4 0 0 -5 1270 1270 ...
357373
1 36147802 71168 -163 130 2289 1260 1277 ...
358374
... ... ... ... (18 frames skipped)
359375
23 36853826 73984 -332 -12 3512 1215 1210 ...
360376
24 36885919 74112 -430 26 3552 1205 1210 ...
361377
362378
P-frame data (50 frames):
363-
Index Time(μs) Loop accSmooth[ accSmooth[ gyroADC[0] motor[0] motor[1] ... (40 more fields)
379+
Index Time(μs) Loop accSmooth accSmooth gyroADC[0] motor[0] motor[1] ... (40 more fields)
364380
0 18446744073709551615 5 -11 9 27 632 637 ...
365381
1 18446744073709551615 6 -11 9 26 948 958 ...
366382
... ... ... ... (18 frames skipped)

src/main.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,7 @@ fn export_logs_to_csv(
12271227
let log_suffix = if logs.len() > 1 {
12281228
format!(".{:02}", log.log_number)
12291229
} else {
1230-
".01".to_string()
1230+
"".to_string()
12311231
};
12321232

12331233
// Export plaintext headers to separate CSV
@@ -1272,7 +1272,7 @@ fn export_single_log_to_csv(
12721272
let log_suffix = if log.total_logs > 1 {
12731273
format!(".{:02}", log.log_number)
12741274
} else {
1275-
".01".to_string()
1275+
"".to_string()
12761276
};
12771277

12781278
// Export plaintext headers to separate CSV
@@ -2647,6 +2647,7 @@ fn parse_bbl_file_streaming(
26472647
if let Err(e) = export_gpx_file(
26482648
file_path,
26492649
log_index,
2650+
log_positions.len(),
26502651
&gps_coords,
26512652
&home_coords,
26522653
export_options,
@@ -2664,7 +2665,13 @@ fn parse_bbl_file_streaming(
26642665

26652666
// Export event data to JSON if requested
26662667
if export_options.event && !events.is_empty() {
2667-
if let Err(e) = export_event_file(file_path, log_index, &events, export_options) {
2668+
if let Err(e) = export_event_file(
2669+
file_path,
2670+
log_index,
2671+
log_positions.len(),
2672+
&events,
2673+
export_options,
2674+
) {
26682675
let filename = file_path
26692676
.file_name()
26702677
.and_then(|n| n.to_str())
@@ -2835,6 +2842,7 @@ fn convert_gps_course(raw_value: i32) -> f64 {
28352842
fn export_gpx_file(
28362843
file_path: &Path,
28372844
log_number: usize,
2845+
total_logs: usize,
28382846
gps_coords: &[GpsCoordinate],
28392847
_home_coords: &[GpsHomeCoordinate], // TODO: Use home coordinates for reference point
28402848
export_options: &ExportOptions,
@@ -2853,11 +2861,13 @@ fn export_gpx_file(
28532861
.as_deref()
28542862
.unwrap_or_else(|| file_path.parent().unwrap().to_str().unwrap());
28552863

2856-
let gpx_filename = if log_number > 0 {
2857-
format!("{}/{}.{:02}.gps.gpx", output_dir, base_name, log_number + 1)
2864+
// Use consistent naming: only add suffix for multiple logs
2865+
let log_suffix = if total_logs > 1 {
2866+
format!(".{:02}", log_number + 1)
28582867
} else {
2859-
format!("{}/{}.gps.gpx", output_dir, base_name)
2868+
"".to_string()
28602869
};
2870+
let gpx_filename = format!("{}/{}{}.gps.gpx", output_dir, base_name, log_suffix);
28612871

28622872
let mut gpx_file = std::fs::File::create(&gpx_filename)?;
28632873
writeln!(gpx_file, r#"<?xml version="1.0" encoding="UTF-8"?>"#)?;
@@ -2906,6 +2916,7 @@ fn export_gpx_file(
29062916
fn export_event_file(
29072917
file_path: &Path,
29082918
log_number: usize,
2919+
total_logs: usize,
29092920
events: &[EventFrame],
29102921
export_options: &ExportOptions,
29112922
) -> Result<()> {
@@ -2923,11 +2934,13 @@ fn export_event_file(
29232934
.as_deref()
29242935
.unwrap_or_else(|| file_path.parent().unwrap().to_str().unwrap());
29252936

2926-
let event_filename = if log_number > 0 {
2927-
format!("{}/{}.{:02}.event", output_dir, base_name, log_number + 1)
2937+
// Use consistent naming: only add suffix for multiple logs
2938+
let log_suffix = if total_logs > 1 {
2939+
format!(".{:02}", log_number + 1)
29282940
} else {
2929-
format!("{}/{}.event", output_dir, base_name)
2941+
"".to_string()
29302942
};
2943+
let event_filename = format!("{}/{}{}.event", output_dir, base_name, log_suffix);
29312944

29322945
let mut event_file = std::fs::File::create(&event_filename)?;
29332946

0 commit comments

Comments
 (0)