Pymodbus Simulator Guide
About
The Pymodbus Simulator is a Modbus Server that can be used as an endpoint for testing communication with the Modbus Device Service Component.
The simulator is available on Docker Hub at iotechsys/pymodbus-sim.
Running the simulator
The Pymodbus simulator can be run with the following command:
docker run -d --rm --name pymodbus-sim iotechsys/pymodbus-sim:1.0
The above command will start the simulator and initialise all registers to 0 within each primary table.
The above command does not make use of any optional arguments, so the default configuration of TCP protocol with port 5020 is used.
Note
For most use cases, it is recommended to run the simulator with an Xrt device profile. Please see the Profile configuration section below.
Configuration Options
--profile
When run with an Xrt device profile, the simulator will initialise only registers which are covered by a resource. It will not allow any reads or writes outside these registers, making it easier to check that modbus requests to the simulator are correct. This profile must be mounted into the Docker container at runtime to allow the simulator to access the file.
The Pymodbus simulator can be run with a device profile using the following command:
docker run -d --rm \
-v host_dir_with_profile:/sim_files \
--name pymodbus-sim iotechsys/pymodbus-sim:1.0 \
--profile /sim_files/modbus_device_profile.json
In the above command, the -v
option is used to mount a directory containing a profile into the docker container. This profile is then selected using the
--profile
option.
--comm
The default transmission protocol is TCP, however a serial connection is also possible using the option --comm serial
. Additional
configuration is also required for a serial connection. For more information, read the Serial Connection section below.
--port
The --port
argument is used to specify the port on which the simulator should be available.
For a TCP connection, the default value is 5020. For a serial connection, this option must be set.
--script
The --script
argument is used to specify a file which details how the values within the simulator should be set on initialisation and/or how they should be
updated over time. This file may contain one or both of the following Python functions.
Note
The --script
option can only be used when --profile
is also set.
To set values once upon startup, the set_initial(resources)
function may be implemented. This takes in a map of available resources resources
as the only parameter.
This map is keyed by resource name, and contains a Resource
object for each. To set the value of any given resource, retrieve its Resource
object and use
the set_value(value)
function. For example:
def set_initial(resources):
this_resource = resources.get("resource name")
this_resource.set_value(5)
The set_value(value)
function does not apply any scale or additive on the resource, and must be passed the exact value to be stored in the register(s).
Type conversion for resources with a different valueType and rawType is also not supported. The value is written as the resource rawType if one is present, otherwise it is written as the valueType.
For string resources, a string can be passed directly to set_value(value)
.
The update_values(resources)
function can also be implemented in order to update values at a given interval. This also takes in the same resources
map
in the same format. A Resource
object also contains a get_value()
function, which is useful for incrementing values over time. For example:
def update_values(resources):
this_resource = resources.get("resource name")
previous_value = this_resource.get_value()
this_resource.set_value(previous_value + 3)
--delay
The --delay
option determines the time in seconds between iterations of the update_values()
function. For this to have any effect, the script
argument
must also be used to select a file containing the update_values()
function.
The default value of --delay
is 1 second.
--log
The --log
argument sets the log level for the simulator. Valid options are: critical
, error
, warning
, info
and debug
.
The default log level is info
.
Serial Connection
To facilitate a virtual serial connection from within a Docker container, the socat
command line tool is required.
First, a TCP listener is set up inside the container. This is done automatically whenever the argument --comm serial
is used, and requires the use of another
argument --serial_over_tcp_port
, specifying the TCP port on which to transfer the data out from the container.
For example:
docker run -d --rm\
-v host_dir_with_profile:/sim_files \
--network=host \
--name pymodbus-sim iotechsys/pymodbus-sim:1.0 \
--profile /sim_files/modbus_device_profile.json \
--comm serial \
--serial_over_tcp_port 50103
On the host machine, socat
must again be used to transfer the data from the TCP connection back to a virtual serial port. This can be done with the
following command:
socat pty,link=/tmp/virtualport,raw,echo=0 tcp:localhost:50103
After using the above command, a device can be configured within Xrt using "address": "/tmp/virtualport"
.