modbus_tcp的实现 through python.

0.引言

当前科技似乎处于加速发展期,各个模块都在快速迭代,迭代的速度会让既有的一些经验产生问题,在用python实现modbus_tcp协议时,网上流传的一些代码中import语句会出现问题。导致pymodbus模块用起来很不好用。

这个原因出在一个子模块的命名上。

pymodbus为了区分同步和异步操作,使用了sync和async作为一整个子模块的分支节点名。然后因为asyn是python的关键字,然后呢,python发现了类似的问题,在3.7附近的某个版本,把这个问题改掉了。但是 pymodbus自己同样做了规避。它也改了,直接取消了这两个分支节点。将代码上移。然后既有的一些代码就都会在import阶段就会报错。

用于物联网的数据传输的这些协议,是协议设计的范本。建议通读相关的原始协议细节。吃透。

1. 示例:写寄存器区域0x10指令的实现

correct code after Dec12,2023

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import struct
from pymodbus.client import ModbusTcpClient

# modbus_tcp 0x10 cmd
def gpModbusTcpWriteRegisters(SERVER_HOST, SERVER_PORT, base_addr, u16arrayInBigEndiant):
    # Create a Modbus TCP client
    client = ModbusTcpClient(SERVER_HOST, SERVER_PORT)

    # Connect to the Modbus TCP server
    client.connect()

    # Write to a range of holding registers 
    slave_address = 1
    response = client.write_registers(base_addr, u16arrayInBigEndiant, slave_address)
    if response.isError():
        print('Write error:', response)
    else:
        print('Write successful')

    # Disconnect from the Modbus TCP server
    client.close()

#sample frame and comments
'''
frame of 0x10 write holding registers:(write to 0x1000, 40 registers = 80Bytes)
去:
00 01 00 00 00 57 01 10 10 00 00 28 50 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 
回:
00 01 00 00 00 06 01 10 10 00 00 28 
            ~~~~~ 06字节(这是协议载荷)
                              ~~~~~ 0x28=40个寄存器(这是协议载荷)

去帧注释:
00 01:事务标识符(Transaction Identifier),用于标识通信的不同事务。
00 00:协议标识符(Protocol Identifier),用于指定使用的 Modbus 协议。
00 57:消息长度(Length),表示请求帧中除了事务标识符和协议标识符之外的字节数。即前六字节后的所有字节和。
01:单元标识符(Unit Identifier),用于指定 Modbus 设备的地址。
10:功能码(Function Code),表示该请求是写多个保持寄存器的请求。
10 00:起始地址(Starting Address),指定要写入的保持寄存器的起始地址。
00 28:寄存器数量(Quantity of Registers),指定要写入的连续保持寄存器的数量。
50:后续数据长度(Byte Count),表示紧随该字节之后的写入数据的字节数。(注意:0x50+0x07=0x57=消息长度(Length))
3F 99:写入数据,表示要写入的第一个保持寄存器的值。3F 99 99 9A = float(1.2)
99 9A:写入数据,表示要写入的第二个保持寄存器的值。
BF 99:写入数据,表示要写入的第三个保持寄存器的值。BF 99 99 9A = float(-1.2)
99 9A:写入数据,表示要写入的第四个保持寄存器的值。
....

注1:modbus_tcp无需校验,因为tcp协议会保证正确性。所以尾部没有追加的校验位。
注2:modbus_tcp没有加密和登陆机制,最简单的实现,可以使用向特定寄存器位置写入Magic Word实现,英文似乎称之为Kick off。
注3:计数器:
     (byte.offset04) 00 57 是字节。(它是帧载荷)
     (byte.offset10) 00 28 是寄存器。(这是协议载荷)
     (byte.offset12) 50 是字节。(这是帧载荷)
    
'''

上面是当前有效的命令0x10,区段寄存器写入的代码。其他依此类推。

Modbus协议遵从大端模式,如果自己整理寄存器数据,建议设置为大端模式,避免不必要的三方调试开销:

def floatArray2U16Array(float_array):
    byte_array = bytes([b for f in float_array for b in bytearray(struct.pack('>f', f))])
    u16_array = [int.from_bytes(byte_array[i:i+2], 'big', signed=False) for i in range(0, len(byte_array), 2)]
    return u16_array

因为Modbus每个寄存器是16位,上面将floatArray转为能够供WriteRegisters使用的ushort数组的过程。其他的数据格式以此类推。

2.0x03 读寄存器区域(写寄存器区域0x10的逆操作)

frame of 0x03帧 及其回应帧
去:00 01 00 00 00 06 01 03 00 00 00 14 
注3:去帧的的计数器 
     (byte.offset04) 00 06 是字节。(它是帧载荷)
     (byte.offset10) 00 14 是寄存器数量: = 20(0x0014 = 20)个寄存器,(这是协议载荷)

回:00 01 00 00 00 2B 01 03 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
注4:回帧的计数器都是字节:
      (byte.offset04)00 2B 是字节;(它是帧载荷)
      (byte.offset08)28 也是字节,(它是帧载荷)

附录A 故障纠错

