using FlyADBase.Inc;
using System;
using System.ComponentModel;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
namespace FlyADBase
{
public class FlyAd2021Comm_SerialPort : IFlyAd2021Comm
{
///
/// 串口号
///
public string Addr { get; set; }
///
/// 是否异常
///
public bool IsError => !string.IsNullOrEmpty(ErrMsg);
///
/// 异常信息
///
public string ErrMsg { get; private set; }
///
/// Open 成功
///
public bool IsConnected { get; private set; }
///
/// 运行中
///
public bool IsRunning { get; private set; }
///
/// 接收task调用
///
public event Action RecMsg;
public event PropertyChangedEventHandler PropertyChanged;
SerialPort sp;
CancellationTokenSource cancellation;
CancellationTokenSource cancellation_waitforSend;
public FlyAd2021Comm_SerialPort()
{
sp = new SerialPort();
sp.BaudRate = 115200 * 2; ;
sp.Parity = Parity.None;
sp.StopBits = StopBits.One;
}
public void SendMsg(byte[] msg)
{
if (!IsConnected)
return;
try
{
sp.Write(msg, 0, msg.Length);
ErrMsg = null;
}
catch (Exception e)
{
ErrMsg = e.Message;
IsConnected = false;
}
}
void OnTask()
{
while (!cancellation.IsCancellationRequested)
{
ConnectTask();
if (IsConnected)
{
//进入接收task
ReceiveTask();
}
//休息一会儿,在重连
try
{
Task.Delay(2000, cancellation.Token).Wait();
}
catch (Exception e)
{
//被打断了
break;
}
}
IsConnected = false;
}
///
/// 连接任务
///
void ConnectTask()
{
sp.PortName = Addr;
while (!cancellation.IsCancellationRequested)
{
try
{
sp.Open();
IsConnected = true;
ErrMsg = null;
return;
}
catch (Exception e)
{
//连接出错
//等待重试
ErrMsg = e.Message;
}
try
{
Task.Delay(2000, cancellation.Token).Wait();
}
catch (Exception e)
{
//被打断
return;
}
}
}
///
/// 接收任务
///
void ReceiveTask()
{
sp.DataReceived += Sp_DataReceived;
while (!cancellation.IsCancellationRequested)
{
if (!IsConnected)
break;
try
{
Task.Delay(1000, cancellation.Token).Wait();
}
catch (Exception e)
{
//被打断了
break;
}
}
sp.DataReceived -= Sp_DataReceived;
}
public void Start()
{
if (IsRunning)
return;
IsRunning = true;
sp.PortName = Addr;
cancellation = new CancellationTokenSource();
Task.Factory.StartNew(OnTask, cancellation.Token);
}
private void Sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int bytesToRead = sp.BytesToRead;
if (bytesToRead <= 0)
return;
byte[] recBuf = new byte[bytesToRead];
sp.Read(recBuf, 0, bytesToRead);
RecMsg?.Invoke(recBuf);
}
public void Stop()
{
if (!IsRunning)
return;
IsRunning = false;
cancellation.Cancel();
sp.Close();
}
}
}