LUA / libmodbus
Caution
- This Router App requires the LUA Router App to be installed first.
Introduction
The LUA / libmodbus Router App extends the LUA Router App by adding support for the Modbus communication protocol. It enables Lua scripts running on the router to exchange data with devices that support Modbus, such as PLCs, sensors, meters, and other industrial equipment.
Communication can be established over:
- Serial port — using the Modbus RTU protocol (RS-232 or RS-485).
- Ethernet — using the Modbus TCP protocol.
Installation
To install the LUA / libmodbus Router App, follow the instructions in the Configuration Manual, section Customization → Router Apps.
The LUA Router App must be installed before installing this Router App.
To verify that the libmodbus library is available from a Lua script, run the following from the router's CLI:
lua -e "require('libmodbus'); print('libmodbus OK')"Modbus Protocol Overview
Modbus is a serial communication protocol widely used in industrial automation. The two most common variants are:
| Variant | Transport | Typical use |
|---|---|---|
| Modbus RTU | Serial (RS-232 / RS-485) | Field devices, sensors, PLCs over serial cable |
| Modbus TCP | Ethernet / TCP/IP | Devices connected to a network |
In both variants, a master device (the router running the Lua script) initiates all communication. Slave devices respond to requests. Each slave has a numeric address (slave ID), and data is organized into four tables:
| Table | Access | Description |
|---|---|---|
| Coils | Read / Write | Single-bit output values (on/off). |
| Discrete Inputs | Read only | Single-bit input values. |
| Holding Registers | Read / Write | 16-bit output values. |
| Input Registers | Read only | 16-bit input values. |
Using libmodbus in Lua
Script Structure
A typical libmodbus Lua script follows this sequence:
- Load the library with
require. - Create a Modbus context for the desired communication type (RTU or TCP).
- Connect to the device.
- Set the slave ID of the target device.
- Read or write data.
- Close the connection and free the context.
Modbus RTU (Serial Port)
The following example reads 10 holding registers from a Modbus RTU slave device connected to the router's serial port.
local modbus = require("libmodbus")
-- Create an RTU context
-- Parameters: device, baud rate, parity ('N'=None, 'E'=Even, 'O'=Odd), data bits, stop bits
local ctx, err = modbus.new_rtu("/dev/ttyS1", 9600, "N", 8, 1)
if not ctx then
print("Failed to create RTU context: " .. tostring(err))
os.exit(1)
end
-- Connect to the serial port
local ok, err = ctx:connect()
if not ok then
print("Connection failed: " .. tostring(err))
ctx:free()
os.exit(1)
end
-- Set the slave ID of the target device
ctx:set_slave(1)
-- Read 10 holding registers starting at address 0
local regs, err = ctx:read_registers(0, 10)
if regs then
for i, value in ipairs(regs) do
print(string.format("Register %d: %d", i - 1, value))
end
else
print("Read failed: " .. tostring(err))
end
-- Clean up
ctx:close()
ctx:free()Modbus TCP (Ethernet)
The following example writes a value to a single holding register on a Modbus TCP device.
local modbus = require("libmodbus")
-- Create a TCP context
-- Parameters: IP address, port (standard Modbus TCP port is 502)
local ctx, err = modbus.new_tcp("192.168.1.100", 502)
if not ctx then
print("Failed to create TCP context: " .. tostring(err))
os.exit(1)
end
-- Connect to the device
local ok, err = ctx:connect()
if not ok then
print("Connection failed: " .. tostring(err))
ctx:free()
os.exit(1)
end
-- Set the slave ID (unit ID in Modbus TCP)
ctx:set_slave(1)
-- Write value 1234 to holding register at address 10
local ok, err = ctx:write_register(10, 1234)
if ok then
print("Register written successfully.")
else
print("Write failed: " .. tostring(err))
end
-- Clean up
ctx:close()
ctx:free()Function Reference
The following functions are provided by the libmodbus Lua binding:
Context Creation
| Function | Description |
|---|---|
modbus.new_rtu(device, baud, parity, data_bits, stop_bits) | Creates a Modbus RTU context for serial communication. Returns a context object or nil, error. |
modbus.new_tcp(host, port) | Creates a Modbus TCP context for Ethernet communication. Returns a context object or nil, error. |
Context Methods
| Method | Description |
|---|---|
ctx:connect() | Establishes the connection (opens the serial port or TCP socket). |
ctx:set_slave(id) | Sets the slave ID (RTU) or unit ID (TCP) of the target device. |
ctx:read_bits(addr, count) | Reads count coils starting at addr. Returns a table of values or nil, error. |
ctx:read_input_bits(addr, count) | Reads count discrete inputs starting at addr. Returns a table of values or nil, error. |
ctx:read_registers(addr, count) | Reads count holding registers starting at addr. Returns a table of values or nil, error. |
ctx:read_input_registers(addr, count) | Reads count input registers starting at addr. Returns a table of values or nil, error. |
ctx:write_bit(addr, value) | Writes a single coil at addr. Value: 1 (on) or 0 (off). |
ctx:write_register(addr, value) | Writes a single holding register at addr. |
ctx:write_bits(addr, values) | Writes multiple coils starting at addr. Pass a table of 0/1 values. |
ctx:write_registers(addr, values) | Writes multiple holding registers starting at addr. Pass a table of integer values. |
ctx:close() | Closes the connection. |
ctx:free() | Frees the context and releases resources. Always call after close(). |
Further Information
The libmodbus C library documentation, which describes the underlying functions and protocol details, is available at https://libmodbus.org/.
For Lua language reference and scripting guidance, refer to the LUA Router App documentation.