1extern crate serde_json;
2
3use serde_json::Value;
4use std::collections::{BTreeMap, BTreeSet, HashSet};
5use std::fmt;
6use std::fs::File;
7use std::io::{BufRead, BufReader, Error};
8
9const MSG_OBS: u64 = 74;
11
12const MSG_EPHEMERIS_GPS: u64 = 138;
14
15const MSG_EPHEMERIS_GAL: u64 = 149;
17
18const MSG_SSR_ORBIT_CLOCK: u64 = 1501;
20
21const MSG_SSR_CODE_BIASES: u64 = 1505;
23
24const MSG_SSR_PHASE_BIASES: u64 = 1510;
26
27const GPS_CODES: [u64; 12] = [0, 1, 5, 6, 7, 8, 9, 10, 11, 56, 57, 58];
29
30const GAL_CODES: [u64; 16] = [
32 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 61,
33];
34
35#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
37struct Sid {
38 sat: u64,
39 code: u64,
40 iod: Option<u64>,
41}
42
43impl fmt::Display for Sid {
44 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
45 if let Some(iod) = self.iod {
46 write!(fmt, "{}:{}-{}", self.sat, self.code, iod)
47 } else {
48 write!(fmt, "{}:{}", self.sat, self.code)
49 }
50 }
51}
52
53#[derive(Debug)]
55struct Msg {
56 msg_type: u64,
57 sender: u64,
58 tow: u64,
59 sid_set: BTreeSet<Sid>,
60}
61
62impl Msg {
63 fn observations(value: &Value, msg_type: u64, sender: u64) -> Option<Msg> {
65 value["header"]["t"]["tow"].as_u64().and_then(|tow| {
66 value["obs"].as_array().and_then(|obs| {
67 let mut sid_set: BTreeSet<Sid> = BTreeSet::new();
68 for ob in obs.iter() {
69 if let Some(sat) = ob["sid"]["sat"].as_u64() {
70 if let Some(code) = ob["sid"]["code"].as_u64() {
71 sid_set.insert(Sid {
72 sat,
73 code,
74 iod: None,
75 });
76 }
77 }
78 }
79 Some(Msg {
80 msg_type,
81 sender,
82 tow: tow / 1000,
83 sid_set,
84 })
85 })
86 })
87 }
88
89 fn ephemerides(value: &Value, msg_type: u64, sender: u64) -> Option<Msg> {
91 value["common"]["toe"]["tow"].as_u64().and_then(|tow| {
92 value["common"]["sid"]["sat"].as_u64().and_then(|sat| {
93 value["common"]["sid"]["code"].as_u64().and_then(|code| {
94 let mut sid_set: BTreeSet<Sid> = BTreeSet::new();
95 sid_set.insert(Sid {
96 sat,
97 code,
98 iod: value["iode"].as_u64(),
99 });
100 Some(Msg {
101 msg_type,
102 sender,
103 tow,
104 sid_set,
105 })
106 })
107 })
108 })
109 }
110
111 fn corrections(value: &Value, msg_type: u64, sender: u64) -> Option<Msg> {
113 value["time"]["tow"].as_u64().and_then(|tow| {
114 value["sid"]["sat"].as_u64().and_then(|sat| {
115 value["sid"]["code"].as_u64().and_then(|code| {
116 let mut sid_set: BTreeSet<Sid> = BTreeSet::new();
117 sid_set.insert(Sid {
118 sat,
119 code,
120 iod: value["iod"].as_u64(),
121 });
122 Some(Msg {
123 msg_type,
124 sender,
125 tow,
126 sid_set,
127 })
128 })
129 })
130 })
131 }
132
133 fn new(value: &Value) -> Option<Msg> {
135 value["msg_type"].as_u64().and_then(|msg_type| {
136 value["sender"].as_u64().and_then(|sender| match msg_type {
137 MSG_OBS => Self::observations(value, msg_type, sender),
138 MSG_EPHEMERIS_GPS => Self::ephemerides(value, msg_type, sender),
139 MSG_EPHEMERIS_GAL => Self::ephemerides(value, msg_type, sender),
140 MSG_SSR_ORBIT_CLOCK => Self::corrections(value, msg_type, sender),
141 MSG_SSR_CODE_BIASES => Self::corrections(value, msg_type, sender),
142 MSG_SSR_PHASE_BIASES => Self::corrections(value, msg_type, sender),
143 _ => None,
144 })
145 })
146 }
147}
148
149pub fn dump(file: &File, matched: bool, gps: bool, gal: bool) -> Result<(), Error> {
151 let buf = BufReader::new(file);
152
153 let mut code_set: HashSet<u64> = HashSet::new();
154 if gps {
155 for code in GPS_CODES.iter() {
156 code_set.insert(*code);
157 }
158 }
159 if gal {
160 for code in GAL_CODES.iter() {
161 code_set.insert(*code);
162 }
163 }
164
165 if matched {
166 let mut tow_map: BTreeMap<u64, BTreeMap<u64, BTreeMap<u64, BTreeSet<Sid>>>> =
167 BTreeMap::new();
168 for line in buf.lines() {
169 let value: Value = serde_json::from_str(&(line?))?;
170 if let Some(msg) = Msg::new(&value) {
171 let mut sid_set = msg.sid_set;
172 tow_map
173 .entry(msg.tow)
174 .or_insert_with(BTreeMap::new)
175 .entry(msg.sender)
176 .or_insert_with(BTreeMap::new)
177 .entry(msg.msg_type)
178 .or_insert_with(BTreeSet::new)
179 .append(&mut sid_set);
180 }
181 }
182
183 for (tow, sender_map) in tow_map.iter() {
184 for (sender, msg_type_map) in sender_map.iter() {
185 for (msg_type, sid_set) in msg_type_map.iter() {
186 let mut sid_set_str = String::new();
187 for sid in sid_set.iter() {
188 if code_set.contains(&sid.code) {
189 sid_set_str.push_str(&format!("{} ", sid));
190 }
191 }
192 println!("{:>6} {:>5} {:>4} {}", tow, sender, msg_type, sid_set_str);
193 }
194 }
195 println!();
196 }
197 } else {
198 for line in buf.lines() {
199 let value: Value = serde_json::from_str(&(line?))?;
200 if let Some(msg) = Msg::new(&value) {
201 let mut sid_set_str = String::new();
202 for sid in msg.sid_set.iter() {
203 if code_set.contains(&sid.code) {
204 sid_set_str.push_str(&format!("{} ", sid));
205 }
206 }
207 println!(
208 "{:>6} {:>5} {:>4} {}",
209 msg.tow, msg.sender, msg.msg_type, sid_set_str
210 );
211 }
212 }
213 }
214
215 Ok(())
216}