1use cu29::prelude::*;
2use cu_msp_lib::structs::MspResponse;
3#[cfg(unix)]
4use cu_msp_lib::MspParser;
5#[cfg(unix)]
6use serialport::SerialPort;
7#[cfg(unix)]
8use serialport::TTYPort;
9use smallvec::SmallVec;
10
11use bincode::de::Decoder;
12use bincode::enc::Encoder;
13use bincode::error::{DecodeError, EncodeError};
14use bincode::{Decode, Encode};
15use serde::{Deserialize, Serialize};
16#[cfg(unix)]
17use std::io::Read;
18
19const MAX_MSG_SIZE: usize = 16;
20
21#[derive(Debug, Clone, Default, Serialize, Deserialize)]
22pub struct MspResponseBatch(pub SmallVec<[MspResponse; MAX_MSG_SIZE]>);
23
24impl Encode for MspResponseBatch {
25 fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
26 Encode::encode(&self.0.as_slice(), encoder)
27 }
28}
29
30impl Decode<()> for MspResponseBatch {
31 fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, DecodeError> {
32 let v = <Vec<MspResponse> as Decode<()>>::decode(decoder)?;
34 Ok(Self(v.into()))
35 }
36}
37
38impl MspResponseBatch {
39 pub fn new() -> Self {
40 Self(SmallVec::new())
41 }
42
43 pub fn push(&mut self, resp: MspResponse) {
44 let MspResponseBatch(ref mut vec) = self;
45 vec.push(resp);
46 }
47
48 pub fn len(&self) -> usize {
49 self.0.len()
50 }
51
52 pub fn is_empty(&self) -> bool {
53 self.0.is_empty()
54 }
55}
56
57pub struct MSPSrc {
58 #[cfg(unix)]
59 serial: TTYPort,
60 #[cfg(unix)]
61 parser: MspParser,
62 buffer: SmallVec<[u8; 512]>,
63}
64
65impl Freezable for MSPSrc {}
66
67impl CuSrcTask for MSPSrc {
68 type Output<'m> = output_msg!(MspResponseBatch);
69
70 fn new(config: Option<&ComponentConfig>) -> CuResult<Self>
71 where
72 Self: Sized,
73 {
74 if config.is_none() {
75 return Err("No config provided".into());
76 }
77 #[cfg(unix)]
78 let port: String = config
79 .and_then(|config| config.get::<String>("device"))
80 .unwrap_or("/dev/ttyUSB0".to_string());
81 #[cfg(unix)]
82 let baudrate = config
83 .and_then(|config| config.get::<u32>("baudrate"))
84 .unwrap_or(115200);
85
86 #[cfg(unix)]
87 let builder = serialport::new(port, baudrate);
88 #[cfg(unix)]
89 let mut serial = TTYPort::open(&builder).unwrap();
90 #[cfg(unix)]
91 serial.set_exclusive(false).unwrap();
92 #[cfg(unix)]
93 serial
94 .set_timeout(std::time::Duration::from_millis(100))
95 .unwrap();
96
97 #[cfg(unix)]
98 let parser = MspParser::new();
99 Ok(Self {
100 #[cfg(unix)]
101 serial,
102 #[cfg(unix)]
103 parser,
104 buffer: SmallVec::new(),
105 })
106 }
107
108 fn process(&mut self, _clock: &RobotClock, output: &mut Self::Output<'_>) -> CuResult<()> {
109 self.buffer.clear();
110 self.buffer.resize(512, 0);
111 #[cfg(unix)]
112 let n = self.serial.read(&mut self.buffer);
113 #[cfg(unix)]
114 if let Err(e) = &n {
115 debug!("read error: {}", e.to_string());
116 return Ok(());
117 }
118 #[cfg(unix)]
119 let n = n.unwrap();
120 #[cfg(unix)]
121 self.buffer.truncate(n);
122
123 #[cfg(unix)]
124 let mut batch = MspResponseBatch::default();
125 #[cfg(unix)]
126 if n > 0 {
127 for &b in &self.buffer {
128 let maybe_packet = self.parser.parse(b);
129 if let Ok(Some(packet)) = maybe_packet {
130 let response = MspResponse::from(packet);
131 debug!("Response: {}", &response);
132 batch.push(response);
133 if batch.len() >= MAX_MSG_SIZE {
134 debug!("batch full, sending");
135 break;
136 }
137 }
138 }
139 }
140 #[cfg(unix)]
141 output.set_payload(batch);
142
143 #[cfg(windows)]
144 output.set_payload(MspResponseBatch::default());
145 Ok(())
146 }
147}
148
149#[cfg(unix)]
150#[cfg(test)]
151mod tests {
152 use serialport::SerialPort;
153 use serialport::TTYPort;
154 use std::io::Read;
155 use std::io::Write;
156
157 #[test]
158 #[ignore]
159 fn test_concurrent_r_w_serial() {
160 let port = "/dev/ttyS4";
161 let baudrate = 115200;
162 let builder = serialport::new(port, baudrate);
163 let mut r = TTYPort::open(&builder).unwrap();
164 r.set_exclusive(false).unwrap();
165 r.set_timeout(std::time::Duration::from_millis(10)).unwrap();
166
167 let mut w = TTYPort::open(&builder).unwrap();
168 w.set_exclusive(false).unwrap();
169
170 let data = [0x01, 0x02, 0x03, 0x04];
172 let nb = w.write(&data).unwrap();
173 assert_eq!(nb, data.len());
174 w.flush().unwrap();
175
176 let mut buf = [0; 4];
177 let nb = r.read(&mut buf).unwrap();
178 assert_eq!(nb, data.len());
179 assert_eq!(data, buf);
180 }
181}