1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use std::str::FromStr;
use regex::Regex;
use serde::{Deserialize, Serialize};
const REGEX_PATTERN: &str = r"DX de (?P<spotter>[A-Z\d\\/-]+)-#:\s*(?P<frequency>[\d.]+)\s+(?P<spotted>[A-Z\d\\/-]+)\s+(?P<mode>[A-Z\d]+)\s+(?P<snr>[\d-]+) dB\s+(?P<speed>\d+) [WPMBPS]+\s+(?P<message>[A-Za-z\\d ]+)\s*(?P<time>[0-9]{4})Z";
#[derive(Debug, PartialEq, PartialOrd, Clone, Deserialize, Serialize)]
pub struct RbnPacket {
pub spotter: String,
pub frequency: f32,
pub spotted: String,
pub mode: String,
pub snr: f32,
pub speed: u8,
pub message: String,
pub time: String,
}
impl RbnPacket {
pub fn dirty_hash(&self) -> String {
format!(
"{}-{}-{}-{}",
self.spotted, self.frequency, self.mode, self.time
)
}
}
impl FromStr for RbnPacket {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let regex = Regex::new(REGEX_PATTERN).unwrap();
let mut captures = regex.captures_iter(s);
let first = captures.next();
if first.is_none() {
return Err(());
}
let first = first.unwrap();
Ok(Self {
spotter: first["spotter"].to_string(),
frequency: first["frequency"].parse().unwrap_or(0.0),
spotted: first["spotted"].to_string(),
mode: first["mode"].to_string(),
snr: first["snr"].parse().unwrap_or(0.0),
speed: first["speed"].parse().unwrap_or(0),
message: first["message"].to_string(),
time: first["time"].to_string(),
})
}
}