Modbus#
Modbus service manages Modbus TCP clients for things and groups. Each client defines a device address, slave ID, function code, poll schedule, and one or more data fields describing how to interpret the register values. On each scheduled poll the service reads the configured registers or coils from the Modbus TCP device, formats the result as a JSON payload, and publishes it as a platform message scoped to the associated thing.
On startup, the service loads all persisted Modbus clients and begins scheduling polls according to each client's configured frequency.
Function codes#
The following Modbus function codes are supported:
| Function code | Description |
|---|---|
ReadCoils |
Read output coils (FC 01) |
ReadDiscreteInputs |
Read discrete input coils (FC 02) |
ReadInputRegisters |
Read input registers (FC 04) |
ReadHoldingRegisters |
Read holding registers (FC 03) |
Data fields#
Each client specifies a list of data fields that describe how to decode the register values into named measurements.
Supported types: bool, int16, uint16, int32, uint32, float32, string.
Byte order can be configured per field to handle different device conventions:
| Byte order | Description |
|---|---|
ABCD |
Big-endian (default) |
DCBA |
Little-endian |
CDAB |
Big-endian, swapped words |
BADC |
Little-endian, swapped words |
An optional scale factor can be applied to numeric values after reading.
{
"data_fields": [
{"name": "temperature", "type": "float32", "unit": "°C", "byte_order": "ABCD"},
{"name": "humidity", "type": "uint16", "unit": "%"},
{"name": "status", "type": "bool"}
]
}
Creating and managing clients#
Modbus clients are created per thing. The required fields are name, ip_address, port, function_code, scheduler, and data_fields.
# Create Modbus clients for a thing
curl -s -S -i -X POST \
-H "Authorization: Bearer <user_token>" \
-H "Content-Type: application/json" \
-d '[
{
"name": "Boiler sensor",
"ip_address": "192.168.1.100",
"port": "502",
"slave_id": 1,
"function_code": "ReadHoldingRegisters",
"scheduler": {"frequency": "minutely"},
"data_fields": [
{"name": "temperature", "type": "float32", "unit": "°C"},
{"name": "pressure", "type": "uint16", "unit": "bar"}
]
}
]' \
https://localhost/modbus/things/<thing_id>/clients
[
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Boiler sensor",
"ip_address": "192.168.1.100",
"port": "502",
"slave_id": 1,
"function_code": "ReadHoldingRegisters",
"scheduler": {"frequency": "minutely"},
"data_fields": [
{"name": "temperature", "type": "float32", "unit": "°C"},
{"name": "pressure", "type": "uint16", "unit": "bar"}
],
"thing_id": "111e4567-e89b-12d3-a456-426614174000",
"group_id": "211e4567-e89b-12d3-a456-426614174000"
}
]
# List clients for a thing
curl -s -S -i \
-H "Authorization: Bearer <user_token>" \
https://localhost/modbus/things/<thing_id>/clients
# List clients for a group
curl -s -S -i \
-H "Authorization: Bearer <user_token>" \
https://localhost/modbus/groups/<group_id>/clients
# View a specific client
curl -s -S -i \
-H "Authorization: Bearer <user_token>" \
https://localhost/modbus/clients/<client_id>
# Update a client
curl -s -S -i -X PUT \
-H "Authorization: Bearer <user_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Boiler sensor",
"ip_address": "192.168.1.100",
"port": "502",
"slave_id": 1,
"function_code": "ReadHoldingRegisters",
"scheduler": {"frequency": "hourly"},
"data_fields": [
{"name": "temperature", "type": "float32", "unit": "°C"}
]
}' \
https://localhost/modbus/clients/<client_id>
# Remove clients
curl -s -S -i -X DELETE \
-H "Authorization: Bearer <user_token>" \
-H "Content-Type: application/json" \
-d '{"client_ids": ["<client_id>"]}' \
https://localhost/modbus/clients
For the full API reference, see the API documentation.