Pymodbus Simulator Guide
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.
For most use cases, it is recommended to run the simulator with an Xrt device profile. Please see the Profile configuration section below.
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
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 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 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.
--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
set_value(value) function. For example:
def set_initial(resources): this_resource = resources.get("resource name") this_resource.set_value(5)
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
update_values(resources) function can also be implemented in order to update values at a given interval. This also takes in the same
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 option determines the time in seconds between iterations of the
update_values() function. For this to have any effect, the
must also be used to select a file containing the
The default value of
--delay is 1 second.
--log argument sets the log level for the simulator. Valid options are:
The default log level is
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
--serial_over_tcp_port, specifying the TCP port on which to transfer the data out from the container.
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
socat pty,link=/tmp/virtualport,raw,echo=0 tcp:localhost:50103
After using the above command, a device can be configured within Xrt using