Functions๏ƒ

This section documents all functions available in the libmodbus library.

๐Ÿงฎ Checksum Functions๏ƒ

CRC-16 Calculation๏ƒ

static uint16_t Checksum::calculateCRC16(const uint8_t *buffer, uint16_t length)

Calculate CRC-16 checksum for Modbus RTU.

Calculates the CRC-16 checksum used by Modbus RTU protocol. This implementation uses the standard Modbus CRC-16 algorithm with polynomial 0xA001 (reversed representation of 0x8005).

Algorithm:

  1. Initialize CRC register to 0xFFFF

  2. For each byte: a. XOR byte with low byte of CRC register b. For each bit (8 iterations):

    • If LSB of CRC is 1: shift right and XOR with 0xA001

    • If LSB of CRC is 0: shift right only

  3. Return final CRC value

Note

The CRC is transmitted LSB first in RTU frames. This function returns the CRC in native byte order; the caller is responsible for proper byte ordering.

Note

This is the standard Modbus CRC-16 algorithm as specified in the Modbus over Serial Line Specification and Implementation Guide V1.02.

Parameters:
  • buffer โ€“ Pointer to the data buffer

  • length โ€“ Length of the data buffer in bytes

Returns:

CRC-16 checksum value (16-bit)

LRC Calculation๏ƒ

static uint8_t Checksum::calculateLRC(const uint8_t *pucFrame, uint16_t usLen)

Calculate LRC (Longitudinal Redundancy Check) for Modbus ASCII.

Calculates the LRC checksum used by Modbus ASCII protocol. The LRC is computed by adding all bytes in the message and taking the twoโ€™s complement of the result.

Algorithm:

  1. Add all bytes in the frame (excluding the LRC itself)

  2. Take the twoโ€™s complement of the sum

  3. Return the result as a single byte

Note

The LRC is calculated over the binary representation of the ASCII characters, not the ASCII characters themselves.

Parameters:
  • pucFrame โ€“ Pointer to the frame data

  • usLen โ€“ Length of the frame data in bytes

Returns:

LRC checksum value (8-bit)

๐Ÿ“Š Data Model Functions๏ƒ

Read Functions๏ƒ

CoilType ModbusDataModel::readCoil(uint16_t index) const

Read a coil value.

Note

This function performs bounds checking and returns false for invalid indices

Parameters:

index โ€“ 0-based index of the coil to read

Returns:

Value of the coil (true/false), or false if index is out of range

DiscreteInputType ModbusDataModel::readDiscreteInput(uint16_t index) const

Read a discrete input value.

Note

This function performs bounds checking and returns false for invalid indices

Parameters:

index โ€“ 0-based index of the discrete input to read

Returns:

Value of the discrete input (true/false), or false if index is out of range

HoldingRegisterType ModbusDataModel::readHoldingRegister(uint16_t index) const

Read a holding register value.

Note

This function performs bounds checking and returns 0 for invalid indices

Parameters:

index โ€“ 0-based index of the holding register to read

Returns:

Value of the holding register (0-65535), or 0 if index is out of range

InputRegisterType ModbusDataModel::readInputRegister(uint16_t index) const

Read an input register value.

Note

This function performs bounds checking and returns 0 for invalid indices

Parameters:

index โ€“ 0-based index of the input register to read

Returns:

Value of the input register (0-65535), or 0 if index is out of range

Write Functions๏ƒ

void ModbusDataModel::writeCoil(uint16_t index, CoilType value)

Write a single coil value.

Note

This function performs bounds checking and ignores writes to invalid indices

Parameters:
  • index โ€“ 0-based index of the coil to write

  • value โ€“ New value for the coil (true/false)

void ModbusDataModel::writeHoldingRegister(uint16_t index, HoldingRegisterType value)

Write a single holding register value.

Note

This function performs bounds checking and ignores writes to invalid indices

Parameters:
  • index โ€“ 0-based index of the holding register to write

  • value โ€“ New value for the holding register (0-65535)

void ModbusDataModel::writeMultipleCoils(uint16_t start_index, const CoilType values[], size_t num_values)

Write multiple coil values starting at a specified address.

Note

This function performs bounds checking and only writes values that fit within the valid address range. Partial writes may occur if the range extends beyond the maximum address.

Parameters:
  • start_index โ€“ 0-based starting index for the write operation

  • values โ€“ Array of coil values to write

  • num_values โ€“ Number of values to write from the array

void ModbusDataModel::writeMultipleHoldingRegisters(uint16_t start_index, const HoldingRegisterType values[], size_t num_values)

Write multiple holding register values starting at a specified address.

Note

This function performs bounds checking and only writes values that fit within the valid address range. Partial writes may occur if the range extends beyond the maximum address.

Parameters:
  • start_index โ€“ 0-based starting index for the write operation

  • values โ€“ Array of holding register values to write

  • num_values โ€“ Number of values to write from the array

