Skip to content

Commit

Permalink
use pymodbus simulator instead of Python mock
Browse files Browse the repository at this point in the history
  • Loading branch information
alexrudd2 committed May 23, 2024
1 parent 8fddec2 commit fcde211
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 8 deletions.
66 changes: 66 additions & 0 deletions clickplc/tests/simulator_setup.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"server_list": {
"server": {
"comm": "tcp",
"host": "0.0.0.0",
"port": 5020,
"ignore_missing_slaves": false,
"framer": "socket",
"identity": {
"VendorName": "pymodbus",
"ProductCode": "PM",
"VendorUrl": "https://github.com/pymodbus-dev/pymodbus/",
"ProductName": "pymodbus Server",
"ModelName": "pymodbus Server",
"MajorMinorRevision": "3.1.0"
}
}
},
"device_list": {
"device": {
"setup": {
"co size": 65536,
"di size": 65536,
"hr size": 65536,
"ir size": 65536,
"shared blocks": false,
"type exception": false,
"defaults": {
"value": {
"bits": 0,
"uint16": 0,
"uint32": 0,
"float32": 0.0,
"string": " "
},
"action": {
"bits": null,
"uint16": null,
"uint32": null,
"float32": null,
"string": null
}
}
},
"invalid": [],
"write": [
[0, 65535],
[131073, 262143]
],
"bits": [
[0, 65535]
],
"uint16": [
[131073, 262143]
],
"uint32": [
],
"float32": [
],
"string": [
],
"repeat": [
]
}
}
}
29 changes: 22 additions & 7 deletions clickplc/tests/test_driver.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
"""Test the driver correctly parses a tags file and responds with correct data."""
from unittest import mock
import contextlib
import os

import pytest
from pymodbus.server import ModbusSimulatorServer

from clickplc import command_line
from clickplc.mock import ClickPLC
from clickplc import ClickPLC, command_line

ADDRESS = 'fakeip'
# from clickplc.driver import ClickPLC
# Test against pymodbus simulator
ADDRESS = '127.0.0.1'
autouse = True
## Uncomment below to use a real PLC
# ADDRESS = '172.16.0.168'
# autouse = False

@pytest.fixture(scope='session', autouse=autouse)
async def _sim():
"""Start a modbus server simulator."""
serverTask = ModbusSimulatorServer(
modbus_server = 'server',
modbus_device = 'device',
json_file = os.path.join('clickplc', 'tests', 'simulator_setup.json')
)
await serverTask.run_forever(only_start=True)
yield
with contextlib.suppress(NameError):
await serverTask.stop()


@pytest.fixture(scope='session')
Expand Down Expand Up @@ -42,7 +59,6 @@ def expected_tags():
}


@mock.patch('clickplc.ClickPLC', ClickPLC)
def test_driver_cli(capsys):
"""Confirm the commandline interface works without a tags file."""
command_line([ADDRESS])
Expand All @@ -52,7 +68,6 @@ def test_driver_cli(capsys):
assert 'df100' in captured.out


@mock.patch('clickplc.ClickPLC', ClickPLC)
def test_driver_cli_tags(capsys):
"""Confirm the commandline interface works with a tags file."""
command_line([ADDRESS, 'clickplc/tests/plc_tags.csv'])
Expand Down
3 changes: 2 additions & 1 deletion clickplc/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ class AsyncioModbusClient:
def __init__(self, address, timeout=1):
"""Set up communication parameters."""
self.ip = address
port = 5020 if address == '127.0.0.1' else 502 # pymodbus simulator is 127.0.0.1:5020
self.timeout = timeout
self._detect_pymodbus_version()
if self.pymodbus30plus:
self.client = AsyncModbusTcpClient(address, timeout=timeout)
self.client = AsyncModbusTcpClient(address, timeout=timeout, port=port)
else: # 2.x
self.client = ReconnectingAsyncioModbusTcpClient()
self.lock = asyncio.Lock()
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
],
extras_require={
'test': [
'pymodbus[simulator]>=3.0.2',
'pytest',
'pytest-asyncio>=0.23.7,<=0.23.9',
'pytest-cov',
Expand Down

0 comments on commit fcde211

Please sign in to comment.