use super::{Display, Frame, ParseError};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Debug, Display, Clone)]
#[repr(align(4))]
pub enum RemoteSource {
App,
KeyFob,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Debug, Display, Clone)]
#[repr(align(8))]
pub enum Remote {
Idle,
LockFrom(RemoteSource),
UnlockFrom(RemoteSource),
DoubleUnlock,
KeylessEntry,
StartFrom(RemoteSource),
CancelStart,
PanicFrom(RemoteSource),
}
impl TryFrom<Frame> for Remote {
type Error = ParseError;
fn try_from(frame: Frame) -> Result<Self, Self::Error> {
use RemoteSource::{App, KeyFob};
const ID: u32 = 0x1c0;
const LEN: usize = 6;
if frame.id() != ID {
return Err(ParseError::Id { frame });
}
let data: [u8; LEN] = match frame.data().try_into() {
Ok(data) => data,
Err(_) => {
return Err(ParseError::Len {
frame,
expected: LEN,
})
}
};
match data[0] {
0x00 => Ok(Remote::Idle), 0x21 => Ok(Remote::LockFrom(KeyFob)), 0x23 => Ok(Remote::UnlockFrom(KeyFob)), 0x24 => Ok(Remote::DoubleUnlock), 0x2E => Ok(Remote::PanicFrom(KeyFob)), 0x43 => Ok(Remote::KeylessEntry), 0x69 => Ok(Remote::StartFrom(KeyFob)), 0x81 => Ok(Remote::LockFrom(App)), 0x83 => Ok(Remote::UnlockFrom(App)), 0x6A => Ok(Remote::CancelStart), _ => Err(ParseError::Data {
frame: frame,
detail: format!(
"Byte at index 0 not recognized: {:X}",
data[0]
),
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_remote_parsing() {
let frame =
Frame::from_id_data_len(0x1c0, [0x21, 0, 0, 0, 0, 0, 0, 0], 6)
.unwrap();
let remote = Remote::try_from(frame).unwrap();
assert_eq!(remote, Remote::LockFrom(RemoteSource::KeyFob))
}
}