Skip to content

Commit 0f4dba4

Browse files
authored
Update server examples to use SimData/SimDevice. (#2893)
1 parent c3ec442 commit 0f4dba4

21 files changed

Lines changed: 132 additions & 206 deletions

check_ci.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ codespell
99
ruff check --fix --exit-non-zero-on-fix .
1010
pylint --recursive=y examples pymodbus test
1111
zuban check pymodbus examples test
12+
if [ $1 ]; then
13+
exit 1
14+
fi
1215
pytest -x --cov --numprocesses auto
1316
echo "Ready to push"

examples/client_async.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
try:
3737
import helper # type: ignore[import-not-found]
3838
except ImportError:
39-
print("*** ERROR --> THIS EXAMPLE needs the example directory, please see \n\
39+
print("*** ERROR --> THIS EXAMPLE needs to be run in the example directory, please see \n\
4040
https://pymodbus.readthedocs.io/en/latest/source/examples.html\n\
4141
for more information.")
4242
sys.exit(-1)

examples/client_async_calls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
try:
4242
import client_async # type: ignore[import-not-found]
4343
except ImportError:
44-
print("*** ERROR --> THIS EXAMPLE needs the example directory, please see \n\
44+
print("*** ERROR --> THIS EXAMPLE needs to be run in the example directory, please see \n\
4545
https://pymodbus.readthedocs.io/en/latest/source/examples.html\n\
4646
for more information.")
4747
sys.exit(-1)

examples/client_calls.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
try:
3939
import client_sync # type: ignore[import-not-found]
4040
except ImportError:
41-
print("*** ERROR --> THIS EXAMPLE needs the example directory, please see \n\
41+
print("*** ERROR --> THIS EXAMPLE needs to be run in the example directory, please see \n\
4242
https://pymodbus.readthedocs.io/en/latest/source/examples.html\n\
4343
for more information.")
4444
sys.exit(-1)

examples/client_sync.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
try:
4040
import helper # type: ignore[import-not-found]
4141
except ImportError:
42-
print("*** ERROR --> THIS EXAMPLE needs the example directory, please see \n\
42+
print("*** ERROR --> THIS EXAMPLE needs to be run in the example directory, please see \n\
4343
https://pymodbus.readthedocs.io/en/latest/source/examples.html\n\
4444
for more information.")
4545
sys.exit(-1)

examples/custom_msg.py

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,19 @@
1515

1616
from pymodbus import FramerType
1717
from pymodbus.client import AsyncModbusTcpClient as ModbusClient
18-
from pymodbus.datastore import (
19-
ModbusDeviceContext,
20-
ModbusSequentialDataBlock,
21-
ModbusServerContext,
22-
)
18+
from pymodbus.datastore import ModbusServerContext
2319
from pymodbus.exceptions import ModbusIOException
2420
from pymodbus.pdu import ModbusPDU
2521
from pymodbus.pdu.bit_message import ReadCoilsRequest
2622
from pymodbus.server import ServerAsyncStop, StartAsyncTcpServer
23+
from pymodbus.simulator import DataType, SimData, SimDevice
2724

2825

2926
# --------------------------------------------------------------------------- #
3027
# create your custom message
3128
# --------------------------------------------------------------------------- #
3229
# The following is simply a read coil request that always reads 16 coils.
33-
# Since the function code is already registered with the decoder factory,
30+
# Since the function code is already registered with the decoder,
3431
# this will be decoded as a read coil response. If you implement a new
3532
# method that is not currently implemented, you must register the request
3633
# and response with the active DecodePDU object.
@@ -121,16 +118,8 @@ def __init__(self, address, device_id=1, transaction=0):
121118

122119
async def main(host="localhost", port=5020):
123120
"""Run versions of read coil."""
124-
store = ModbusServerContext(devices=ModbusDeviceContext(
125-
di=ModbusSequentialDataBlock(0, [17] * 100),
126-
co=ModbusSequentialDataBlock(0, [17] * 100),
127-
hr=ModbusSequentialDataBlock(0, [17] * 100),
128-
ir=ModbusSequentialDataBlock(0, [17] * 100),
129-
),
130-
single=True
131-
)
132121
task = asyncio.create_task(StartAsyncTcpServer(
133-
context=store,
122+
context=SimDevice(0, SimData(0, datatype=DataType.REGISTERS, values=[17]*100)),
134123
address=(host, port),
135124
custom_pdu=[CustomRequest])
136125
)

examples/helper.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,6 @@ def get_commandline(server: bool = False, description: str | None = None, extras
6767
type=str,
6868
)
6969
if server:
70-
parser.add_argument(
71-
"--store",
72-
choices=["sequential", "sparse", "factory", "none"],
73-
help="set type of datastore",
74-
default="sequential",
75-
type=str,
76-
)
7770
parser.add_argument(
7871
"--device_ids",
7972
help="set number of device_ids, default is 0 (any)",

examples/package_test_tool.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,8 @@
5555
ModbusException,
5656
pymodbus_apply_logging_config,
5757
)
58-
from pymodbus.datastore import (
59-
ModbusDeviceContext,
60-
ModbusSequentialDataBlock,
61-
ModbusServerContext,
62-
)
6358
from pymodbus.logging import Log
59+
from pymodbus.simulator import DataType, SimData, SimDevice
6460
from pymodbus.transport import NULLMODEM_HOST, CommParams, CommType, ModbusProtocol
6561

6662

@@ -149,13 +145,7 @@ class ServerTester: # pylint: disable=too-few-public-methods
149145
def __init__(self, comm: CommType):
150146
"""Initialize runtime tester."""
151147
self.comm = comm
152-
self.store = ModbusDeviceContext(
153-
di=ModbusSequentialDataBlock(0, [17] * 100),
154-
co=ModbusSequentialDataBlock(0, [17] * 100),
155-
hr=ModbusSequentialDataBlock(0, [17] * 100),
156-
ir=ModbusSequentialDataBlock(0, [17] * 100),
157-
)
158-
self.context = ModbusServerContext(devices=self.store, single=True)
148+
self.context = SimDevice(0, SimData(0, datatype=DataType.REGISTERS, values=[17]*100))
159149
self.identity = ModbusDeviceIdentification(
160150
info_name={"VendorName": "VendorName"}
161151
)

examples/server_async.py

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
server_async.py [-h] [--comm {tcp,udp,serial,tls}]
99
[--framer {ascii,rtu,socket,tls}]
1010
[--log {critical,error,warning,info,debug}]
11-
[--port PORT] [--store {sequential,sparse,factory,none}]
11+
[--port PORT]
1212
[--device_ids DEVICE_IDS]
1313
1414
-h, --help
@@ -22,8 +22,6 @@
2222
-p, --port PORT
2323
set port
2424
set serial device baud rate
25-
--store {sequential,sparse,factory,none}
26-
set datastore type
2725
--device_ids DEVICE IDs
2826
set list of devices to respond to
2927
@@ -35,32 +33,25 @@
3533
import asyncio
3634
import logging
3735
import sys
38-
from collections.abc import Callable
39-
from typing import Any
4036

4137

4238
try:
4339
import helper # type: ignore[import-not-found]
4440
except ImportError:
45-
print("*** ERROR --> THIS EXAMPLE needs the example directory, please see \n\
41+
print("*** ERROR --> THIS EXAMPLE needs to be run in the example directory, please see \n\
4642
https://pymodbus.readthedocs.io/en/latest/source/examples.html\n\
4743
for more information.")
4844
sys.exit(-1)
4945

5046
from pymodbus import ModbusDeviceIdentification
5147
from pymodbus import __version__ as pymodbus_version
52-
from pymodbus.datastore import (
53-
ModbusDeviceContext,
54-
ModbusSequentialDataBlock,
55-
ModbusServerContext,
56-
ModbusSparseDataBlock,
57-
)
5848
from pymodbus.server import (
5949
StartAsyncSerialServer,
6050
StartAsyncTcpServer,
6151
StartAsyncTlsServer,
6252
StartAsyncUdpServer,
6353
)
54+
from pymodbus.simulator import DataType, SimData, SimDevice
6455

6556

6657
_logger = logging.getLogger(__file__)
@@ -70,53 +61,17 @@
7061
def setup_server(description=None, context=None, cmdline=None):
7162
"""Run server setup."""
7263
args = helper.get_commandline(server=True, description=description, cmdline=cmdline)
73-
if context:
64+
if context: # pragma: no cover
7465
args.context = context
75-
datablock: Callable[[], Any]
76-
if not args.context:
66+
if not args.context: # pragma: no cover
7767
_logger.info("### Create datastore")
78-
# The datastores only respond to the addresses that are initialized
79-
# If you initialize a DataBlock to addresses of 0x00 to 0xFF, a request to
80-
# 0x100 will respond with an invalid address exception.
81-
# This is because many devices exhibit this kind of behavior (but not all)
82-
if args.store == "sequential": # pragma: no cover
83-
# Continuing, use a sequential block without gaps.
84-
datablock = lambda : ModbusSequentialDataBlock(0x00, [17] * 100) # pylint: disable=unnecessary-lambda-assignment
85-
elif args.store == "sparse": # pragma: no cover
86-
# Continuing, or use a sparse DataBlock which can have gaps
87-
datablock = lambda : ModbusSparseDataBlock({0x00: 0, 0x05: 1}) # pylint: disable=unnecessary-lambda-assignment
88-
elif args.store == "factory" or True: # pragma: no cover # pylint: disable=condition-evals-to-constant
89-
# Alternately, use the factory methods to initialize the DataBlocks
90-
# or simply do not pass them to have them initialized to 0x00 on the
91-
# full address range::
92-
datablock = lambda : ModbusSequentialDataBlock(0x00, [0x00] * 65536) # pylint: disable=unnecessary-lambda-assignment
9368

69+
# Build data storage
9470
if args.device_ids > 1: # pragma: no cover
95-
# The server then makes use of a server context that allows the server
96-
# to respond with different device contexts for different device ids.
97-
# By default it will return the same context for every device id supplied
98-
# (broadcast mode).
99-
# However, this can be overloaded by setting the single flag to False and
100-
# then supplying a dictionary of device id to context mapping::
101-
context = {
102-
device_id : ModbusDeviceContext(
103-
di=datablock(),
104-
co=datablock(),
105-
hr=datablock(),
106-
ir=datablock(),
107-
)
108-
for device_id in range(args.device_ids)
109-
}
110-
111-
single = False
71+
args.context = [SimDevice(device_id, SimData(0, datatype=DataType.REGISTERS, values=[17]*100))
72+
for device_id in range(args.device_ids)]
11273
else:
113-
context = ModbusDeviceContext(
114-
di=datablock(), co=datablock(), hr=datablock(), ir=datablock()
115-
)
116-
single = True
117-
118-
# Build data storage
119-
args.context = ModbusServerContext(devices=context, single=single)
74+
args.context = SimDevice(0, SimData(0, datatype=DataType.REGISTERS, values=[17]*100))
12075

12176
# ----------------------------------------------------------------------- #
12277
# initialize the server information

examples/server_hook.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,15 @@
1111
import sys
1212

1313
from pymodbus import FramerType, pymodbus_apply_logging_config
14-
from pymodbus.datastore import (
15-
ModbusDeviceContext,
16-
ModbusSequentialDataBlock,
17-
ModbusServerContext,
18-
)
1914
from pymodbus.pdu import ModbusPDU
2015
from pymodbus.server import ModbusTcpServer
16+
from pymodbus.simulator import DataType, SimData, SimDevice
2117

2218

2319
try:
2420
import helper # type: ignore[import-not-found]
2521
except ImportError:
26-
print("*** ERROR --> THIS EXAMPLE needs the example directory, please see \n\
22+
print("*** ERROR --> THIS EXAMPLE needs to be run in the example directory, please see \n\
2723
https://pymodbus.readthedocs.io/en/latest/source/examples.html\n\
2824
for more information.")
2925
sys.exit(-1)
@@ -57,16 +53,9 @@ async def setup(self, cmdline):
5753
"""Prepare server."""
5854
args = helper.get_commandline(server=True, description="server hooks", cmdline=cmdline)
5955
pymodbus_apply_logging_config(logging.DEBUG)
60-
datablock = ModbusSequentialDataBlock(0x00, [17] * 100)
61-
context = ModbusServerContext(
62-
devices=ModbusDeviceContext(
63-
di=datablock, co=datablock, hr=datablock, ir=datablock
64-
),
65-
single=True,
66-
)
6756
address: tuple[str, int] = (args.host if args.host else "", args.port if args.port else 0)
6857
self.server = ModbusTcpServer(
69-
context,
58+
SimDevice(0, SimData(0, datatype=DataType.REGISTERS, values=[17]*100)),
7059
framer=FramerType.SOCKET,
7160
identity=None,
7261
address=address,

0 commit comments

Comments
 (0)