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 fp = pdu.fifo_payload()?;
39 let fifo_byte_count = fp.fifo_byte_count as usize;
40 let fifo_count = fp.fifo_count as usize;
41
42 if fp.values.len() + 2 != fifo_byte_count {
44 return Err(MbusError::InvalidAduLength);
45 }
46
47 if fifo_byte_count != 2 + fifo_count * 2 {
49 return Err(MbusError::ParseError);
50 }
51
52 if fifo_count > MAX_FIFO_QUEUE_COUNT_PER_PDU {
53 return Err(MbusError::BufferLenMissmatch);
54 }
55
56 let mut values = [0u16; MAX_FIFO_QUEUE_COUNT_PER_PDU];
57 let mut index = 0;
58 for chunk in fp.values.chunks_exact(2) {
59 if index >= MAX_FIFO_QUEUE_COUNT_PER_PDU {
60 return Err(MbusError::BufferLenMissmatch);
61 }
62 values[index] = u16::from_be_bytes([chunk[0], chunk[1]]);
63 index += 1;
64 }
65
66 if index != fifo_count {
67 return Err(MbusError::ParseError);
68 }
69
70 Ok((values, fifo_count))
71 }
72}
73
74impl<TRANSPORT, APP, const N: usize> ClientServices<TRANSPORT, APP, N>
75where
76 TRANSPORT: Transport,
77 APP: ClientCommon + FifoQueueResponse,
78{
79 pub(super) fn handle_read_fifo_queue_response(
84 &mut self,
85 ctx: &ExpectedResponse<TRANSPORT, APP, N>,
86 message: &ModbusMessage,
87 ) {
88 let pdu = message.pdu();
89 let function_code = pdu.function_code();
90 let transaction_id = ctx.txn_id;
91 let unit_id_or_slave_addr = message.unit_id_or_slave_addr();
92
93 let register_rsp = match fifo_queue::service::ServiceDecompiler::handle_read_fifo_queue_rsp(
94 function_code,
95 pdu,
96 ) {
97 Ok(register_response) => register_response,
98 Err(e) => {
99 self.app
100 .request_failed(transaction_id, unit_id_or_slave_addr, e);
101 return;
102 }
103 };
104
105 self.app
106 .read_fifo_queue_response(transaction_id, unit_id_or_slave_addr, ®ister_rsp);
107 }
108}