今天中午没睡午觉,头昏眼花的,实在写不了代码,把这几天写的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层的更多相关文章

  1. S3C6410串口平台设备注册流程分析

    1.mdesc->map_io() start_kernel -->setup_arch(&command_line); -->paging_init(mdesc); --& ...

  2. [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)

    星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...

  3. [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计

    目       录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章           框架总体的设计... 2 2.1           ...

  4. 【工业串口和网络软件通讯平台(SuperIO)教程】二.架构和组成部分

    1.1    架构结构图 1.1.1    层次示意图 1.1.2    模型对象示意图 1.2    IO管理器 IO管理器是对串口和网络通讯链路的管理.调度.针对串口和网络通讯链路的特点,在IO管 ...

  5. Linux下串口编制【转】

    串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统.调制解调 ...

  6. Smart210学习记录------linux串口驱动

    转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=27025492&id=327609 一.核心数据结构 串口驱动有 ...

  7. 四轴飞行器1.2.2 RT-Thread 串口

    四轴飞行器1.2.2 RT-Thread 串口        本来是打算说根据RT-Thread的设备管理提供的驱动接口些串口驱动的,但是仔细一看,我去,串口驱动写好了,只需要调用就可以了.下面我们说 ...

  8. Linux串口编程详解(转)

    串口本身,标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接 ...

  9. linux串口编程总结

    串口本身.标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口以前被广泛用于连接计算机和终端设备和各种外部设备.尽管以太网接口和USB接口也是以一个串行流进行数据传送的.可是串口连接 ...

随机推荐

  1. 【数据库】百万级数据库SQL优化大总结

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  2. 【Java并发编程】之四:守护线程与线程阻塞的四种情况

    守护线程 Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) ​ 用户线程即运行在前台的线程,而守护线程是运行在后台的线程. 守护线程作用是为其他前台线程 ...

  3. 学习Python最好的方法就是实践和教程并行,以下有一些资源和教程,还有一些学习思维导图:

    1.Python 的 14 张思维导图下载地址: https://woaielf.github.io/2017/06/13/python3-all/ 2.Python基础教程|菜鸟教程: http:/ ...

  4. 洛谷 Roy&October之取石子

    题目背景 Roy和October两人在玩一个取石子的游戏. 题目描述 游戏规则是这样的:共有n个石子,两人每次都只能取pk 个(p为质数,k为自然数,且pk小于等于当前剩余石子数),谁取走最后一个石子 ...

  5. Ajax请求会话过期处理(JS)

    对于页面来说,处理session过期比较简单,一般只需在过滤器里面判断session用户是否存在,不存在则跳转页面到登陆页即可. 对于Ajax请求来说,这个办法则无效,只能获取到登录页的html代码. ...

  6. C++操作Windows WIFI

    原文链接地址:https://blog.csdn.net/just_do_1122/article/details/78031024 实现功能     无线网卡列表     无线热点扫面     无线 ...

  7. NOIP2015Day1T3斗地主(DFS)

    这类题...真的写不动T T 首先可以发现没有顺子的话出牌次数是一定的, 换句话说只有顺子会影响出牌次数. 所以可以暴搜出所有顺子的方案, 搜完之后记忆化搜索求一下a张1张同色牌, b张2张同色牌,c ...

  8. jdk1.5后枚举类的定义规则

    转: http://blog.csdn.net/willcold/article/details/12844487  JDK1.5 新增的enum关键字用于定义枚举类             枚举类也 ...

  9. UVA-11582 数学

    UVA-11582 题意: 求f[a^b]%n ,其中f是斐波那契数列,1<=n<=1000,0<=a,b<=2^64; 代码: //这题重点是要发现 f[i]%n会出现循环, ...

  10. ios 替换字符串中的部分字符串

    1.使用NSString中的stringByTrimmingCharactersInset:[NSCharacterSet whitespaceCharacterSet]方法去掉左右两边的空格: 2. ...