Implement automatic connecting loop

Add virtual com port manager
pull/7/head
LeapwardKoex 2024-02-08 22:55:04 +13:00
parent d97eeafdcb
commit 3a7183399e
6 changed files with 233 additions and 127 deletions

View File

@ -12,6 +12,7 @@ internal class MaiTouchComConnector
{ {
private static SerialPort? serialPort; private static SerialPort? serialPort;
private bool isActiveMode; private bool isActiveMode;
private bool _connected;
private readonly MaiTouchSensorButtonStateManager _buttonState; private readonly MaiTouchSensorButtonStateManager _buttonState;
public Action<string> OnConnectStatusChange public Action<string> OnConnectStatusChange
@ -35,61 +36,53 @@ internal class MaiTouchComConnector
_buttonState = buttonState; _buttonState = buttonState;
} }
public async Task startLoopAsync() public async Task StartTouchSensorPolling()
{ {
string virtualPort = "COM23"; // Adjust as needed if (!_connected)
try
{ {
var virtualPort = "COM23"; // Adjust as needed
// Use setupc.exe to create a virtual COM port pair try
//StartProcessWithAdminRights("C:\\Program Files (x86)\\com0com\\setupc.exe", $"PortName=COM3 PortName=COM23");
serialPort = new SerialPort(virtualPort, 9600, Parity.None, 8, StopBits.One);
serialPort.DataReceived += SerialPort_DataReceived;
serialPort.Open();
Console.WriteLine("Serial port opened successfully.");
OnConnectStatusChange("Connected");
// Simulate receiving a STAT packet
// Keep the program running to simulate active mode
while (true)
{ {
if (isActiveMode) OnConnectStatusChange("Conecting...");
serialPort = new SerialPort(virtualPort, 9600, Parity.None, 8, StopBits.One);
serialPort.DataReceived += SerialPort_DataReceived;
serialPort.Open();
Console.WriteLine("Serial port opened successfully.");
OnConnectStatusChange("Connected to port");
_connected = true;
while (true)
{ {
SendTouchscreenState(); if (isActiveMode)
await Task.Delay(1); {
SendTouchscreenState();
await Task.Delay(1);
}
else
{
await Task.Delay(100);
}
} }
else
}
catch (Exception ex)
{
Console.WriteLine($"Error opening serial port: {ex.Message}");
Application.Current.Dispatcher.Invoke(() =>
{ {
await Task.Delay(100); MessageBox.Show(ex.Message, "Error connecting to COM port", MessageBoxButton.OK, MessageBoxImage.Error);
});
}
finally
{
_connected = false;
OnConnectStatusChange("Not Connected");
if (serialPort?.IsOpen == true)
{
serialPort.Close();
} }
} }
}
catch (Exception ex)
{
Console.WriteLine($"Error opening serial port: {ex.Message}");
Application.Current.Dispatcher.Invoke(() =>
{
MessageBox.Show(ex.Message, "Error connecting to COM port", MessageBoxButton.OK, MessageBoxImage.Error);
});
}
finally
{
OnConnectStatusChange("Not Connected");
// Close the serial port when done
if (serialPort.IsOpen)
{
serialPort.Close();
}
// Use setupc.exe to remove the virtual COM port pair with administrator privileges
//StartProcessWithAdminRights("C:\\Program Files (x86)\\com0com\\setupc.exe", $"remove 0");
} }
} }
@ -142,6 +135,5 @@ internal class MaiTouchComConnector
{ {
var currentState = _buttonState.GetCurrentState(); var currentState = _buttonState.GetCurrentState();
serialPort?.Write(currentState, 0, currentState.Length); serialPort?.Write(currentState, 0, currentState.Length);
//Console.WriteLine($"Sent Touchscreen State: {report}");*/
} }
} }

View File

