C00225155-02/C00225155/MegaRobo.C00225155/MegaRobo.C00225155.ControlD.../USBScanner/USBScannerService.cs

176 lines
5.5 KiB
C#
Raw Permalink Normal View History

2026-04-13 09:12:49 +00:00
using MegaRobo.Connections;
using MegaRobo.Contract;
using MegaRobo.ControlDevices.Abstractions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MegaRobo.C00225155.ControlDevices.USBScanner
{
public class USBScannerService : ConnectorBase
{
public SerialPortService MegaSerialPort { get; set; }
public bool IsConnected => this.MegaSerialPort?.IsOpen ?? false;
/// <summary>
/// 扫描仪数据接收事件(外部可订阅,实时获取串口数据)
/// </summary>
public event EventHandler<Message> ScannerDataReceived;
#region Base
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
{
await Task.Delay(0);
this.CoreService = coreService;
if (args != null && args.Length > 0 && args[0] is string portName)
{
this.SetConnection(portName);
}
//else
//{
// throw new ArgumentException("初始化失败未传入有效的串口名称portName");
//}
return string.Empty;
}
private void SetConnection(string portName)
{
// 若已有串口实例,先断开并清理
if (MegaSerialPort != null)
{
Disconnect();
}
this.MegaSerialPort = new SerialPortService(portName);
this.Connection();
}
public string Connection()
{
try
{
if (MegaSerialPort != null && !MegaSerialPort.IsOpen)
{
this.MegaSerialPort.Open();
// 2. 连接成功后订阅串口DataReceived事件先取消再订阅防止重复
MegaSerialPort.DataReceived -= MegaSerialPort_DataReceived; // 取消旧订阅
MegaSerialPort.DataReceived += MegaSerialPort_DataReceived; // 新订阅
}
}
catch (Exception ex)
{
return ex.Message;
}
return this.MegaSerialPort.IsOpen ? null : "连接异常";
}
public Task<string> ConnectionAsync()
{
return Task.Run(this.Connection);
}
public bool Disconnect()
{
if (MegaSerialPort != null)
{
// 3. 断开连接前取消事件订阅(避免内存泄漏)
MegaSerialPort.DataReceived -= MegaSerialPort_DataReceived;
MegaSerialPort.Dispose(); // 触发SerialPortService的Close和资源释放
}
return true;
}
public void Dispose()
{
this.Disconnect();
this.MegaSerialPort = null;
}
#endregion Base
/// <summary>
/// 串口DataReceived事件的处理方法自动触发
/// </summary>
private void MegaSerialPort_DataReceived(object sender, Message msg)
{
if (msg == null || msg.Data == null || msg.Data.Length == 0)
return;
string receivedData = msg.ReadString(SerialPortDataFormat.Char); // 用串口配置的格式解析
// --------------------------
// 步骤2对外透传数据触发自定义事件
// 外部订阅ScannerDataReceived即可实时获取数据
// --------------------------
OnScannerDataReceived(msg);
}
/// <summary>
/// 触发自定义事件(线程安全的事件触发方式)
/// </summary>
protected virtual void OnScannerDataReceived(Message msg)
{
// 临时保存事件引用,避免多线程下事件被注销后为空
var handler = ScannerDataReceived;
handler?.Invoke(this, msg);
}
public string SendAndReceive(string cmd, TimeSpan timeout)
{
string mReply = string.Empty;
EventHandler<Message> tempHandler = (sender, msg) =>
{
mReply = msg.ReadString(SerialPortDataFormat.Char);
};
try
{
MegaSerialPort.DataReceived += tempHandler;
MegaSerialPort.WriteLine(cmd);
Stopwatch stopwatch = Stopwatch.StartNew();
while (string.IsNullOrEmpty(mReply) && stopwatch.Elapsed < timeout)
{
Thread.Sleep(50);
}
}
finally
{
MegaSerialPort.DataReceived -= tempHandler;
}
return mReply;
}
public override async Task<ConnectionState> CheckConnected()
{
await Task.Delay(0);
if (this.MegaSerialPort.IsOpen)
{
return ConnectionState.IsConnected;
}
else
{
return ConnectionState.NotConnected;
}
}
public override async Task<ConnectionState> ReconnectAsync()
{
await Task.Delay(0);
if (string.IsNullOrEmpty(await ConnectionAsync()))
{
return ConnectionState.IsConnected;
}
else
{
return ConnectionState.NotConnected;
}
}
}
}