mbus_client/app/app_trait.rs
1//! Application Layer Traits
2//!
3//! This module defines the core traits used to bridge the Modbus protocol stack with
4//! user-defined application logic. It follows a callback-based (observer) pattern
5//! where the stack notifies the application of successful responses or failures.
6//!
7//! Each trait corresponds to a functional group of Modbus services (Coils, Registers, etc.).
8//!
9//! ## Callback Contract (applies to all traits in this file)
10//!
11//! - Callbacks are dispatched from `ClientServices::poll()`. No callback is invoked unless
12//! the application actively calls `poll()`.
13//! - A successful callback means the response was fully parsed and validated against the
14//! queued request context (transaction id, unit/slave address, and operation metadata).
15//! - For a single request, either:
16//! - one success callback is invoked from the corresponding response trait, or
17//! - one failure callback is invoked via [`RequestErrorNotifier::request_failed`].
18//! - After either callback path runs, the request is removed from the internal queue.
19//! - Callback implementations should remain lightweight and non-blocking. If heavy work is
20//! needed (database writes, UI updates, IPC), enqueue that work into your own task queue.
21//! - `txn_id` is always the original id supplied by the caller, including Serial modes where
22//! transaction ids are not transmitted on the wire.
23
24use mbus_core::{
25 errors::MbusError,
26 function_codes::public::{DiagnosticSubFunction, EncapsulatedInterfaceType},
27 transport::UnitIdOrSlaveAddr,
28};
29
30#[cfg(feature = "coils")]
31use crate::services::coil::Coils;
32#[cfg(feature = "diagnostics")]
33use crate::services::diagnostic::DeviceIdentificationResponse;
34#[cfg(feature = "discrete-inputs")]
35use crate::services::discrete_input::DiscreteInputs;
36#[cfg(feature = "fifo")]
37use crate::services::fifo_queue::FifoQueue;
38#[cfg(feature = "file-record")]
39use crate::services::file_record::SubRequestParams;
40#[cfg(feature = "registers")]
41use crate::services::register::Registers;
42
43/// Trait for receiving notifications about failed Modbus requests.
44///
45/// This is used to handle timeouts, connection issues, or Modbus exception responses
46/// at the application level, allowing the implementor to gracefully recover or alert the user.
47pub trait RequestErrorNotifier {
48 /// Called by the client stack whenever a previously queued request cannot be completed.
49 ///
50 /// The `error` parameter identifies the exact failure cause. The following variants are
51 /// delivered by the stack's internal `poll()` and `handle_timeouts()` logic:
52 ///
53 /// - **`MbusError::ModbusException(code)`** — The remote device replied with a Modbus
54 /// exception frame (`function code 0x80 + FC`). The server understood the request but
55 /// refused to execute it (e.g. illegal data address, illegal function). Delivered
56 /// immediately inside the `poll()` call that received the exception response, before
57 /// any retry logic runs.
58 ///
59 /// - **`MbusError::NoRetriesLeft`** — The response timeout expired and every configured
60 /// retry attempt was exhausted. `handle_timeouts()` waits `response_timeout_ms`
61 /// milliseconds after each send, schedules each retry according to the configured
62 /// `BackoffStrategy` and `JitterStrategy`, and fires this error only after the last
63 /// retry attempt has itself timed out without a response. The request is permanently
64 /// removed from the queue.
65 ///
66 /// - **`MbusError::SendFailed`** — A scheduled retry was due (its backoff timestamp was
67 /// reached inside `handle_timeouts()`), but the call to `transport.send()` returned an
68 /// error (e.g. the TCP connection or serial port was lost between the original send and
69 /// the retry). The request is dropped immediately; remaining retries in the budget are
70 /// not consumed.
71 ///
72 /// # Notes
73 /// - Each call corresponds to exactly one transaction. After this call the request is
74 /// permanently removed from the internal expected-response queue and will not be retried
75 /// again. No further callbacks will be issued for the same `txn_id`.
76 /// - The `txn_id` is always the value supplied when the request was originally enqueued,
77 /// even for Serial transports that do not transmit a transaction ID on the wire.
78 ///
79 /// # Parameters
80 /// - `txn_id`: Transaction ID of the original request.
81 /// - `unit_id_slave_addr`: The target Modbus unit ID (TCP) or slave address (Serial).
82 /// - `error`: The specific [`MbusError`] variant describing the failure (see above).
83 fn request_failed(
84 &mut self,
85 txn_id: u16,
86 unit_id_slave_addr: UnitIdOrSlaveAddr,
87 error: MbusError,
88 );
89}
90
91/// Trait defining the expected response handling for coil-related Modbus operations.
92///
93/// Implementors of this trait to deliver the responses to the application layer,
94/// allowing application developers to process the coil data and update their application state accordingly.
95///
96/// ## When Each Callback Is Fired
97/// - `read_coils_response`: after a successful FC 0x01 response for a multi-coil read.
98/// - `read_single_coil_response`: convenience callback when quantity was 1.
99/// - `write_single_coil_response`: after a successful FC 0x05 echo/ack response.
100/// - `write_multiple_coils_response`: after a successful FC 0x0F response containing
101/// start address and quantity written by the server.
102///
103/// ## Data Semantics
104/// - Address values are Modbus data-model addresses exactly as acknowledged by the server.
105/// - Boolean coil values follow Modbus conventions: `true` = ON (`0xFF00` in FC 0x05 request),
106/// `false` = OFF (`0x0000`).
107#[cfg(feature = "coils")]
108pub trait CoilResponse {
109 /// Handles a Read Coils response by invoking the appropriate application callback with the coil states.
110 ///
111 /// # Parameters
112 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
113 /// does not natively use transaction IDs, the stack preserves the ID provided in
114 /// the request and returns it here to allow for asynchronous tracking.
115 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
116 /// - `unit_id`: if transport is tcp
117 /// - `slave_addr`: if transport is serial
118 /// - `coils`: A wrapper containing the bit-packed boolean statuses of the requested coils.
119 fn read_coils_response(
120 &mut self,
121 txn_id: u16,
122 unit_id_slave_addr: UnitIdOrSlaveAddr,
123 coils: &Coils,
124 );
125
126 /// Handles a Read Single Coil response.
127 ///
128 /// # Parameters
129 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
130 /// does not natively use transaction IDs, the stack preserves the ID provided in
131 /// the request and returns it here to allow for asynchronous tracking.
132 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
133 /// - `unit_id`: if transport is tcp
134 /// - `slave_addr`: if transport is serial
135 /// - `address`: The exact address of the single coil that was read.
136 /// - `value`: The boolean state of the coil (`true` = ON, `false` = OFF).
137 fn read_single_coil_response(
138 &mut self,
139 txn_id: u16,
140 unit_id_slave_addr: UnitIdOrSlaveAddr,
141 address: u16,
142 value: bool,
143 );
144
145 /// Handles a Write Single Coil response, confirming the state change.
146 ///
147 /// # Parameters
148 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
149 /// does not natively use transaction IDs, the stack preserves the ID provided in
150 /// the request and returns it here to allow for asynchronous tracking.
151 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
152 /// - `unit_id`: if transport is tcp
153 /// - `slave_addr`: if transport is serial
154 /// - `address`: The address of the coil that was successfully written.
155 /// - `value`: The boolean state applied to the coil (`true` = ON, `false` = OFF).
156 fn write_single_coil_response(
157 &mut self,
158 txn_id: u16,
159 unit_id_slave_addr: UnitIdOrSlaveAddr,
160 address: u16,
161 value: bool,
162 );
163
164 /// Handles a Write Multiple Coils response, confirming the bulk state change.
165 ///
166 /// # Parameters
167 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
168 /// does not natively use transaction IDs, the stack preserves the ID provided in
169 /// the request and returns it here to allow for asynchronous tracking.
170 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
171 /// - `unit_id`: if transport is tcp
172 /// - `slave_addr`: if transport is serial
173 /// - `address`: The starting address where the bulk write began.
174 /// - `quantity`: The total number of consecutive coils updated.
175 fn write_multiple_coils_response(
176 &mut self,
177 txn_id: u16,
178 unit_id_slave_addr: UnitIdOrSlaveAddr,
179 address: u16,
180 quantity: u16,
181 );
182}
183
184/// Trait defining the expected response handling for FIFO Queue Modbus operations.
185///
186/// ## When Callback Is Fired
187/// - `read_fifo_queue_response` is invoked after a successful FC 0x18 response.
188///
189/// ## Data Semantics
190/// - `fifo_queue` contains values in server-returned order.
191/// - Quantity in the payload may vary between calls depending on device state.
192///
193/// ## Implementation Guidance
194/// non-blocking because it runs in the `poll()` execution path.
195#[cfg(feature = "fifo")]
196pub trait FifoQueueResponse {
197 /// Handles a Read FIFO Queue response.
198 ///
199 /// # Parameters
200 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
201 /// does not natively use transaction IDs, the stack preserves the ID provided in
202 /// the request and returns it here to allow for asynchronous tracking.
203 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
204 /// - `unit_id`: if transport is tcp
205 /// - `slave_addr`: if transport is serial
206 /// - `fifo_queue`: A `FifoQueue` struct containing the values pulled from the queue.
207 fn read_fifo_queue_response(
208 &mut self,
209 txn_id: u16,
210 unit_id_slave_addr: UnitIdOrSlaveAddr,
211 fifo_queue: &FifoQueue,
212 );
213}
214
215/// Trait defining the expected response handling for File Record Modbus operations.
216///
217/// ## When Each Callback Is Fired
218/// - `read_file_record_response`: after successful FC 0x14 response parsing.
219/// - `write_file_record_response`: after successful FC 0x15 acknowledgement.
220///
221/// ## Data Semantics
222/// - For read responses, each `SubRequestParams` entry reflects one returned record chunk.
223/// - Per Modbus spec, the response does not echo `file_number` or `record_number`; those
224/// fields are therefore reported as `0` in callback data and should not be used as identity.
225#[cfg(feature = "file-record")]
226pub trait FileRecordResponse {
227 /// Handles a Read File Record response.
228 ///
229 /// # Parameters
230 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
231 /// does not natively use transaction IDs, the stack preserves the ID provided in
232 /// the request and returns it here to allow for asynchronous tracking.
233 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
234 /// - `unit_id`: if transport is tcp
235 /// - `slave_addr`: if transport is serial
236 /// - `data`: A slice containing the sub-request responses. Note that `file_number` and `record_number`
237 ///
238 /// are not returned by the server in the response PDU and will be set to 0 in the parameters.
239 fn read_file_record_response(
240 &mut self,
241 txn_id: u16,
242 unit_id_slave_addr: UnitIdOrSlaveAddr,
243 data: &[SubRequestParams],
244 );
245
246 /// Handles a Write File Record response, confirming the write was successful.
247 ///
248 /// # Parameters
249 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
250 /// does not natively use transaction IDs, the stack preserves the ID provided in
251 /// the request and returns it here to allow for asynchronous tracking.
252 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
253 /// - `unit_id`: if transport is tcp
254 /// - `slave_addr`: if transport is serial
255 fn write_file_record_response(&mut self, txn_id: u16, unit_id_slave_addr: UnitIdOrSlaveAddr);
256}
257
258/// Defines callbacks for handling responses to Modbus register-related requests.
259///
260/// Implementors of this trait can process the data received from a Modbus server
261/// and update their application state accordingly. Each method corresponds to a
262/// specific Modbus register operation response.
263///
264/// ## Callback Mapping
265/// - FC 0x03: `read_multiple_holding_registers_response`, `read_single_holding_register_response`
266/// - FC 0x04: `read_multiple_input_registers_response`, `read_single_input_register_response`
267/// - FC 0x06: `write_single_register_response`
268/// - FC 0x10: `write_multiple_registers_response`
269/// - FC 0x16: `mask_write_register_response`
270/// - FC 0x17: `read_write_multiple_registers_response`
271///
272/// ## Data Semantics
273/// - Register values are 16-bit words (`u16`) already decoded from Modbus big-endian byte pairs.
274/// - Address and quantity values are echoed/validated values corresponding to the original request.
275#[cfg(feature = "registers")]
276pub trait RegisterResponse {
277 /// Handles a response for a `Read Input Registers` (FC 0x04) request.
278 ///
279 /// # Parameters
280 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
281 /// does not natively use transaction IDs, the stack preserves the ID provided in
282 /// the request and returns it here to allow for asynchronous tracking.
283 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
284 /// - `unit_id`: if transport is tcp
285 /// - `slave_addr`: if transport is serial
286 /// - `registers`: A `Registers` struct containing the values of the read input registers.
287 fn read_multiple_input_registers_response(
288 &mut self,
289 txn_id: u16,
290 unit_id_slave_addr: UnitIdOrSlaveAddr,
291 registers: &Registers,
292 );
293
294 /// Handles a response for a `Read Single Input Register` (FC 0x04) request.
295 ///
296 /// # Parameters
297 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
298 /// does not natively use transaction IDs, the stack preserves the ID provided in
299 /// the request and returns it here to allow for asynchronous tracking.
300 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
301 /// - `unit_id`: if transport is tcp
302 /// - `slave_addr`: if transport is serial
303 /// - `address`: The address of the register that was read.
304 /// - `value`: The value of the read register.
305 fn read_single_input_register_response(
306 &mut self,
307 txn_id: u16,
308 unit_id_slave_addr: UnitIdOrSlaveAddr,
309 address: u16,
310 value: u16,
311 );
312
313 /// Handles a response for a `Read Holding Registers` (FC 0x03) request.
314 ///
315 /// # Parameters
316 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
317 /// does not natively use transaction IDs, the stack preserves the ID provided in
318 /// the request and returns it here to allow for asynchronous tracking.
319 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
320 /// - `unit_id`: if transport is tcp
321 /// - `slave_addr`: if transport is serial
322 /// - `registers`: A `Registers` struct containing the values of the read holding registers.
323 fn read_multiple_holding_registers_response(
324 &mut self,
325 txn_id: u16,
326 unit_id_slave_addr: UnitIdOrSlaveAddr,
327 registers: &Registers,
328 );
329
330 /// Handles a response for a `Write Single Register` (FC 0x06) request, confirming a successful write.
331 ///
332 /// # Parameters
333 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
334 /// does not natively use transaction IDs, the stack preserves the ID provided in
335 /// the request and returns it here to allow for asynchronous tracking.
336 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
337 /// - `unit_id`: if transport is tcp
338 /// - `slave_addr`: if transport is serial
339 /// - `address`: The address of the register that was written.
340 /// - `value`: The value that was written to the register.
341 fn write_single_register_response(
342 &mut self,
343 txn_id: u16,
344 unit_id_slave_addr: UnitIdOrSlaveAddr,
345 address: u16,
346 value: u16,
347 );
348
349 /// Handles a response for a `Write Multiple Registers` (FC 0x10) request, confirming a successful write.
350 ///
351 /// # Parameters
352 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
353 /// does not natively use transaction IDs, the stack preserves the ID provided in
354 /// the request and returns it here to allow for asynchronous tracking.
355 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
356 /// - `unit_id`: if transport is tcp
357 /// - `slave_addr`: if transport is serial
358 /// - `starting_address`: The starting address of the registers that were written.
359 /// - `quantity`: The number of registers that were written.
360 fn write_multiple_registers_response(
361 &mut self,
362 txn_id: u16,
363 unit_id_slave_addr: UnitIdOrSlaveAddr,
364 starting_address: u16,
365 quantity: u16,
366 );
367
368 /// Handles a response for a `Read/Write Multiple Registers` (FC 0x17) request.
369 ///
370 /// # Parameters
371 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
372 /// does not natively use transaction IDs, the stack preserves the ID provided in
373 /// the request and returns it here to allow for asynchronous tracking.
374 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
375 /// - `unit_id`: if transport is tcp
376 /// - `slave_addr`: if transport is serial
377 /// - `registers`: A `Registers` struct containing the values of the registers that were read.
378 fn read_write_multiple_registers_response(
379 &mut self,
380 txn_id: u16,
381 unit_id_slave_addr: UnitIdOrSlaveAddr,
382 registers: &Registers,
383 );
384
385 /// Handles a response for a single register read request.
386 ///
387 /// This is a convenience callback for when only one register is requested.
388 ///
389 /// # Parameters
390 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
391 /// does not natively use transaction IDs, the stack preserves the ID provided in
392 /// the request and returns it here to allow for asynchronous tracking.
393 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
394 /// - `unit_id`: if transport is tcp
395 /// - `slave_addr`: if transport is serial
396 /// - `address`: The address of the register that was read.
397 /// - `value`: The value of the read register.
398 fn read_single_register_response(
399 &mut self,
400 txn_id: u16,
401 unit_id_slave_addr: UnitIdOrSlaveAddr,
402 address: u16,
403 value: u16,
404 );
405
406 /// Handles a response for a single holding register write request.
407 ///
408 /// # Parameters
409 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
410 /// does not natively use transaction IDs, the stack preserves the ID provided in
411 /// the request and returns it here to allow for asynchronous tracking.
412 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
413 /// - `unit_id`: if transport is tcp
414 /// - `slave_addr`: if transport is serial
415 /// - `address`: The address of the register that was written.
416 /// - `value`: The value that was written to the register.
417 fn read_single_holding_register_response(
418 &mut self,
419 txn_id: u16,
420 unit_id_slave_addr: UnitIdOrSlaveAddr,
421 address: u16,
422 value: u16,
423 );
424
425 /// Handles a response for a `Mask Write Register` (FC 0x16) request, confirming a successful operation.
426 ///
427 /// # Parameters
428 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
429 /// does not natively use transaction IDs, the stack preserves the ID provided in
430 /// the request and returns it here to allow for asynchronous tracking.
431 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
432 /// - `unit_id`: if transport is tcp
433 /// - `slave_addr`: if transport is serial
434 fn mask_write_register_response(&mut self, txn_id: u16, unit_id_slave_addr: UnitIdOrSlaveAddr);
435}
436
437/// Defines callbacks for handling responses to Modbus discrete input-related requests.
438///
439/// Implementors of this trait can process the data received from a Modbus server
440/// and update their application state accordingly.
441///
442/// ## When Each Callback Is Fired
443/// - `read_multiple_discrete_inputs_response`: after successful FC 0x02 with quantity > 1.
444/// - `read_single_discrete_input_response`: convenience callback when quantity was 1.
445///
446/// ## Data Semantics
447/// - `DiscreteInputs` stores bit-packed values; use helper methods on the type instead of
448/// manually decoding bit offsets in application code.
449#[cfg(feature = "discrete-inputs")]
450pub trait DiscreteInputResponse {
451 /// Handles a response for a `Read Discrete Inputs` (FC 0x02) request.
452 ///
453 /// # Parameters
454 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
455 /// does not natively use transaction IDs, the stack preserves the ID provided in
456 /// the request and returns it here to allow for asynchronous tracking.
457 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
458 /// - `unit_id`: if transport is tcp
459 /// - `slave_addr`: if transport is serial
460 /// - `discrete_inputs`: A `DiscreteInputs` struct containing the states of the read inputs.
461 fn read_multiple_discrete_inputs_response(
462 &mut self,
463 txn_id: u16,
464 unit_id_slave_addr: UnitIdOrSlaveAddr,
465 discrete_inputs: &DiscreteInputs,
466 );
467
468 /// Handles a response for a single discrete input read request.
469 ///
470 /// # Parameters
471 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
472 /// does not natively use transaction IDs, the stack preserves the ID provided in
473 /// the request and returns it here to allow for asynchronous tracking.
474 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
475 /// - `unit_id`: if transport is tcp
476 /// - `slave_addr`: if transport is serial
477 /// - `address`: The address of the input that was read.
478 /// - `value`: The boolean state of the read input.
479 fn read_single_discrete_input_response(
480 &mut self,
481 txn_id: u16,
482 unit_id_slave_addr: UnitIdOrSlaveAddr,
483 address: u16,
484 value: bool,
485 );
486}
487
488/// Trait for handling Diagnostics-family responses.
489///
490/// ## Callback Mapping
491/// - FC 0x2B / MEI 0x0E: `read_device_identification_response`
492/// - FC 0x2B / other MEI: `encapsulated_interface_transport_response`
493/// - FC 0x07: `read_exception_status_response`
494/// - FC 0x08: `diagnostics_response`
495/// - FC 0x0B: `get_comm_event_counter_response`
496/// - FC 0x0C: `get_comm_event_log_response`
497/// - FC 0x11: `report_server_id_response`
498///
499/// ## Data Semantics
500/// - `mei_type`, `sub_function`, counters, and event buffers are already validated and decoded.
501/// - Large payloads (event logs, generic encapsulated transport data) should typically be copied
502/// or forwarded quickly, then processed outside the callback hot path.
503#[cfg(feature = "diagnostics")]
504pub trait DiagnosticsResponse {
505 /// Called when a Read Device Identification response is received.
506 ///
507 /// Implementors can use this callback to process the device identity info (Vendor, Product Code, etc.).
508 ///
509 /// # Parameters
510 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
511 /// does not natively use transaction IDs, the stack preserves the ID provided in
512 /// the request and returns it here to allow for asynchronous tracking.
513 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
514 /// - `unit_id`: if transport is tcp
515 /// - `slave_addr`: if transport is serial
516 /// - `response`: Extracted device identification strings.
517 fn read_device_identification_response(
518 &mut self,
519 txn_id: u16,
520 unit_id_slave_addr: UnitIdOrSlaveAddr,
521 response: &DeviceIdentificationResponse,
522 );
523
524 /// Called when a generic Encapsulated Interface Transport response (FC 43) is received.
525 ///
526 /// # Parameters
527 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
528 /// does not natively use transaction IDs, the stack preserves the ID provided in
529 /// the request and returns it here to allow for asynchronous tracking.
530 /// - `unit_id_slave_addr`: The unit ID of the device that responded.
531 /// - `unit_id`: if transport is tcp
532 /// - `slave_addr`: if transport is serial
533 /// - `mei_type`: The MEI type returned in the response.
534 /// - `data`: The data payload returned in the response.
535 fn encapsulated_interface_transport_response(
536 &mut self,
537 txn_id: u16,
538 unit_id_slave_addr: UnitIdOrSlaveAddr,
539 mei_type: EncapsulatedInterfaceType,
540 data: &[u8],
541 );
542
543 /// Called when a Read Exception Status response (FC 07) is received.
544 ///
545 /// # Parameters
546 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
547 /// does not natively use transaction IDs, the stack preserves the ID provided in
548 /// the request and returns it here to allow for asynchronous tracking.
549 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
550 /// - `unit_id`: if transport is tcp
551 /// - `slave_addr`: if transport is serial
552 /// - `status`: The 8-bit exception status code returned by the server.
553 fn read_exception_status_response(
554 &mut self,
555 txn_id: u16,
556 unit_id_slave_addr: UnitIdOrSlaveAddr,
557 status: u8,
558 );
559
560 /// Called when a Diagnostics response (FC 08) is received.
561 ///
562 /// # Parameters
563 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
564 /// does not natively use transaction IDs, the stack preserves the ID provided in
565 /// the request and returns it here to allow for asynchronous tracking.
566 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
567 /// - `unit_id`: if transport is tcp
568 /// - `slave_addr`: if transport is serial
569 /// - `sub_function`: The sub-function code confirming the diagnostic test.
570 /// - `data`: Data payload returned by the diagnostic test (e.g., echoed loopback data).
571 fn diagnostics_response(
572 &mut self,
573 txn_id: u16,
574 unit_id_slave_addr: UnitIdOrSlaveAddr,
575 sub_function: DiagnosticSubFunction,
576 data: &[u16],
577 );
578
579 /// Called when a Get Comm Event Counter response (FC 11) is received.
580 ///
581 /// # Parameters
582 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
583 /// does not natively use transaction IDs, the stack preserves the ID provided in
584 /// the request and returns it here to allow for asynchronous tracking.
585 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
586 /// - `unit_id`: if transport is tcp
587 /// - `slave_addr`: if transport is serial
588 /// - `status`: The status word indicating if the device is busy.
589 /// - `event_count`: The number of successful messages processed by the device.
590 fn get_comm_event_counter_response(
591 &mut self,
592 txn_id: u16,
593 unit_id_slave_addr: UnitIdOrSlaveAddr,
594 status: u16,
595 event_count: u16,
596 );
597
598 /// Called when a Get Comm Event Log response (FC 12) is received.
599 ///
600 /// # Parameters
601 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
602 /// does not natively use transaction IDs, the stack preserves the ID provided in
603 /// the request and returns it here to allow for asynchronous tracking.
604 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
605 /// - `unit_id`: if transport is tcp
606 /// - `slave_addr`: if transport is serial
607 /// - `status`: The status word indicating device state.
608 /// - `event_count`: Number of successful messages processed.
609 /// - `message_count`: Quantity of messages processed since the last restart.
610 /// - `events`: Raw byte array containing the device's internal event log.
611 fn get_comm_event_log_response(
612 &mut self,
613 txn_id: u16,
614 unit_id_slave_addr: UnitIdOrSlaveAddr,
615 status: u16,
616 event_count: u16,
617 message_count: u16,
618 events: &[u8],
619 );
620
621 /// Called when a Report Server ID response (FC 17) is received.
622 ///
623 /// # Parameters
624 /// - `txn_id`: Transaction ID of the original request. While Modbus Serial (RTU/ASCII)
625 /// does not natively use transaction IDs, the stack preserves the ID provided in
626 /// the request and returns it here to allow for asynchronous tracking.
627 /// - `unit_id_slave_addr`: The target Modbus unit ID or slave address.
628 /// - `unit_id`: if transport is tcp
629 /// - `slave_addr`: if transport is serial
630 /// - `data`: Raw identity/status data provided by the manufacturer.
631 fn report_server_id_response(
632 &mut self,
633 txn_id: u16,
634 unit_id_slave_addr: UnitIdOrSlaveAddr,
635 data: &[u8],
636 );
637}