c64_userport_playground/web/c64_inteface/MonitorBackgroundService.cs

159 lines
5.2 KiB
C#

using System.IO.Ports;
using System.Text;
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 readonly ArduinoHub _arduinoHub;
private SerialPort? _arduinoPort;
public MonitorBackgroundService(ILogger<MonitorBackgroundService> logger, ArduinoMessageContainer arduinoMessageContainer, ArduinoHub arduinoHub)
{
_logger = logger;
_arduinoMessageContainer = arduinoMessageContainer;
_arduinoHub = arduinoHub;
}
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
{
await _arduinoHub.SendMessage(new ArduinoMessage
{
Status = "online",
StatusText =
$"Sending message with {Encoding.ASCII.GetBytes(_arduinoMessageContainer.Message).Length} bytes..."
});
_logger.LogInformation("Sending message: {Message}", _arduinoMessageContainer.Message);
await _arduinoHub.SendMessage(new ArduinoMessage
{
Status = "online",
StatusText = "Done"
});
_arduinoPort?.WriteLine(_arduinoMessageContainer.Message);
_arduinoMessageContainer.Ready = false;
}
catch (Exception e)
{
Console.WriteLine(e);
await _arduinoHub.SendMessage(new ArduinoMessage()
{
StatusText = "Error: " + e.Message,
Status = "offline"
});
}
}
}
}
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)
{
await _arduinoHub.SendMessage(new ArduinoMessage()
{
StatusText = "Searching for Arduino...",
Status = "offline"
});
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);
await _arduinoHub.SendMessage(new ArduinoMessage()
{
StatusText = $"Arduino found on {portName}",
Status = "online"
});
_arduinoPort = port;
return;
}
await Task.Delay(1000, cancellationToken);
}
}
public void Dispose()
{
_arduinoPort?.Close();
_arduinoPort?.Dispose();
}
}