MaiTouchSensorEmulator/Managers/MaiTouchComConnector.cs

200 lines
6.3 KiB
C#
Raw Permalink Normal View History

2024-02-08 18:02:54 +08:00
using System.IO.Ports;
2024-02-08 12:41:21 +08:00
using System.Windows;
2024-11-09 06:30:47 +08:00
namespace WpfMaiTouchEmulator.Managers;
2024-04-24 18:49:02 +08:00
internal class MaiTouchComConnector(MaiTouchSensorButtonStateManager buttonState, MainWindowViewModel viewModel)
2024-02-08 12:41:21 +08:00
{
private static SerialPort? serialPort;
private bool isActiveMode;
private bool _connected;
private CancellationTokenSource? _tokenSource;
private Thread? _pollThread;
2024-02-11 17:54:28 +08:00
private bool _shouldReconnect = true;
private readonly MaiTouchSensorButtonStateManager _buttonState = buttonState;
2024-04-24 18:49:02 +08:00
private readonly MainWindowViewModel _viewModel = viewModel;
2024-02-08 12:41:21 +08:00
public Action<string>? OnConnectStatusChange
2024-02-08 12:41:21 +08:00
{
get;
internal set;
}
public Action? OnConnectError
2024-02-10 07:58:13 +08:00
{
get;
internal set;
}
public Action<string>? OnDataSent
2024-02-08 12:41:21 +08:00
{
get;
internal set;
}
public Action<string>? OnDataRecieved
2024-02-08 12:41:21 +08:00
{
get;
internal set;
}
public void StartTouchSensorPolling()
2024-02-08 12:41:21 +08:00
{
2024-02-11 17:54:28 +08:00
if (!_connected && _shouldReconnect)
2024-02-08 12:41:21 +08:00
{
Logger.Info("Trying to connect to COM port...");
var virtualPort = "COM23"; // Adjust as needed
try
2024-02-08 12:41:21 +08:00
{
2024-04-24 18:49:02 +08:00
OnConnectStatusChange?.Invoke(_viewModel.TxtComPortConnecting);
serialPort = new SerialPort(virtualPort, 9600, Parity.None, 8, StopBits.One)
{
WriteTimeout = 100
};
serialPort.DataReceived += SerialPort_DataReceived;
serialPort.Open();
Logger.Info("Serial port opened successfully.");
2024-04-24 18:49:02 +08:00
OnConnectStatusChange?.Invoke(_viewModel.TxtComPortConnected);
_connected = true;
_tokenSource = new CancellationTokenSource(); // Create a token source.
_pollThread = new Thread(() => PollingThread(_tokenSource.Token)); // Pass the token to the thread you want to stop.
_pollThread.Priority = ThreadPriority.Highest;
_pollThread.Start();
2024-02-08 12:41:21 +08:00
}
2024-02-11 18:34:51 +08:00
catch (TimeoutException) { }
catch (Exception ex)
2024-02-08 12:41:21 +08:00
{
OnConnectError?.Invoke();
Application.Current.Dispatcher.Invoke(() =>
{
2024-04-24 18:49:02 +08:00
MessageBox.Show(ex.Message, _viewModel.TxtErrorConnectingToPortHeader, MessageBoxButton.OK, MessageBoxImage.Error);
});
2024-04-24 18:49:02 +08:00
Logger.Error("Error on starting polling", ex);
Logger.Info("Disconnecting from COM port");
_connected = false;
2024-04-24 18:49:02 +08:00
OnConnectStatusChange?.Invoke(_viewModel.LbConnectionStateNotConnected);
if (serialPort?.IsOpen == true)
{
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
serialPort.Close();
}
}
}
}
private void PollingThread(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
if (isActiveMode)
{
SendTouchscreenState();
Thread.Sleep(1);
}
else
{
Thread.Sleep(100);
2024-02-08 12:41:21 +08:00
}
}
}
2024-02-11 18:34:51 +08:00
public async Task Disconnect()
2024-02-11 17:54:28 +08:00
{
Logger.Info("Disconnecting from COM port");
2024-02-11 17:54:28 +08:00
_shouldReconnect = false;
2024-02-11 18:34:51 +08:00
_connected = false;
try
2024-02-11 17:54:28 +08:00
{
if (_tokenSource != null && !_tokenSource.IsCancellationRequested)
{
_tokenSource.Cancel();
_pollThread?.Join();
_tokenSource.Dispose();
_tokenSource = null;
}
if (serialPort != null)
2024-02-11 18:34:51 +08:00
{
serialPort.DtrEnable = false;
serialPort.RtsEnable = false;
serialPort.DataReceived -= SerialPort_DataReceived;
await Task.Delay(200);
if (serialPort.IsOpen)
{
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
serialPort.Close();
}
2024-02-11 18:34:51 +08:00
}
2024-02-11 18:34:51 +08:00
}
catch (Exception ex)
{
Logger.Error("Error whilst disconnecting from COM port", ex);
2024-02-11 18:34:51 +08:00
MessageBox.Show(ex.Message);
2024-02-11 17:54:28 +08:00
}
}
2024-02-08 12:41:21 +08:00
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var recievedData = serialPort?.ReadExisting();
var commands = recievedData?.Split(new[] { '}' }, StringSplitOptions.RemoveEmptyEntries);
if (commands != null)
2024-02-08 12:41:21 +08:00
{
foreach (var command in commands)
2024-02-08 12:41:21 +08:00
{
var cleanedCommand = command.TrimStart('{');
Logger.Info($"Received serial data: {cleanedCommand}");
OnDataRecieved?.Invoke(cleanedCommand);
2024-02-08 12:41:21 +08:00
if (cleanedCommand == "STAT")
{
isActiveMode = true;
}
else if (cleanedCommand == "RSET")
{
2024-02-08 12:41:21 +08:00
}
else if (cleanedCommand == "HALT")
{
isActiveMode = false;
}
else if (cleanedCommand[2] == 'r' || cleanedCommand[2] == 'k')
{
var leftOrRight = cleanedCommand[0];
var sensor = cleanedCommand[1];
var ratio = cleanedCommand[3];
var newString = $"({leftOrRight}{sensor}{cleanedCommand[2]}{ratio})";
serialPort?.Write(newString);
OnDataSent?.Invoke(newString);
}
else
{
Logger.Warn($"Unhandled serial data command {cleanedCommand}");
}
2024-02-08 12:41:21 +08:00
}
}
}
void SendTouchscreenState()
{
2024-02-11 18:34:51 +08:00
if (_connected)
{
var currentState = _buttonState.GetCurrentState();
try
{
serialPort?.Write(currentState, 0, currentState.Length);
}
2024-11-09 06:30:47 +08:00
catch (Exception ex)
{
if (Properties.Settings.Default.IsDebugEnabled)
{
Logger.Error("Error when writing to serial port on button update", ex);
}
}
2024-02-11 18:34:51 +08:00
}
2024-02-08 12:41:21 +08:00
}
}