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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use kubos_telemetry_db::Database;
use log::{error, info};
use serde::Deserialize;
use std::net::{SocketAddr, UdpSocket};
use std::sync::{Arc, Mutex};
pub struct DirectUdp {
db: Arc<Mutex<Database>>,
}
#[derive(Debug, Deserialize)]
struct DataPoint {
timestamp: Option<f64>,
subsystem: String,
parameter: String,
value: String,
}
impl DirectUdp {
pub fn new(db: Arc<Mutex<Database>>) -> Self {
DirectUdp { db }
}
pub fn start(&self, url: String) {
let socket = UdpSocket::bind(url.parse::<SocketAddr>().unwrap_or_else(|err| {
error!(
"Couldn't start direct UDP connection. Failed to parse {}: {:?}",
url, err
);
panic!()
}))
.unwrap_or_else(|err| {
error!(
"Couldn't start direct UDP connection. Failed to bind {}: {:?}",
url, err
);
panic!()
});
info!("Direct UDP listening on: {}", socket.local_addr().unwrap());
loop {
let mut buf = [0; 4096];
let (size, _peer) = socket
.recv_from(&mut buf)
.map_err(|err| format!("Failed to receive a message: {}", err))
.unwrap();
if let Ok(val) = serde_json::from_slice::<DataPoint>(&buf[0..(size)]) {
if let Err(err) = self.process(&val) {
error!("Error {:?} storing message {:?}", err, val);
}
} else if let Ok(vec) = serde_json::from_slice::<Vec<DataPoint>>(&buf[0..(size)]) {
for val in vec.iter() {
if let Err(err) = self.process(val) {
error!("Error {:?} storing message {:?}", err, val);
}
}
} else {
error!(
"Couldn't deserialize JSON object or object array from {:?}",
String::from_utf8_lossy(&buf[0..size])
);
}
}
}
fn process(&self, message: &DataPoint) -> Result<(), String> {
if let Some(time) = message.timestamp {
self.db
.lock()
.map_err(|err| {
error!("udp - Failed to get lock on database: {}", err);
format!("{}", err)
})?
.insert(time, &message.subsystem, &message.parameter, &message.value)
.map_err(|err| {
error!("udp - Failed to get lock on database: {}", err);
format!("{}", err)
})?;
} else {
self.db
.lock()
.map_err(|err| {
error!("udp - Failed to get lock on database: {}", err);
format!("{}", err)
})?
.insert_systime(&message.subsystem, &message.parameter, &message.value)
.map_err(|err| {
error!("udp - Failed to get lock on database: {}", err);
format!("{}", err)
})?;
}
Ok(())
}
}