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 clientclient = ModbusTcpClient(SERVER_HOST, SERVER_PORT)# Connect to the Modbus TCP serverclient.connect()# Write to a range of holding registers slave_address = 1response = client.write_registers(base_addr, u16arrayInBigEndiant, slave_address)if response.isError():print('Write error:', response)else:print('Write successful')# Disconnect from the Modbus TCP serverclient.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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ps】常见工具说明

1&#xff1a;污点修复工具 》内容识别 去除脸部珍珠 》创建纹理 2&#xff1a;修复画笔工具 按住ALT选择一处你想移动的地方 3&#xff1a;修补工具 》内容识别 选择一个区域 将区域内的东西移动到 另一处皮肤上

C语言之字符串

目录 字符串字面量 ​编辑 字符串字面量的长度 ◆具有静态生命周期 ◆对于同一个字符串字面量的处理方式依赖于编译器 字符串 字符数组的初始化赋值 空字符串 字符串的读取 在前面的学习中就会发现&#xff0c;仅仅能用一个字符表示的事物少之又少&#xff0c;对于地…

日志服务 SLS 深度解析:拥抱云原生和 AI,基于 SLS 的可观测分析创新

云布道师 10 月 31 日&#xff0c;杭州云栖大会上&#xff0c;日志服务 SLS 研发负责人简志和产品经理孟威等人发表了《日志服务 SLS 深度解析&#xff1a;拥抱云原生和 AI&#xff0c;基于 SLS 的可观测分析创新》的主题演讲&#xff0c;对阿里云日志服务 SLS 产品服务创新以…

2023/12/21作业

思维导图 代码 .text .global _start _start: 灯1 gpio时钟使能 [4]->1 0x5000A28 LDR R0,0x50000A28 指定寄存器地址 LDR R1,[R0]将寄存器取出放到R1 ORR R1,R1,#(0x1<<4)将第四位设置为1 STR R1,[R0]读取R0寄存器到R1 PE…

Ubuntu 常用命令之 reboot 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 reboot命令在Ubuntu系统中用于重新启动系统。这个命令通常需要管理员权限才能执行。 reboot命令的参数如下 -f 或 --force&#xff1a;强制重启&#xff0c;不调用shutdown -r进行友好重启。-p 或 --poweroff&#xff1a;在重启…

arm和x86架构服务器拉取arm64架构的docker镜像

dockerhub提供的镜像部分支持arm64架构 Docker arm架构服务器拉取docker镜像&#xff0c;默认是arm架构 # docker pull centos Using default tag: latest latest: Pulling from library/centos 52f9ef134af7: Pull complete Digest: sha256:a27fd8080b517143cbbbab9dfb7c8…

HarmonyOS布局之scroll

对于Scroll 布局官方讲解非常好&#xff0c;我在这做个总结&#xff0c;主要结合实际应用进行补充 Scroll — 首先他是一个容器布局&#xff0c;所有的容器布局都可包含子布局&#xff0c;因此scroll 布局也可包含子组件但是&#xff08;他只能包含一个子组件&#xff09;&…

nodejs微信小程序+python+PHP医院挂号系统-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

0基础学习VR全景平台篇第130篇:曝光三要素—感光度

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 众所周知&#xff0c;摄影是一门用光的艺术。随着天气、地点、时间的变化&#xff0c;我们所处环境的光线也随之发生改变。而在不同的环境下该如何去正确的调节曝光&#xff0c;是…

PyTorch加载数据以及Tensorboard的使用

一、PyTorch加载数据初认识 Dataset:提供一种方式去获取数据及其label 如何获取每一个数据及其label 总共有多少的数据 Dataloader:为后面的网络提供不同的数据形式 数据集 在编译器中导入Dataset from torch.utils.data import Dataset 可以在jupyter中查看Dataset官方文档&…

confluence操作手册

文章目录 快捷键插入宏插入代码块 自动为标题编号使用方法&#xff1a; 移动页面到其它目录层级下 快捷键 插入宏 英文输入法下输入{ 插入代码块 输入三个会跳出 点编辑可以调整样式 自动为标题编号 安装插件Numbered Headings 下载链接&#xff1a;https://appfire.…

微服务 Spring Cloud 10,如何追踪微服务调用?服务治理的常见手段

目录 一、服务追踪的作用1、优化系统瓶颈2、优化链路调用3、故障排查4、性能优化5、生成网络拓扑图4、透明传输数据 二、节点管理1、服务调用失败一般有两类原因造成&#xff1a;2、服务调用失败的解决方式&#xff1a;3、服务调用失败的具体解决方式&#xff1a; 三、负载均衡…

ansible的控制语句

本章内容主要介绍 playbook 中的控制语句 使用when判断语句block-rescue判断循环语句 一个play中可以包含多个task&#xff0c;如果不想所有的task全部执行&#xff0c;可以设置只有满足某个条件才执行这个task&#xff0c;不满足条件则不执行此task。本章主要讲解when 和 blo…

Epson爱普生手臂机器人与PC通讯 C#

一、Epson手臂配置 1.安装Epson手臂控制软件 安装Epson手臂控制软体EPSON RC+ 7.0(根据实际需求下载应用),可以去官网下载安装。 2.硬件配置 准备一台PC,用网线连接PC和EPSON手臂控制器。 3.在PC上修改IP地址 EPSON手臂默认IP(192.168.0.1),PC IP改为手臂同一网段…

XML简介 (EXtensible Markup Language)

XML简介 (EXtensible Markup Language) 可扩展标记语言 特点 XML与操作系统、编程语言的开发平台无关实现不同系统之间的数据交换 作用 数据交互配置应用程序和网站Ajax基石 XML标签 XML文档内容由一系列标签元素组成 <元素名 属性名"属性值">元素内容&l…

【模式识别】探秘判别奥秘:Fisher线性判别算法的解密与实战

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《模式之谜 | 数据奇迹解码》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1f30c;1 初识模式识…

如何通过蓝牙串口启动智能物联网?

1、低功耗蓝牙(BLE)介绍 BLE 技术是一种低成本、短距离、可互操作的鲁棒性无线技术&#xff0c;工作在免许可的 2,4 GHZ 工业、科学、医学(Industrial Scientific Medical&#xff0c;ISM)频段。BLE在设计之初便被定位为一种超低功耗(Ultra Low Power&#xff0c;ULP)无线技术&…

C语言实现UCS2、UTF8与GBK2312编码转换

一、引言 在软件开发中&#xff0c;字符编码是一个非常重要的概念。不同的编码方式用于在不同的系统和应用中表示文本数据。UCS2、UTF8和GBK2312是三种常见的字符编码方式。为了实现不同编码间的转换&#xff0c;我们可以使用C语言进行编程&#xff0c;利用已有的库或者手动实…

浅谈Guava Cache的参数使用

CacheLoader 用于数据加载方式比较固定且统一的场景&#xff0c;在缓存容器创建的时候就需要指定此具体的加载逻辑。通常开发中使用时我们需要继承CacheLoader类或写一个匿名实现类实现其load方法和reload方法 load方法 当执行get操作没有命中缓存或者判断缓存已经超出expir…

【Prometheus|报错】Out of bounds

【背景】进入Prometheus地址的9090端口&#xff0c;pushgateway&#xff08;0/1&#xff09;error : out of bounds 【排查分析】 1、out of bounds报错&#xff0c;是由于Prometheus向tsdb存数据出错&#xff0c;与最新存数据的时间序列有问题&#xff0c;有可能当前时间与最…