Modbus调试过程中最容易出现问题有这么几个:

  • 各种计数值的单位,是字节还是寄存器数量。
  • 是否加校验位。
  • 设备id.

A1可直接用于调试的测帧

 A1.1 图例和数据识读

00 57,这是字节尺寸,同一个帧的字节尺寸要彼此匹配。

10 00,这是寄存器地址,可能涉及回应帧之间的匹配。

00 28,这是寄存器数量,可能涉及回应帧字节尺寸和寄存器数量之间的匹配;当前帧字节尺寸的匹配。

  • 字节顺序Offset 04的两个字节,= 整个数据帧长度-6.即帧头6字节以后的所有字节数量。它只和当前待发送的数据帧尺寸有关。
  • 在命令帧之后,真正的寄存器数据之前,还有一个字节长度。这个长度仅仅与数据区段的字节长度有关。仅仅与当前帧有关。

A1.2 0x10 区段寄存器写

  1. 去:
    00 01 00 00 00 57 01 10 10 00 00 28 50 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 3F 99 99 9A BF 99 99 9A 
  2. 回:
    00 01 00 00 00 06 01 10 10 00 00 28 

A1.3 0x03 区段寄存器读

  1. 去:
    00 01 00 00 00 06 01 03 00 00 00 14
  2. 回:
    00 01 00 00 00 2B 01 03 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

附录B 一个测试用的modbus_tcp服务器

pymodbus目前似乎在尝试把服务器功能再次封装。而不是通过直接封装在pymodbus里的StartAsyncTcpServer来实现。当前的doc甚至把这些函数的传入参数隐藏了起来。

注意:pyModbusTCP是一个独立的组件。

#!/usr/bin/env python3

"""
Modbus/TCP server
~~~~~~~~~~~~~~~~~

Run this as root to listen on TCP privileged ports (<= 1024).

Add "--host 0.0.0.0" to listen on all available IPv4 addresses of the host.
$ sudo ./server.py --host 0.0.0.0
"""

import argparse
import logging
from pyModbusTCP.server import ModbusServer


# init logging
logging.basicConfig()
# parse args
parser = argparse.ArgumentParser()
parser.add_argument('-H', '--host', type=str, default='localhost', help='Host (default: localhost)')
parser.add_argument('-p', '--port', type=int, default=502, help='TCP port (default: 502)')
parser.add_argument('-d', '--debug', action='store_true', help='set debug mode')
args = parser.parse_args()
# logging setup
if args.debug:
    logging.getLogger('pyModbusTCP.server').setLevel(logging.DEBUG)
# start modbus server
server = ModbusServer(host=args.host, port=args.port)
server.start()

附录C python相关的组件安装指令:

这里有一个用于组件升级的语法,还有一个用于组件安装的语法。国内访问国外原始的python组件库速度会太慢。这里实际引用的是国内镜像站。另外,使用python打头的语法,可以控制当前设备上具体的python示例(你的机器上可能安装有多个Python版本),你可以把最前面的python替换为某个特定目录下的python.exe的全路径。

python -m pip install --upgrade pip --timeout 200 -i http://mirrors.aliyun.com/pypi/simple/  --trusted-host mirrors.aliyun.com


python -m pip install pymodbus  --timeout 200 -i http://mirrors.aliyun.com/pypi/simple/  --trusted-host mirrors.aliyun.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/263892.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于YOLOv8深度学习的智能玉米害虫检测识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

react当中生命周期(旧生命周期详解)

新生命周期https://blog.csdn.net/kkkys_kkk/article/details/135156102?spm1001.2014.3001.5501 目录 什么是生命周期 react中的生命周期 旧生命周期 生命周期图示 常用的生命周期钩子函数 初始化阶段 挂载阶段 在严格模式下挂载阶段的生命周期函数会执行两次原因 更…

W25Q128

什么是 W25Q128 &#xff1f; W25Q128是一款由Winbond&#xff08;威邦电子&#xff09;公司生产的闪存存储器芯片&#xff0c;属于串行闪存系列。具体来说&#xff0c;W25Q128是一颗128Mb&#xff08;兆位&#xff09;容量的串行闪存芯片&#xff0c;其中"W"代表Wi…

Python匹配文件模块的实战技巧

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python中&#xff0c;文件匹配是许多应用中常见的需求&#xff0c;例如文件管理、数据处理等。本文将深入探讨Python中用于文件匹配的模块&#xff0c;包括glob、fnmatch和os.path等&#xff0c;通过丰富的示例…

第11章 GUI Page403~405 步骤三 设置滚动范围

运行效果&#xff1a; 源代码&#xff1a; /**************************************************************** Name: wxMyPainterApp.h* Purpose: Defines Application Class* Author: yanzhenxi (3065598272qq.com)* Created: 2023-12-21* Copyright: yanzhen…

C# 跨越配置

跨越配置1 项目框架 .NET Framework 1.web.config配置 在system.webServer节点中添httpProtocol子节点 Access-Control-Allow-Origin值为“*”” <httpProtocol><customHeaders><add name"Access-Control-Allow-Origin" value"*" /><…

