using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Core.ONH.Collection.Send;
namespace Core.ONH.Collection.comm
{
public delegate void ReceiveDataHandler(object sender, ONHData data, string Message);
public class SerialPortEntity : SerialPort
{
private CancellationTokenSource ct = new CancellationTokenSource();
private Task task;
public string StrBaudRate
{
get { return BaudRate.ToString(); }
set
{
var iBaudRate = 0;
if (!int.TryParse(value, out iBaudRate))
iBaudRate = 2400;
BaudRate = iBaudRate;
}
}
public string StrDataBits
{
get { return DataBits.ToString(); }
set
{
var iDataBits = 0;
if (!int.TryParse(value, out iDataBits))
iDataBits = 8;
DataBits = iDataBits;
}
}
public string StrParity
{
get
{
switch (Parity)
{
case Parity.None:
return "NONE";
case Parity.Even:
return "EVEN";
case Parity.Mark:
return "MARK";
case Parity.Odd:
return "ODD";
case Parity.Space:
return "SPACE";
default:
return "EVEN";
;
}
}
set
{
switch (value)
{
case "EVEN":
Parity = Parity.Even;
break;
case "MARK":
Parity = Parity.Mark;
break;
case "NONE":
Parity = Parity.None;
break;
case "ODD":
Parity = Parity.Odd;
break;
case "SPACE":
Parity = Parity.Space;
break;
default:
Parity = Parity.Even;
break;
}
}
}
public string StrStopBits
{
get
{
switch (StopBits)
{
case StopBits.None:
return "NONE";
case StopBits.One:
return "ONE";
case StopBits.OnePointFive:
return "ONEPOINTFIVE";
case StopBits.Two:
return "TWO";
default:
return "ONE";
;
}
}
set
{
switch (value)
{
case "NONE":
StopBits = StopBits.None;
break;
case "ONE":
StopBits = StopBits.One;
break;
case "ONEPOINTFIVE":
StopBits = StopBits.OnePointFive;
break;
case "TWO":
StopBits = StopBits.Two;
break;
default:
StopBits = StopBits.One;
break;
}
}
}
public string DeviceName { get; set; }
public event ReceiveDataHandler ReceiveData;
///
/// 触发试样编号值改变事件
///
///
protected virtual void OnReceiveData(ONHData data, string message)
{
var handler = ReceiveData;
if (handler != null)
new Task(() => { handler(this, data, DeviceName + " " + message); }).Start();
// handler(this, data, DeviceName + " " + message);
}
public void SendDataWithReplay(string data)
{
var byteArray = Encoding.Default.GetBytes(data);
//组成特定帧
var fullyByte = CoreProtocol.Framing(byteArray); // 组成符合自定义协议的数据帧
Open();
Thread.Sleep(200);
try
{
Write(fullyByte, 0, fullyByte.Length);
var ts1 = new TimeSpan(DateTime.Now.Ticks);
var ReadData = new List();
var OverTime = false;
var RightReplay = false;
List Data = null;
while (!OverTime && !RightReplay)
if (BytesToRead > 0)
{
var Datas = new byte[BytesToRead];
Read(Datas, 0, Datas.Length);
ReadData = ReadData.Concat(Datas).ToList();
if (AnalaysData(ReadData, out Data) == DeframeType.RightFrame)
RightReplay = true;
}
else
{
var ts2 = new TimeSpan(DateTime.Now.Ticks);
var ts3 = ts1.Subtract(ts2).Duration();
if (ts3.TotalSeconds > 10) OverTime = true;
}
if (OverTime)
throw new Exception("发送超时");
if (Data!=null && Data.Count>0 && Data[0] == 0x00)
{
}
else
{
throw new Exception("通讯异常, 请重新发送");
}
}
finally
{
if (IsOpen)
Close();
}
}
public void Start()
{
try
{
Open();
OnReceiveData(null,
string.Format("打开串口[{0}--{1} {2} {3} {4}]成功!", PortName, StrBaudRate, StrParity, StrDataBits,
StrStopBits));
ct = new CancellationTokenSource();
task = new Task(ReceiveTask, ct.Token);
task.Start();
OnReceiveData(null, "开始监听数据");
}
catch (Exception ex)
{
OnReceiveData(null, ex.Message);
}
}
public void ReceiveTask()
{
var ReceiveData = new List();
while (!ct.IsCancellationRequested)
try
{
if (!IsOpen) continue;
if (BytesToRead > 0)
{
//等待100毫秒 等足够帧过来
Thread.Sleep(100);
var Datas = new byte[BytesToRead];
Read(Datas, 0, Datas.Length);
ReceiveData = ReceiveData.Concat(Datas).ToList();
List Data;
DeframeType Result = AnalaysData(ReceiveData, out Data);
if(Result!= DeframeType.LengthLess) ReceiveData.Clear();
if (Result == DeframeType.RightFrame)
{
//回应0x00 收到正确数据
var replay = CoreProtocol.Framing(new byte[] { 0x00 });
Write(replay, 0, replay.Length);
ONHData ONHData = new ONHData();
String StrData = Encoding.Default.GetString(Data.ToArray());
ONHDataHelper.AnalysisString(StrData, out ONHData);
ONHData.DeviceName = DeviceName;
OnReceiveData(ONHData, "成功接受数据:" + StrData);
}
if (Result == DeframeType.WrongFrame)
{
//回应0x01 收到数据异常
var replay1 = CoreProtocol.Framing(new byte[] { 0x01 });
Write(replay1, 0, replay1.Length);
OnReceiveData(null, "数据丢失,请重新发送 ");
}
}
}
catch (Exception)
{
}
OnReceiveData(null, "停止监听数据");
}
private DeframeType AnalaysData(List ReceiveData, out List Data)
{
ReceiveData = ReceiveData.SkipWhile(p => p != 0x68).ToList();
DeframeType Result = CoreProtocol.Deframe(ReceiveData, out Data);
if (Result == DeframeType.WrongHead)
{
//帧头 不正确 去掉第一字节 递归
ReceiveData.RemoveAt(0);
return AnalaysData(ReceiveData, out Data);
}
return Result;
}
public void Stop()
{
try
{
ct.Cancel();
task.Wait();
}
catch (Exception ex)
{
// ignored
}
Thread.Sleep(100);
if (IsOpen)
{
Close();
OnReceiveData(null, string.Format("关闭串口[{0}]成功!", PortName));
}
}
}
}