python实现FINS协议的UDP服务端

python实现FINS协议的UDP服务端是一件稍微麻烦点的事情。它不像modbusTCP那样,可以使用现成的pymodbus模块去实现。但是,我们可以根据协议帧进行组包,自己去实现帧的格式,而这一切可以基于socket模块。本文基于原先 FINS协议的TCP服务端的文章进行修改。

一、FINS TCP与FINS UDP

1、FINS_UDP与FINS_TCP有什么不同

FINS(Factory Interface Network Service)是欧姆龙(Omron)PLC(可编程逻辑控制器)的通信协议。FINS支持两种主要的传输方式:FINS over TCP(FINS_TCP)和FINS over UDP(FINS_UDP)。

下面是它们之间的主要区别:

(1)传输层协议:

FINS_TCP: 使用TCP(Transmission Control Protocol)作为传输层协议。TCP是面向连接的、可靠的协议,确保数据的可靠性和顺序传输。

FINS_UDP: 使用UDP(User Datagram Protocol)作为传输层协议。UDP是面向无连接的协议,它不保证数据的可靠性和顺序传输,但通常具有更低的延迟。

(2)连接方式:

FINS_TCP: 建立连接后进行通信,类似于常见的TCP通信方式。

FINS_UDP: 无连接,每个数据包独立发送,适用于对实时性要求较高的应用场景。

(3)可靠性和顺序性:

FINS_TCP: 提供TCP的可靠性和顺序性,适用于对数据完整性和传输顺序有要求的应用。

FINS_UDP: 不提供可靠性和顺序性的保证,适用于对实时性要求较高,可以容忍一些数据丢失的场景。

(4)用途:

FINS_TCP: 适用于对数据完整性和传输顺序要求较高的应用,例如需要确保每个数据包都被正确接收的场景。

FINS_UDP: 适用于实时性要求较高,可以容忍一些数据丢失的应用,例如对于实时控制要求较高的系统。

选择使用哪种方式取决于具体的应用场景和对通信特性的要求。

2、FINS_UDP与FINS_TCP的协议包有什么不同

(1)握手包

FINS_TCP有握手包,而FINS_UDP没有握手包。

(2)请求头

FINS_TCP的请求头是FINS,而FINS_UDP没有请求头。

(3)其他部分

一致。相关文档请查阅我之前写的“python实现FINS协议的TCP服务端(篇一)”等文章,现对比如下:

FINS_TCP

46 49 4E 53 00 00 00 1A 00 00 00 02 00 00 00 00 80 00 02 00 01 00 00 01 00 3D 01 01 82 00 64 00 00 01

FINS_UDP

                                                                                 80 00 02 00 FF 00 00 05 00 64 01 01 82 00 64 00 00 01

二、程序实现

1、构建响应帧

def recognition_frame(req_bytes_frame, Trigger):get_frame = req_bytes_frame.hex().upper()print("设备请求:", get_frame)SRC_value = get_frame[22:24]  # 判断读写,01为读,02为写Area_value = get_frame[24:26]  # 判断寄存器区域,82为保持寄存器# print(SRC_value)# print(Area_value)if SRC_value == "01":if Area_value == "82":response_1 = "00000000000000000000010100000001"  # Trigger位为Trueresponse_0 = "00000000000000000000010100000000"  # Trigger位为Falseif Trigger == True:return bytes().fromhex(response_1)else:return bytes().fromhex(response_0)else:raise ValueError("Area_value is error!")elif SRC_value == "02":if Area_value == "82":print("***************************************")# 写保持寄存器的响应print("扫码器写入的结果数据:", bytes().fromhex(get_frame))response = "0000000000000000000001020000"return bytes().fromhex(response)else:raise ValueError("Area_value is error!")else:raise ValueError("SRC_value is error!")

这个函数是针对读取或写入保持寄存器的请求,以下是对函数的解释:

(1)输入参数:

req_bytes_frame: 一个字节序列,表示设备请求的原始帧。Trigger: 一个布尔值,似乎用于确定设备是否处于触发状态。

