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
impl Pdu
Sourcepub fn new(
function_code: FunctionCode,
data: Vec<u8, MAX_PDU_DATA_LEN>,
data_len: u8,
) -> Self
pub fn new( function_code: FunctionCode, data: Vec<u8, MAX_PDU_DATA_LEN>, data_len: u8, ) -> Self
Sourcepub fn function_code(&self) -> FunctionCode
pub fn function_code(&self) -> FunctionCode
Accessor for the function code.
Sourcepub fn error_code(&self) -> Option<u8>
pub fn error_code(&self) -> Option<u8>
Accessor for the error code from the PDU.
Sourcepub fn build_read_window(
fc: FunctionCode,
address: u16,
quantity: u16,
) -> Result<Self, MbusError>
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.
Sourcepub fn build_write_single_u16(
fc: FunctionCode,
address: u16,
value: u16,
) -> Result<Self, MbusError>
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.
Sourcepub fn build_write_multiple(
fc: FunctionCode,
address: u16,
quantity: u16,
values: &[u8],
) -> Result<Self, MbusError>
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.
Sourcepub fn build_mask_write_register(
address: u16,
and_mask: u16,
or_mask: u16,
) -> Result<Self, MbusError>
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.
Sourcepub fn build_read_write_multiple(
read_address: u16,
read_quantity: u16,
write_address: u16,
write_quantity: u16,
write_values: &[u8],
) -> Result<Self, MbusError>
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().
Sourcepub fn build_sub_function(
fc: FunctionCode,
sub_function: u16,
words: &[u16],
) -> Result<Self, MbusError>
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.
Sourcepub fn build_mei_type(
fc: FunctionCode,
mei_type: u8,
payload: &[u8],
) -> Result<Self, MbusError>
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.
Sourcepub fn build_u16_payload(
fc: FunctionCode,
value: u16,
) -> Result<Self, MbusError>
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).
Sourcepub fn build_byte_payload(fc: FunctionCode, byte: u8) -> Result<Self, MbusError>
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.
Sourcepub fn build_empty(fc: FunctionCode) -> Self
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.
Sourcepub fn build_byte_count_payload(
fc: FunctionCode,
payload: &[u8],
) -> Result<Self, MbusError>
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.
Sourcepub fn build_diagnostics(
sub_function: u16,
result: u16,
) -> Result<Self, MbusError>
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.
Sourcepub fn build_fifo_payload(app_payload: &[u8]) -> Result<Self, MbusError>
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.
Sourcepub fn read_window(&self) -> Result<ReadWindow, MbusError>
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].
Sourcepub fn write_single_u16_fields(&self) -> Result<WriteSingleU16Fields, MbusError>
pub fn write_single_u16_fields(&self) -> Result<WriteSingleU16Fields, MbusError>
Parses FC05/FC06-style payloads: address + value.
Sourcepub fn write_multiple_fields(
&self,
) -> Result<WriteMultipleFields<'_>, MbusError>
pub fn write_multiple_fields( &self, ) -> Result<WriteMultipleFields<'_>, MbusError>
Parses FC0F/FC10-style payloads: address + quantity + byte_count + values.
Sourcepub fn mask_write_register_fields(
&self,
) -> Result<MaskWriteRegisterFields, MbusError>
pub fn mask_write_register_fields( &self, ) -> Result<MaskWriteRegisterFields, MbusError>
Parses FC16 mask-write payload: address + and-mask + or-mask.
Sourcepub fn byte_count_payload(&self) -> Result<ByteCountPayload<'_>, MbusError>
pub fn byte_count_payload(&self) -> Result<ByteCountPayload<'_>, MbusError>
Parses byte-count prefixed payloads used by read-style responses.
Sourcepub fn read_write_multiple_fields(
&self,
) -> Result<ReadWriteMultipleFields<'_>, MbusError>
pub fn read_write_multiple_fields( &self, ) -> Result<ReadWriteMultipleFields<'_>, MbusError>
Parses FC17 read/write multiple registers payload.
Sourcepub fn single_byte_payload(&self) -> Result<u8, MbusError>
pub fn single_byte_payload(&self) -> Result<u8, MbusError>
Parses a single-byte payload for FC07-style responses. Data must be exactly 1 byte.
Sourcepub fn sub_function_payload(&self) -> Result<SubFunctionPayload<'_>, MbusError>
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.
Sourcepub fn u16_pair_fields(&self) -> Result<U16PairFields, MbusError>
pub fn u16_pair_fields(&self) -> Result<U16PairFields, MbusError>
Parses FC0B-style payloads: exactly two consecutive 16-bit values (4 bytes total).
Sourcepub fn mei_type_payload(&self) -> Result<MeiTypePayload<'_>, MbusError>
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.
Sourcepub fn fifo_payload(&self) -> Result<FifoPayload<'_>, MbusError>
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.
Sourcepub fn fifo_pointer(&self) -> Result<u16, MbusError>
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.
Sourcepub fn diagnostics_fields(&self) -> Result<(u16, u16), MbusError>
pub fn diagnostics_fields(&self) -> Result<(u16, u16), MbusError>
Parses FC08 (Diagnostics) request/response: sub-function code + data word. Returns (sub_function, data_word).
Sourcepub fn file_record_read_sub_requests(
&self,
) -> Result<Vec<FileRecordReadSubRequest, { crate::models::file_record::MAX_SUB_REQUESTS_PER_PDU }>, MbusError>
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)
Sourcepub fn file_record_write_sub_requests<'a>(
&'a self,
) -> Result<Vec<FileRecordWriteSubRequest<'a>, { crate::models::file_record::MAX_SUB_REQUESTS_PER_PDU }>, MbusError>
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)
Sourcepub fn read_device_id_fields(&self) -> Result<ReadDeviceIdPduFields, MbusError>
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_byteandconformity_level_byteviaTryFrom
Sourcepub fn to_bytes(&self) -> Result<Vec<u8, 253>, MbusError>
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).