213 lines
6.6 KiB
C#
213 lines
6.6 KiB
C#
using System.IO.Ports;
|
|
using System.Text;
|
|
using System.Collections.Concurrent;
|
|
|
|
namespace DualScreenDemo
|
|
{
|
|
public class SerialPortManager
|
|
{
|
|
internal static SerialPort mySerialPort;
|
|
private readonly CommandHandler commandHandler;
|
|
|
|
public SerialPortManager(CommandHandler commandHandler)
|
|
{
|
|
this.commandHandler = commandHandler;
|
|
}
|
|
|
|
public void InitializeSerialPort()
|
|
{
|
|
string[] ports = SerialPort.GetPortNames();
|
|
Console.WriteLine("可用的串列埠:");
|
|
foreach (var port in ports)
|
|
{
|
|
Console.WriteLine(port);
|
|
}
|
|
|
|
// 定義優先選擇的串列埠順序
|
|
string[] preferredPorts = { "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM1" };
|
|
|
|
// 選擇第一個符合的串列埠
|
|
string selectedPort = preferredPorts.FirstOrDefault(port => ports.Contains(port));
|
|
|
|
if (!string.IsNullOrEmpty(selectedPort))
|
|
{
|
|
mySerialPort = new SerialPort(selectedPort);
|
|
Console.WriteLine($"已選擇串列埠: {selectedPort}");
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("未找到任何可用的串列埠!");
|
|
return;
|
|
}
|
|
|
|
// 配置串列埠參數
|
|
mySerialPort.BaudRate = 9600;
|
|
mySerialPort.Parity = Parity.None;
|
|
mySerialPort.StopBits = StopBits.One;
|
|
mySerialPort.DataBits = 8;
|
|
mySerialPort.Handshake = Handshake.None;
|
|
|
|
// 綁定資料接收事件
|
|
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
|
|
AppDomain.CurrentDomain.ProcessExit += (s, e) =>
|
|
{
|
|
cts.Cancel();
|
|
};
|
|
|
|
try
|
|
{
|
|
mySerialPort.Open();
|
|
Console.WriteLine($"{selectedPort} 串列埠已成功開啟。");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"開啟 {selectedPort} 串列埠時發生錯誤: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
|
|
private readonly ConcurrentQueue<string> commandQueue = new();
|
|
public readonly CancellationTokenSource cts = new();
|
|
private bool isProcessing = false;
|
|
|
|
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
SerialPort sp = (SerialPort)sender;
|
|
|
|
if (!sp.IsOpen)
|
|
return;
|
|
|
|
int bytesToRead = sp.BytesToRead;
|
|
if (bytesToRead > 0)
|
|
{
|
|
byte[] buffer = new byte[bytesToRead];
|
|
int bytesRead = sp.Read(buffer, 0, bytesToRead);
|
|
|
|
StringBuilder hexData = new StringBuilder(bytesRead * 2);
|
|
for (int i = 0; i < bytesRead; i++)
|
|
{
|
|
hexData.AppendFormat("{0:X2}", buffer[i]);
|
|
}
|
|
|
|
string indata = hexData.ToString();
|
|
|
|
Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 遙控器: {indata}");
|
|
|
|
// 將資料放入佇列
|
|
commandQueue.Enqueue(indata);
|
|
|
|
// 如果尚未啟動處理迴圈,則啟動
|
|
if (!isProcessing)
|
|
{
|
|
isProcessing = true;
|
|
Task.Run(ProcessQueueAsync);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"接收資料時發生錯誤: {ex.Message}");
|
|
}
|
|
}
|
|
private async Task ProcessQueueAsync()
|
|
{
|
|
while (!cts.Token.IsCancellationRequested)
|
|
{
|
|
while (commandQueue.TryDequeue(out var cmd))
|
|
{
|
|
try
|
|
{
|
|
commandHandler.ProcessData(cmd);
|
|
}
|
|
catch (Exception processEx)
|
|
{
|
|
Console.WriteLine($"處理資料時發生錯誤: {processEx.Message}");
|
|
}
|
|
}
|
|
|
|
await Task.Delay(10); // 避免 CPU 空轉
|
|
}
|
|
cts.Cancel();
|
|
isProcessing = false;
|
|
}
|
|
|
|
|
|
|
|
public static void CloseSerialPortSafely()
|
|
{
|
|
if (mySerialPort != null)
|
|
{
|
|
try
|
|
{
|
|
if (mySerialPort.IsOpen)
|
|
{
|
|
mySerialPort.Close();
|
|
// Console.WriteLine("串列埠已成功關閉。");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"關閉串列埠時發生錯誤: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// public void EnsurePortConnection()
|
|
// {
|
|
// try
|
|
// {
|
|
// if (mySerialPort == null || !mySerialPort.IsOpen)
|
|
// {
|
|
// // Console.WriteLine("串列埠已中斷,重新初始化...");
|
|
// InitializeSerialPort();
|
|
// }
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
// // Console.WriteLine($"檢查串列埠連接時發生錯誤: {ex.Message}");
|
|
// }
|
|
// }
|
|
|
|
|
|
// public static void LogData(string data)
|
|
// {
|
|
// string filePath = Path.Combine(Application.StartupPath, "dataLog.txt");
|
|
|
|
// try
|
|
// {
|
|
// File.AppendAllText(filePath, $"{DateTime.Now}: {data}{Environment.NewLine}");
|
|
// // Console.WriteLine($"資料已記錄到日誌: {data}");
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
// // Console.WriteLine($"記錄日誌時發生錯誤: {ex.Message}");
|
|
// }
|
|
// }
|
|
// public void CheckAndResetConnection()
|
|
// {
|
|
// if (mySerialPort == null || !mySerialPort.IsOpen)
|
|
// {
|
|
// // Console.WriteLine("發現串列埠問題,嘗試重啟連線...");
|
|
// EnsurePortConnection();
|
|
// }
|
|
// }
|
|
// public void SendHeartbeat()
|
|
// {
|
|
// if (mySerialPort != null && mySerialPort.IsOpen)
|
|
// {
|
|
// try
|
|
// {
|
|
// mySerialPort.Write("HEARTBEAT");
|
|
// // Console.WriteLine("已發送心跳信號");
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
// // Console.WriteLine($"發送心跳信號時發生錯誤: {ex.Message}");
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
}
|