use crc16::MODBUS;
mod ac_control_message;
mod ac_status_message;
mod group_control_message;
mod group_status_message;
pub use ac_control_message::ACControlMessage;
pub use ac_status_message::{ACStatus, GET_AC_STATUS_PACKET};
pub use group_control_message::GroupControlMessage;
pub use group_status_message::{GroupStatus, GET_GROUP_STATUS_PACKET};
struct MessageType;
impl MessageType {
pub const GROUP_CONTROL_MESSAGE: u8 = 0x2A;
pub const GROUP_STATUS_MESSAGE: u8 = 0x2B;
pub const AC_CONTROL_MESSAGE: u8 = 0x2C;
pub const AC_STATUS_MESSAGE: u8 = 0x2D;
}
#[derive(Debug)]
pub enum ReceivableMessage {
GroupStatuses(Vec<GroupStatus>),
ACStatuses(Vec<ACStatus>),
}
pub fn parse_message(bytes: &[u8]) -> Result<ReceivableMessage, &'static str> {
if bytes.len() < 10 {
return Err("bytes length is too short to be a valid AT4 message.");
}
if bytes[0] != 0x55 || bytes[1] != 0x55 {
return Err("invalid header.");
}
if bytes[3] != 0x80 && bytes[3] != 0x90 {
return Err("invalid address byte.");
}
let message_length: usize = (((bytes[6] as u16) << 2) | (bytes[7] as u16)) as usize;
if bytes.len() < (message_length + 10) {
return Err("bytes length is not long enough for parsed length.");
}
let data = bytes.get(2..(8 + message_length)).unwrap();
let crc = bytes
.get((8 + message_length)..(8 + message_length + 2))
.unwrap();
let crc: u16 = (crc[0] as u16) << 8 | (crc[1] as u16);
if crc16::State::<MODBUS>::calculate(data) != crc {
return Err("crc check failed.");
}
match bytes[5] {
MessageType::GROUP_STATUS_MESSAGE => group_status::parse(bytes),
MessageType::AC_STATUS_MESSAGE => ac_status::parse(bytes),
_ => return Err("invalid message type."),
}
}
mod ac_status;
mod group_status;
#[cfg(test)]
mod tests;