milstd1553b_parser/
protocol.rs1use crate::core::{Address, Bus};
4use crate::error::Result;
5use std::collections::HashMap;
6use std::time::{Duration, Instant};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub enum RTState {
12 Idle,
14 Busy,
16 Error,
18 NoResponse,
20}
21
22#[derive(Debug, Clone)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub struct RemoteTerminal {
26 pub address: Address,
28 pub state: RTState,
30 pub last_seen: Option<Instant>,
32 pub error_count: u32,
34 pub success_count: u32,
36}
37
38impl RemoteTerminal {
39 pub fn new(address: Address) -> Self {
41 RemoteTerminal {
42 address,
43 state: RTState::Idle,
44 last_seen: None,
45 error_count: 0,
46 success_count: 0,
47 }
48 }
49
50 pub fn record_success(&mut self) {
52 self.success_count += 1;
53 self.state = RTState::Idle;
54 self.last_seen = Some(Instant::now());
55 }
56
57 pub fn record_error(&mut self) {
59 self.error_count += 1;
60 self.state = RTState::Error;
61 self.last_seen = Some(Instant::now());
62 }
63
64 pub fn is_responding(&self, timeout: Duration) -> bool {
66 match self.last_seen {
67 Some(instant) => instant.elapsed() < timeout,
68 None => false,
69 }
70 }
71}
72
73#[derive(Debug)]
75pub struct BusController {
76 pub bus: Bus,
78 remote_terminals: HashMap<u8, RemoteTerminal>,
80 pub response_timeout: Duration,
82}
83
84impl BusController {
85 pub fn new(bus: Bus) -> Self {
87 BusController {
88 bus,
89 remote_terminals: HashMap::new(),
90 response_timeout: Duration::from_micros(12), }
92 }
93
94 pub fn register_rt(&mut self, address: Address) -> Result<()> {
96 if !address.is_remote_terminal() {
97 return Err(crate::error::ParseError::invalid_address(
98 "Address must be a valid RT (0-29)".to_string(),
99 ));
100 }
101 self.remote_terminals
102 .insert(address.value(), RemoteTerminal::new(address));
103 Ok(())
104 }
105
106 pub fn register_rts(&mut self, addresses: &[u8]) -> Result<()> {
108 for &addr in addresses {
109 self.register_rt(Address::new(addr)?)?;
110 }
111 Ok(())
112 }
113
114 pub fn get_rt(&self, address: Address) -> Option<&RemoteTerminal> {
116 self.remote_terminals.get(&address.value())
117 }
118
119 pub fn get_rt_mut(&mut self, address: Address) -> Option<&mut RemoteTerminal> {
121 self.remote_terminals.get_mut(&address.value())
122 }
123
124 pub fn list_rts(&self) -> Vec<&RemoteTerminal> {
126 self.remote_terminals.values().collect()
127 }
128
129 pub fn get_responding_rts(&self) -> Vec<&RemoteTerminal> {
131 self.remote_terminals
132 .values()
133 .filter(|rt| rt.is_responding(self.response_timeout))
134 .collect()
135 }
136
137 pub fn rt_count(&self) -> usize {
139 self.remote_terminals.len()
140 }
141
142 pub fn record_rt_success(&mut self, address: Address) -> Result<()> {
144 if let Some(rt) = self.get_rt_mut(address) {
145 rt.record_success();
146 Ok(())
147 } else {
148 Err(crate::error::ParseError::invalid_address(
149 "RT not registered".to_string(),
150 ))
151 }
152 }
153
154 pub fn record_rt_error(&mut self, address: Address) -> Result<()> {
156 if let Some(rt) = self.get_rt_mut(address) {
157 rt.record_error();
158 Ok(())
159 } else {
160 Err(crate::error::ParseError::invalid_address(
161 "RT not registered".to_string(),
162 ))
163 }
164 }
165
166 pub fn get_rt_stats(&self, address: Address) -> Option<RTStats> {
168 self.get_rt(address).map(|rt| RTStats {
169 address: rt.address,
170 state: rt.state,
171 success_count: rt.success_count,
172 error_count: rt.error_count,
173 error_rate: if rt.success_count + rt.error_count > 0 {
174 rt.error_count as f32 / (rt.success_count + rt.error_count) as f32
175 } else {
176 0.0
177 },
178 is_responding: rt.is_responding(self.response_timeout),
179 })
180 }
181
182 pub fn get_all_stats(&self) -> Vec<RTStats> {
184 self.list_rts()
185 .into_iter()
186 .filter_map(|rt| self.get_rt_stats(rt.address))
187 .collect()
188 }
189}
190
191#[derive(Debug, Clone)]
193#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
194pub struct RTStats {
195 pub address: Address,
197 pub state: RTState,
199 pub success_count: u32,
201 pub error_count: u32,
203 pub error_rate: f32,
205 pub is_responding: bool,
207}
208
209pub struct MessageValidator;
211
212impl MessageValidator {
213 pub fn validate_address(address: Address) -> Result<()> {
215 let _ = address;
218 Ok(())
219 }
220
221 pub fn validate_word_count(count: u16) -> Result<()> {
223 if count > 32 {
224 return Err(crate::error::ParseError::validation_error(
225 "Word count exceeds maximum of 32".to_string(),
226 ));
227 }
228 Ok(())
229 }
230
231 pub fn validate_sub_address(sub_addr: u8) -> Result<()> {
233 if sub_addr > 31 {
234 return Err(crate::error::ParseError::validation_error(
235 "Sub-address out of range [0, 31]".to_string(),
236 ));
237 }
238 Ok(())
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 use super::*;
245
246 #[test]
247 fn test_rt_creation() {
248 let rt = RemoteTerminal::new(Address::new(5).unwrap());
249 assert_eq!(rt.address.value(), 5);
250 assert_eq!(rt.state, RTState::Idle);
251 assert_eq!(rt.error_count, 0);
252 assert_eq!(rt.success_count, 0);
253 }
254
255 #[test]
256 fn test_bc_register_rt() -> Result<()> {
257 let mut bc = BusController::new(Bus::BusA);
258 bc.register_rt(Address::new(5)?)?;
259 assert_eq!(bc.rt_count(), 1);
260 assert!(bc.get_rt(Address::new(5)?).is_some());
261 Ok(())
262 }
263
264 #[test]
265 fn test_bc_register_multiple_rts() -> Result<()> {
266 let mut bc = BusController::new(Bus::BusA);
267 bc.register_rts(&[0, 5, 10, 15])?;
268 assert_eq!(bc.rt_count(), 4);
269 Ok(())
270 }
271
272 #[test]
273 fn test_rt_recording() -> Result<()> {
274 let mut rt = RemoteTerminal::new(Address::new(5)?);
275 rt.record_success();
276 assert_eq!(rt.success_count, 1);
277 assert_eq!(rt.state, RTState::Idle);
278
279 rt.record_error();
280 assert_eq!(rt.error_count, 1);
281 assert_eq!(rt.state, RTState::Error);
282 Ok(())
283 }
284
285 #[test]
286 fn test_message_validator() -> Result<()> {
287 MessageValidator::validate_word_count(16)?;
288 assert!(MessageValidator::validate_word_count(33).is_err());
289
290 MessageValidator::validate_sub_address(31)?;
291 assert!(MessageValidator::validate_sub_address(32).is_err());
292 Ok(())
293 }
294}