Set Functions (Testing/Initialization)๏ƒ

void ModbusDataModel::setDiscreteInput(uint16_t index, DiscreteInputType value)

Set a discrete input value (for testing/initialization)

Note

This function is primarily intended for testing and initialization. In a real Modbus device, discrete inputs would typically be updated by hardware or other system components, not by Modbus commands.

Note

This function performs bounds checking and ignores writes to invalid indices

Parameters:
  • index โ€“ 0-based index of the discrete input to set

  • value โ€“ New value for the discrete input (true/false)

void ModbusDataModel::setInputRegister(uint16_t index, InputRegisterType value)

Set an input register value (for testing/initialization)

Note

This function is primarily intended for testing and initialization. In a real Modbus device, input registers would typically be updated by hardware or other system components, not by Modbus commands.

Note

This function performs bounds checking and ignores writes to invalid indices

Parameters:
  • index โ€“ 0-based index of the input register to set

  • value โ€“ New value for the input register (0-65535)

Size Getters๏ƒ

inline size_t ModbusDataModel::getMaxCoils() const

Get the maximum number of coils.

Returns:

Maximum number of coils this data model can store

inline size_t ModbusDataModel::getMaxDiscreteInputs() const

Get the maximum number of discrete inputs.

Returns:

Maximum number of discrete inputs this data model can store

inline size_t ModbusDataModel::getMaxHoldingRegisters() const

Get the maximum number of holding registers.

Returns:

Maximum number of holding registers this data model can store

inline size_t ModbusDataModel::getMaxInputRegisters() const

Get the maximum number of input registers.

Returns:

Maximum number of input registers this data model can store

๐Ÿ–ผ๏ธ Frame Processing Functions๏ƒ

RTU Frame Functions๏ƒ

std::vector<uint8_t> ModbusRtuFrame::serialize()

Serialize the RTU frame to a byte vector.

Converts the RTU frame to its binary representation suitable for transmission over a serial link. The function automatically calculates and appends the CRC-16 checksum.

Note

The CRC is calculated using the Modbus CRC-16 algorithm

Returns:

Vector of bytes representing the serialized frame

void ModbusRtuFrame::deserialize(ModbusFrameType frameType, const std::vector<uint8_t> &data)

Deserialize a byte vector into an RTU frame.

Parses a received byte vector and populates the RTU frame fields. The function extracts the slave address, function code, data, and CRC.

Note

This function does not validate the CRC - that should be done by the caller before calling this function.

Parameters:
  • frameType โ€“ Expected frame type (REQUEST, RESPONSE, or EXCEPTION)

  • data โ€“ Byte vector containing the raw frame data

ASCII Frame Functions๏ƒ

std::vector<uint8_t> ModbusAsciiFrame::serialize()

Serialize the ASCII frame to a byte vector.

Todo:

This method is not yet implemented

Returns:

Vector of bytes representing the serialized frame

void ModbusAsciiFrame::deserialize(const std::vector<uint8_t> &data)

Deserialize a byte vector into an ASCII frame.

Todo:

This method is not yet implemented

Parameters:

data โ€“ Byte vector containing the raw frame data

TCP Frame Functions๏ƒ

std::vector<uint8_t> ModbusTcpFrame::serialize()

Serialize the TCP frame to a byte vector.

Todo:

This method is not yet implemented

Returns:

Vector of bytes representing the serialized frame

void ModbusTcpFrame::deserialize(const std::vector<uint8_t> &data)

Deserialize a byte vector into a TCP frame.

Todo:

This method is not yet implemented

Parameters:

data โ€“ Byte vector containing the raw frame data

๐Ÿ–ฅ๏ธ Server Functions๏ƒ

Request Processing๏ƒ

inline virtual std::vector<uint8_t> ModbusBaseServer::process(const std::vector<uint8_t> &requestData)

Process a Modbus request and generate a response.

This is the main entry point for request processing. Each protocol-specific derived class must implement this method to handle the protocol-specific frame formatting and validation.

Note

The base implementation returns an empty vector. Derived classes must override this method to provide actual functionality.

Parameters:

requestData โ€“ Raw request data as received from the transport layer

Returns:

Raw response data to be sent back, or empty vector if no response

virtual std::vector<uint8_t> ModbusRtuServer::process(const std::vector<uint8_t> &requestData)

Process an RTU request and generate an RTU response.

This method handles the complete RTU request processing pipeline:

  1. Frame validation (minimum size, CRC check)

  2. Slave address verification

  3. Function code lookup and command execution

  4. Response frame generation and CRC calculation

The method performs the following validations:

  • Minimum frame size (4 bytes: address + function + CRC)

  • CRC integrity check

  • Slave address matching (responds to address 1 only)

  • Function code support check

Exception responses are generated for:

  • Unsupported function codes

  • Invalid request parameters

  • Data access errors

