赞
踩
python实现ModBusTCP协议的server是一件简单的事情,只要通过pymodbus、pyModbusTCP等模块都可以实现,本文采用pymodbus。
相关文章见:
python实现ModBusTCP协议的client-CSDN博客
pymodbus.server中的模块,能够用于用于实现 Modbus 协议的服务器端。以下是每个模块的功能介绍:
(1)ModbusSerialServer: 这个模块提供了一个基于串口的 Modbus 服务器。它允许通过串口与 Modbus 客户端通信。
(2)ModbusTcpServer: 这个模块提供了一个基于 TCP/IP 的 Modbus 服务器。它通过 TCP/IP 网络接口与 Modbus 客户端通信。
(3)ModbusTlsServer: 这个模块提供了一个基于 TLS 加密的 Modbus 服务器。它通过安全的 TLS 连接与 Modbus 客户端通信,确保通信的安全性。
(4)ModbusUdpServer: 这个模块提供了一个基于 UDP 的 Modbus 服务器。与 TCP 不同,UDP 是一种面向无连接的协议,适用于某些特定的网络环境。
(5)ServerAsyncStop: 这个类用于异步服务器的停止信号。通过发送这个信号,可以优雅地停止异步服务器的运行。
(6)ServerStop: 这个类用于同步服务器的停止信号。与 ServerAsyncStop
类似,但用于同步服务器。
(7)StartAsyncSerialServer: 这个函数用于启动一个异步的基于串口的 Modbus 服务器。
(8)StartAsyncTcpServer: 这个函数用于启动一个异步的基于 TCP/IP 的 Modbus 服务器。
(9)StartAsyncTlsServer: 这个函数用于启动一个异步的基于 TLS 加密的 Modbus 服务器。
(10)StartAsyncUdpServer: 这个函数用于启动一个异步的基于 UDP 的 Modbus 服务器。
(11)StartSerialServer: 这个函数用于启动一个同步的基于串口的 Modbus 服务器。
(12)StartTcpServer: 这个函数期望用于启动一个同步的基于 TCP/IP 的 Modbus 服务器。(备注:源码其实是异步的)
(13)StartTlsServer: 这个函数期望用于启动一个同步的基于 TLS 加密的 Modbus 服务器。(备注:源码其实是异步的)
(14)StartUdpServer: 这个函数期望用于启动一个同步的基于 UDP 的 Modbus 服务器。(备注:源码其实是异步的)
这些模块和函数提供了多种不同类型的 Modbus 服务器的实现方式,可以根据具体的需求选择合适的模块和函数来创建和启动 Modbus 服务器。
StartAsyncTcpServer
和 StartTcpServer
是 pymodbus
库中用于启动 Modbus TCP 服务器的两种不同的方法,其主要区别在于同步(Synchronous)和异步(Asynchronous)执行方式。
(1)StartAsyncTcpServer(异步方式):
StartAsyncTcpServer
是一个异步函数,它使用 Python 的 asyncio
模块来实现异步的 Modbus TCP 服务器。在异步编程中,事件循环(event loop)可以处理多个任务,使得程序在等待某些耗时操作(比如 I/O 操作)时不会被阻塞。这意味着它可以同时处理多个客户端连接,提高了服务器的并发性能。
该函数的调用方式是异步的,需要在异步上下文(比如异步函数内部或者异步脚本中)使用。
(2)StartTcpServer(同步方式):
StartTcpServer
是一个同步函数,它使用 Python 的标准同步执行方式,会阻塞当前线程。在同步模式下,每次只能处理一个客户端连接。这意味着服务器只能顺序处理客户端请求,一个接一个地处理。
该函数的调用方式是同步的,可以在任何地方调用。
总之,选择哪种方式取决于你的应用场景。如果需要处理大量并发连接并提高性能,可以选择异步方式;如果简单的同步处理能够满足需求,可以选择同步方式。
本文采用StartAsyncTcpServer,所以他涉及到的模块是StartTcpServer,源码如下:
- def StartTcpServer(**kwargs): # pylint: disable=invalid-name
- """Start and run a serial modbus server."""
- return asyncio.run(StartAsyncTcpServer(**kwargs))
如果要停止异步,需要调用ServerAsyncStop模块。
- import asyncio
- import threading
- import time
- import json
- from pymodbus.server import StartTcpServer, ServerAsyncStop
- from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext
-
-
- if __name__ == "__main__":
- # Modbus TCP服务器的IP地址和端口号
- server_ip = "192.168.1.188"
- port = 502
- station = 1
-
- # 创建一个数据存储区,用于存储从客户端读取的数据
- store = ModbusSlaveContext(
- hr=ModbusSequentialDataBlock(0, [0] * 100)
- )
-
- # 创建一个服务器上下文,用于处理客户端的请求
- context = ModbusServerContext(slaves=store, single=True)
- # 启动ModBusTCP服务器
- # 创建并启动线程(启动异步服务器)
- # StartTcpServer(context=context, address=(server_ip, port))
- modbus_server_thread = threading.Thread(target=StartTcpServer, kwargs=({"context":context, "address":(server_ip, port)}))
- modbus_server_thread.start()
-
- # 设置保持寄存器的0地址的值为s
- # 定义函数参数
- fc_as_hex = 0x03 # 功能码,例如读保持寄存器是"0x03"
- write_address = 0 # 起始地址
- read_address = 10
- read_count = 1
- values = [115] # 触发指令s 要设置的多个值列表,如[10, 20, 30]
-
- # 调用函数,设置0地址为触发指令s
- store.setValues(fc_as_hex, write_address, values)
- # 获取保持寄存器的值并打印
- hr_values = store.getValues(3, read_address, count=read_count)
- print("Hold Register Values:", hr_values)
-
- assert hr_values == [0], print("测试失败!")
-
- time.sleep(10)
-
- try:
- print("停止服务器")
- asyncio.run(ServerAsyncStop()) # 停止服务器
- except:
- pass
上一章节我们说到协议帧的格式,现在我们用上一章节的内容解析一下实际协议帧的情况。
(1)一个完整的收发协议帧
[2023-11-02 10:45:31-315]NET001-发送:[00 23 00 00 00 0b] 01 10 00 00 00 02 04 73 00 00 00 [2023-11-02 10:45:31-317]NET001-接收:[00 23 00 00 00 06] 01 10 00 00 00 02
(2)发送
这条消息的结构可以分解为:
(3)接收
这条消息的结构可以分解为:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。