roco_z21_driver/messages/
system_state.rs

1use tokio::io;
2
3/// Represents the system state as reported by the Z21 station.
4///
5/// The structure corresponds to 16 bytes of data in the LAN_SYSTEMSTATE_DATACHANGED event.
6#[derive(Debug, Clone)]
7pub struct SystemState {
8    /// Current on the main track in mA.
9    pub main_current: i16,
10    /// Current on the programming track in mA.
11    pub prog_current: i16,
12    /// Smoothed current on the main track in mA.
13    pub filtered_main_current: i16,
14    /// Command station internal temperature in °C.
15    pub temperature: i16,
16    /// Supply voltage in mV.
17    pub supply_voltage: u16,
18    /// Internal voltage (identical to track voltage) in mV.
19    pub vcc_voltage: u16,
20    /// Bitmask representing the central state.
21    pub central_state: u8,
22    /// Extended central state bitmask.
23    pub central_state_ex: u8,
24    /// Reserved byte.
25    pub reserved: u8,
26    /// Capabilities bitmask (from Z21 FW Version 1.42).
27    pub capabilities: u8,
28}
29impl TryFrom<&[u8]> for SystemState {
30    type Error = io::Error;
31
32    /// Attempts to parse a `SystemState` from a 16-byte slice.
33    ///
34    /// # Errors
35    ///
36    /// Returns an error if the provided slice is not exactly 16 bytes long.
37    fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
38        if data.len() != 16 {
39            return Err(io::Error::new(
40                io::ErrorKind::InvalidData,
41                "Invalid SystemState data length",
42            ));
43        }
44        Ok(SystemState {
45            main_current: i16::from_le_bytes([data[0], data[1]]),
46            prog_current: i16::from_le_bytes([data[2], data[3]]),
47            filtered_main_current: i16::from_le_bytes([data[4], data[5]]),
48            temperature: i16::from_le_bytes([data[6], data[7]]),
49            supply_voltage: u16::from_le_bytes([data[8], data[9]]),
50            vcc_voltage: u16::from_le_bytes([data[10], data[11]]),
51            central_state: data[12],
52            central_state_ex: data[13],
53            reserved: data[14],
54            capabilities: data[15],
55        })
56    }
57}
58impl Into<Vec<u8>> for SystemState {
59    /// Converts a `SystemState` into a 16-byte vector.
60    fn into(self) -> Vec<u8> {
61        let mut result = Vec::with_capacity(16);
62        result.extend(&self.main_current.to_le_bytes());
63        result.extend(&self.prog_current.to_le_bytes());
64        result.extend(&self.filtered_main_current.to_le_bytes());
65        result.extend(&self.temperature.to_le_bytes());
66        result.extend(&self.supply_voltage.to_le_bytes());
67        result.extend(&self.vcc_voltage.to_le_bytes());
68        result.push(self.central_state);
69        result.push(self.central_state_ex);
70        result.push(self.reserved);
71        result.push(self.capabilities);
72        result
73    }
74}