ross_protocol/event/
relay.rs

1use alloc::vec;
2use alloc::vec::Vec;
3use core::convert::TryInto;
4
5use crate::convert_packet::{ConvertPacket, ConvertPacketError};
6use crate::event::event_code::*;
7use crate::event::EventError;
8use crate::packet::Packet;
9
10#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
11pub enum RelayValue {
12    Single(bool),
13    DoubleExclusive(RelayDoubleExclusiveValue),
14}
15
16impl RelayValue {
17    fn serialize(self) -> Vec<u8> {
18        match self {
19            Self::Single(value) => vec![if value { 0x00 } else { 0x01 }],
20            Self::DoubleExclusive(RelayDoubleExclusiveValue::FirstChannelOn) => vec![0x02],
21            Self::DoubleExclusive(RelayDoubleExclusiveValue::SecondChannelOn) => vec![0x03],
22            Self::DoubleExclusive(RelayDoubleExclusiveValue::NoChannelOn) => vec![0x04],
23        }
24    }
25
26    fn deserialize(data: &[u8]) -> Result<Self, ConvertPacketError> {
27        if data.len() != 1 {
28            return Err(ConvertPacketError::WrongSize);
29        }
30
31        match data[0] {
32            0x00 => Ok(Self::Single(true)),
33            0x01 => Ok(Self::Single(false)),
34            0x02 => Ok(Self::DoubleExclusive(
35                RelayDoubleExclusiveValue::FirstChannelOn,
36            )),
37            0x03 => Ok(Self::DoubleExclusive(
38                RelayDoubleExclusiveValue::SecondChannelOn,
39            )),
40            0x04 => Ok(Self::DoubleExclusive(
41                RelayDoubleExclusiveValue::NoChannelOn,
42            )),
43            _ => Err(ConvertPacketError::UnknownEnumVariant),
44        }
45    }
46}
47
48#[repr(C)]
49#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
50pub enum RelayDoubleExclusiveValue {
51    FirstChannelOn,
52    SecondChannelOn,
53    NoChannelOn,
54}
55
56#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
57pub struct RelaySetValueEvent {
58    pub relay_address: u16,
59    pub transmitter_address: u16,
60    pub index: u8,
61    pub value: RelayValue,
62}
63
64impl ConvertPacket<RelaySetValueEvent> for RelaySetValueEvent {
65    fn try_from_packet(packet: &Packet) -> Result<Self, ConvertPacketError> {
66        if packet.data.len() != 6 {
67            return Err(ConvertPacketError::WrongSize);
68        }
69
70        if packet.is_error {
71            return Err(ConvertPacketError::WrongType);
72        }
73
74        if u16::from_be_bytes(packet.data[0..=1].try_into().unwrap()) != RELAY_SET_VALUE_EVENT_CODE
75        {
76            return Err(ConvertPacketError::Event(EventError::WrongEventType));
77        }
78
79        let relay_address = packet.device_address;
80        let transmitter_address = u16::from_be_bytes(packet.data[2..=3].try_into().unwrap());
81        let index = packet.data[4];
82        let value = RelayValue::deserialize(&packet.data[5..])?;
83
84        Ok(Self {
85            relay_address,
86            transmitter_address,
87            index,
88            value,
89        })
90    }
91
92    fn to_packet(&self) -> Packet {
93        let mut data = vec![];
94
95        for byte in u16::to_be_bytes(RELAY_SET_VALUE_EVENT_CODE).iter() {
96            data.push(*byte);
97        }
98
99        for byte in u16::to_be_bytes(self.transmitter_address).iter() {
100            data.push(*byte);
101        }
102
103        data.push(self.index);
104        data.append(&mut self.value.serialize());
105
106        Packet {
107            is_error: false,
108            device_address: self.relay_address,
109            data,
110        }
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117
118    const EVENT_PACKET: Packet = Packet {
119        is_error: false,
120        device_address: 0xabab,
121        data: vec![],
122    };
123
124    #[test]
125    fn set_state_try_from_packet_test() {
126        let mut packet = EVENT_PACKET;
127        packet.data = vec![
128            ((RELAY_SET_VALUE_EVENT_CODE >> 8) & 0xff) as u8, // event code
129            ((RELAY_SET_VALUE_EVENT_CODE >> 0) & 0xff) as u8, // event code
130            0x01,                                             // transmitter address
131            0x23,                                             // transmitter address
132            0x45,                                             // index
133            0x03,                                             // value
134        ];
135
136        let event = RelaySetValueEvent::try_from_packet(&packet).unwrap();
137
138        assert_eq!(event.relay_address, 0xabab);
139        assert_eq!(event.transmitter_address, 0x0123);
140        assert_eq!(event.index, 0x45);
141        assert_eq!(
142            event.value,
143            RelayValue::DoubleExclusive(RelayDoubleExclusiveValue::SecondChannelOn)
144        );
145    }
146
147    #[test]
148    fn set_state_to_packet_test() {
149        let event = RelaySetValueEvent {
150            relay_address: 0xabab,
151            transmitter_address: 0x0123,
152            index: 0x45,
153            value: RelayValue::DoubleExclusive(RelayDoubleExclusiveValue::SecondChannelOn),
154        };
155
156        let mut packet = EVENT_PACKET;
157        packet.data = vec![
158            ((RELAY_SET_VALUE_EVENT_CODE >> 8) & 0xff) as u8, // event code
159            ((RELAY_SET_VALUE_EVENT_CODE >> 0) & 0xff) as u8, // event code
160            0x01,                                             // transmitter address
161            0x23,                                             // transmitter address
162            0x45,                                             // index
163            0x03,                                             // value
164        ];
165
166        assert_eq!(event.to_packet(), packet);
167    }
168}