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将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Python Websockets库的使用指南

《PythonWebsockets库的使用指南》pythonwebsockets库是一个用于创建WebSocket服务器和客户端的Python库,它提供了一种简单的方式来实现实时通信,支持异步和同步... 目录一、WebSocket 简介二、python 的 websockets 库安装三、完整代码示例1.

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同