(2)函数操作:

将输入的字节序列转换为十六进制表示,并转换为大写形式。从帧中提取 SRC(源)和 Area(寄存器区域)的值。

根据 SRC 和 Area 的值执行相应的逻辑:

如果 SRC 是 "01",表示读取请求,继续判断 Area 是否为 "82"(保持寄存器)。

如果不是 "82",抛出 ValueError 异常,表示 Area 值错误。

如果 SRC 是 "02",表示写入请求,同样判断 Area 是否为 "82"。

如果是,打印扫码器写入的结果数据,构建写保持寄存器的响应帧。如果不是 "82",同样抛出 ValueError 异常。

如果 SRC 不是 "01" 或 "02",抛出 ValueError 异常,表示 SRC 值错误。

如果是,根据 Trigger 的值构建响应帧,其中 Trigger 为 True 时触发位为 1,否则为 0。

(3)返回值:

如果是读取请求,返回构建的响应帧(True 触发位或 False 触发位)。

如果是写入请求,返回构建的写保持寄存器的响应帧。

(4)异常处理:

如果 Area 值不是 "82",或者 SRC 值不是 "01" 或 "02",都会抛出 ValueError 异常,提示相应的错误信息。

总体来说,该函数是为了处理设备的读取和写入请求,并根据请求类型和条件构建相应的响应帧。

2、服务器实现

if __name__ == "__main__":DM_start = 1000# 创建FINS服务端# 创建一个TCP/IP套接字server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 绑定套接字到特定地址和端口server_address = ('192.168.1.188', 9600)  # 服务器地址和端口server_socket.bind(server_address)try:num = 0  # 触发标志Trigger_rec = 0  # Trigger置为True时,对应变为1,表示触发一次response = "" # 响应while True:# 接收客户端请求request, client_address = server_socket.recvfrom(1024)if request:# 如果收到的不是请求头if "800002" in request.hex():# print(request.hex()[22:24])# 实现扫码触发if request.hex()[22:24] == "01":  # 判断读写,01为读触发指令,02为写触发结果if Trigger_rec != 2:Trigger_rec += 1if Trigger_rec == 1:response = recognition_frame(request, Trigger=False)  # 先清空触发信号server_socket.sendto(response, client_address)elif Trigger_rec == 2:  # 复位Trigger信号response = recognition_frame(request, Trigger=True)  # 再置位触发信号server_socket.sendto(response, client_address)# 实现结果接收elif request.hex()[22:24] == "02":print(request.hex())# print("---------------", int(request.hex()[26:30], 16))if int(request.hex()[26:30], 16) == DM_start + 4:if any(c != '0' for c in request.hex()[36:]):  # 不全为0print("扫码结果:", request.hex()[36:])num += 1Trigger_rec = 0else:response = recognition_frame(request, Trigger=True)server_socket.sendto(response, client_address)print("还没有收到结果,继续等待扫码结果!")else:response = recognition_frame(request, Trigger=True)server_socket.sendto(response, client_address)# 处理其他请求else:response = recognition_frame(request, Trigger=True)server_socket.sendto(response, client_address)print("服务响应:", response.hex())  # 可以响应为空if num == 1:assert bytes().fromhex(request.hex()[36:]).decode() != "NG", "实际扫码结果为:{},不符合预期".format(bytes().fromhex(request.hex()[36:]).decode())breakrequest = Falsefinally:# 清理连接server_socket.close()

这段代码是一个服务端程序,是套接字UDP服务端。让我们分析主要的部分:

(1)服务端设置:

创建一个UDP套接字(socket.AF_INET, socket.SOCK_DGRAM)用于与客户端通信。绑定套接字到特定的地址和端口(('192.168.1.188', 9600))。

(2)主循环:

在一个无限循环中,服务端等待从客户端接收请求。对于收到的请求,根据请求的内容进行不同的处理。

(3)请求处理:

判断请求是否包含特定的头部标识 "800002"。如果是读触发指令("01"),则处理触发逻辑。如果是写触发结果指令("02"),则处理扫码结果。如果是其他请求,统一进行处理。

