Skip to main content

Pdu

Struct Pdu 

Source
pub struct Pdu { /* private fields */ }
Expand description

Modbus Protocol Data Unit (PDU).

The PDU is the core of the Modbus message, consisting of a function code and the associated data payload.

Implementations§

Source§

impl Pdu

Source

pub fn new( function_code: FunctionCode, data: Vec<u8, MAX_PDU_DATA_LEN>, data_len: u8, ) -> Self

Creates a new Pdu instance.

§Arguments
  • function_code - The Modbus function code.
  • data - The data payload (either raw bytes or structured sub-codes).
  • data_len - The actual length of the data payload in bytes.
§Returns

A new Pdu instance.

Source

pub fn function_code(&self) -> FunctionCode

Accessor for the function code.

Source

pub fn data(&self) -> &Vec<u8, MAX_PDU_DATA_LEN>

Accessor for the data payload.

Source

pub fn data_len(&self) -> u8

Accessor for the actual length of the data payload.

Source

pub fn error_code(&self) -> Option<u8>

Accessor for the error code from the PDU.

Source

pub fn build_read_window( fc: FunctionCode, address: u16, quantity: u16, ) -> Result<Self, MbusError>

Builds a PDU with [address_hi, address_lo, quantity_hi, quantity_lo] layout (4 bytes).

Used by FC01/02/03/04 requests and as a general address+quantity builder.

Source

pub fn build_write_single_u16( fc: FunctionCode, address: u16, value: u16, ) -> Result<Self, MbusError>

Builds a PDU with [address_hi, address_lo, value_hi, value_lo] layout (4 bytes).

Used by FC05 and FC06 single-write requests.

Source

pub fn build_write_multiple( fc: FunctionCode, address: u16, quantity: u16, values: &[u8], ) -> Result<Self, MbusError>

Builds a PDU with [address, quantity, byte_count, values...] layout.

values must already be the packed byte representation (coil bits or register word bytes). byte_count is derived from values.len().

Used by FC0F (Write Multiple Coils) and FC10 (Write Multiple Registers) requests.

Source

pub fn build_mask_write_register( address: u16, and_mask: u16, or_mask: u16, ) -> Result<Self, MbusError>

Builds a PDU with [address, and_mask, or_mask] layout (6 bytes).

Used by FC16 (Mask Write Register) requests.

Source

pub fn build_read_write_multiple( read_address: u16, read_quantity: u16, write_address: u16, write_quantity: u16, write_values: &[u8], ) -> Result<Self, MbusError>

Builds a PDU for FC17 (Read/Write Multiple Registers) requests.

write_values must already be the packed byte representation of the register words. write_byte_count is derived from write_values.len().

Source

pub fn build_sub_function( fc: FunctionCode, sub_function: u16, words: &[u16], ) -> Result<Self, MbusError>

Builds a PDU with [sub_function_hi, sub_function_lo, word0_hi, word0_lo, ...] layout.

Used by FC08 (Diagnostics) requests.

Source

pub fn build_mei_type( fc: FunctionCode, mei_type: u8, payload: &[u8], ) -> Result<Self, MbusError>

Builds a PDU with [mei_type, payload...] layout.

Used by FC2B (Encapsulated Interface Transport) requests.

Source

pub fn build_u16_payload( fc: FunctionCode, value: u16, ) -> Result<Self, MbusError>

Builds a PDU containing a single u16 value [value_hi, value_lo] (2 bytes).

Used by FC18 (Read FIFO Queue) request (pointer address).

Source

pub fn build_byte_payload(fc: FunctionCode, byte: u8) -> Result<Self, MbusError>

Builds a PDU containing a single byte payload [byte] (1 byte).

Used for exception response PDUs.

Source

pub fn build_empty(fc: FunctionCode) -> Self

Builds a PDU with an empty data payload (0 bytes).

Used by no-argument requests such as FC07, FC0B, FC0C, and FC11.

Source

pub fn build_byte_count_payload( fc: FunctionCode, payload: &[u8], ) -> Result<Self, MbusError>

Builds a PDU with [byte_count, payload...] layout.

byte_count is derived from payload.len(). Returns InvalidByteCount if the payload is longer than 255 bytes.

Used by FC01–FC04 read responses, FC11, FC14, FC15, and FC17 responses.

Source

pub fn build_diagnostics( sub_function: u16, result: u16, ) -> Result<Self, MbusError>

Builds a PDU for FC08 (Diagnostics) responses.

Response layout: [sub_function_hi, sub_function_lo, result_hi, result_lo] (4 bytes). Echoes the sub-function code with a result word.

Source

pub fn build_fifo_payload(app_payload: &[u8]) -> Result<Self, MbusError>

Builds a PDU for FC18 (Read FIFO Queue) responses.

Response layout: [byte_count_hi, byte_count_lo, payload...] where byte_count is u16. app_payload is the application data: [fifo_count_hi, fifo_count_lo, values...]. Returns InvalidByteCount if payload exceeds 65535 bytes.

Source

pub fn read_window(&self) -> Result<ReadWindow, MbusError>

Parses a read-window request payload into typed fields.

Expected PDU data layout: [address_hi, address_lo, quantity_hi, quantity_lo].