@ -3,9 +3,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfMaiTouchEmulator"
mc:Ignorable="d" mc:Ignorable="d"
Title="MainWindow" Height="243" Width="800"> Closing="MainWindow_Closing"
Title="MainWindow" Height="282" Width="800">
<Grid Background="Transparent"> <Grid Background="Transparent">
<Button x:Name="ConnectToPortButton" Content="Connect to port" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="ConnectToPortButton_Click" Width="105"/> <Button x:Name="ConnectToPortButton" Content="Connect to port" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="ConnectToPortButton_Click" Width="105"/>
<TextBox x:Name="RecievedLogBox" <TextBox x:Name="RecievedLogBox"
@ -31,7 +31,10 @@
<CheckBox x:Name="automaticPortConnecting" HorizontalAlignment="Left" Margin="10,81,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="Automatic port connecting" IsChecked="{Binding Path=IsAutomaticPortConnectingEnabled}" Click="automaticPortConnecting_Click"/> <CheckBox x:Name="automaticPortConnecting" HorizontalAlignment="Left" Margin="10,81,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="Automatic port connecting" IsChecked="{Binding Path=IsAutomaticPortConnectingEnabled}" Click="automaticPortConnecting_Click"/>
<Label x:Name="label1" Content="Connection state" HorizontalAlignment="Left" Margin="238,8,0,0" VerticalAlignment="Top"/> <Label x:Name="label1" Content="Connection state" HorizontalAlignment="Left" Margin="238,8,0,0" VerticalAlignment="Top"/>
<Label x:Name="connectionStateLabel" Content="Not connected" HorizontalAlignment="Left" Margin="238,31,0,0" VerticalAlignment="Top" FontSize="10"/> <Label x:Name="connectionStateLabel" Content="Not connected" HorizontalAlignment="Left" Margin="238,31,0,0" VerticalAlignment="Top" FontSize="10"/>
<CheckBox x:Name="exitWithSinmai" HorizontalAlignment="Left" Margin="10,103,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="Automatic port connecting" IsChecked="{Binding IsExitWithSinmaiEnabled}" Click="exitWithSinmai_Click"/> <CheckBox x:Name="exitWithSinmai" HorizontalAlignment="Left" Margin="10,103,0,0" VerticalAlignment="Top" Height="17" Width="224" Content="Exit when Sinmai exits" IsChecked="{Binding IsExitWithSinmaiEnabled}" Click="exitWithSinmai_Click"/>
<Button x:Name="buttonInstallComPort" Content="Install com port" HorizontalAlignment="Left" Margin="10,147,0,0" VerticalAlignment="Top" Click="buttonInstallComPort_Click"/>
<Button x:Name="buttonUninstallComPorts" Content="Uninstall com port" HorizontalAlignment="Left" Margin="10,172,0,0" VerticalAlignment="Top" Click="buttonUninstallComPorts_Click"/>
<Button x:Name="buttonListComPorts" Content="List installed com ports" HorizontalAlignment="Left" Margin="10,197,0,0" VerticalAlignment="Top" Click="buttonListComPorts_Click"/>
</Grid> </Grid>

View File

