decode_meas3/
decode_meas3.rs1use std::collections::HashMap;
2use std::env;
3use std::error::Error;
4use std::fs::File;
5
6use sbf_tools::{Meas3BlockSet, Meas3Decoder, SbfBlock, SbfReader};
7
8fn main() -> Result<(), Box<dyn Error>> {
9 let path = env::args()
10 .nth(1)
11 .ok_or("usage: cargo run --example decode_meas3 -- <path-to-file.sbf>")?;
12
13 let file = File::open(&path)?;
14 let reader = SbfReader::new(file);
15
16 let mut decoder = Meas3Decoder::new();
17 let mut current_tow: Option<u32> = None;
18 let mut bundles: HashMap<u8, Meas3BlockSet> = HashMap::new();
19
20 for block in reader {
21 let block = block?;
22
23 if let Some((tow_ms, antenna_id)) = meas3_epoch_key(&block) {
24 if current_tow != Some(tow_ms) {
25 flush_bundles(&mut bundles, &mut decoder)?;
26 current_tow = Some(tow_ms);
27 }
28 bundles.entry(antenna_id).or_default().insert_block(&block);
29 continue;
30 }
31
32 if matches!(block, SbfBlock::EndOfMeas(_)) {
33 flush_bundles(&mut bundles, &mut decoder)?;
34 current_tow = None;
35 }
36 }
37
38 flush_bundles(&mut bundles, &mut decoder)?;
39 Ok(())
40}
41
42fn meas3_epoch_key(block: &SbfBlock) -> Option<(u32, u8)> {
43 match block {
44 SbfBlock::Meas3Ranges(b) => Some((b.tow_ms(), b.antenna_id())),
45 SbfBlock::Meas3Cn0HiRes(b) => Some((b.tow_ms(), b.antenna_id())),
46 SbfBlock::Meas3Doppler(b) => Some((b.tow_ms(), b.antenna_id())),
47 SbfBlock::Meas3Pp(b) => Some((b.tow_ms(), b.antenna_id())),
48 SbfBlock::Meas3Mp(b) => Some((b.tow_ms(), b.antenna_id())),
49 _ => None,
50 }
51}
52
53fn flush_bundles(
54 bundles: &mut HashMap<u8, Meas3BlockSet>,
55 decoder: &mut Meas3Decoder,
56) -> Result<(), Box<dyn Error>> {
57 let mut antenna_ids: Vec<u8> = bundles.keys().copied().collect();
58 antenna_ids.sort_unstable();
59
60 for antenna_id in antenna_ids {
61 if let Some(block_set) = bundles.get(&antenna_id) {
62 if block_set.ranges.is_none() {
63 continue;
64 }
65
66 let epoch = decoder.decode_block_set(block_set)?;
67 println!(
68 "TOW {} WNc {} antenna {}: {} satellites, {} measurements",
69 epoch.tow_ms(),
70 epoch.wnc(),
71 epoch.antenna_id,
72 epoch.num_satellites(),
73 epoch.num_measurements()
74 );
75
76 for satellite in epoch.satellites.iter().take(4) {
77 let signal_summary = satellite
78 .measurements
79 .iter()
80 .map(|meas| match meas.cn0_dbhz() {
81 Some(cn0) => format!("{}:{cn0:.2}dB-Hz", meas.signal_type),
82 None => meas.signal_type.to_string(),
83 })
84 .collect::<Vec<_>>()
85 .join(", ");
86 println!(" {} {}", satellite.sat_id, signal_summary);
87 }
88 }
89 }
90
91 bundles.clear();
92 Ok(())
93}