use crate::{messaging::group_status_message::GroupStatus, states};
use super::ReceivableMessage;
pub fn parse(bytes: &[u8]) -> Result<ReceivableMessage, &'static str> {
let data_length: usize = (((bytes[6] as u16) << 2) | (bytes[7] as u16)) as usize;
if data_length % 6 != 0 {
return Err("invalid message data length to be a group status message.");
}
let data = bytes.get(8..8 + data_length).unwrap();
let mut groups: Vec<GroupStatus> = Vec::with_capacity(data_length / 6);
for g in data.chunks(6) {
let power_state = match g[0] >> 6 {
0 => states::GroupPowerState::Off,
1 => states::GroupPowerState::On,
2 => states::GroupPowerState::Turbo,
_ => return Err("invalid value for `power_state`."),
};
let group_number = g[0] & 0b00111111;
let control_method = match g[1] >> 7 {
0 => states::GroupControlMethod::Percentage,
1 => states::GroupControlMethod::Temperature,
_ => unreachable!(),
};
let open_percentage = g[1] & 0b01111111;
let battery_low: bool = (g[2] >> 7) == 1;
let turbo_support: bool = ((g[2] >> 6) & 1) == 1;
let target_setpoint = g[2] & 0b00111111;
let has_sensor = (g[3] >> 7) == 1;
let current_temperature: Option<f64> = {
if g[4] == 0xff {
None
} else {
let g4 = g[4] as u16;
let g5 = g[5] as u16;
let num = (g4 << 3) | (g5 >> 5);
Some(((num as f64) - 500.00) / 10.00)
}
};
let spill = ((g[5] >> 4) & 0b1) == 1;
groups.push(GroupStatus {
battery_low,
control_method,
current_temperature,
group_number,
has_sensor,
spill,
turbo_support,
open_percentage,
target_setpoint,
power_state,
})
}
Ok(ReceivableMessage::GroupStatuses(groups))
}
#[cfg(test)]
mod test {
use crate::{messaging::group_status_message::GroupStatus, states};
use super::parse;
#[test]
fn test_parses_valid() {
let groups = parse(&[
0x55, 0x55, 0xb0, 0x80, 0x01, 0x2b, 0x00, 0x0c, 0x40, 0x64, 0x00, 0x00, 0xff, 0x00,
0x41, 0xe4, 0x1a, 0x80, 0x61, 0x80, 0x65, 0x79,
])
.unwrap();
match groups {
crate::messaging::ReceivableMessage::GroupStatuses(m) => {
let valid = vec![
GroupStatus {
power_state: states::GroupPowerState::On,
group_number: 0,
control_method: states::GroupControlMethod::Percentage,
open_percentage: 100,
battery_low: false,
turbo_support: false,
target_setpoint: 0,
has_sensor: false,
current_temperature: None,
spill: false,
},
GroupStatus {
power_state: states::GroupPowerState::On,
group_number: 1,
control_method: states::GroupControlMethod::Temperature,
open_percentage: 100,
battery_low: false,
turbo_support: false,
target_setpoint: 26,
has_sensor: true,
current_temperature: Some(28.0),
spill: false,
},
];
m.iter()
.zip(valid.iter())
.for_each(|(a, b)| assert_eq!(a, b));
}
_ => panic!("incorrect message type returned."),
}
}
}