milstd1553b_parser/
protocol.rs

1//! Protocol-level handling and validation for MIL-STD-1553B
2
3use crate::core::{Address, Bus};
4use crate::error::Result;
5use std::collections::HashMap;
6use std::time::{Duration, Instant};
7
8/// State of a Remote Terminal device
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub enum RTState {
12    /// Device is idle
13    Idle,
14    /// Device is busy processing
15    Busy,
16    /// Device reported an error
17    Error,
18    /// Device is not responding
19    NoResponse,
20}
21
22/// Information about a Remote Terminal
23#[derive(Debug, Clone)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub struct RemoteTerminal {
26    /// Address of the RT
27    pub address: Address,
28    /// Current state
29    pub state: RTState,
30    /// Last communication time
31    pub last_seen: Option<Instant>,
32    /// Number of errors detected
33    pub error_count: u32,
34    /// Number of successful transactions
35    pub success_count: u32,
36}
37
38impl RemoteTerminal {
39    /// Create a new Remote Terminal info
40    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    /// Record a successful transaction
51    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    /// Record a failed transaction
58    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    /// Check if device is responding (seen within timeout)
65    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/// Bus Controller state and management
74#[derive(Debug)]
75pub struct BusController {
76    /// Bus identifier
77    pub bus: Bus,
78    /// Remote terminals on this bus
79    remote_terminals: HashMap<u8, RemoteTerminal>,
80    /// Expected response timeout
81    pub response_timeout: Duration,
82}
83
84impl BusController {
85    /// Create a new Bus Controller for a bus
86    pub fn new(bus: Bus) -> Self {
87        BusController {
88            bus,
89            remote_terminals: HashMap::new(),
90            response_timeout: Duration::from_micros(12), // Typical 12 microseconds
91        }
92    }
93
94    /// Register a Remote Terminal
95    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    /// Register multiple Remote Terminals
107    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    /// Get Remote Terminal info
115    pub fn get_rt(&self, address: Address) -> Option<&RemoteTerminal> {
116        self.remote_terminals.get(&address.value())
117    }
118
119    /// Get mutable Remote Terminal info
120    pub fn get_rt_mut(&mut self, address: Address) -> Option<&mut RemoteTerminal> {
121        self.remote_terminals.get_mut(&address.value())
122    }
123
124    /// List all registered Remote Terminals
125    pub fn list_rts(&self) -> Vec<&RemoteTerminal> {
126        self.remote_terminals.values().collect()
127    }
128
129    /// Get all responding Remote Terminals
130    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    /// Get total number of RTs
138    pub fn rt_count(&self) -> usize {
139        self.remote_terminals.len()
140    }
141
142    /// Record a successful transaction with an RT
143    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    /// Record a failed transaction with an RT
155    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    /// Get statistics for a Remote Terminal
167    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    /// Get statistics for all Remote Terminals
183    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/// Statistics for a Remote Terminal
192#[derive(Debug, Clone)]
193#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
194pub struct RTStats {
195    /// Address of the RT
196    pub address: Address,
197    /// Current state
198    pub state: RTState,
199    /// Number of successful transactions
200    pub success_count: u32,
201    /// Number of failed transactions
202    pub error_count: u32,
203    /// Error rate (0.0 to 1.0)
204    pub error_rate: f32,
205    /// Whether the RT is currently responding
206    pub is_responding: bool,
207}
208
209/// Message validator for protocol compliance
210pub struct MessageValidator;
211
212impl MessageValidator {
213    /// Validate message addressing
214    pub fn validate_address(address: Address) -> Result<()> {
215        // All addresses 0-31 are valid in different contexts
216        // This is a placeholder for more complex validation
217        let _ = address;
218        Ok(())
219    }
220
221    /// Validate word count
222    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    /// Validate sub-address
232    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}