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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法