(4)触发逻辑:

根据触发标志 (Trigger_rec) 的状态,对触发指令进行相应的处理。首先清空触发信号,然后再置位触发信号。

(5)扫码结果处理:

对于写触发结果指令,检查是否收到了预期的扫码结果。如果扫码结果不全为0,则认为收到有效的扫码结果,增加计数。如果结果为0,继续等待扫码结果。

(6)响应处理:

根据处理后的结果,调用 recognition_frame 函数构建响应帧。将响应发送给客户端。

(7)断言和终止条件:

当计数 num 达到1时,使用断言检查扫码结果是否符合预期,并终止程序。

(8)清理:

finally 块中关闭套接字,确保程序退出时资源被释放。

总体来说,这个服务端程序用于处理来自客户端的请求,其中包括了特定的触发指令和扫码结果指令。在处理这些指令时,它通过 recognition_frame 函数构建响应,并对结果进行相应的处理。

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

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

相关文章

处理k8s中创建ingress失败

创建ingress: 如果在创建过程中出错了: 处理方法就是: kubectl get ValidatingWebhookConfiguration kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission 然后再次创建,发现可以:

spdlog 简介与基础示例

0. 概况 0.1 源码搭建环境 源码网址: GitHub - gabime/spdlog: Fast C logging library. 可以只是用头文件,也可以先编译后使用;后面的示例都是直接使用头文件的方式。 编译方法: $ git clone https://github.com/gabime/spd…

推荐5个节省90%精力的GitHub工具库

下面五个GitHub工具库可节约你大部分时间,提升效率: 1、Trigger.dev 如果您有长时间运行的作业,请在应用中实现Trigger。 使用 API 集成、Webhooks、调度和延迟等功能直接在代码库中创建长时间运行的作业。 例如, 当用户升级他们…

vscode创建python虚拟环境

一、创建虚拟环境 python -m venv vsvenv 二、激活虚拟环境 cd .\myvenv\Scripts.\Activate.ps1 如果出现下图所示: 1、使用管理员运行PowerShell 2、输入命令:Get-ExecutionPolicy 3、输入命令:Set-ExecutionPolicy RemoteSigned&…

嵌入式设备里,SOC与MCU的区别是什么?

今日话题,嵌入式设备里,SOC与MCU的区别是什么?MCU与SOC有着明显的区别。MCU是嵌入式微控制器,而SOC则是片上系统。虽然这两者看似只有一个"嵌入式系统"的区别,但实际上在软件和硬件方面存在显著差异。首先,…

探索医学影像:如何通过ROI灰度直方图和ROI区域方格图揭示隐秘细节?

一、引言 医学影像是现代医学诊断的重要手段,其中nrrd文件格式作为一种常见的医学影像数据存储方式,被广泛应用于各种医学影像设备和软件中。这种文件格式具有丰富的元数据信息,可以精确记录影像的空间位置、方向和尺度等信息,对于…

CentOS7安装最新版本git

CentOS7上的git是1.8.3.1,比较老,使用体验不好。下载源码来升级一下。 sudo yum -y install dh-autoreconf curl-devel expat-devel gettext-devel openssl-devel perl-devel zlib-devel sudo yum -y iinstall asciidoc xmlto docbook2X sudo yum -y in…

StarGAN 使用指南:一个模型实现多个域的迁移

StarGAN 使用指南 网络结构多数据集训练使用指南StarGAN v2 论文地址:https://arxiv.org/pdf/1711.09020.pdf 我们有猫的图片集、狗的图片集和兔子的图片集。 目标是让猫的图片看起来像狗的图片,狗的图片看起来像兔子的图片,兔子的图片看起…

什么情况下要使用迷宫式油封?

在机械领域,选择正确的密封件可以显着影响设备的效率和寿命。一种这样的密封件是迷宫式油封。本文将探讨迷宫式油封会在哪些场景下使用。 迷宫式油封是一种非接触式密封件,可提供曲折的路径或“迷宫”,以帮助防止油等流体泄漏。与其他密封件…

