0
# Server Operations
1
2
PyModbus provides full-featured Modbus server implementations supporting TCP, UDP, Serial, and TLS transports. Servers can be configured with custom data stores, function handlers, and simulation capabilities for development and testing.
3
4
## Capabilities
5
6
### Server Classes
7
8
Server implementations for different transport protocols with both blocking and async variants.
9
10
```python { .api }
11
class ModbusTcpServer:
12
def __init__(self, context, framer=None, identity=None, address=None,
13
handler=None, allow_reuse_address=False, allow_reuse_port=False,
14
defer_start=False, backlog=20, loop=None, **kwargs): ...
15
def serve_forever(self): ...
16
def server_close(self): ...
17
def shutdown(self): ...
18
19
class ModbusUdpServer:
20
def __init__(self, context, framer=None, identity=None, address=None,
21
handler=None, allow_reuse_address=False, allow_reuse_port=False,
22
defer_start=False, backlog=20, loop=None, **kwargs): ...
23
def serve_forever(self): ...
24
def server_close(self): ...
25
def shutdown(self): ...
26
27
class ModbusSerialServer:
28
def __init__(self, context, framer=None, identity=None, port=None,
29
stopbits=1, bytesize=8, parity='N', baudrate=19200,
30
timeout=1, handle_local_echo=False, ignore_missing_slaves=False,
31
broadcast_enable=False, auto_open=True, auto_close=False, **kwargs): ...
32
def serve_forever(self): ...
33
def server_close(self): ...
34
def shutdown(self): ...
35
36
class ModbusTlsServer:
37
def __init__(self, context, framer=None, identity=None, address=None,
38
sslctx=None, certfile=None, keyfile=None, allow_reuse_address=False,
39
allow_reuse_port=False, defer_start=False, backlog=20, loop=None, **kwargs): ...
40
def serve_forever(self): ...
41
def server_close(self): ...
42
def shutdown(self): ...
43
```
44
45
### Server Start Functions
46
47
Convenience functions for starting servers with simplified configuration.
48
49
```python { .api }
50
def StartTcpServer(context=None, identity=None, address=None, custom_functions=None,
51
**kwargs) -> None:
52
"""
53
Start TCP server (blocking).
54
55
Parameters:
56
- context: ModbusServerContext instance
57
- identity: ModbusDeviceIdentification instance
58
- address: tuple of (host, port), defaults to ('127.0.0.1', 502)
59
- custom_functions: list of custom function handlers
60
- **kwargs: additional server parameters
61
"""
62
63
def StartUdpServer(context=None, identity=None, address=None, custom_functions=None,
64
**kwargs) -> None:
65
"""
66
Start UDP server (blocking).
67
68
Parameters:
69
- context: ModbusServerContext instance
70
- identity: ModbusDeviceIdentification instance
71
- address: tuple of (host, port), defaults to ('127.0.0.1', 502)
72
- custom_functions: list of custom function handlers
73
- **kwargs: additional server parameters
74
"""
75
76
def StartSerialServer(context=None, identity=None, port=None, custom_functions=None,
77
**kwargs) -> None:
78
"""
79
Start Serial server (blocking).
80
81
Parameters:
82
- context: ModbusServerContext instance
83
- identity: ModbusDeviceIdentification instance
84
- port: serial port device (e.g., '/dev/ttyUSB0', 'COM1')
85
- custom_functions: list of custom function handlers
86
- **kwargs: additional serial and server parameters
87
"""
88
89
def StartTlsServer(context=None, identity=None, address=None, sslctx=None,
90
custom_functions=None, **kwargs) -> None:
91
"""
92
Start TLS server (blocking).
93
94
Parameters:
95
- context: ModbusServerContext instance
96
- identity: ModbusDeviceIdentification instance
97
- address: tuple of (host, port), defaults to ('127.0.0.1', 802)
98
- sslctx: SSL context or None for default
99
- custom_functions: list of custom function handlers
100
- **kwargs: additional server parameters
101
"""
102
103
# Asynchronous server start functions
104
async def StartAsyncTcpServer(context=None, identity=None, address=None,
105
custom_functions=None, **kwargs) -> ModbusTcpServer:
106
"""Start async TCP server."""
107
108
async def StartAsyncUdpServer(context=None, identity=None, address=None,
109
custom_functions=None, **kwargs) -> ModbusUdpServer:
110
"""Start async UDP server."""
111
112
async def StartAsyncSerialServer(context=None, identity=None, port=None,
113
custom_functions=None, **kwargs) -> ModbusSerialServer:
114
"""Start async Serial server."""
115
116
async def StartAsyncTlsServer(context=None, identity=None, address=None, sslctx=None,
117
custom_functions=None, **kwargs) -> ModbusTlsServer:
118
"""Start async TLS server."""
119
```
120
121
### Server Stop Functions
122
123
Functions for stopping running servers.
124
125
```python { .api }
126
def ServerStop() -> None:
127
"""Stop currently running synchronous server."""
128
129
async def ServerAsyncStop() -> None:
130
"""Stop currently running asynchronous server."""
131
```
132
133
### Server Base Classes
134
135
Base classes providing common server functionality.
136
137
```python { .api }
138
class ModbusBaseServer:
139
def __init__(self, context, framer=None, identity=None, **kwargs): ...
140
def serve_forever(self): ...
141
def server_close(self): ...
142
def shutdown(self): ...
143
def process_request(self, request, client): ...
144
def validate_device_id(self, device_id): ...
145
```
146
147
### Simulator Server
148
149
HTTP-based simulator server for testing and development.
150
151
```python { .api }
152
class ModbusSimulatorServer:
153
def __init__(self, modbus_server=None, modbus_device=None, http_host="localhost",
154
http_port=8080, json_file=None, custom_actions_module=None,
155
web_app_path=None): ...
156
async def run_forever(self, only_start=False): ...
157
def stop(self): ...
158
def build_html(self, html_template, json_data): ...
159
```
160
161
### Server Context Management
162
163
Classes for managing server data and device contexts.
164
165
```python { .api }
166
class ModbusServerContext:
167
def __init__(self, device_default=None, single=False, **kwargs): ...
168
def __getitem__(self, device_id): ...
169
def __setitem__(self, device_id, context): ...
170
def __delitem__(self, device_id): ...
171
def __contains__(self, device_id): ...
172
173
class ModbusDeviceContext:
174
def __init__(self, co=None, di=None, hr=None, ir=None, zero_mode=False): ...
175
def validate(self, fx, address, count=1): ...
176
def getValues(self, fx, address, count=1): ...
177
def setValues(self, fx, address, values): ...
178
179
class ModbusBaseDeviceContext:
180
def decode(self, fx): ...
181
def encode(self, fx): ...
182
def reset(self): ...
183
def register(self, fx, slave_id=0x00, func=None): ...
184
def validate(self, fx, address, count=1): ...
185
def getValues(self, fx, address, count=1): ...
186
def setValues(self, fx, address, values): ...
187
```
188
189
## Usage Examples
190
191
### Simple TCP Server
192
193
```python
194
from pymodbus.server import StartTcpServer
195
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
196
197
# Create data stores for different data types
198
store = ModbusSequentialDataBlock(0, [0] * 100)
199
200
# Create device context with data stores
201
context = ModbusDeviceContext(
202
co=store, # coils
203
di=store, # discrete inputs
204
hr=store, # holding registers
205
ir=store # input registers
206
)
207
208
# Create server context
209
server_context = ModbusServerContext(device_default=context, single=True)
210
211
# Start TCP server (blocking)
212
StartTcpServer(
213
context=server_context,
214
address=('127.0.0.1', 5020)
215
)
216
```
217
218
### Multi-Device Server
219
220
```python
221
from pymodbus.server import StartTcpServer
222
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
223
224
# Create data stores for device 1
225
device1_store = ModbusSequentialDataBlock(0, [10, 20, 30, 40, 50])
226
device1_context = ModbusDeviceContext(
227
co=device1_store,
228
di=device1_store,
229
hr=device1_store,
230
ir=device1_store
231
)
232
233
# Create data stores for device 2
234
device2_store = ModbusSequentialDataBlock(0, [100, 200, 300, 400, 500])
235
device2_context = ModbusDeviceContext(
236
co=device2_store,
237
di=device2_store,
238
hr=device2_store,
239
ir=device2_store
240
)
241
242
# Create server context with multiple devices
243
server_context = ModbusServerContext(single=False)
244
server_context[1] = device1_context # Device ID 1
245
server_context[2] = device2_context # Device ID 2
246
247
# Start server
248
StartTcpServer(context=server_context, address=('0.0.0.0', 502))
249
```
250
251
### Server with Device Identity
252
253
```python
254
from pymodbus.server import StartTcpServer
255
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
256
from pymodbus import ModbusDeviceIdentification
257
258
# Create data store
259
store = ModbusSequentialDataBlock(0, [0] * 100)
260
context = ModbusDeviceContext(co=store, di=store, hr=store, ir=store)
261
server_context = ModbusServerContext(device_default=context, single=True)
262
263
# Configure device identity
264
identity = ModbusDeviceIdentification()
265
identity.VendorName = 'PyModbus'
266
identity.ProductCode = 'PM'
267
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
268
identity.ProductName = 'PyModbus Server'
269
identity.ModelName = 'PyModbus Server'
270
identity.MajorMinorRevision = '3.11.1'
271
272
# Start server with identity
273
StartTcpServer(
274
context=server_context,
275
identity=identity,
276
address=('127.0.0.1', 502)
277
)
278
```
279
280
### Async TCP Server
281
282
```python
283
import asyncio
284
from pymodbus.server import StartAsyncTcpServer, ServerAsyncStop
285
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
286
287
async def run_async_server():
288
# Create data store
289
store = ModbusSequentialDataBlock(0, list(range(100)))
290
context = ModbusDeviceContext(co=store, di=store, hr=store, ir=store)
291
server_context = ModbusServerContext(device_default=context, single=True)
292
293
# Start async server
294
server = await StartAsyncTcpServer(
295
context=server_context,
296
address=('127.0.0.1', 5020)
297
)
298
299
try:
300
# Server runs until interrupted
301
await asyncio.Event().wait()
302
except KeyboardInterrupt:
303
print("Server interrupted, shutting down...")
304
finally:
305
await ServerAsyncStop()
306
307
# Run async server
308
asyncio.run(run_async_server())
309
```
310
311
### Serial Server
312
313
```python
314
from pymodbus.server import StartSerialServer
315
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
316
from pymodbus import FramerType
317
318
# Create data store
319
store = ModbusSequentialDataBlock(0, [0] * 100)
320
context = ModbusDeviceContext(co=store, di=store, hr=store, ir=store)
321
server_context = ModbusServerContext(device_default=context, single=True)
322
323
# Start serial server
324
StartSerialServer(
325
context=server_context,
326
port='/dev/ttyUSB0', # Linux
327
# port='COM1', # Windows
328
framer=FramerType.RTU,
329
baudrate=9600,
330
bytesize=8,
331
parity='N',
332
stopbits=1,
333
timeout=1
334
)
335
```
336
337
### Server with Custom Functions
338
339
```python
340
from pymodbus.server import StartTcpServer
341
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
342
from pymodbus.pdu import ModbusPDU
343
from pymodbus import ModbusDeviceIdentification
344
345
# Define custom function
346
class CustomFunction(ModbusPDU):
347
function_code = 0x40 # Custom function code
348
349
def __init__(self, **kwargs):
350
ModbusPDU.__init__(self, **kwargs)
351
352
def encode(self):
353
return b''
354
355
def decode(self, data):
356
pass
357
358
def execute(self, context):
359
# Custom function logic
360
return CustomFunctionResponse()
361
362
class CustomFunctionResponse(ModbusPDU):
363
function_code = 0x40
364
365
def __init__(self, **kwargs):
366
ModbusPDU.__init__(self, **kwargs)
367
368
def encode(self):
369
return b'Custom response'
370
371
# Create server context
372
store = ModbusSequentialDataBlock(0, [0] * 100)
373
context = ModbusDeviceContext(co=store, di=store, hr=store, ir=store)
374
server_context = ModbusServerContext(device_default=context, single=True)
375
376
# Start server with custom function
377
StartTcpServer(
378
context=server_context,
379
custom_functions=[CustomFunction],
380
address=('127.0.0.1', 502)
381
)
382
```
383
384
### TLS Server
385
386
```python
387
import ssl
388
from pymodbus.server import StartTlsServer
389
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
390
391
# Create SSL context
392
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
393
ssl_context.load_cert_chain(certfile="server.crt", keyfile="server.key")
394
395
# Create data store
396
store = ModbusSequentialDataBlock(0, [0] * 100)
397
context = ModbusDeviceContext(co=store, di=store, hr=store, ir=store)
398
server_context = ModbusServerContext(device_default=context, single=True)
399
400
# Start TLS server
401
StartTlsServer(
402
context=server_context,
403
sslctx=ssl_context,
404
address=('127.0.0.1', 802)
405
)
406
```
407
408
### Simulator Server
409
410
```python
411
import asyncio
412
from pymodbus.server import ModbusSimulatorServer
413
414
async def run_simulator():
415
# Create simulator server
416
simulator = ModbusSimulatorServer(
417
http_host="localhost",
418
http_port=8080,
419
json_file="simulation_config.json"
420
)
421
422
try:
423
# Start simulator (includes HTTP interface)
424
await simulator.run_forever()
425
except KeyboardInterrupt:
426
print("Stopping simulator...")
427
simulator.stop()
428
429
# Run simulator
430
asyncio.run(run_simulator())
431
```
432
433
### Server Configuration Options
434
435
```python
436
from pymodbus.server import StartTcpServer
437
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusDeviceContext
438
439
# Create data store
440
store = ModbusSequentialDataBlock(0, [0] * 100)
441
context = ModbusDeviceContext(co=store, di=store, hr=store, ir=store)
442
server_context = ModbusServerContext(device_default=context, single=True)
443
444
# Start server with various configuration options
445
StartTcpServer(
446
context=server_context,
447
address=('0.0.0.0', 502),
448
allow_reuse_address=True,
449
allow_reuse_port=True,
450
defer_start=False,
451
backlog=20,
452
ignore_missing_slaves=True,
453
broadcast_enable=False,
454
timeout=1
455
)
456
```