Note

No response is generated for:

  • Invalid CRC

  • Wrong slave address

  • Broadcast messages (address 0)

Parameters:

requestData โ€“ Raw RTU frame data including slave address and CRC

Returns:

Complete RTU response frame, or empty vector if no response needed

๐ŸŽฎ Command Validation Functions๏ƒ

Generic Validation๏ƒ

bool ModbusCommand::validateQuantity(const ModbusFrame &request, uint16_t minQuantity, uint16_t maxQuantity, ModbusFrame &response)๏ƒ

Generic quantity validation for Modbus requests.

Validates that the quantity field in a Modbus request falls within the specified minimum and maximum values.

Note

This method assumes the quantity is in bytes 2-3 of the frame data

Parameters:
  • request โ€“ The incoming request frame

  • minQuantity โ€“ Minimum allowed quantity

  • maxQuantity โ€“ Maximum allowed quantity

  • response โ€“ Reference to response frame (populated with exception if validation fails)

Returns:

true if validation passes, false if exception was generated

bool ModbusCommand::validateAddress(const ModbusFrame &request, uint16_t maxValidAddress, ModbusFrame &response)๏ƒ

Address range validation for Modbus requests.

Validates that the starting address and quantity combination is within the valid address range for the data type.

Note

This method assumes address is in bytes 0-1 and quantity in bytes 2-3

Parameters:
  • request โ€“ The incoming request frame

  • maxValidAddress โ€“ Maximum valid address for this data type

  • response โ€“ Reference to response frame (populated with exception if validation fails)

Returns:

true if validation passes, false if exception was generated

Function-Specific Validation๏ƒ

bool ModbusCommand::validateReadCoilsQuantity(const ModbusFrame &request, ModbusFrame &response)๏ƒ

Validate quantity for Read Coils function (FC 01)

Validates quantity range for coil reading operations (1-2000 coils).

Parameters:
  • request โ€“ The incoming request frame

  • response โ€“ Reference to response frame (populated with exception if validation fails)

Returns:

true if validation passes, false if exception was generated

bool ModbusCommand::validateReadRegistersQuantity(const ModbusFrame &request, ModbusFrame &response)๏ƒ

Validate quantity for Read Registers functions (FC 03, 04)

Validates quantity range for register reading operations (1-125 registers).

Parameters:
  • request โ€“ The incoming request frame

  • response โ€“ Reference to response frame (populated with exception if validation fails)

Returns:

true if validation passes, false if exception was generated

bool ModbusCommand::validateWriteMultipleCoilsQuantity(const ModbusFrame &request, ModbusFrame &response)๏ƒ

Validate quantity for Write Multiple Coils function (FC 15)

Validates quantity range for multiple coil writing operations (1-1968 coils).

Parameters:
  • request โ€“ The incoming request frame

  • response โ€“ Reference to response frame (populated with exception if validation fails)

Returns:

true if validation passes, false if exception was generated

bool ModbusCommand::validateWriteMultipleRegistersQuantity(const ModbusFrame &request, ModbusFrame &response)๏ƒ

Validate quantity for Write Multiple Registers function (FC 16)

Validates quantity range for multiple register writing operations (1-123 registers).

Parameters:
  • request โ€“ The incoming request frame

  • response โ€“ Reference to response frame (populated with exception if validation fails)

Returns:

true if validation passes, false if exception was generated

Command Execution๏ƒ

virtual ModbusFrame ModbusCommand::execute(ModbusDataModel &data, const ModbusFrame &request) = 0

Execute the command with given data model and request.

This is the main entry point for command execution. Each derived class implements this method to handle its specific function code.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming Modbus request frame

Returns:

Response frame (normal response or exception)

virtual ModbusFrame ReadCoilCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Read Coils command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame containing coil status or exception

virtual ModbusFrame ReadDiscreteInputCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Read Discrete Inputs command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame containing input status or exception

virtual ModbusFrame ReadHoldingRegisterCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Read Holding Registers command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame containing register values or exception

virtual ModbusFrame ReadInputRegisterCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Read Input Registers command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame containing register values or exception

virtual ModbusFrame WriteCoilCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Write Single Coil command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame (echo of request) or exception

virtual ModbusFrame WriteHoldingRegisterCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Write Single Register command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame (echo of request) or exception

virtual ModbusFrame WriteMultipleCoilsCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Write Multiple Coils command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame containing address and quantity or exception

virtual ModbusFrame WriteMultipleRegistersCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Write Multiple Registers command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame containing address and quantity or exception

virtual ModbusFrame DiagnosticsCommand::execute(ModbusDataModel &data, const ModbusFrame &request)

Execute the Diagnostics command.

Parameters:
  • data โ€“ Reference to the Modbus data model

  • request โ€“ The incoming request frame

Returns:

Response frame containing diagnostic response or exception