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