基于DeepSpeed对 llama2-7b的LORA精调

DeepSpeed数据并行研究 1. 技术调研 a. DeepSpeed DeepSpeed是一个开源深度学习训练优化库&#xff0c;其中包含一个新的显存优化技术—— ZeRO&#xff08;零冗余优化器&#xff09;。该框架包含四个技术亮点&#xff1a; 用 3D 并行化实现万亿参数模型训练&#xff1a; D…

【算法】使用二分查找解决算法问题:理解二分法思想,模板讲解与例题实践

文章目录 二分算法思想 / 性质 / 朴素模板二分查找的引入&#xff08;二段性&#xff09;704.二分查找 模板34.在排序数组中查找元素的第一个和最后一个位置 二分查找的前提条件 / 时间复杂度分析 算法题69.x的平方根35.搜索插入位置852.山脉数组的峰顶索引162.寻找峰值153.寻找…

服务熔断(Hystrix)

服务雪崩 多个微服务之间调用的时候&#xff0c;假设微服务A调用微服务B和微服务C&#xff0c;微服务B和微服务C又调用其他的微服务&#xff0c;这就是所谓的“扇出”&#xff0c;如果扇出的链路上某个微服务的调用响应时间过长&#xff0c;或者不可用&#xff0c;对微服务A的…

《每天一分钟学习C语言·六》

1、 1字节&#xff08;Byte&#xff09;8位&#xff0c;1KB1024字节&#xff0c;1M1024KB&#xff0c;1G1024MB 2、 char ch A; printf(“ch %d\n”, ch);ch为65 这里是ASCII码转换 3、 scanf("%d", &i); //一般scanf直接加输入控制符 scanf("m%d&qu…

TKEStack容器管理平台实战之部署wordpress应用

TKEStack容器管理平台实战之部署wordpress应用 一、TKEStack介绍1.1 TKEStack简介1.2 TKEStack特点1.3 TKEStack架构图 二、kubernetes集群介绍2.1 k8s简介2.2 k8s架构图 三、本次实践介绍3.1 实践环境要求3.2 本次实践环境规划3.3 本次实践简介 四、安装容器管理平台4.1 安装T…

WinRAR如何设置和清除密码?

WinRAR是一款功能强大的压缩管理器&#xff0c;除了能把文件打包变小&#xff0c;还能给压缩包设置密码保护&#xff0c;让文件不能随意打开&#xff0c;不需要时还可以把密码取消。下面来说说具体怎么操作吧。 WinRAR根据需要可以设置单次密码和永久密码&#xff0c;我们分别…

C++ Qt开发:Charts绘图组件概述

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍QCharts二维绘图组件的常用方法及灵活运用。 …

Git 配置多个 SSH-Key

Git 配置多个 SSH-Key &#xff08;两个都是gitee&#xff09; 先看图&#xff0c;官网固然重要&#xff0c;但是不完全行&#xff08;因为官网示例是一个gitee一个github&#xff09;&#xff0c;现在想是想多个都是gitee在他上面稍微更改即可 一般不对遇到这种问题&#xf…

Windows电脑向ipad和iOS系统共享文件夹

Windows电脑向ipad和iOS系统共享文件夹 这个方案不需要下载任何软件&#xff0c;但是要求 iOS 和 Windows 在同一个局域网内。再大的文件都可以在 iOS13 自带的的“文件App”里实时显示&#xff0c;可以直接打开。这个解决方案需要你 Windows 电脑上登陆了微软账号&#xff0c…

数字技术:引领未来的创新驱动力

数字技术&#xff0c;作为当代最具创新性和影响力的技术领域之一&#xff0c;已经在全球范围内引起了广泛的关注和研究。当前&#xff0c;数字技术正以惊人的速度改变着我们的世界&#xff0c;从日常生活到商业领域&#xff0c;无一不受到其影响。数字技术的发展不仅改变了人们…

深度学习美化图片,绝对可行,美化效果挺好 DPED

一、背景 要美化生成的图片的效果&#xff0c;找到一个 效果如下&#xff1a; 二、步骤 1、python3.6环境&#xff0c;TensorFlow 2.0.0 2、下载代码&#xff1a;https://github.com/aiff22/DPEDx 3、将要增强的照片放在以下目录中&#xff0c;没有就新建&#xff1a; dpe…

基于改进YOLOv7的绝缘子缺陷检测算法

摘要 现有的检测方法面临着巨大的挑战&#xff0c;在识别绝缘子的微小缺陷时&#xff0c;针对输电线路图像与复杂的背景。为保证输电线路的安全运行&#xff0c;提出一种改进的YOLOv 7模型&#xff0c;以提高检测结果。 首先&#xff0c;基于K-means对绝缘子数据集的目标盒进…

Python并行编程详解:发挥多核优势的艺术

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在当今计算机时代&#xff0c;充分发挥多核处理器的性能是提高程序运行效率的关键。Python作为一门强大的编程语言&#xff0c;提供了多种并行编程工具和库。本文将深入介绍Python中的并行编程&#xff0c;探讨如…