C#实现数据采集系统-数据反写(2)消息内容处理和写入通信类队列

C#实现数据采集系统-数据反写

实现步骤

  1. MQTT订阅,接收消息 链接-MQTT订阅接收消息
  2. 反写内容写入通信类,添加到写入队列中
  3. 实现Modbustcp通信写入

具体实现

2. 消息内容写入通信类,添加到写入队列中

在服务类DAqService中添加通信集合_modbusTcps用于存储每个设备的通信类,使用键值对Dictionary存储设备ID和通信类,用于快速查找

然后在启动的时候,订阅各个设备ID的写入主题,添加控制方法DeviceControl

    public class DAqService{public static string MainTopic = "DTSDAQ/";private Dictionary<string, ModbusTcp> _modbusTcps;public DAqService(DAqOption option){_modbusTcps = new Dictionary<string, ModbusTcp>();//...}/// <summary>/// 启动服务/// </summary>public void Start(){MqttControllor = new MqttControllor(_option.MqttConfig);foreach (var item in _deviceLinks){ModbusTcp modbusTcp = new ModbusTcp(item);modbusTcp.DoMonitor();modbusTcp.ValueUpdated += ModbusTcp_ValueUpdated;//将_modbusTcps.Add(item.UID, modbusTcp);MqttControllor.SubscribeTopic($"{MainTopic}{item.UID}/write", DeviceControl);}if (_serviceConfig.IsPushScheduled){timer.Start();}}}

实现消息订阅方法-设备控制DeviceControl

处理消息,将消息转换成对应点位和值,然后调用modbustcp的写入方法

 <summary>
/// 设备控制,反写
/// </summary>
/// <param name="topic"></param>
/// <param name="msg"></param>
private void DeviceControl(string topic, string msg)
{var message = JsonSerializer.Deserialize<DeviceMessage>(msg);//如果消息不为null,则通过设备id找到对应的modbustcp对象,并写入值if (message != null){var link = _deviceLinks.FirstOrDefault(x => x.UID == message.DeviceId); //通过设备id找到对应的modbustcp对象if (link != null){var modbusTcp = _modbusTcps[link.UID]; //通过设备id找到对应的modbustcp对象//循环消息中的数据对象,然后再设备link对象点位中找到对应的点位对象,并写入值foreach (var item in message.Data){var point = link.Points.FirstOrDefault(x => x.UID == item.Key); //通过点位id找到对应的点位对象if (point != null){var parseMethod = point.Type.GetMethod("Parse",BindingFlags.Public | BindingFlags.Static,new[] { typeof(string) });point.WriteValue = parseMethod.Invoke(null,new object[] { item.Value.ToString() }); //通过点位id找到对应的点位对象}modbusTcp.Write(point);}}}
}

在ModbusTcp通信类中,添加一个写入队列和写入方法,写入点位先添加在队列中,然后再读数据间隙中,实现写入

 public class ModbusTcp{/// <summary>/// 写入队列/// </summary>private Queue<RegisterPoint> _writeQueue = new Queue<RegisterPoint>();·//写入值先加入一个队列public void Write(RegisterPoint point){_writeQueue.Enqueue(point);}}

完整代码

public class DAqService
{public static string MainTopic = "DTSDAQ/";private MqttControllor MqttControllor;private Dictionary<string, ModbusTcp> _modbusTcps;private DAqOption _option;private List<DeviceLink> _deviceLinks;private ServiceConfig _serviceConfig;private System.Timers.Timer timer;public DAqService(DAqOption option){_modbusTcps = new Dictionary<string, ModbusTcp>();_option = option;_deviceLinks = option.DeviceLinks;_serviceConfig = option.ServiceConfig;timer = new System.Timers.Timer(_serviceConfig.PushTimeSpan * 1000);timer.Elapsed += Timer_Elapsed;}/// <summary>/// 启动服务/// </summary>public void Start(){MqttControllor = new MqttControllor(_option.MqttConfig);foreach (var item in _deviceLinks){ModbusTcp modbusTcp = new ModbusTcp(item);modbusTcp.DoMonitor();modbusTcp.ValueUpdated += ModbusTcp_ValueUpdated;_modbusTcps.Add(item.UID, modbusTcp);MqttControllor.SubscribeTopic($"{MainTopic}{item.UID}/write", DeviceControl);}if (_serviceConfig.IsPushScheduled){timer.Start();}}/// <summary>/// 设备控制,反写/// </summary>/// <param name="topic"></param>/// <param name="msg"></param>private void DeviceControl(string topic, string msg){var message = JsonSerializer.Deserialize<DeviceMessage>(msg);//如果消息不为null,则通过设备id找到对应的modbustcp对象,并写入值if (message != null){var link = _deviceLinks.FirstOrDefault(x => x.UID == message.DeviceId); //通过设备id找到对应的modbustcp对象if (link != null){var modbusTcp = _modbusTcps[link.UID]; //通过设备id找到对应的modbustcp对象//循环消息中的数据对象,然后再设备link对象点位中找到对应的点位对象,并写入值foreach (var item in message.Data){var point = link.Points.FirstOrDefault(x => x.UID == item.Key); //通过点位id找到对应的点位对象if (point != null){var parseMethod = point.Type.GetMethod("Parse",BindingFlags.Public | BindingFlags.Static,new[] { typeof(string) });point.WriteValue = parseMethod.Invoke(null,new object[] { item.Value.ToString() }); //通过点位id找到对应的点位对象}modbusTcp.Write(point);}}}}private void Timer_Elapsed(object? sender, ElapsedEventArgs e){foreach (var link in _deviceLinks){try{DeviceMessage device = new DeviceMessage { DeviceId = link.UID };foreach (RegisterPoint point in link.Points){// Console.WriteLine($"Point:{point.UID}-->Value:{point.Value}");device.Data.Add(point.UID, point.Value);}var data = JsonSerializer.Serialize(device);MqttControllor.Publish($"{MainTopic}{link.UID}/Time", data); //定时推送}catch (Exception ex){Console.WriteLine(ex.Message);}}}private void ModbusTcp_ValueUpdated(RegisterPoint point, object value){if (_serviceConfig.IsPushChanged){try{DeviceMessage device = new DeviceMessage { DeviceId = point.DeviceId };device.Data.Add(point.UID, value);var data = JsonSerializer.Serialize(device);MqttControllor.Publish($"{MainTopic}{point.DeviceId}/Update", data); //采集立刻推送}catch (Exception ex){Console.WriteLine(ex.Message);}}Console.WriteLine($"Point:{point.UID}-->Value:{value}");}
}

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

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

相关文章

MySQL索引(三)

MySQL索引(三) 文章目录 MySQL索引(三)为什么建索引&#xff1f;怎么建立索引为什么不是说索引越多越好什么时候不用索引更好 索引怎么优化索引失效如何解决索引失效 学习网站&#xff1a;https://xiaolincoding.com/ 为什么建索引&#xff1f; 1.索引大大减少了MySQL需要扫描…

线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析

阵列信号处理——线性约束最小方差准则(LCMV)波束形成算法及MATLAB深入仿真分析 目录 前言 一、LCMV算法 二、仿真参数设置 三、抗干扰权值计算仿真 四、不同干扰方位下抗干扰性能仿真 五、不同信噪比和干噪比下抗干扰性能仿真 总结 前言 在信号处理模块中&#xff0c;通…

day13JS-MoseEvent事件

1. MouseEvent的类别 mousedown &#xff1a;按下键mouseup &#xff1a;释放键click &#xff1a;左键单击dblclick &#xff1a;左键双击contextmenu &#xff1a;右键菜单mousemove &#xff1a;鼠标移动mouseover : 鼠标经过 。 可以做事件委托&#xff0c;子元素可以冒泡…

机器学习——贝叶斯分类器

一、贝叶斯决策论 贝叶斯决策论是概率框架下实施决策的基本方法。   假设有 N N N种可能的类别标记&#xff0c;即 Y { c 1 , c 2 , . . . , c N } Y\{c_1,c_2,...,c_N \} Y{c1​,c2​,...,cN​}&#xff0c; λ i j \lambda_{ij} λij​是将一个真实标记为 c j c_j cj​的样…

【网络】网络层协议——IP协议

目录 1.TCP和IP的关系 2.IP协议报文 2.1. 4位首部长度&#xff0c;16位总长度&#xff0c;8位协议 2.2. 8位生存时间 &#xff0c;32位源IP地址和32位目的IP地址 3.IP地址的划分 3.1.IP地址的表现形式 3.2.旧版IP地址的划分 3.2.1.旧版IP地址的划分思路 3.2.2.分类划…

一文读懂flask

一文读懂flask 在实际工作中遇到了需要在通过gunicorn启动flask应用&#xff0c;并在gunicorn启动的每个woker之前为每个woker初始化ros节点信息&#xff0c;但在改造的过程中遇到通过worker数指定节点名称时多次初始化节点时只有一个woker的节点能够初始化成功&#xff0c;因…

鸿蒙开发 数组改变,ui渲染没有刷新

问题描述&#xff1a; 数组push, 数组长度改变&#xff0c;ui也没有刷新 打印出了数组 console.log(this.toDoData.map(item > ${item.name}).join(, ), this.toDoData.length) 原代码&#xff1a; Text().fontSize(36).margin({ right: 40 }).onClick(() > {TextPicker…

MySQL 数据库深度解析:安装、语法与高级查询实战

一、引言 在现代软件开发和数据管理领域中&#xff0c;MySQL 数据库凭借其高效性、稳定性、开源性以及广泛的适用性&#xff0c;成为了众多开发者和企业的首选。无论是小型项目还是大型企业级应用&#xff0c;MySQL 都能提供可靠的数据存储和管理解决方案。本文将深入探讨 MyS…

uni-app - - - - - 使用uview-plus详细步骤

uni-app - - - - - 使用uview-plus详细步骤 1. 使用HbuilderX创建空白项目2. 安装插件3. uview-plus配置使用3.1 main.js配置3.2 uni.scss配置3.3 App.vue配置3.4 pages.json 4. 重启Hbuilderx 1. 使用HbuilderX创建空白项目 2. 安装插件 工具 > 插件安装 > 前往插件市场…

“精读”怎么翻译?

中文版 “Intensive reading” 是指一种深度阅读的方式&#xff0c;通常用于精读和分析文本的细节。与广泛阅读&#xff08;extensive reading&#xff09;不同&#xff0c;广泛阅读的目标是通过阅读大量的内容来提高整体的语言理解能力&#xff0c;而集中的阅读则注重理解单一…

Linux上安装Conda以管理Python环境

在Windows下装了Linux发行版Debian&#xff0c;以后不用来回开启VMware啦&#xff01;并在Debian中安装了Conda,记录一下所需命令(其他版本如Ubuntu中安装是一样的命令)。 目录 1.WSL 2.安装Conda 3.Python环境配置 1.WSL Install WSL | Microsoft Learn 微软官网 ①以管理…

STM32(F103ZET6)第二十四课:IAP离线固件升级

目录 开发需求IAP介绍内部的内存分区1.内部FLASH划分2.内部数据读取3.数据写入与擦除4.具体升级函数 IAP更新升级步骤1.系统启动流程2.IAP启动流程详解3.整体设计流程4.Boot Loader的代码编写5.APP1代码编写&#xff08;目前&#xff09;6.APP2代码编写&#xff08;待升级&…

WEB开发---使用HTML CSS开发网页实时显示当前日期和时间

自己刚开始学习html css知识&#xff0c;临时做个网页&#xff0c;实时显示当前日期和时间功能。 代码如下&#xff1a; test.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport&q…

python解释器[源代码层面]

1 PyDictObject 在c中STL中的map是基于 RB-tree平衡二元树实现&#xff0c;搜索的时间复杂度为O(log2n) Python中PyDictObject是基于散列表(散列函数)实现&#xff0c;搜索时间最优为O(1) 1.1 散列列表 问题&#xff1a;散列冲突&#xff1a;多个元素计算得到相同的哈希值 …

ARM 寻址方式(18)

立即寻址&#xff1a; 也叫作立即数寻址。 就是 立即数&#xff0c;本身就包含在了 指令当中。 举例&#xff1a; ADD R0, R0,#1 其中&#xff0c;#1 &#xff0c; 就是立即数&#xff0c;对于16进制的立即数&#xff0c; 需要在# 后加上 #0x. 寄存器寻址。 就是数据就在…

219. 存在重复元素 II【 力扣(LeetCode) 】

一、题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;判断数组中是否存在两个 不同的索引 i 和 j &#xff0c;满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 二、测试用例 示例 1&…

多模态论文学习8.28

系列文章目录 文章目录 系列文章目录LAMM: Label Alignment for Multi-Modal Prompt Learning学习1、论文理解1、研究背景2、论文贡献3、方法框架4、研究思路5、实验6、限制 LAMM: Label Alignment for Multi-Modal Prompt Learning学习 1、论文理解 VL模型和下游任务之间的类…

单调栈,LeetCode 2289. 使数组按非递减顺序排列

一、题目 1、题目描述 给你一个下标从 0 开始的整数数组 nums 。在一步操作中&#xff0c;移除所有满足 nums[i - 1] > nums[i] 的 nums[i] &#xff0c;其中 0 < i < nums.length 。 重复执行步骤&#xff0c;直到 nums 变为 非递减 数组&#xff0c;返回所需执行的…

Amos百度云下载与安装 附图文安装教程

如大家所了解的&#xff0c;Amos是一款经常被运用在社会科学研究中的数据分析软件&#xff0c;尤其广泛用于人文社会科学领域的各种研究中。运用Amos&#xff0c;可以帮助研究人员使用结构方程模型 (SEM) 对他们收集到的数据进行分析与解释。 自用Amos 24安装包&#xff0c;可按…

数据结构与算法(循环链表,双向链表)

循环链表 最后一个元素指向首元素 带尾指针的循环链表合并 双向链表 双向链表:在单链表的每个结点里再增加一个指向其直接前驱的指针 域 prior &#xff0c;这样链表中就形成了有两个方向不同的链&#xff0c;故称为双向链表 双向链表插入操作 思路 代码 删除操作 思路 代…