Source

pub fn write_single_u16_fields(&self) -> Result<WriteSingleU16Fields, MbusError>

Parses FC05/FC06-style payloads: address + value.

Source

pub fn write_multiple_fields( &self, ) -> Result<WriteMultipleFields<'_>, MbusError>

Parses FC0F/FC10-style payloads: address + quantity + byte_count + values.

Source

pub fn mask_write_register_fields( &self, ) -> Result<MaskWriteRegisterFields, MbusError>

Parses FC16 mask-write payload: address + and-mask + or-mask.

Source

pub fn byte_count_payload(&self) -> Result<ByteCountPayload<'_>, MbusError>

Parses byte-count prefixed payloads used by read-style responses.

Source

pub fn read_write_multiple_fields( &self, ) -> Result<ReadWriteMultipleFields<'_>, MbusError>

Parses FC17 read/write multiple registers payload.

Source

pub fn single_byte_payload(&self) -> Result<u8, MbusError>

Parses a single-byte payload for FC07-style responses. Data must be exactly 1 byte.

Source

pub fn sub_function_payload(&self) -> Result<SubFunctionPayload<'_>, MbusError>

Parses FC08-style payloads: a 2-byte sub-function code followed by an even-length sequence of data words. Validates minimum length and even alignment.

Source

pub fn u16_pair_fields(&self) -> Result<U16PairFields, MbusError>

Parses FC0B-style payloads: exactly two consecutive 16-bit values (4 bytes total).

Source

pub fn mei_type_payload(&self) -> Result<MeiTypePayload<'_>, MbusError>

Parses FC2B-style payloads: a 1-byte MEI type followed by variable-length data. Data must have at least 1 byte.

Source

pub fn fifo_payload(&self) -> Result<FifoPayload<'_>, MbusError>

Parses FC18-style payloads: a 2-byte FIFO byte count, 2-byte FIFO count, and raw value bytes. Data must have at least 4 bytes. Cross-field consistency validation (byte count vs FIFO count) is left to the caller.

Source

pub fn fifo_pointer(&self) -> Result<u16, MbusError>

Parses FC18 (Read FIFO Queue) request: a single 2-byte FIFO pointer address. Used to extract the pointer address from read FIFO queue requests.

Source

pub fn diagnostics_fields(&self) -> Result<(u16, u16), MbusError>

Parses FC08 (Diagnostics) request/response: sub-function code + data word. Returns (sub_function, data_word).

Source

pub fn file_record_read_sub_requests( &self, ) -> Result<Vec<FileRecordReadSubRequest, { crate::models::file_record::MAX_SUB_REQUESTS_PER_PDU }>, MbusError>

Parses FC14 (Read File Record) requests into validated sub-requests.

Request PDU data layout:

  • byte_count (1)
  • repeated sub-requests (7 bytes each):
    • reference_type (1) = 0x06
    • file_number (2)
    • record_number (2)
    • record_length (2)
Source

pub fn file_record_write_sub_requests<'a>( &'a self, ) -> Result<Vec<FileRecordWriteSubRequest<'a>, { crate::models::file_record::MAX_SUB_REQUESTS_PER_PDU }>, MbusError>

Parses FC15 (Write File Record) requests into validated sub-requests.

Request PDU data layout:

  • byte_count (1)
  • repeated sub-requests:
    • reference_type (1) = 0x06
    • file_number (2)
    • record_number (2)
    • record_length (2)
    • record_data (record_length * 2)
Source

pub fn read_device_id_fields(&self) -> Result<ReadDeviceIdPduFields, MbusError>

Parses FC2B / MEI 0x0E (Read Device Identification) response structural fields.

Validates the 6-byte header minimum length, walks through all declared objects to confirm their lengths fit within the PDU, and returns raw bytes for each header field. Callers must:

  • Check mei_type_byte == EncapsulatedInterfaceType::ReadDeviceIdentification as u8
  • Convert read_device_id_code_byte and conformity_level_byte via TryFrom
Source

pub fn to_bytes(&self) -> Result<Vec<u8, 253>, MbusError>

Converts the PDU into its byte representation.

This method serializes the function code and its associated data payload. It uses an unsafe block to access the Data union, assuming that self.data.bytes contains the full data payload and self.data_len accurately reflects its length.

§Returns

Ok(Vec<u8, 253>) containing the PDU bytes, or an MbusError if the PDU cannot be serialized (e.g., due to buffer overflow).

Source

pub fn from_bytes(bytes: &[u8]) -> Result<Self, MbusError>

Creates a PDU from its byte representation.

This method parses the function code and data payload from the given byte slice.

§Arguments
  • bytes - A byte slice containing the PDU (Function Code + Data).
§Returns

Ok(Pdu) if the bytes represent a valid PDU, or an MbusError otherwise.

Trait Implementations§

Source§

impl Clone for Pdu

Source§

fn clone(&self) -> Pdu

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Pdu

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Pdu

§

impl RefUnwindSafe for Pdu

§

impl Send for Pdu

§

impl Sync for Pdu

§

impl Unpin for Pdu

§

impl UnsafeUnpin for Pdu

§

impl UnwindSafe for Pdu

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.