use crc16::MODBUS;
use crate::{messaging::MessageType, states};
#[derive(Debug, Clone, Copy)]
pub struct GroupControlMessage {
pub group_number: u8,
pub target_value: states::SetGroupSettingValue,
pub control_method: states::SetGroupControlMethod,
pub power: states::SetGroupPower,
}
impl GroupControlMessage {
pub fn new(
group_number: u8,
target_value: states::SetGroupSettingValue,
control_method: states::SetGroupControlMethod,
power: states::SetGroupPower,
) -> Self {
Self {
group_number,
target_value,
control_method,
power,
}
}
pub fn set_off(group_number: u8) -> Self {
Self::new(
group_number,
states::SetGroupSettingValue::Maintain,
states::SetGroupControlMethod::Maintain,
states::SetGroupPower::SetOff,
)
}
pub fn build(&self) -> [u8; 14] {
assert!(self.group_number <= 15);
let mut value: u8 = 0;
let target_value = match self.target_value {
states::SetGroupSettingValue::Maintain => 0,
states::SetGroupSettingValue::Decrease => 0b010,
states::SetGroupSettingValue::Increase => 0b011,
states::SetGroupSettingValue::SetOpenPercentage(v) => {
assert!(v <= 100);
value = v;
0b100
}
states::SetGroupSettingValue::SetTargetSetpoint(v) => {
value = v;
0b101
}
};
let control_method = match self.control_method {
states::SetGroupControlMethod::Maintain => 0,
states::SetGroupControlMethod::Toggle => 0b01,
states::SetGroupControlMethod::Percentage => 0b10,
states::SetGroupControlMethod::Temperature => 0b11,
};
let power = match self.power {
states::SetGroupPower::Maintain => 0,
states::SetGroupPower::ChangeToNextState => 0b001,
states::SetGroupPower::SetOff => 0b010,
states::SetGroupPower::SetOn => 0b011,
states::SetGroupPower::SetTurbo => 0b101,
};
let byte2 = (target_value << 5) | (control_method << 3) | power;
let crc = crc16::State::<MODBUS>::calculate(&[
0x80,
0xb0,
0x01,
MessageType::GROUP_CONTROL_MESSAGE,
0x00,
0x04,
self.group_number,
byte2,
value,
0,
]);
return [
0x55,
0x55,
0x80,
0xb0,
0x01,
MessageType::GROUP_CONTROL_MESSAGE,
0x00,
0x04,
self.group_number,
byte2,
value,
0,
(crc >> 8) as u8,
(crc & 0xff) as u8,
];
}
}
#[cfg(test)]
mod test {
use super::GroupControlMessage;
use crate::states;
#[test]
fn test_create_group_control_packet() {
let packet = GroupControlMessage::new(
1,
states::SetGroupSettingValue::Maintain,
states::SetGroupControlMethod::Maintain,
states::SetGroupPower::SetOff,
)
.build();
assert_eq!(
packet,
[0x55, 0x55, 0x80, 0xb0, 0x1, 0x2a, 0x0, 0x4, 0x1, 0x2, 0x0, 0x0, 0xda, 0x59]
)
}
}