mbus_client/services/fifo_queue/apis.rs
1use crate::app::FifoQueueResponse;
2use crate::services::{ClientCommon, ClientServices, OperationMeta, fifo_queue};
3use mbus_core::{
4 errors::MbusError,
5 transport::{Transport, UnitIdOrSlaveAddr},
6};
7
8impl<TRANSPORT, APP, const N: usize> ClientServices<TRANSPORT, APP, N>
9where
10 TRANSPORT: Transport,
11 APP: ClientCommon + FifoQueueResponse,
12{
13 /// Sends a Read FIFO Queue request (Function Code 0x18).
14 ///
15 /// This function allows reading the contents of a remote FIFO queue of registers.
16 /// The FIFO structure is address-specific, and the response contains the current
17 /// count of registers in the queue followed by the register data itself.
18 ///
19 /// # Parameters
20 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
21 /// does not natively use transaction IDs, the stack preserves the ID provided in
22 /// the request and returns it here to allow for asynchronous tracking.
23 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
24 /// - `unit_id`: if transport is tcp
25 /// - `slave_addr`: if transport is serial
26 /// - `address`: The starting address of the FIFO queue.
27 ///
28 /// # Returns
29 /// - `Ok(())`: If the request was successfully built, the expectation was queued,
30 /// and the frame was transmitted via the transport layer.
31 /// - `Err(MbusError)`: If the address is a broadcast address, if the frame
32 /// construction fails, or if the transport layer fails to send.
33 #[must_use = "request submission errors should be handled; the request may not have been queued/sent"]
34 pub fn read_fifo_queue(
35 &mut self,
36 txn_id: u16,
37 unit_id_slave_addr: UnitIdOrSlaveAddr,
38 address: u16,
39 ) -> Result<(), MbusError> {
40 // Modbus protocol specification: Broadcast is not supported for Read operations.
41 if unit_id_slave_addr.is_broadcast() {
42 return Err(MbusError::BroadcastNotAllowed); // Modbus forbids broadcast Read operations
43 }
44
45 let frame = fifo_queue::service::ServiceBuilder::read_fifo_queue(
46 txn_id,
47 unit_id_slave_addr.get(),
48 address,
49 self.transport.transport_type(),
50 )?;
51
52 // Register an expectation in the client state machine.
53 // This ensures that when a response arrives, it is routed to the correct handler.
54 self.add_an_expectation(
55 txn_id,
56 unit_id_slave_addr,
57 &frame,
58 OperationMeta::Other,
59 Self::handle_read_fifo_queue_response,
60 )?;
61
62 // Dispatch the compiled ADU frame through the underlying transport (TCP/RTU/ASCII).
63 self.transport
64 .send(&frame)
65 .map_err(|_e| MbusError::SendFailed)?;
66 Ok(())
67 }
68}