【开源视频联动物联网平台】J2mod库写一个Modbus TCP 服务器

j2mod 是一个用于 Modbus 通信协议的 Java 库,可以用来创建 Modbus TCP 服务器。以下是一个简单的示例代码,演示如何使用 j2mod 创建一个 Modbus TCP 服务器。 首先,确保你已经添加 j2mod 库到你的项目中。你可以从 j2mod 的官方网站&#x…

HarmonyOS三方库涵盖了7大类

✍️作者简介:大鹏编码(专注于HarmonyOS、Android、Java、Web、TCP/IP等技术方向) 🐳博客主页: 开源中国、稀土掘金、51cto博客、知乎、简书、CSDN 🔔如果文章对您有一定的帮助请👉关注✨、点赞…

面试前自测题,接口自动化测试过程中怎么处理接口依赖?

面试的时候经常会被问到在接口自动化测试,过程中怎么处理接口依赖?首先我们要搞清楚什么是接口依赖。 前言 01.什么是接口依赖 接口依赖指的是,在接口测试的过程中一个接口的测试经常需要依赖另一个或多个接口成功请求后的返回数据。 那怎么…

Stable Diffusion WebUI训练Lora测试XYZ显示例图

方式一 1.1 选择模型放入目录 将模型放入sd项目的models\Lora\目录,尽量保持和其他模型分开。 sd中显示如下: 1.2 脚本X/Y/Zplot选择 X轴类型:提示词搜索/替换 X轴值:NUM,000001,000002, 000003, 000004, 000005, 000006, 000007, 000008, 000009, 000010 Y轴类型:提…

Mysql进阶-事务锁

前置知识-事务 事务简介 事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。 就比如: 张三给李四转账1000块钱&#xff0…

文件下载保存接口的创建_FastAPI

文件下载保存接口的创建 功能描述实现代码功能演示 功能描述 在网页上对数据进行下载保存处理。例如点击网页上的保存按钮,会把文件下载到本地。下面就是对下载保存功能的实现。 实现代码 gpt_router.get("/export_data") async def export_data():# 需…

应用在触摸开关触控屏中的电容式触摸芯片

触摸开关是一种电子开关,使用时轻按开关按钮即可打开开关。松开手时,开关断开,内部结构由金属弹片受力弹动断开或者由电容值,电阻值等电气参数改变而控制。触摸开关一般是指应用触摸感应芯片原理设计的一种墙壁开关,是…

nginx部署和安装-后端程序多端口访问-后端代理设置

部分补充 查看nginx是否安装http_ssl_module模块 ./nginx -V 看到有 configure arguments: --with-http_ssl_module, 则已安装。 如果没有安装:参考文档 nginx官网地址:nginx: download 这里下载nginx-1.18.0稳定版tar.gz 下载后,利用…

阶段四:数据分析与机器学习(学习如何使用matplotlib和seaborn进行数据可视化)

Matplotlib 和 Seaborn 是 Python 中常用的数据可视化库。Matplotlib 是一个基本的绘图库,可以用于绘制各种静态、动态、交互式和三维图表。Seaborn 基于 Matplotlib,提供了更高级的接口和更美观的默认样式。 下面是一个简单的教程,介绍如何使用 Matplotlib 和 Seaborn 进行…

JavaScript 数组方法 reduce() 的用法

一、概述 在JavaScript中,reduce()方法是一个非常实用的数组方法,它接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。这个方法在处理数组…

OpenTelemetry系列 - 第4篇 OpenTelemetry K8S生态

目录 一、【Helm】添加OTel Helm repo二、【Helm Chart】OTel Collector2.1 daemonset2.2 deloyment 三、【K8S Operator】OTel Operator3.1 安装OTel Operator3.2 部署OpenTelemetryCollector3.2.1 Deloyment Mode3.2.2 DeamonSet Mode3.2.3 StatefulSetMode3.2.4 Sidecar Mod…