use crate::ast::*;
use crate::builders::WireContext;
use alloc::vec::Vec;
pub fn build_modbus_payload(
_ctx: &WireContext,
spec: &ModbusSpec,
payload_bytes: &[u8],
) -> Vec<u8> {
let txid = spec.txid.unwrap_or(1);
let proto_id = spec.proto_id.unwrap_or(0);
let unit_id = spec.unitid.unwrap_or(1);
let func_code: u8 = match spec.func.unwrap_or("READ_HOLDING_REGISTERS").to_ascii_uppercase().as_str() {
"READ_COILS" => 1,
"READ_DISCRETE_INPUTS" => 2,
"READ_HOLDING_REGISTERS" => 3,
"READ_INPUT_REGISTERS" => 4,
"WRITE_SINGLE_COIL" => 5,
"WRITE_SINGLE_REGISTER" => 6,
"WRITE_MULTIPLE_REGISTERS" => 16,
_ => 3,
};
let mut pdu = Vec::new();
pdu.push(func_code);
if spec.is_response {
let count = spec.count.unwrap_or(1);
let byte_count = (count * 2) as u8;
pdu.push(byte_count);
for _ in 0..count {
pdu.extend_from_slice(&spec.value.unwrap_or(0).to_be_bytes());
}
} else if func_code == 1 || func_code == 2 || func_code == 3 || func_code == 4 {
pdu.extend_from_slice(&spec.addr.unwrap_or(0).to_be_bytes());
pdu.extend_from_slice(&spec.count.unwrap_or(1).to_be_bytes());
} else if func_code == 5 || func_code == 6 {
pdu.extend_from_slice(&spec.addr.unwrap_or(0).to_be_bytes());
pdu.extend_from_slice(&spec.value.unwrap_or(0).to_be_bytes());
} else {
pdu.extend_from_slice(&spec.addr.unwrap_or(0).to_be_bytes());
pdu.extend_from_slice(&spec.count.unwrap_or(1).to_be_bytes());
}
if !payload_bytes.is_empty() {
pdu.extend_from_slice(payload_bytes);
}
let length = (1 + pdu.len()) as u16; let mut pkt = Vec::with_capacity(7 + pdu.len());
pkt.extend_from_slice(&txid.to_be_bytes());
pkt.extend_from_slice(&proto_id.to_be_bytes());
pkt.extend_from_slice(&length.to_be_bytes());
pkt.push(unit_id);
pkt.extend_from_slice(&pdu);
pkt
}