@ -18,7 +18,8 @@ public partial class MainWindow : Window
{ {
private readonly MaiTouchSensorButtonStateManager buttonState; private readonly MaiTouchSensorButtonStateManager buttonState;
private MaiTouchComConnector connector; private MaiTouchComConnector connector;
private readonly TouchPanel _touchPanel; private readonly VirtualComPortManager comPortManager;
private TouchPanel _touchPanel;
public MainWindow() public MainWindow()
{ {
@ -26,7 +27,12 @@ public partial class MainWindow : Window
Title = "Mai Touch Emulator"; Title = "Mai Touch Emulator";
buttonState = new MaiTouchSensorButtonStateManager(buttonStateValue); buttonState = new MaiTouchSensorButtonStateManager(buttonStateValue);
connector = new MaiTouchComConnector(buttonState); connector = new MaiTouchComConnector(buttonState);
connector.OnConnectStatusChange = (status) => Title = $"Mai Touch Emulator - {status}"; comPortManager = new VirtualComPortManager();
connector.OnConnectStatusChange = (status) =>
{
connectionStateLabel.Content = status;
};
connector.OnDataSent = (data) => connector.OnDataSent = (data) =>
{ {
Application.Current.Dispatcher.Invoke(() => Application.Current.Dispatcher.Invoke(() =>
@ -44,22 +50,34 @@ public partial class MainWindow : Window
}); });
}; };
_touchPanel = new TouchPanel(); Loaded += (s, e) => {
_touchPanel.onTouch = (value) => { buttonState.PressButton(value); }; _touchPanel = new TouchPanel();
_touchPanel.onRelease = (value) => { buttonState.ReleaseButton(value); }; _touchPanel.onTouch = (value) => { buttonState.PressButton(value); };
_touchPanel.Show(); _touchPanel.onRelease = (value) => { buttonState.ReleaseButton(value); };
DataContext = new MainWindowViewModel() _touchPanel.Show();
{ _touchPanel.Owner = this;
IsDebugEnabled = Properties.Settings.Default.IsDebugEnabled, DataContext = new MainWindowViewModel()
IsAutomaticPortConnectingEnabled = Properties.Settings.Default.IsAutomaticPortConnectingEnabled, {
IsAutomaticPositioningEnabled = Properties.Settings.Default.IsAutomaticPositioningEnabled, IsDebugEnabled = Properties.Settings.Default.IsDebugEnabled,
IsExitWithSinmaiEnabled = Properties.Settings.Default.IsExitWithSinmaiEnabled IsAutomaticPortConnectingEnabled = Properties.Settings.Default.IsAutomaticPortConnectingEnabled,
}; IsAutomaticPositioningEnabled = Properties.Settings.Default.IsAutomaticPositioningEnabled,
IsExitWithSinmaiEnabled = Properties.Settings.Default.IsExitWithSinmaiEnabled
};
var dataContext = (MainWindowViewModel)DataContext; var dataContext = (MainWindowViewModel)DataContext;
_touchPanel.SetDebugMode(dataContext.IsDebugEnabled); _touchPanel.SetDebugMode(dataContext.IsDebugEnabled);
AutomaticTouchPanelPositioningLoop(); AutomaticTouchPanelPositioningLoop();
ExitWithSinmaiLoop(); AutomaticcPortConnectingLoop();
ExitWithSinmaiLoop();
};
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
foreach (Window childWindow in OwnedWindows)
{
childWindow.Close();
}
} }
private async void ExitWithSinmaiLoop() private async void ExitWithSinmaiLoop()
@ -98,9 +116,23 @@ public partial class MainWindow : Window
} }
} }
private async void AutomaticcPortConnectingLoop()
{
var dataContext = (MainWindowViewModel)DataContext;
while (true)
{
if (dataContext.IsAutomaticPortConnectingEnabled)
{
await connector.StartTouchSensorPolling();
}
await Task.Delay(1000);
}
}
private async void ConnectToPortButton_Click(object sender, RoutedEventArgs e) private async void ConnectToPortButton_Click(object sender, RoutedEventArgs e)
{ {
await connector.startLoopAsync(); await connector.StartTouchSensorPolling();
} }
private void debugMode_Click(object sender, RoutedEventArgs e) private void debugMode_Click(object sender, RoutedEventArgs e)
@ -139,4 +171,22 @@ public partial class MainWindow : Window
Properties.Settings.Default.IsExitWithSinmaiEnabled = dataContext.IsExitWithSinmaiEnabled; Properties.Settings.Default.IsExitWithSinmaiEnabled = dataContext.IsExitWithSinmaiEnabled;
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();
} }
private async void buttonInstallComPort_Click(object sender, RoutedEventArgs e)
{
var output = await comPortManager.InstallComPort();
MessageBox.Show(output);
}
private async void buttonUninstallComPorts_Click(object sender, RoutedEventArgs e)
{
var output = await comPortManager.UninstallVirtualPorts();
MessageBox.Show(output);
}
private async void buttonListComPorts_Click(object sender, RoutedEventArgs e)
{
var output = await comPortManager.CheckInstalledPortsAsync();
MessageBox.Show(output);
}
} }

