1515
1616from pymodbus import FramerType
1717from pymodbus .client import AsyncModbusTcpClient as ModbusClient
18+ from pymodbus .datastore import (
19+ ModbusSequentialDataBlock ,
20+ ModbusServerContext ,
21+ ModbusSlaveContext ,
22+ )
1823from pymodbus .exceptions import ModbusIOException
19- from pymodbus .pdu import ExceptionResponse , ModbusPDU
24+ from pymodbus .pdu import ModbusPDU
2025from pymodbus .pdu .bit_message import ReadCoilsRequest
26+ from pymodbus .server import ServerAsyncStop , StartAsyncTcpServer
2127
2228
2329# --------------------------------------------------------------------------- #
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
120122async 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
145161if __name__ == "__main__" :
0 commit comments