ross_protocol/event/
pwm.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 PwmValue {
12    Binary(bool),
13    Single(u8),
14    Rgb(u8, u8, u8),
15    RgbB(u8, u8, u8, u8),
16    Rgbw(u8, u8, u8, u8),
17    RgbwB(u8, u8, u8, u8, u8),
18}
19
20impl PwmValue {
21    fn serialize(self) -> Vec<u8> {
22        match self {
23            Self::Binary(value) => vec![0x00, if value { 0x01 } else { 0x00 }],
24            Self::Single(value) => vec![0x01, value],
25            Self::Rgb(red, green, blue) => vec![0x02, red, green, blue],
26            Self::RgbB(red, green, blue, brightness) => vec![0x03, red, green, blue, brightness],
27            Self::Rgbw(red, green, blue, white) => {
28                vec![0x04, red, green, blue, white]
29            }
30            Self::RgbwB(red, green, blue, white, brightness) => {
31                vec![0x05, red, green, blue, white, brightness]
32            }
33        }
34    }
35
36    fn deserialize(data: &[u8]) -> Result<Self, ConvertPacketError> {
37        if data.len() < 2 {
38            return Err(ConvertPacketError::WrongSize);
39        }
40
41        match data[0] {
42            0x00 => {
43                if data.len() != 2 {
44                    return Err(ConvertPacketError::WrongSize);
45                }
46
47                Ok(Self::Binary(data[1] != 0x00))
48            }
49            0x01 => {
50                if data.len() != 2 {
51                    return Err(ConvertPacketError::WrongSize);
52                }
53
54                Ok(Self::Single(data[1]))
55            }
56            0x02 => {
57                if data.len() != 4 {
58                    return Err(ConvertPacketError::WrongSize);
59                }
60
61                Ok(Self::Rgb(data[1], data[2], data[3]))
62            }
63            0x03 => {
64                if data.len() != 5 {
65                    return Err(ConvertPacketError::WrongSize);
66                }
67
68                Ok(Self::RgbB(data[1], data[2], data[3], data[4]))
69            }
70            0x04 => {
71                if data.len() != 5 {
72                    return Err(ConvertPacketError::WrongSize);
73                }
74
75                Ok(Self::Rgbw(data[1], data[2], data[3], data[4]))
76            }
77            0x05 => {
78                if data.len() != 6 {
79                    return Err(ConvertPacketError::WrongSize);
80                }
81
82                Ok(Self::RgbwB(data[1], data[2], data[3], data[4], data[5]))
83            }
84            _ => Err(ConvertPacketError::UnknownEnumVariant),
85        }
86    }
87}
88
89#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
90pub struct PwmChangeBrightnessEvent {
91    pub pwm_address: u16,
92    pub transmitter_address: u16,
93    pub index: u8,
94    pub value: PwmValue,
95}
96
97impl ConvertPacket<PwmChangeBrightnessEvent> for PwmChangeBrightnessEvent {
98    fn try_from_packet(packet: &Packet) -> Result<Self, ConvertPacketError> {
99        if packet.data.len() < 7 {
100            return Err(ConvertPacketError::WrongSize);
101        }
102
103        if packet.is_error {
104            return Err(ConvertPacketError::WrongType);
105        }
106
107        if u16::from_be_bytes(packet.data[0..=1].try_into().unwrap())
108            != PWM_CHANGE_BRIGHTNESS_EVENT_CODE
109        {
110            return Err(ConvertPacketError::Event(EventError::WrongEventType));
111        }
112
113        let pwm_address = packet.device_address;
114        let transmitter_address = u16::from_be_bytes(packet.data[2..=3].try_into().unwrap());
115        let index = packet.data[4];
116        let value = PwmValue::deserialize(&packet.data[5..])?;
117
118        Ok(PwmChangeBrightnessEvent {
119            pwm_address,
120            transmitter_address,
121            index,
122            value,
123        })
124    }
125
126    fn to_packet(&self) -> Packet {
127        let mut data = vec![];
128
129        for byte in u16::to_be_bytes(PWM_CHANGE_BRIGHTNESS_EVENT_CODE).iter() {
130            data.push(*byte);
131        }
132
133        for byte in u16::to_be_bytes(self.transmitter_address).iter() {
134            data.push(*byte);
135        }
136
137        data.push(self.index);
138        data.append(&mut self.value.serialize());
139
140        Packet {
141            is_error: false,
142            device_address: self.pwm_address,
143            data,
144        }
145    }
146}
147
148#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
149pub struct PwmAnimateBrightnessEvent {
150    pub pwm_address: u16,
151    pub transmitter_address: u16,
152    pub index: u8,
153    pub duration: u32,
154    pub target_value: PwmValue,
155}
156
157impl ConvertPacket<PwmAnimateBrightnessEvent> for PwmAnimateBrightnessEvent {
158    fn try_from_packet(packet: &Packet) -> Result<Self, ConvertPacketError> {
159        if packet.data.len() < 11 {
160            return Err(ConvertPacketError::WrongSize);
161        }
162
163        if packet.is_error {
164            return Err(ConvertPacketError::WrongType);
165        }
166
167        if u16::from_be_bytes(packet.data[0..=1].try_into().unwrap())
168            != PWM_ANIMATE_BRIGHTNESS_EVENT_CODE
169        {
170            return Err(ConvertPacketError::Event(EventError::WrongEventType));
171        }
172
173        let pwm_address = packet.device_address;
174        let transmitter_address = u16::from_be_bytes(packet.data[2..=3].try_into().unwrap());
175        let index = packet.data[4];
176        let duration = u32::from_be_bytes(packet.data[5..=8].try_into().unwrap());
177        let target_value = PwmValue::deserialize(&packet.data[9..])?;
178
179        Ok(Self {
180            pwm_address,
181            transmitter_address,
182            index,
183            duration,
184            target_value,
185        })
186    }
187
188    fn to_packet(&self) -> Packet {
189        let mut data = vec![];
190
191        for byte in u16::to_be_bytes(PWM_ANIMATE_BRIGHTNESS_EVENT_CODE).iter() {
192            data.push(*byte);
193        }
194
195        for byte in u16::to_be_bytes(self.transmitter_address).iter() {
196            data.push(*byte);
197        }
198
199        data.push(self.index);
200
201        for byte in u32::to_be_bytes(self.duration).iter() {
202            data.push(*byte);
203        }
204
205        data.append(&mut self.target_value.serialize());
206
207        Packet {
208            is_error: false,
209            device_address: self.pwm_address,
210            data,
211        }
212    }
213}
214
215#[cfg(test)]
216mod tests {
217    use super::*;
218
219    const EVENT_PACKET: Packet = Packet {
220        is_error: false,
221        device_address: 0xabab,
222        data: vec![],
223    };
224
225    #[test]
226    fn change_brightness_try_from_packet_test() {
227        let mut packet = EVENT_PACKET;
228        packet.data = vec![
229            ((PWM_CHANGE_BRIGHTNESS_EVENT_CODE >> 8) & 0xff) as u8, // event code
230            ((PWM_CHANGE_BRIGHTNESS_EVENT_CODE >> 0) & 0xff) as u8, // event code
231            0x00,                                                   // transmitter address
232            0x00,                                                   // transmitter address
233            0x01,                                                   // index
234            0x02,                                                   // value
235            0x23,                                                   // value
236            0x45,                                                   // value
237            0x67,                                                   // value
238        ];
239
240        let event = PwmChangeBrightnessEvent::try_from_packet(&packet).unwrap();
241
242        assert_eq!(event.pwm_address, 0xabab);
243        assert_eq!(event.transmitter_address, 0x0000);
244        assert_eq!(event.index, 0x01);
245        assert_eq!(event.value, PwmValue::Rgb(0x23, 0x45, 0x67));
246    }
247
248    #[test]
249    fn change_brightness_to_packet_test() {
250        let event = PwmChangeBrightnessEvent {
251            pwm_address: 0xabab,
252            transmitter_address: 0x0000,
253            index: 0x01,
254            value: PwmValue::Rgb(0x23, 0x45, 0x67),
255        };
256
257        let mut packet = EVENT_PACKET;
258        packet.data = vec![
259            ((PWM_CHANGE_BRIGHTNESS_EVENT_CODE >> 8) & 0xff) as u8, // event code
260            ((PWM_CHANGE_BRIGHTNESS_EVENT_CODE >> 0) & 0xff) as u8, // event code
261            0x00,                                                   // transmitter address
262            0x00,                                                   // transmitter address
263            0x01,                                                   // index
264            0x02,                                                   // value
265            0x23,                                                   // value
266            0x45,                                                   // value
267            0x67,                                                   // value
268        ];
269
270        assert_eq!(event.to_packet(), packet);
271    }
272
273    #[test]
274    fn animate_brightness_try_from_packet_test() {
275        let mut packet = EVENT_PACKET;
276        packet.data = vec![
277            ((PWM_ANIMATE_BRIGHTNESS_EVENT_CODE >> 8) & 0xff) as u8, // event code
278            ((PWM_ANIMATE_BRIGHTNESS_EVENT_CODE >> 0) & 0xff) as u8, // event code
279            0x00,                                                    // transmitter address
280            0x00,                                                    // transmitter address
281            0x01,                                                    // index
282            0xab,                                                    // duration
283            0xab,                                                    // duration
284            0xab,                                                    // duration
285            0xab,                                                    // duration
286            0x02,                                                    // target value
287            0x23,                                                    // target value
288            0x45,                                                    // target value
289            0x67,                                                    // target value
290        ];
291
292        let event = PwmAnimateBrightnessEvent::try_from_packet(&packet).unwrap();
293
294        assert_eq!(event.pwm_address, 0xabab);
295        assert_eq!(event.transmitter_address, 0x0000);
296        assert_eq!(event.index, 0x01);
297        assert_eq!(event.duration, 0xabab_abab);
298        assert_eq!(event.target_value, PwmValue::Rgb(0x23, 0x45, 0x67));
299    }
300
301    #[test]
302    fn animate_brightness_to_packet_test() {
303        let event = PwmAnimateBrightnessEvent {
304            pwm_address: 0xabab,
305            transmitter_address: 0x0000,
306            index: 0x01,
307            duration: 0xabab_abab,
308            target_value: PwmValue::Rgb(0x23, 0x45, 0x67),
309        };
310
311        let mut packet = EVENT_PACKET;
312        packet.data = vec![
313            ((PWM_ANIMATE_BRIGHTNESS_EVENT_CODE >> 8) & 0xff) as u8, // event code
314            ((PWM_ANIMATE_BRIGHTNESS_EVENT_CODE >> 0) & 0xff) as u8, // event code
315            0x00,                                                    // transmitter address
316            0x00,                                                    // transmitter address
317            0x01,                                                    // index
318            0xab,                                                    // duration
319            0xab,                                                    // duration
320            0xab,                                                    // duration
321            0xab,                                                    // duration
322            0x02,                                                    // target value
323            0x23,                                                    // target value
324            0x45,                                                    // target value
325            0x67,                                                    // target value
326        ];
327
328        assert_eq!(event.to_packet(), packet);
329    }
330}