View File

@ -1,65 +1,59 @@
using System; using System.ComponentModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace WpfMaiTouchEmulator namespace WpfMaiTouchEmulator;
internal class MainWindowViewModel : INotifyPropertyChanged
{ {
class MainWindowViewModel : INotifyPropertyChanged private bool _isAutomaticPortConnectingEnabled;
private bool _isDebugEnabled;
private bool _isAutomaticPositioningEnabled;
private bool _isExitWithSinmaiEnabled;
public bool IsDebugEnabled
{ {
private bool _isAutomaticPortConnectingEnabled; get => _isDebugEnabled;
private bool _isDebugEnabled; set
private bool _isAutomaticPositioningEnabled;
private bool _isExitWithSinmaiEnabled;
public bool IsDebugEnabled
{ {
get => _isDebugEnabled; _isDebugEnabled = value;
set OnPropertyChanged();
{
_isDebugEnabled = value;
OnPropertyChanged();
}
}
public bool IsAutomaticPositioningEnabled
{
get => _isAutomaticPositioningEnabled;
set
{
_isAutomaticPositioningEnabled = value;
OnPropertyChanged();
}
}
public bool IsAutomaticPortConnectingEnabled
{
get => _isAutomaticPortConnectingEnabled;
set
{
_isAutomaticPortConnectingEnabled = value;
OnPropertyChanged();
}
}
public bool IsExitWithSinmaiEnabled
{
get => _isExitWithSinmaiEnabled;
set
{
_isExitWithSinmaiEnabled = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
} }
public bool IsAutomaticPositioningEnabled
{
get => _isAutomaticPositioningEnabled;
set
{
_isAutomaticPositioningEnabled = value;
OnPropertyChanged();
}
}
public bool IsAutomaticPortConnectingEnabled
{
get => _isAutomaticPortConnectingEnabled;
set
{
_isAutomaticPortConnectingEnabled = value;
OnPropertyChanged();
}
}
public bool IsExitWithSinmaiEnabled
{
get => _isExitWithSinmaiEnabled;
set
{
_isExitWithSinmaiEnabled = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
} }

View File

@ -189,7 +189,10 @@ public partial class TouchPanel : Window
private void HighlightElement(System.Windows.Controls.Image element, bool highlight) private void HighlightElement(System.Windows.Controls.Image element, bool highlight)
{ {
element.Opacity = highlight ? 0.8 : 0.3; if (Properties.Settings.Default.IsDebugEnabled)
{
element.Opacity = highlight ? 0.8 : 0.3;
}
} }
} }

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfMaiTouchEmulator
{
class VirtualComPortManager
{
public Task<string> CheckInstalledPortsAsync()
{
return ExecuteCommandAsync("C:\\Program Files (x86)\\com0com\\setupc.exe", $"list");
}
public Task<string> InstallComPort()
{
return ExecuteCommandAsync("C:\\Program Files (x86)\\com0com\\setupc.exe", $"install PortName=COM3 PortName=COM23");
}
public Task<string> UninstallVirtualPorts()
{
return ExecuteCommandAsync("C:\\Program Files (x86)\\com0com\\setupc.exe", $"uninstall");
}
private async Task<string> ExecuteCommandAsync(string command, string arguments)
{
var processStartInfo = new ProcessStartInfo
{
FileName = command,
Arguments = arguments,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = "C:\\Program Files (x86)\\com0com"
};
var outputBuilder = new StringBuilder();
using (var process = new Process { StartInfo = processStartInfo })
{
process.OutputDataReceived += (sender, args) =>
{
if (args.Data != null)
outputBuilder.AppendLine(args.Data);
};
process.ErrorDataReceived += (sender, args) =>
{
if (args.Data != null)
outputBuilder.AppendLine(args.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
await process.WaitForExitAsync();
return outputBuilder.ToString();
}
}
}
}