c64_userport_playground/web/c64_inteface/MonitorBackgroundService.cs
2025-09-28 20:11:11 +02:00

124 lines
3.9 KiB
C#

using System.IO.Ports;
namespace c64_inteface;
public class MonitorBackgroundService : IHostedService, IDisposable
{
private const string ArduinoId = "F28339B0-78C6-4445-905A-76F77F667D95";
private const string ArduinoPingMsg = "ping " + ArduinoId + "\n";
private const string ArduinoPongMsg = "pong " + ArduinoId;
private readonly ILogger<MonitorBackgroundService> _logger;
private readonly ArduinoMessageContainer _arduinoMessageContainer;
private SerialPort? _arduinoPort;
public MonitorBackgroundService(ILogger<MonitorBackgroundService> logger, ArduinoMessageContainer arduinoMessageContainer)
{
_logger = logger;
_arduinoMessageContainer = arduinoMessageContainer;
}
public Task StartAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("{Service} running.", nameof(MonitorBackgroundService));
Task.Run(() => RunServiceAsync(stoppingToken), stoppingToken);
return Task.CompletedTask;
}
private async Task DoWork(CancellationToken cancellationToken)
{
_logger.LogInformation("DoWork running...");
while (!cancellationToken.IsCancellationRequested)
{
if (_arduinoMessageContainer.Ready)
{
try
{
_logger.LogInformation("Sending message: {Message}", _arduinoMessageContainer.Message);
_arduinoPort?.WriteLine(_arduinoMessageContainer.Message);
_arduinoMessageContainer.Ready = false;
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
private async Task RunServiceAsync(CancellationToken cancellationToken)
{
await FindArduinoPort(cancellationToken);
await DoWork(cancellationToken);
}
public Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("{Service} is stopping.", nameof(MonitorBackgroundService));
return Task.CompletedTask;
}
private async Task FindArduinoPort(CancellationToken cancellationToken)
{
while (_arduinoPort is null && !cancellationToken.IsCancellationRequested)
{
var ports = SerialPort.GetPortNames().ToList();
_logger.LogInformation("available ports: {Ports}", ports);
foreach (var portName in ports)
{
var port = new SerialPort(portName, 9600);
port.ReadTimeout = 1000;
try
{
port.Open();
await Task.Delay(2000, cancellationToken);
}
catch (IOException)
{
continue;
}
port.WriteLine(ArduinoPingMsg);
try
{
var response = port.ReadLine();
_logger.LogInformation(response);
if (!response.Contains(ArduinoPongMsg))
{
_logger.LogInformation("{portName} not my arduino", portName);
port.Close();
continue;
}
}
catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
_logger.LogInformation("{portName} did not respond", portName);
continue;
}
_logger.LogInformation("Arduino found on {portName}", portName);
_arduinoPort = port;
return;
}
await Task.Delay(1000, cancellationToken);
}
}
public void Dispose()
{
_arduinoPort?.Close();
_arduinoPort?.Dispose();
}
}