用C#实现通过串口对设备的数据采集--Server层
今天中午没睡午觉,头昏眼花的,实在写不了代码,把这几天写的Server层数据采集的程序整理了一下。
WatrLevelDataCollectServer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using SMOS.Model.Device;
using System.Text.RegularExpressions; namespace SMOS.Server.Impl.Collection
{
public class WaterLevelDataCollectServer : DataCollectServer
{
private SerialPort comm = new SerialPort();
private bool Closing = false;//是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke
private bool Listening = false;//是否没有执行完invoke相关操作
private List<byte> buffer = new List<byte>();//默认分配1页内存,并始终限制不允许超过
private byte[] binary_data = new byte[];//FF FF 01 03 1B 1D
private decimal dataValue = ;
private bool dataCatched;
private bool workManner = true;//工作方式,true--使用设备默认的自动报告方式,false--使用查询方式
/// <summary>
/// 采集水位计数据(默认方式,自动报告方式)
/// </summary>
/// <param name="waterLevelSetInfo"></param>
/// <returns></returns>
public override Model.Device.DeviceRecordInfo GetData(Model.Device.DeviceSetInfo deviceSet)
{
WaterLevelSetInfo entity = deviceSet as WaterLevelSetInfo;
//根据当前串口对象,来判断操作
if (comm.IsOpen)
{
comm.Close();
}
try
{
comm.PortName = entity.Port;
comm.BaudRate = entity.BaudRate;
comm.Open();
}
catch (Exception ex)
{
throw ex;
}
if(workManner == false )//采集水位计数据(查询方式,需要对设备进行手动设置)
{
//发送采集指令 ,16进制发送
byte extensionNo = 0x01;//分机编号默认为"01"
byte checkData = 0x6B;//在分机编号默认时,校验位为“6B”
checkData =(byte)(0xFC + 0x6E + (int)extensionNo);
MatchCollection mc = Regex.Matches("FC 6E "+""+extensionNo+"00 00 "+ checkData.ToString("X"), @"(?i)[\da-f]{2}");
List<byte> buf = new List<byte>();//填充到临时列表中
//依次添加到列表中
foreach (Match m in mc)
{
buf.Add(byte.Parse(m.Value, System.Globalization.NumberStyles.HexNumber));
}
//转换列表为数组后发送
comm.Write(buf.ToArray(), , buf.Count);
}
WaterLevelRecordInfo waterLevelRecordInfo = new WaterLevelRecordInfo();
//添加事件注册
comm.DataReceived += comm_DataReceived;
DateTime dtOld = DateTime.Now;
while (true)
{
if (DateTime.Compare(dtOld.AddSeconds(Convert.ToDouble(entity.AcquisitionInterval)), DateTime.Now) > )
{
System.Threading.Thread.Sleep();
if (dataCatched)
{
waterLevelRecordInfo.MeasuredLevel = dataValue;
waterLevelRecordInfo.RecordTime = DateTime.Now;
waterLevelRecordInfo.DeviceID = entity.DeviceID;
//end operation //解绑事件
comm.DataReceived -= comm_DataReceived;
comm.Close();
return waterLevelRecordInfo as DeviceRecordInfo;
}
}
else
{
comm.DataReceived -= comm_DataReceived;
comm.Close();
return null;
}
}
}
/// <summary>
/// 串口数据接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Closing) return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
try
{
Listening = true;//设置标记
int n = comm.BytesToRead;//记录缓存
byte[] buf = new byte[n];//声明一个临时数组存储串口数据
comm.Read(buf, , n);//读取缓冲数据
dataCatched = false;//缓存记录数据是否捕获到
//缓存数据
buffer.AddRange(buf);
//完整性判断
while (buffer.Count >= )//至少要包含头(2字节)+分机编号(1字节)+测量数据(2字节)+校验(1字节)
{
//查找数据头
if (buffer[] == 0xFF && buffer[] == 0xFF)
{
int len = ;//数据长度
//数据完整判断第一步,长度是否足够
if (buffer.Count < len) break;
buffer.CopyTo(, binary_data, , len);//复制一条完整数据到数据缓存
//分析数据
dataValue = (decimal)((binary_data[] * + binary_data[]) / 1000.000);
dataCatched = true;
buffer.RemoveRange(, len);//正确分析一条数据,从缓存中移除数据
}
else
{
//如果数据开始不是头,则删除数据
buffer.RemoveAt();
}
}
}
catch (Exception ex)
{
dataCatched = false;
}
finally
{
Listening = false;//可以关闭串口
}
}
}
}
在WaterLevelDataCollectServer这个类里主要通过GetData这个方法来实现的水位计数据的采集,使用SerialPort控件,当串口接收导数据的时候自动触发comm_DataReceived事件,但是由于这个事件被触发的时刻不确定,所以在GetData方法中使用循环等待,当接收到数据时跳出循环,并将采集结果返回。
在没有实际设备的时候可以用串口调试助手并通过虚拟串口给程序发送数据,注意COM口,波特率等通信参数的设置应该一一对应。
用C#实现通过串口对设备的数据采集--Server层的更多相关文章
- S3C6410串口平台设备注册流程分析
1.mdesc->map_io() start_kernel -->setup_arch(&command_line); -->paging_init(mdesc); --& ...
- [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)
星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计
目 录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章 框架总体的设计... 2 2.1 ...
- 【工业串口和网络软件通讯平台(SuperIO)教程】二.架构和组成部分
1.1 架构结构图 1.1.1 层次示意图 1.1.2 模型对象示意图 1.2 IO管理器 IO管理器是对串口和网络通讯链路的管理.调度.针对串口和网络通讯链路的特点,在IO管 ...
- Linux下串口编制【转】
串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统.调制解调 ...
- Smart210学习记录------linux串口驱动
转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=27025492&id=327609 一.核心数据结构 串口驱动有 ...
- 四轴飞行器1.2.2 RT-Thread 串口
四轴飞行器1.2.2 RT-Thread 串口 本来是打算说根据RT-Thread的设备管理提供的驱动接口些串口驱动的,但是仔细一看,我去,串口驱动写好了,只需要调用就可以了.下面我们说 ...
- Linux串口编程详解(转)
串口本身,标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接 ...
- linux串口编程总结
串口本身.标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口以前被广泛用于连接计算机和终端设备和各种外部设备.尽管以太网接口和USB接口也是以一个串行流进行数据传送的.可是串口连接 ...
随机推荐
- Oracle中三种循环(For、While、Loop)案例
1.ORACLE中的FOR循环用法(九九乘法表) declare i ; j ; begin .. loop ..i loop Dbms_Output.put(i||'*'||j||'='||i*j) ...
- 常州day5
Task 1 小 W 和小 M 一起玩拼图游戏啦~ 小 M 给小 M 一张 N 个点的图,有 M 条可选无向边,每条边有一个甜蜜值,小 W 要选 K条边,使得任意两点间最多有一条路径,并且选择的 K条 ...
- 【BZOJ5338】[TJOI2018]异或(主席树)
[BZOJ5338][TJOI2018]异或(主席树) 题面 洛谷 题解 很明显的是\(Trie\)树上暴力判断答案 因为要支持区间,用主席树的结构存\(Trie\)树就好了 #include< ...
- 【BZOJ4456】旅行者(最短路,分治)
[BZOJ4456]旅行者(最短路,分治) 题面 BZOJ Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北 的道路,这些 ...
- 扔几道sb题
1.给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间. 你能求 ...
- Java考试题
1. public class GC { 2. private Object o; 3. private voiddoSomethingElse(Object obj) { o ...
- echars画折线图的一种数据处理方式
echars画折线图的一种数据处理方式 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...
- bzoj 2277 [Poi2011]Strongbox 数论
2277: [Poi2011]Strongbox Time Limit: 60 Sec Memory Limit: 32 MBSubmit: 527 Solved: 231[Submit][Sta ...
- 「Python」python-nmap安装与入门
1.安装namp https://nmap.org/download.html 下载链接 PS:windows安装似乎麻烦一些,需要多下载npcap,官网有链接 2.python安装 注意,注意,注意 ...
- Vue.js随笔四(方法的声明和使用)
1.首先你需要新建路由,这个就不多说了 2.然后在你的新的.vue里面需要如下所示的添加methods:{方法},然后按钮的里面你会看到v-on:click,这就是点击这个按钮会触发的动作,这个就是触 ...