ir_remote/ir_signal/
decode.rs

1use std::time::Duration;
2
3use bitvec::bitarr;
4use bitvec::prelude::*;
5
6use crate::are_all_equal::AreAllEqual;
7use crate::is_around::IsAround;
8
9use super::{
10    Event, IrPacket, IrSignal, RemoteType, Repeat, FIRST_LOW_DURATION, HIGH_DURATION,
11    LOW_0_DURATION, LOW_1_DURATION,
12};
13
14#[derive(Debug)]
15pub enum DecodeError {
16    FirstHighMissing,
17    LengthBad,
18    FirstHighBad,
19    FirstLowBad,
20    HighNotHigh,
21    HighBad(Duration),
22    LowNotLow,
23    LowBad(Duration),
24    IdBad,
25    LastByteBad,
26    SpaceNotLow,
27    MultipleDifferentPackets(Vec<IrPacket>),
28}
29
30impl IrSignal {
31    pub fn decode<'a, T: Iterator<Item = &'a Event>>(mut events: T) -> Result<Self, DecodeError> {
32        let acceptable_error: f64 = 0.2;
33
34        let decode_packet = |events: &mut T| {
35            // Check for first two special events
36            let signal_type = {
37                let first_high = events.next().ok_or(DecodeError::FirstHighMissing)?;
38                if !first_high.is_on {
39                    return Err(DecodeError::FirstHighBad);
40                }
41
42                RemoteType::decode_first_high(first_high.duration).ok_or(DecodeError::FirstHighBad)
43            }?;
44            {
45                let first_low = events.next().ok_or(DecodeError::LengthBad)?;
46                if first_low.is_on {
47                    return Err(DecodeError::FirstLowBad);
48                }
49                if !first_low.duration.is_around(
50                    Duration::from_secs_f64(FIRST_LOW_DURATION),
51                    acceptable_error,
52                ) {
53                    return Err(DecodeError::FirstLowBad);
54                }
55            }
56
57            let consume_high = |events: &mut T| -> Result<(), DecodeError> {
58                let high = events.next().ok_or(DecodeError::LengthBad)?;
59                if !high.is_on {
60                    return Err(DecodeError::HighNotHigh);
61                }
62                if !high
63                    .duration
64                    .is_around(Duration::from_secs_f64(HIGH_DURATION), acceptable_error)
65                {
66                    return Err(DecodeError::HighBad(high.duration));
67                }
68                Ok(())
69            };
70            // Get actual bits
71            let mut bits = bitarr!(u32, Msb0; 0; 32);
72            for i in 0..bits.len() {
73                consume_high(events)?;
74                {
75                    let low = events.next().ok_or(DecodeError::LengthBad)?;
76                    if low.is_on {
77                        return Err(DecodeError::LowNotLow);
78                    }
79                    let bit = match low.duration {
80                        duration
81                            if duration.is_around(
82                                Duration::from_secs_f64(LOW_0_DURATION),
83                                acceptable_error,
84                            ) =>
85                        {
86                            Some(false)
87                        }
88                        duration
89                            if duration.is_around(
90                                Duration::from_secs_f64(LOW_1_DURATION),
91                                acceptable_error,
92                            ) =>
93                        {
94                            Some(true)
95                        }
96                        _ => None,
97                    };
98                    bits.set(i, bit.ok_or(DecodeError::LowBad(low.duration))?);
99                }
100            }
101            // Always one last high
102            consume_high(events)?;
103
104            // Make sure 4th byte is 3rd byte inverted
105            if bits[24..32] != !bits[16..24].to_owned() {
106                return Err(DecodeError::LastByteBad);
107            }
108
109            Ok(IrPacket {
110                remote_type: signal_type,
111                receiver_id: bits[..16].load(),
112                button: bits[16..24].load(),
113            })
114        };
115        let mut packets = vec![decode_packet(&mut events)?];
116        let mut spaces = vec![];
117        loop {
118            match events.next() {
119                Some(event) => {
120                    if event.is_on {
121                        println!("{:#?}", event);
122                        break Err(DecodeError::SpaceNotLow);
123                    }
124                    spaces.push(event.duration);
125                    packets.push(decode_packet(&mut events)?);
126                }
127                None => {
128                    if !packets.are_all_equal() {
129                        break Err(DecodeError::MultipleDifferentPackets(packets));
130                    }
131                    // Verify packets are all identical
132                    // TODO: Verify consistent space durations with a margin of error
133                    break Ok(Self {
134                        packet: packets[0],
135                        repeat: match spaces.len() {
136                            0 => None,
137                            1.. => Some(Repeat {
138                                times: packets.len(),
139                                // TODO: get average duration between
140                                duration_between: spaces[0],
141                            }),
142                        },
143                    });
144                }
145            };
146        }
147    }
148}