use crate::services::diagnostic::{ObjectId, ReadDeviceIdCode};
use heapless::Vec;
use mbus_core::{
data_unit::common::{MAX_PDU_DATA_LEN, Pdu},
errors::MbusError,
function_codes::public::{DiagnosticSubFunction, EncapsulatedInterfaceType, FunctionCode},
};
pub(super) struct ReqPduCompiler {}
impl ReqPduCompiler {
pub(super) fn read_exception_status_request() -> Result<Pdu, MbusError> {
Ok(Pdu::new(FunctionCode::ReadExceptionStatus, Vec::new(), 0))
}
pub(super) fn diagnostics_request(
sub_function: DiagnosticSubFunction,
data: &[u16],
) -> Result<Pdu, MbusError> {
if data.len() > 125 {
return Err(MbusError::InvalidPduLength);
}
let mut pdu_data: Vec<u8, MAX_PDU_DATA_LEN> = Vec::new();
pdu_data
.extend_from_slice(&sub_function.to_be_bytes())
.map_err(|_| MbusError::BufferLenMissmatch)?;
for word in data {
pdu_data
.extend_from_slice(&word.to_be_bytes())
.map_err(|_| MbusError::BufferLenMissmatch)?;
}
Ok(Pdu::new(
FunctionCode::Diagnostics,
pdu_data,
(2 + data.len() * 2) as u8,
))
}
pub(super) fn get_comm_event_counter_request() -> Result<Pdu, MbusError> {
Ok(Pdu::new(FunctionCode::GetCommEventCounter, Vec::new(), 0))
}
pub(super) fn get_comm_event_log_request() -> Result<Pdu, MbusError> {
Ok(Pdu::new(FunctionCode::GetCommEventLog, Vec::new(), 0))
}
pub(super) fn report_server_id_request() -> Result<Pdu, MbusError> {
Ok(Pdu::new(FunctionCode::ReportServerId, Vec::new(), 0))
}
pub(super) fn encapsulated_interface_transport_request(
mei_type: EncapsulatedInterfaceType,
data: &[u8],
) -> Result<Pdu, MbusError> {
let mut pdu_data = Vec::new();
pdu_data
.push(mei_type.into())
.map_err(|_| MbusError::BufferTooSmall)?;
pdu_data
.extend_from_slice(data)
.map_err(|_| MbusError::BufferTooSmall)?;
Ok(Pdu::new(
FunctionCode::EncapsulatedInterfaceTransport,
pdu_data,
(1 + data.len()) as u8,
))
}
pub(super) fn read_device_identification_request(
read_device_id_code: ReadDeviceIdCode,
object_id: ObjectId,
) -> Result<Pdu, MbusError> {
let mut data = Vec::new();
data.push(EncapsulatedInterfaceType::ReadDeviceIdentification as u8)
.map_err(|_| MbusError::BufferTooSmall)?;
data.push(read_device_id_code as u8)
.map_err(|_| MbusError::BufferTooSmall)?;
data.push(object_id.into())
.map_err(|_| MbusError::BufferTooSmall)?;
Ok(Pdu::new(
FunctionCode::EncapsulatedInterfaceTransport,
data,
3,
))
}
}