166 lines
4.7 KiB
C#
166 lines
4.7 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using RobotNet10.CANOpen;
|
|
|
|
namespace RobotNet10.RobotApp.Drivers.Battery.Varta;
|
|
|
|
public sealed class VartaChargerSimulatorService : IHostedService, IDisposable
|
|
{
|
|
private readonly ILogger<VartaChargerSimulatorService> _logger;
|
|
private readonly ICanOpenManager _canOpenManager;
|
|
private readonly VartaChargerSimulatorOptions _options;
|
|
private readonly SemaphoreSlim _controlLock = new(1, 1);
|
|
|
|
private Task? _runTask;
|
|
private CancellationTokenSource? _runCts;
|
|
private string _currentInterface = "can0";
|
|
private bool _disposed;
|
|
|
|
public bool IsRunning => _runTask is { IsCompleted: false };
|
|
public string CurrentInterface => _currentInterface;
|
|
|
|
public VartaChargerSimulatorService(
|
|
IConfiguration configuration,
|
|
ILogger<VartaChargerSimulatorService> logger,
|
|
ICanOpenManager canOpenManager)
|
|
{
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
_canOpenManager = canOpenManager ?? throw new ArgumentNullException(nameof(canOpenManager));
|
|
|
|
_options = new VartaChargerSimulatorOptions();
|
|
configuration.GetSection("Varta:Charger59VSimulator").Bind(_options);
|
|
}
|
|
|
|
public async Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
if (_options.Enabled)
|
|
{
|
|
await StartSimulatorAsync(_options.CanInterface, cancellationToken);
|
|
return;
|
|
}
|
|
|
|
_logger.LogInformation("Varta Charger59V simulator is disabled at startup.");
|
|
}
|
|
|
|
public async Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
await StopSimulatorAsync(cancellationToken);
|
|
}
|
|
|
|
public async Task<bool> StartSimulatorAsync(string? canInterface = null, CancellationToken cancellationToken = default)
|
|
{
|
|
ThrowIfDisposed();
|
|
|
|
await _controlLock.WaitAsync(cancellationToken);
|
|
try
|
|
{
|
|
if (_runTask is { IsCompleted: false })
|
|
{
|
|
return false;
|
|
}
|
|
|
|
_currentInterface = string.IsNullOrWhiteSpace(canInterface) ? "can0" : canInterface;
|
|
_runCts = new CancellationTokenSource();
|
|
_runTask = RunSimulatorAsync(_currentInterface, _runCts.Token);
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
_controlLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<bool> StopSimulatorAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
ThrowIfDisposed();
|
|
|
|
Task? runTask;
|
|
CancellationTokenSource? runCts;
|
|
|
|
await _controlLock.WaitAsync(cancellationToken);
|
|
try
|
|
{
|
|
if (_runTask is not { IsCompleted: false } || _runCts is null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
runTask = _runTask;
|
|
runCts = _runCts;
|
|
_runTask = null;
|
|
_runCts = null;
|
|
}
|
|
finally
|
|
{
|
|
_controlLock.Release();
|
|
}
|
|
|
|
runCts.Cancel();
|
|
try
|
|
{
|
|
await runTask.WaitAsync(cancellationToken);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
runCts.Dispose();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private async Task RunSimulatorAsync(string canInterface, CancellationToken token)
|
|
{
|
|
_logger.LogInformation("Starting Varta Charger59V simulator on CAN interface {CanInterface}", canInterface);
|
|
|
|
try
|
|
{
|
|
var simulator = new Charger59V(_canOpenManager, canInterface, token);
|
|
await simulator.RunAsync();
|
|
}
|
|
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
|
{
|
|
_logger.LogInformation("Varta Charger59V simulator stopped.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Varta Charger59V simulator crashed.");
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_disposed = true;
|
|
_runCts?.Cancel();
|
|
_runCts?.Dispose();
|
|
_controlLock.Dispose();
|
|
}
|
|
|
|
private void ThrowIfDisposed()
|
|
{
|
|
if (_disposed)
|
|
{
|
|
throw new ObjectDisposedException(nameof(VartaChargerSimulatorService));
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed class VartaChargerSimulatorOptions
|
|
{
|
|
public bool Enabled { get; set; }
|
|
public string CanInterface { get; set; } = "can0";
|
|
}
|
|
|
|
public sealed class VartaChargerSimulatorStartRequest
|
|
{
|
|
public string? CanInterface { get; set; }
|
|
}
|