use mbus_core::{data_unit::common::Pdu, errors::MbusError, function_codes::public::FunctionCode};
pub(super) struct ReqPduCompiler {}
impl ReqPduCompiler {
pub(super) fn read_holding_registers_request(
address: u16,
quantity: u16,
) -> Result<Pdu, MbusError> {
if !(1..=125).contains(&quantity) {
return Err(MbusError::InvalidPduLength);
}
Pdu::build_read_window(FunctionCode::ReadHoldingRegisters, address, quantity)
}
pub(super) fn read_input_registers_request(
address: u16,
quantity: u16,
) -> Result<Pdu, MbusError> {
if !(1..=125).contains(&quantity) {
return Err(MbusError::InvalidPduLength);
}
Pdu::build_read_window(FunctionCode::ReadInputRegisters, address, quantity)
}
pub(super) fn write_single_register_request(
address: u16,
value: u16,
) -> Result<Pdu, MbusError> {
Pdu::build_write_single_u16(FunctionCode::WriteSingleRegister, address, value)
}
pub(super) fn write_multiple_registers_request(
address: u16,
quantity: u16,
values: &[u16],
) -> Result<Pdu, MbusError> {
if !(1..=123).contains(&quantity) {
return Err(MbusError::InvalidPduLength);
}
if values.len() as u16 != quantity {
return Err(MbusError::InvalidPduLength);
}
let mut packed: heapless::Vec<u8, { mbus_core::data_unit::common::MAX_PDU_DATA_LEN }> =
heapless::Vec::new();
for &v in values {
packed
.extend_from_slice(&v.to_be_bytes())
.map_err(|_| MbusError::BufferLenMissmatch)?;
}
Pdu::build_write_multiple(
FunctionCode::WriteMultipleRegisters,
address,
quantity,
&packed,
)
}
pub(super) fn read_write_multiple_registers_request(
read_address: u16,
read_quantity: u16,
write_address: u16,
write_values: &[u16],
) -> Result<Pdu, MbusError> {
if !(1..=125).contains(&read_quantity) {
return Err(MbusError::InvalidPduLength);
}
let write_quantity = write_values.len() as u16;
if !(1..=121).contains(&write_quantity) {
return Err(MbusError::InvalidPduLength);
}
let mut packed: heapless::Vec<u8, { mbus_core::data_unit::common::MAX_PDU_DATA_LEN }> =
heapless::Vec::new();
for &v in write_values {
packed
.extend_from_slice(&v.to_be_bytes())
.map_err(|_| MbusError::BufferLenMissmatch)?;
}
Pdu::build_read_write_multiple(
read_address,
read_quantity,
write_address,
write_quantity,
&packed,
)
}
pub(super) fn mask_write_register_request(
address: u16,
and_mask: u16,
or_mask: u16,
) -> Result<Pdu, MbusError> {
Pdu::build_mask_write_register(address, and_mask, or_mask)
}
}