use heapless::Vec;
use crate::services::coil::{Coils, request::ReqPduCompiler, response::ResponseParser};
use mbus_core::{
data_unit::common::{self, MAX_ADU_FRAME_LEN, Pdu},
errors::MbusError,
function_codes::public::FunctionCode,
transport::TransportType,
};
#[derive(Debug, Clone)]
pub struct ServiceBuilder;
impl ServiceBuilder {
pub fn read_coils(
txn_id: u16,
unit_id: u8,
address: u16,
quantity: u16,
transport_type: TransportType,
) -> Result<Vec<u8, MAX_ADU_FRAME_LEN>, MbusError> {
let pdu = ReqPduCompiler::read_coils_request(address, quantity)?;
common::compile_adu_frame(txn_id, unit_id, pdu, transport_type)
}
pub fn write_single_coil(
txn_id: u16,
unit_id: u8,
address: u16,
value: bool,
transport_type: TransportType,
) -> Result<Vec<u8, MAX_ADU_FRAME_LEN>, MbusError> {
let pdu = ReqPduCompiler::write_single_coil_request(address, value)?;
common::compile_adu_frame(txn_id, unit_id, pdu, transport_type)
}
pub fn write_multiple_coils(
txn_id: u16,
unit_id: u8,
address: u16,
quantity: u16,
values: &Coils,
transport_type: TransportType,
) -> Result<Vec<u8, MAX_ADU_FRAME_LEN>, MbusError> {
let pdu = ReqPduCompiler::write_multiple_coils_request(address, quantity, values)?;
common::compile_adu_frame(txn_id, unit_id, pdu, transport_type)
}
pub fn handle_read_coil_rsp(
pdu: &Pdu,
expected_quantity: u16,
from_address: u16,
) -> Result<Coils, MbusError> {
if pdu.function_code() != FunctionCode::ReadCoils {
return Err(MbusError::InvalidFunctionCode); }
let coil_response =
ResponseParser::handle_coil_response(pdu, expected_quantity, from_address)?;
Ok(coil_response)
}
pub fn handle_write_single_coil_rsp(
function_code: FunctionCode,
pdu: &Pdu,
address: u16,
value: bool,
) -> Result<(), MbusError> {
if function_code != FunctionCode::WriteSingleCoil {
return Err(MbusError::InvalidFunctionCode);
}
if ResponseParser::parse_write_single_coil_response(pdu, address, value).is_ok() {
Ok(())
} else {
Err(MbusError::ParseError)
}
}
pub fn handle_write_multiple_coils_rsp(
function_code: FunctionCode,
pdu: &Pdu,
address: u16,
quantity: u16,
) -> Result<(), MbusError> {
if function_code != FunctionCode::WriteMultipleCoils {
return Err(MbusError::InvalidFunctionCode);
}
if ResponseParser::parse_write_multiple_coils_response(pdu, address, quantity).is_ok() {
Ok(())
} else {
Err(MbusError::ParseError)
}
}
}