Simple read/write on Modbusο
This example shows how to read and write Modbus coil registers by configuring a slave connection, an owner file, and an output file with a callback trigger.
Register a Modbus slave device using
slave.modbuswith IP address and read frequency.Read coil register address 0 via
owner.modbusand expose it as avalue.ospp.Write to the Modbus device using
output.modbus.Trigger the write automatically on value change using a
callback.osppwith expression-based inversion.
git checkout origin/osp-modbus-configuration .
git checkout origin/example-modbus-simple-read-write-example .
Prerequisitesο
Modbus connector
A Modbus device or a virtualized Modbus device like
oitc/modbus-server:1.1.2
docker container run -p 5020:5020 --name=modbus-test oitc/modbus-server:1.1.2
Stepsο
1. Register a Modbus slaveο
The first step is to create a βslaveβ file in which we define how to connect to the slave. Replace the IP by the IP of the Modbus device. We are using a read frequency of 1 second for our test. This means the input from the Modbus will be updated every second.
Content : root/plc/slave-1/slave.modbus
{
"host": "10.0.2.15:5020",
"moduleId": "modules.modbus.modbus-1",
"readPeriod": {
"value": 1,
"unit": "SECONDS"
}
}
2. Create a coil inputο
Content : root/input-coil/value.ospp
{
"name": "input-coil",
"description": "input-coil",
"type": "BOOLEAN"
}
We introduce an entity called owner.modbus. This file serves the purpose of indicating our intention to interpret address 0 as a coil for reading. The slave ID field serves as the connection identifier to the corresponding slave device.
Content : root/input-coil/owner.modbus
{
"address": 0,
"endianness": "BIG",
"modbusType": "COIL",
"slaveId": "root.plc.slave-1",
"valueType": "BOOLEAN"
}
1. Create an output file to write value on the modbus deviceο
The output.modbus file describes how we want to write to the Modbus device, but does nothing if nobody interacts with it.
Content : root/output-coil/output.modbus
{
"address": 0,
"endianness": "BIG",
"modbusType": "COIL",
"slaveId": "root.plc.slave-1",
"valueType": "BOOLEAN"
}
4. Call the output from an event.ο
To create a state inversion, this test adds some simple logic to read the value from address 0 then call the output with the inverted value using the expression capabilities.
Content : root/input-coil/callback.ospp
{
"linkedOutputs": [
{
"outputId": "root.output-coil",
"transform": "not(value)"
}
]
}
1. Push the configuration and check the resultο
git add .
git commit -m "Add simple modbus test"
git push
Check the value of the device :
docker container logs -f modbus-test
Logs must show :
The connexion from `osp-modbus` :
2023-08-14 14:10:48,922 MainThread DEBUG sync :347 Started thread to serve client at ('172.17.0.1', 51850)
2023-08-14 14:10:48,922 Thread-1 DEBUG sync :46 Client Connected [172.17.0.1:51850]
A write request between 0 and 1 on the coil address (each second) :
2023-08-14 14:11:23,922 Thread-1 DEBUG sync :229 send: [ReadBitResponse(1)]- b'003d0000000401010100'
2023-08-14 14:11:23,922 Thread-1 DEBUG sync :199 Handling data: 0x0 0x3e 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0xff 0x0
2023-08-14 14:11:23,923 Thread-1 DEBUG socket_framer :147 Processing: 0x0 0x3e 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0xff 0x0
2023-08-14 14:11:23,923 Thread-1 DEBUG factory :137 Factory Request[WriteSingleCoilRequest: 5]
2023-08-14 14:11:23,923 Thread-1 DEBUG context :63 validate: fc-[5] address-1: count-1
2023-08-14 14:11:23,923 Thread-1 DEBUG context :90 setValues[5] 1:1
2023-08-14 14:11:23,923 Thread-1 DEBUG context :77 getValues fc-[5] address-1: count-1
2023-08-14 14:11:23,923 Thread-1 DEBUG sync :229 send: [WriteCoilResponse(0) => 1]- b'003e0000000601050000ff00'
2023-08-14 14:11:24,921 Thread-1 DEBUG sync :199 Handling data: 0x0 0x3f 0x0 0x0 0x0 0x6 0x1 0x1 0x0 0x0 0x0 0x1
2023-08-14 14:11:24,922 Thread-1 DEBUG socket_framer :147 Processing: 0x0 0x3f 0x0 0x0 0x0 0x6 0x1 0x1 0x0 0x0 0x0 0x1
2023-08-14 14:11:24,922 Thread-1 DEBUG factory :137 Factory Request[ReadCoilsRequest: 1]
2023-08-14 14:11:24,922 Thread-1 DEBUG context :63 validate: fc-[1] address-1: count-1
2023-08-14 14:11:24,922 Thread-1 DEBUG context :77 getValues fc-[1] address-1: count-1
2023-08-14 14:11:24,922 Thread-1 DEBUG sync :229 send: [ReadBitResponse(1)]- b'003f0000000401010101'
2023-08-14 14:11:24,923 Thread-1 DEBUG sync :199 Handling data: 0x0 0x40 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0x0 0x0
2023-08-14 14:11:24,923 Thread-1 DEBUG socket_framer :147 Processing: 0x0 0x40 0x0 0x0 0x0 0x6 0x1 0x5 0x0 0x0 0x0 0x0
2023-08-14 14:11:24,923 Thread-1 DEBUG factory :137 Factory Request[WriteSingleCoilRequest: 5]
2023-08-14 14:11:24,923 Thread-1 DEBUG context :63 validate: fc-[5] address-1: count-1
2023-08-14 14:11:24,923 Thread-1 DEBUG context :90 setValues[5] 1:1
2023-08-14 14:11:24,923 Thread-1 DEBUG context :77 getValues fc-[5] address-1: count-1
2023-08-14 14:11:24,924 Thread-1 DEBUG sync :229 send: [WriteCoilResponse(0) => 0]- b'004000000006010500000000'