mbus_client/services/fifo_queue/
response.rs1use crate::app::FifoQueueResponse;
17use crate::services::fifo_queue::MAX_FIFO_QUEUE_COUNT_PER_PDU;
18use crate::services::{ClientCommon, ClientServices, ExpectedResponse, fifo_queue};
19use mbus_core::{
20 data_unit::common::{ModbusMessage, Pdu},
21 errors::MbusError,
22 function_codes::public::FunctionCode,
23 transport::Transport,
24};
25
26pub(super) struct ResponseParser;
27
28impl ResponseParser {
29 pub(super) fn parse_read_fifo_queue_response(
31 pdu: &Pdu,
32 ) -> Result<([u16; MAX_FIFO_QUEUE_COUNT_PER_PDU], usize), MbusError> {
33 if pdu.function_code() != FunctionCode::ReadFifoQueue {
34 return Err(MbusError::InvalidFunctionCode);
35 }
36
37 let data = pdu.data().as_slice();
38 if data.len() < 4 {
40 return Err(MbusError::InvalidPduLength);
41 }
42
43 let fifo_byte_count = u16::from_be_bytes([data[0], data[1]]) as usize;
44 if data.len() != 2 + fifo_byte_count {
46 return Err(MbusError::InvalidAduLength);
47 }
48
49 let fifo_count = u16::from_be_bytes([data[2], data[3]]) as usize;
50
51 if fifo_byte_count != 2 + fifo_count * 2 {
53 return Err(MbusError::ParseError);
54 }
55
56 if fifo_count > MAX_FIFO_QUEUE_COUNT_PER_PDU {
57 return Err(MbusError::BufferLenMissmatch);
58 }
59
60 let mut values = [0u16; MAX_FIFO_QUEUE_COUNT_PER_PDU];
61 let mut index = 0;
62 for chunk in data[4..].chunks_exact(2) {
63 if index >= MAX_FIFO_QUEUE_COUNT_PER_PDU {
64 return Err(MbusError::BufferLenMissmatch);
65 }
66 values[index] = u16::from_be_bytes([chunk[0], chunk[1]]);
67 index += 1;
68 }
69
70 if index != fifo_count {
71 return Err(MbusError::ParseError);
72 }
73
74 Ok((values, fifo_count))
75 }
76}
77
78impl<TRANSPORT, APP, const N: usize> ClientServices<TRANSPORT, APP, N>
79where
80 TRANSPORT: Transport,
81 APP: ClientCommon + FifoQueueResponse,
82{
83 pub(super) fn handle_read_fifo_queue_response(
88 &mut self,
89 ctx: &ExpectedResponse<TRANSPORT, APP, N>,
90 message: &ModbusMessage,
91 ) {
92 let pdu = message.pdu();
93 let function_code = pdu.function_code();
94 let transaction_id = ctx.txn_id;
95 let unit_id_or_slave_addr = message.unit_id_or_slave_addr();
96
97 let register_rsp = match fifo_queue::service::ServiceDecompiler::handle_read_fifo_queue_rsp(
98 function_code,
99 pdu,
100 ) {
101 Ok(register_response) => register_response,
102 Err(e) => {
103 self.app
104 .request_failed(transaction_id, unit_id_or_slave_addr, e);
105 return;
106 }
107 };
108
109 self.app
110 .read_fifo_queue_response(transaction_id, unit_id_or_slave_addr, ®ister_rsp);
111 }
112}