Skip to content

Commit 46879e0

Browse files
authored
Update custom_msg example to include server. (#2527)
1 parent af53830 commit 46879e0

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

doc/source/examples.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,11 @@ Source: :github:`examples/client_calls.py`
7979
:noindex:
8080

8181

82-
Client custom message
83-
^^^^^^^^^^^^^^^^^^^^^
84-
Source: :github:`examples/client_custom_msg.py`
82+
Custom message
83+
^^^^^^^^^^^^^^
84+
Source: :github:`examples/custom_msg.py`
8585

86-
.. automodule:: examples.client_custom_msg
86+
.. automodule:: examples.custom_msg
8787
:undoc-members:
8888
:noindex:
8989

examples/client_custom_msg.py renamed to examples/custom_msg.py

+31-15
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@
1515

1616
from pymodbus import FramerType
1717
from pymodbus.client import AsyncModbusTcpClient as ModbusClient
18+
from pymodbus.datastore import (
19+
ModbusSequentialDataBlock,
20+
ModbusServerContext,
21+
ModbusSlaveContext,
22+
)
1823
from pymodbus.exceptions import ModbusIOException
19-
from pymodbus.pdu import ExceptionResponse, ModbusPDU
24+
from pymodbus.pdu import ModbusPDU
2025
from pymodbus.pdu.bit_message import ReadCoilsRequest
26+
from pymodbus.server import ServerAsyncStop, StartAsyncTcpServer
2127

2228

2329
# --------------------------------------------------------------------------- #
@@ -31,7 +37,7 @@
3137
# --------------------------------------------------------------------------- #
3238

3339

34-
class CustomModbusPDU(ModbusPDU):
40+
class CustomModbusResponse(ModbusPDU):
3541
"""Custom modbus response."""
3642

3743
function_code = 55
@@ -73,7 +79,7 @@ def __init__(self, address=None, slave=1, transaction=0):
7379
"""Initialize."""
7480
super().__init__(dev_id=slave, transaction_id=transaction)
7581
self.address = address
76-
self.count = 16
82+
self.count = 2
7783

7884
def encode(self):
7985
"""Encode."""
@@ -83,14 +89,10 @@ def decode(self, data):
8389
"""Decode."""
8490
self.address, self.count = struct.unpack(">HH", data)
8591

86-
def execute(self, context):
92+
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
8793
"""Execute."""
88-
if not 1 <= self.count <= 0x7D0:
89-
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
90-
if not context.validate(self.function_code, self.address, self.count):
91-
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
92-
values = context.getValues(self.function_code, self.address, self.count)
93-
return CustomModbusPDU(values)
94+
_ = context
95+
return CustomModbusResponse()
9496

9597

9698
# --------------------------------------------------------------------------- #
@@ -119,14 +121,25 @@ def __init__(self, address, slave=1, transaction=0):
119121

120122
async def main(host="localhost", port=5020):
121123
"""Run versions of read coil."""
124+
store = ModbusServerContext(slaves=ModbusSlaveContext(
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+
)
132+
task = asyncio.create_task(StartAsyncTcpServer(
133+
context=store,
134+
address=(host, port),
135+
custom_functions=[CustomRequest])
136+
)
137+
await asyncio.sleep(0.1)
122138
async with ModbusClient(host=host, port=port, framer=FramerType.SOCKET) as client:
123139
await client.connect()
124140

125-
# create a response object to control it works
126-
CustomModbusPDU()
127-
128-
# new modbus function code.
129-
client.register(CustomModbusPDU)
141+
# add new modbus function code.
142+
client.register(CustomModbusResponse)
130143
slave=1
131144
request1 = CustomRequest(32, slave=slave)
132145
try:
@@ -140,6 +153,9 @@ async def main(host="localhost", port=5020):
140153
request2 = Read16CoilsRequest(32, slave)
141154
result = await client.execute(False, request2)
142155
print(result)
156+
await ServerAsyncStop()
157+
task.cancel()
158+
await task
143159

144160

145161
if __name__ == "__main__":

test/examples/test_examples.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
from examples.client_async_calls import main as main_client_async_calls
1616
from examples.client_calls import main as main_client_calls
1717
from examples.client_calls import template_call
18-
from examples.client_custom_msg import main as main_custom_client
1918
from examples.client_payload import main as main_payload_calls
19+
from examples.custom_msg import main as main_custom_client
2020
from examples.datastore_simulator_share import main as main_datastore_simulator_share
2121
from examples.message_parser import main as main_parse_messages
2222
from examples.server_async import setup_server
@@ -149,13 +149,11 @@ async def test_client_calls_errors(self, mock_server):
149149
await run_async_client(client, modbus_calls=template_call)
150150
client.close()
151151

152-
async def test_custom_msg(
153-
self, mock_server, use_comm, use_framer, use_port, use_host
154-
):
152+
async def test_custom_msg(self, use_comm, use_port, use_framer, use_host):
155153
"""Test client with custom message."""
156-
if use_comm != "tcp" or use_framer != "socket":
154+
_ = use_framer
155+
if use_comm != "tcp":
157156
return
158-
assert mock_server
159157
await main_custom_client(port=use_port, host=use_host)
160158

161159
async def test_payload(self, mock_clc, mock_cls):

0 commit comments

Comments
 (0)