-
Notifications
You must be signed in to change notification settings - Fork 957
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
901a87d
commit d6abf15
Showing
16 changed files
with
454 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
Simulator (3.x) | ||
=============== | ||
|
||
The simulator is a full fledged modbus simulator, which is | ||
constantly being evolved with user ideas / amendments. | ||
|
||
The purpose of the simulator is to provide support for client | ||
application test harnesses with end-to-end testing simulating real life | ||
modbus devices. | ||
|
||
The datastore simulator allows the user to (all automated) | ||
|
||
- simulate a modbus device by adding a simple configuration, | ||
- test how a client handles modbus exceptions, | ||
- test a client apps correct use of the simulated device. | ||
|
||
The web interface allows the user to (online / manual) | ||
|
||
- test how a client handles modbus errors, | ||
- test how a client handles communication errors like divided messages, | ||
- run your test server in the cloud, | ||
- monitor requests/responses, | ||
- inject modbus errors like malicious a response, | ||
- see/Change values online. | ||
|
||
The REST API allow the test process to be automated | ||
|
||
- spin up a test server with unix domain sockets in your test harness, | ||
- set expected responses with a simple REST API command, | ||
- check the result with another simple REST API command, | ||
- test your client app in a true end-to-end fashion. | ||
|
||
.. toctree:: | ||
:maxdepth: 4 | ||
:hidden: | ||
|
||
library/simulator/config | ||
library/simulator/datastore | ||
library/simulator/web | ||
library/simulator/restapi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#!/usr/bin/env python3 | ||
"""Pymodbus simulator server/client Example. | ||
An example of how to use the simulator (server) with a client. | ||
for usage see documentation of simulator | ||
.. tip:: pymodbus.simulator starts the server directly from the commandline | ||
""" | ||
import asyncio | ||
import logging | ||
|
||
from pymodbus import FramerType | ||
from pymodbus.client import AsyncModbusTcpClient | ||
from pymodbus.datastore import ModbusSimulatorContext | ||
from pymodbus.server import ModbusSimulatorServer, get_simulator_commandline | ||
|
||
|
||
_logger = logging.getLogger(__file__) | ||
|
||
|
||
async def read_registers( | ||
client, addr, count, is_int, curval=None, minval=None, maxval=None | ||
): | ||
"""Run modbus call.""" | ||
rr = await client.read_holding_registers(addr, count=count, slave=1) | ||
assert not rr.isError() | ||
if count == 1: | ||
value = rr.registers[0] | ||
else: | ||
value = ModbusSimulatorContext.build_value_from_registers(rr.registers, is_int) | ||
if not is_int: | ||
value = round(value, 1) | ||
if curval: | ||
assert value == curval, f"{value} == {curval}" | ||
else: | ||
assert minval <= value <= maxval, f"{minval} <= {value} <= {maxval}" | ||
|
||
|
||
async def run_calls(client, count): | ||
"""Run client calls.""" | ||
_logger.info("### Read fixed/increment/random value of different types.") | ||
_logger.info("--> UINT16") | ||
for count in range(1, 5): | ||
await read_registers(client, 1148, 1, True, curval=32117) | ||
await read_registers(client, 2305, 1, True, curval=50 + count) | ||
await read_registers(client, 2306, 1, True, minval=45, maxval=55) | ||
|
||
_logger.info("--> UINT32") | ||
await read_registers(client, 3188, 2, True, curval=32514) | ||
await read_registers(client, 3876, 2, True, curval=50000 + count) | ||
await read_registers(client, 3878, 2, True, minval=45000, maxval=55000) | ||
|
||
_logger.info("--> FLOAT32") | ||
await read_registers(client, 4188, 2, False, curval=32514.2) | ||
await read_registers(client, 4876, 2, False, curval=50000.0 + count) | ||
await read_registers(client, 4878, 2, False, minval=45000.0, maxval=55000.0) | ||
|
||
|
||
async def run_simulator(): | ||
"""Run server.""" | ||
_logger.info("### start server simulator") | ||
cmdline = [ | ||
"--modbus_device", | ||
"device_try", | ||
"--modbus_server", | ||
"server", | ||
] | ||
cmd_args = get_simulator_commandline(cmdline=cmdline) | ||
task = ModbusSimulatorServer(**cmd_args) | ||
await task.run_forever(only_start=True) | ||
|
||
_logger.info("### start client") | ||
client = AsyncModbusTcpClient( | ||
"127.0.0.1", | ||
port=5020, | ||
framer=FramerType.SOCKET, | ||
) | ||
await client.connect() | ||
assert client.connected | ||
|
||
_logger.info("### run calls") | ||
await run_calls(client, 1) | ||
|
||
_logger.info("### shutdown client") | ||
client.close() | ||
|
||
_logger.info("### shutdown server") | ||
await task.stop() | ||
_logger.info("### Thanks for now.") | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(run_simulator(), debug=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
"""Simulator.""" | ||
|
||
__all__ = [ | ||
"SimActions", | ||
"SimData", | ||
"SimDataType", | ||
"SimDevice", | ||
] | ||
|
||
from pymodbus.simulator.simdata import SimActions, SimData, SimDataType, SimDevice |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
"""Simulator data model classes.""" | ||
from __future__ import annotations |
Oops, something went wrong.