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 _logger; private readonly ArduinoMessageContainer _arduinoMessageContainer; private SerialPort? _arduinoPort; public MonitorBackgroundService(ILogger 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(); } }