124 lines
3.9 KiB
C#
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();
|
|
}
|
|
} |