using Prism.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CommonLib.Communication
{
/// <summary>
/// 可连接设备接口
/// </summary>
public interface IDeviceConnect : IDisposable
{
/// <summary>
/// 数据监控委托。参数1为数据传输方向"Send"/"Receive",参数2为数据字节数组。
/// </summary>
Action<string, byte[]> DataMonitor { get; set; }
/// <summary>
/// 连接状态,"Connected"-已连接、"UnConnected"-未连接 等等其它状态。
/// </summary>
string ConnectState { get; set; }
/// <summary>
/// 设置通参数
/// </summary>
/// <param name="parameters">通讯参数接口对象(具体参数详见实现类)</param>
void SetCommunicationParameters(IParameters parameters);
/// <summary>
/// 连接设备
/// </summary>
/// <returns></returns>
bool Connect();
/// <summary>
/// 断开设备
/// </summary>
void Disconnect();
/// <summary>
/// 发送并读取数据(读取指定长度),可单发,也可单读。
/// </summary>
/// <param name="sendBytes">发送字节集合,如果为null或者长度为零表示不发送只读取。</param>
/// <param name="readDelay">回读数据前延时时间,如果小于等于零表示不延时。</param>
/// <param name="readLength">读取长度,如果小于等于令表示不读取。</param>
/// <param name="readTimeout">读取超时时间,单位毫秒。</param>
/// <returns></returns>
List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readLength, int readTimeout);
/// <summary>
/// 发送并读取数据(读取串口缓冲区所有数据),必需有读回送。
/// </summary>
/// <param name="sendBytes">发送字节集合,如果为null或者长度为零表示不发送只读取。</param>
/// <param name="readDelay">回读数据前延时时间,如果小于等于零表示不延时。</param>
/// <param name="readTimeout">读取超时时间,单位毫秒。</param>
/// <returns></returns>
List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readTimeout);
/// <summary>
/// 终止读写数据
/// </summary>
void AbortSRBytes();
}
}
SocketCommunication
using CommonLib.Communication.SerialPortCommunication;
using CommonLib.Timer;
using Prism.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CommonLib.Communication.SocketCommunication
{
public abstract class SocketConnectionDeveice : IDeviceConnect, IDisposable
{
public virtual Action<string, byte[]> DataMonitor { get; set; }
public virtual string ConnectState { get; set; } = "UnConnected";
protected virtual SocketConnectionParameters ConnectionParameters { get; set; }
/// <summary>
/// 线程取消信号源对象
/// </summary>
protected virtual CancellationTokenSource CTS { get; set; }
/// <summary>
/// 初始线程取消信息源对象
/// </summary>
protected virtual void InitCTS()
{
if (CTS == null || CTS.IsCancellationRequested)
{
CTS = new CancellationTokenSource();
//CTS.Token.Register(CancelCallBack);//线程取消回调函数
}
}
/// <summary>
/// Socket对象
/// </summary>
protected virtual Socket Socket { get; set; }
/// <summary>
/// 打开Socket连接
/// </summary>
/// <returns></returns>
protected virtual bool OpenSocket()
{
if (this.Socket == null) return false;
if (!this.Socket.Connected)
{
var result = this.Socket.BeginConnect(this.ConnectionParameters.IP, this.ConnectionParameters.Port, null, null);
result.AsyncWaitHandle.WaitOne(2000);
if (!result.IsCompleted)
{
this.Socket.Close();
}
}
return this.Socket.Connected;
}
public virtual void AbortSRBytes()
{
CTS.Cancel();
}
public virtual bool Connect()
{
InitSocket(ConnectionParameters.IP, ConnectionParameters.Port);
return OpenSocket();
}
public virtual void Disconnect()
{
Socket?.Close();
Socket = null;
}
public virtual void Dispose()
{
Disconnect();
}
public virtual void SetCommunicationParameters(IParameters parameters)
{
this.ConnectionParameters = parameters as SocketConnectionParameters;
InitSocket(ConnectionParameters.IP, ConnectionParameters.Port);
}
public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readLength, int readTimeout)
{
InitCTS();
Exception err = null;
var ls = Task.Run(async () =>
{
try
{
if (!OpenSocket()) throw new Exception("Socket connect failed!");
if (sendBytes != null && sendBytes.Count > 0)
{
var data = sendBytes.ToArray();
this.Socket.Send(data);
DataMonitor?.Invoke("Send", data);//监听发送数据
}
if (readLength <= 0) return null;// 判断是否需要回读
if (readDelay > 0)
{
await Task.Delay(readDelay, CTS.Token);
}
this.Socket.ReceiveTimeout = readTimeout;
byte[] buff = new byte[1024];
int iRet = this.Socket.Receive(buff);
if (iRet == readLength)
{
var retData = buff.Take(iRet).ToArray();
DataMonitor?.Invoke("Receive", retData);//监听回读数据
return retData.ToList();
}
else
{
throw new Exception("Reading socket data timeout!");
}
}
catch (Exception ex)
{
err = ex;
return null;
}
}, CTS.Token).Result;
if (err != null) throw err;
return ls;
}
public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readTimeout)
{
InitCTS();
Exception err = null;
var ls = Task.Run(async () =>
{
try
{
if (!OpenSocket()) throw new Exception("Socket connect failed!");
if (sendBytes != null && sendBytes.Count > 0)
{
var data = sendBytes.ToArray();
this.Socket.Send(data);
DataMonitor?.Invoke("Send", data);//监听发送数据
}
if (readDelay > 0)
{
await Task.Delay(readDelay, CTS.Token);
}
this.Socket.ReceiveTimeout = readTimeout;
byte[] buff = new byte[1024];
int iRet = this.Socket.Receive(buff);
if (iRet > 0)
{
var retData = buff.Take(iRet).ToArray();
DataMonitor?.Invoke("Receive", retData);//监听回读数据
return retData.ToList();
}
else
{
throw new Exception("Reading socket data timeout!");
}
}
catch (Exception ex)
{
err = ex;
return null;
}
}, CTS.Token).Result;
if (err != null) throw err;
return ls;
}
/// <summary>
/// 初始化Socket对象
/// </summary>
/// <param name="ip">ip地址</param>
/// <param name="port">端口</param>
/// <param name="pt">socket支持的协议</param>
protected virtual void InitSocket(string ip, int port, ProtocolType pt = ProtocolType.Tcp)
{
if (Socket != null && Socket.Connected) Socket.Close();
Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, pt);
}
}
}
using Prism.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace CommonLib.Communication.SocketCommunication
{
public class SocketConnectionParameters : ParametersBase, IParameters
{
public string IP => GetPropertyValue<string>();
public int Port => GetPropertyValue<int>();
protected T GetPropertyValue<T>([CallerMemberName] string properityName = "")
{
return GetValue<T>(properityName);
}
}
}
SerialPortCommunication
using CommonLib.LogUtils.Log4net;
using CommonLib.Timer;
using Prism.Common;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CommonLib.Communication.SerialPortCommunication
{
/// <summary>
/// 串口通讯设备基类
/// </summary>
public abstract class SerialPortConnectionDeveice : Log4Base, IDeviceConnect, IDisposable
{
public virtual Action<string, byte[]> DataMonitor { get; set; }
public virtual string ConnectState { get; set; } = "UnConnected";
/// <summary>
/// 线程锁对象
/// </summary>
protected readonly object lockObj = new object();
/// <summary>
/// 线程取消信号源对象
/// </summary>
protected virtual CancellationTokenSource CTS { get; set; }
/// <summary>
/// 初始线程取消信息源对象
/// </summary>
protected virtual void InitCTS()
{
if (CTS == null || CTS.IsCancellationRequested)
{
CTS = new CancellationTokenSource();
//CTS.Token.Register(CancelCallBack);//线程取消回调函数
}
}
/// <summary>
/// 串口对象
/// </summary>
protected virtual SerialPort ComPort { get; set; }
/// <summary>
/// 初始化串口
/// </summary>
/// <param name="portName">串口名称</param>
/// <param name="baudRate">波特率</param>
protected virtual void InitComPort(string portName, int baudRate)
{
if (ComPort != null)
{
if (ComPort.IsOpen) ComPort.Close();
ComPort.PortName = portName;
ComPort.BaudRate = baudRate;
}
else
{
ComPort = new SerialPort(portName, baudRate);
}
}
protected virtual bool OpenComPort()
{
if (ComPort == null) return false;
if (!ComPort.IsOpen) ComPort.Open();
return ComPort.IsOpen;
}
protected virtual void ClosePort()
{
if (ComPort != null && ComPort.IsOpen) ComPort.Close();
}
public virtual void SetCommunicationParameters(IParameters parameters)
{
var objConnectionParameters = parameters as SerialPortConnectionParameters;
if (objConnectionParameters.ContainsKey("SerialPort"))
{
this.ComPort = objConnectionParameters.GetValue<SerialPort>("SerialPort");
}
else
{
InitComPort(objConnectionParameters.PortName, objConnectionParameters.BaudRate);
}
}
public virtual bool Connect()
{
return OpenComPort();
}
public virtual void Disconnect()
{
ClosePort();
}
public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readLength, int readTimeout)
{
InitCTS();
Exception err = null;
var ls = Task.Run(() =>
{
try
{
lock (lockObj)
{
if (!OpenComPort()) throw new Exception("Serial port opening failed!");
if (sendBytes != null && sendBytes.Count > 0)
{
var data = sendBytes.ToArray();
this.ComPort.Write(data, 0, data.Length);
DataMonitor?.Invoke("Send", data);//监听发送数据
}
if (readLength <= 0) return null;// 判断是否需要回读
if (readDelay > 0)
{
Task.Delay(readDelay, CTS.Token).Wait();
}
MyTimer timer = new MyTimer() { AbortFun = () => CTS.IsCancellationRequested };
var bRet = timer.WaitingBusinessTrue(() => this.ComPort.BytesToRead >= readLength, readTimeout);
if (bRet)
{
byte[] buff = new byte[readLength];
int iRet = this.ComPort.Read(buff, 0, buff.Length);
var retData = buff.Take(iRet).ToArray();
DataMonitor?.Invoke("Receive", retData);//监听回读数据
return retData.ToList();
}
else
{
throw new Exception("Reading serial port data timeout!");
}
}
}
catch (Exception ex)
{
err = ex;
return null;
}
}, CTS.Token).Result;
if (err != null) throw err;
return ls;
}
public virtual List<byte> SRBytes(List<byte> sendBytes, int readDelay, int readTimeout)
{
InitCTS();
Exception err = null;
var ls = Task.Run(() =>
{
try
{
lock (lockObj)
{
if (!OpenComPort()) throw new Exception("Serial port opening failed!");
if (sendBytes != null && sendBytes.Count > 0)
{
var data = sendBytes.ToArray();
this.ComPort.Write(data, 0, data.Length);
DataMonitor?.Invoke("Send", data);//监听发送数据
}
if (readDelay > 0)
{
Task.Delay(readDelay, CTS.Token).Wait();
}
MyTimer timer = new MyTimer() { AbortFun = () => CTS.IsCancellationRequested };
var bRet = timer.WaitingBusinessTrue(() => this.ComPort.BytesToRead > 0, readTimeout);
if (bRet)
{
int buffBytesCount = this.ComPort.BytesToRead;
byte[] buff = new byte[buffBytesCount];
int iRet = this.ComPort.Read(buff, 0, buff.Length);
var retData = buff.Take(iRet).ToArray();
DataMonitor?.Invoke("Receive", retData);//监听回读数据
return retData.ToList();
}
else
{
throw new Exception("Reading serial port data timeout!");
}
}
}
catch (Exception ex)
{
err = ex;
return null;
}
}, CTS.Token).Result;
if (err != null) throw err;
return ls;
}
public virtual void AbortSRBytes()
{
CTS.Cancel();
}
public virtual void Dispose()
{
Disconnect();
}
}
}
using Prism.Common;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace CommonLib.Communication.SerialPortCommunication
{
/// <summary>
/// 串口通讯参数访问实现类
/// </summary>
public class SerialPortConnectionParameters : ParametersBase, IParameters
{
/// <summary>
/// 串口名称
/// </summary>
public string PortName => GetPropertyValue<string>();
public int BaudRate => GetPropertyValue<int>();
protected T GetPropertyValue<T>([CallerMemberName] string properityName = "")
{
return GetValue<T>(properityName);
}
}
}