python实现ModBusTCP协议的server

python实现ModBusTCP协议的server是一件简单的事情,只要通过pymodbus、pyModbusTCP等模块都可以实现,本文采用pymodbus。

相关文章见:

python实现ModBusTCP协议的client-CSDN博客

一、了解pymodbus的Server

1、pymodbus.server的模块

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 服务器。

2、模块的选用

StartAsyncTcpServerStartTcpServerpymodbus 库中用于启动 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模块。

二、一个Demo

1、服务端读写自身的保持寄存器的示例

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

2、实际协议帧解析

上一章节我们说到协议帧的格式,现在我们用上一章节的内容解析一下实际协议帧的情况。

(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)发送

这条消息的结构可以分解为:

  • [00 23 00 00 00 0b]: 帧头,pymodbus自动封装好,不用自己写,表示消息的起始标志和长度。依次包含事务标识符(2字节协议标识符(2字节长度字段(2字节
  • 01: 请求目标站号。
  • 10: 命令码(功能码),这里表示写入多个寄存器。
  • 00 00: 请求的寄存器起始地址。
  • 00 02: 请求的寄存器数量。
  • 04: 请求数据的字节数。
  • 73 00 00 00: 具体的请求数据,以十六进制表示。

(3)接收

这条消息的结构可以分解为:

  • [00 23 00 00 00 06]: 帧头,表示消息的起始标志和长度。
  • 01: 请求目标站号。
  • 10: 命令码(功能码),这里表示写入多个寄存器。
  • 00 00: 请求的寄存器起始地址。
  • 00 02: 请求的寄存器数量。
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python可以使用pymodbus库来实现Modbus TCP通信。pymodbus库是一个功能强大的库,可以轻松解决工业通信中的各种问题。例如,可以使用pymodbus库进行Modbus TCP仿真,实现PC端读取PLC或工业设备的Modbus变量\[1\]。此外,还可以使用Python编写程序来测试Modbus TCP网关设备,以实现与现场的Modbus RTU协议的仪表设备和IO设备的通信\[2\]。 在Python实现Modbus TCP通信的示例代码如下所示\[3\]: ```python from pymodbus.server.sync import StartTcpServer from pymodbus.datastore import ModbusSequentialDataBlock, ModbusServerContext, ModbusSlaveContext from pymodbus.version import version # 创建数据块 datablock = ModbusSequentialDataBlock.create() # 创建Modbus从机上下文 context = ModbusSlaveContext(di=datablock, co=datablock, hr=datablock, ir=datablock) # 是否只有一个从机 single = True # 创建数据存储 store = ModbusServerContext(slaves=context, single=single) if __name__ == '__main__': address = ("0.0.0.0", 503) StartTcpServer(context=store, address=address, allow_reuse_address=True) ``` 这段代码创建了一个Modbus TCP服务器,可以监听指定的地址和端口。通过修改数据块和上下文,可以实现对不同类型的Modbus寄存器进行读写操作。 总结起来,使用Python的pymodbus库可以方便地实现Modbus TCP通信,并且可以根据具体需求进行灵活的配置和扩展。 #### 引用[.reference_title] - *1* *3* [python使用pymodbus库进行modbus tcp通信](https://blog.csdn.net/brandon_l/article/details/127169641)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [用Python实现ModbusTcp协议](https://blog.csdn.net/silencestarsky/article/details/123678669)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion King

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值