python实现MC协议(SLMP 3E帧)的TCP服务端(篇二)

2023-11-05 07:15

本文主要是介绍python实现MC协议(SLMP 3E帧)的TCP服务端(篇二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

python实现MC协议(SLMP 3E帧)的TCP服务端是一件稍微麻烦点的事情。它不像modbusTCP那样,可以使用现成的pymodbus模块去实现。但是,我们可以根据协议帧进行组包,自己去实现帧的格式,而这一切可以基于socket模块。本文为第二篇。

二、读写保持寄存器的完整交互包

# 客户端发送(读) -》
50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 00 00 00 A8 05 00
# 《- 服务端应答
D0 00 00 FF FF 03 00 0C 00 00 00 73 00 00 00 00 00 00 00 00 00
# 客户端发送(写) -》
50 00 00 FF FF 03 00 16 00 10 00 01 14 00 00 0A 00 00 A8 05 00 4E 47 00 00 00 00 00 00 00 00
# 《- 服务端应答
D0 00 00 FF FF 03 00 02 00 00 00

1、分析交互包

基于上述交互包,我们查阅官方文档发现交互包使用的是二进制代码。那么,二进制代码与ASCII代码有什么区别呢?

SLMP(Seamless Message Protocol)3E帧有两种表示方式:二进制格式和ASCII格式。它们的区别在于数据的传输方式和呈现形式。

(1)二进制格式

在二进制格式中,SLMP 3E帧中的各个字段(如帧头、副帧头、命令码、数据等)以二进制形式直接编码和传输。数据在网络中以原始的二进制位模式传输,这种方式效率较高,适用于网络传输。二进制格式通常用于实际的网络通信中,数据以二进制流的形式在网络上传输。

(2)ASCII格式

在ASCII格式中,SLMP 3E帧中的各个字段被转换成ASCII字符表示。数据以ASCII码的文本形式进行传输,每个字节被转换为两个ASCII字符(通常是十六进制表示)。ASCII格式通常用于调试和人机界面中,方便人们查看和理解数据。

总的来说,二进制格式适用于机器之间的网络通信,而ASCII格式适用于人机交互和调试过程中的数据显示。选择哪种格式取决于具体的应用场景和需求。

因此,本文实现的是二进制格式,如果你会实现二进制格式,那么你也能实现ASCII格式。

2、读写保持寄存器的请求处理

(1)表头

客户端的两个请求,相同部分都为50 00 00 FF FF 03 00,我们姑且称之为表头。

(2)读/写长度(协议帧的长度)

0C 00是固定长度(读的时候报文都是这么长)与16 00 根据实际长度变化,表示后面数据的长度,例如前者,应该以00 0C来看长度,表示后面有12个00那样的长度。

(3)固定值

10 00

(4)读/写指令

01 04 / 01 14

(5)读/写寄存器地址

00 00 00 00 00 A8 05 00 /  00 00 0A 00 00 A8 05 00,其中写的0A 00代表从第10个保持寄存器,05表示读写5个寄存器

3、读写保持寄存器的响应处理

(1)表头

客户端的两个请求,相同部分都为D0 00 00 FF FF 03 00,我们姑且称之为表头。

(2)长度(协议帧的长度)

读:0C 00根据实际长度变化,写:02 00 可以不变化。

(3)固定值

00 00

(4)读/写响应

响应实际读到的数据 / 无

4、程序设计

根据上述内容,实现了一个定制MC服务器,能够处理保持寄存器的读写请求,给出正确的响应。

import socket
import struct# 创建一个TCP/IP套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定套接字到特定地址和端口
server_address = ('192.168.1.188', 12345)  # 服务器地址和端口
server_socket.bind(server_address)# 监听连接
server_socket.listen(1)print('等待客户端连接...')
connection, client_address = server_socket.accept()print('客户端已连接:', client_address)def request_verdict(req_bytes_frame):  # req_bytes_frame是字节数据b'\x02\x00\x08\x00\x00\x00\x00\x00\x10\x00\x01\x01\x02\x03\x04\x03'command = req_bytes_frame.hex()[22:26]  # 转成16进制字符串好数据处理if command in ["0104", "0401"]:  # 判断读写return False # 读elif command in ["0114", "1401"]:return True  # 写else:raise ValueError("读写指令错误!")def write_response_frame(req_bytes_frame):response = "D00000FFFF030002000000"  # 写成功则返回这一串数据content = req_bytes_frame.hex()[42:]  # 看一下客户端想写的内容print("客户端想要写入的内容:", bytes.fromhex(content).decode())return bytes().fromhex(response)def read_response_frame(req_bytes_frame, res_data):header = "D00000FFFF03000C000000"  # 读的响应头nums = req_bytes_frame.hex()[38:42]  # 获取客户端想要读的寄存器个数act_nums_hex = nums[2:] + nums[:2]  # 涉及大端序和小端序,需要转一下act_nums = int(act_nums_hex, 16)  # 得到实际数量res_data_hex = ''.join([hex(ord(c))[2:].zfill(2) for c in res_data])  # 将要返回的数据转成16进制字符串response = header + res_data_hex + '0'*(act_nums*2*2-len(res_data_hex))  # 根据请求数量返回对应的内容return bytes().fromhex(response)try:while True:# 接收客户端请求request = connection.recv(1024)print("001:", request)if request:flag = request_verdict(request)if flag:  # 响应写response = write_response_frame(request)print("002:",response)else:  # 响应读response = read_response_frame(request, "start")print("003:",response)connection.sendall(response)
finally:# 清理连接connection.close()

三、关于MC协议的整体实现

通过“二”,我们实现了一个基于MC协议的保持寄存器的读写服务器,但并没有像pymodbus这种现成模块那样完整实现,这里探讨一下还可以做的事。

1、SLMP 3E帧实现步骤

实现SLMP(Seamless Message Protocol) 3E帧协议涉及到网络通信、数据处理、错误处理等多个步骤。以下是实现SLMP 3E帧的一般步骤:

(1)建立TCP连接:

在服务端,监听指定端口(通常是4999)。
在客户端,连接到服务端的IP地址和端口。
(2)接收请求:

服务端接收客户端发送的SLMP 3E帧请求。
解析SLMP 3E帧,获取命令码、子命令码、数据等信息。
(3)处理请求:

根据SLMP 3E帧中的命令码和数据,执行相应的操作,如读取、写入、控制等。
处理请求可能涉及到对PLC或其他设备进行读写操作,具体实现根据设备和应用需求而定。
(4)生成响应:

根据请求处理的结果,生成SLMP 3E帧的响应数据。
设置响应帧的命令码、子命令码、数据等。
(5)发送响应:

将生成的SLMP 3E帧响应数据发送回客户端。
(6)错误处理:

在处理请求和生成响应的过程中,可能出现各种错误,如无效命令、数据不合法等。
针对不同的错误情况,生成相应的错误响应帧。
(7)关闭连接:

当通信结束或出现错误时,关闭TCP连接,释放资源。
请注意,SLMP 3E帧协议具体的实现步骤和数据格式可能因具体设备和应用而有所不同。在实际开发中,需要参考设备文档和SLMP协议规范来进行具体的实现。

2、SLMP协议规范

查阅三菱PLC关于SLMP的文档!

SLMP的详细规范通常由设备厂商提供,以便开发者能够正确地使用该协议与设备进行通信。规范文件通常包含SLMP协议的命令码、数据格式、通信流程、错误处理等方面的详细信息。

3、为什么会有SLMP协议

SLMP(Seamless Message Protocol)协议是为了在自动化领域(例如工业自动化、制造业、机器人技术等)中实现设备之间的无缝通信而设计的。它提供了一种标准化的通信协议,使不同厂商、不同类型的设备能够在同一个网络上进行通信,实现设备的互联互通。

在现代工业自动化系统中,通常涉及到各种各样的设备,这些设备由不同的厂商制造,可能使用不同的通信协议和数据格式。为了实现这些设备之间的互联互通,需要一种通用的、标准化的通信协议。SLMP就是为了满足这种需求而被开发出来的。

SLMP协议的设计目标包括:

标准化通信: 提供一种通用的通信协议,使得不同厂商生产的设备可以在同一个网络上进行通信。

灵活性: 允许不同类型的数据(例如状态信息、控制命令等)通过同一个协议进行传输。

高效性: 设计为高效的通信协议,以满足工业自动化系统对实时性和响应速度的要求。

易用性: 设计为易于实现和配置,使得工程师能够方便地将SLMP协议集成到他们的设备和系统中。

综上所述,SLMP协议的存在使得不同类型的自动化设备能够方便地相互通信,实现了工业自动化系统的互操作性和灵活性。

4、我是否可以自定义一套协议

你完全可以自定义一套通信协议,以满足特定需求或者应用场景。自定义通信协议通常涉及到以下几个步骤:

确定通信需求: 首先,你需要明确通信双方之间需要传输哪些数据,以及数据的格式和类型。确定通信的数据结构、命令类型、错误处理机制等。

选择传输方式: 确定通信采用的传输方式,可以是基于串口的通信(例如RS-232、RS-485)、基于网络的通信(例如TCP/IP、UDP)、无线通信(例如Wi-Fi、蓝牙)等。

制定协议规范: 定义协议的数据帧格式,包括帧头、帧尾、校验码等信息。确保通信双方遵循相同的协议规范。

实现协议解析和封装: 在通信的发送端和接收端分别实现协议的封装和解析逻辑。封装就是将待发送的数据按照协议格式组织成数据帧,解析则是在接收端将接收到的数据帧按照协议格式解析成可处理的数据。

添加错误处理和安全性: 考虑数据传输中可能出现的错误情况,设计相应的错误处理机制,确保数据的完整性和可靠性。如果通信需要保密性,可以考虑加密通信数据。

测试和验证: 在实际环境中进行测试和验证,确保自定义协议能够正常工作,并且满足通信需求。

请注意,自定义协议需要考虑通信的稳定性、可靠性和安全性。在设计过程中,建议参考现有通信协议的设计经验,以及相关领域的最佳实践。同时,文档化自定义协议的规范,以便未来的维护和扩展。

这篇关于python实现MC协议(SLMP 3E帧)的TCP服务端(篇二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/348269

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P