111 lines
4.1 KiB
C#
111 lines
4.1 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace RobotNet10.RobotApp.Xloc;
|
|
|
|
/// <summary>
|
|
/// Polls XLOC diagnostics and calls <see cref="XlocIntegrationService.StartLocalization"/> when
|
|
/// state transitions to READY (3) with an active map. Does not depend on the web UI.
|
|
/// </summary>
|
|
public sealed class XlocAutoLocalizationHostedService : BackgroundService
|
|
{
|
|
private readonly XlocIntegrationService _xloc;
|
|
private readonly ILogger<XlocAutoLocalizationHostedService> _logger;
|
|
private readonly XlocIntegrationConfiguration _config = new();
|
|
private byte? _previousXlocState;
|
|
private bool _hasAutoStartedOnce;
|
|
|
|
public XlocAutoLocalizationHostedService(
|
|
XlocIntegrationService xloc,
|
|
IConfiguration configuration,
|
|
ILogger<XlocAutoLocalizationHostedService> logger)
|
|
{
|
|
_xloc = xloc;
|
|
_logger = logger;
|
|
|
|
var section = configuration.GetSection("Xloc:Integration");
|
|
if (section.Exists())
|
|
section.Bind(_config);
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
if (!_config.Enabled)
|
|
{
|
|
_logger.LogInformation("XlocAutoLocalizationHostedService skipped: Xloc:Integration:Enabled is false");
|
|
return;
|
|
}
|
|
|
|
if (!_config.AutoStartLocalizationOnReady)
|
|
{
|
|
_logger.LogInformation("XlocAutoLocalizationHostedService skipped: AutoStartLocalizationOnReady is false");
|
|
return;
|
|
}
|
|
|
|
var pollMs = Math.Clamp(_config.AutoStartLocalizationPollIntervalMs, 100, 10_000);
|
|
var cooldownMs = Math.Max(0, _config.AutoStartLocalizationCooldownAfterStopMs);
|
|
|
|
_logger.LogInformation(
|
|
"XlocAutoLocalizationHostedService running (poll {PollMs}ms, stop cooldown {CooldownMs}ms)",
|
|
pollMs,
|
|
cooldownMs);
|
|
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
await Task.Delay(pollMs, stoppingToken).ConfigureAwait(false);
|
|
|
|
var diag = _xloc.GetDiagnostics();
|
|
if (diag == null)
|
|
continue;
|
|
|
|
var s = diag.XlocState;
|
|
var transitionedToReady = s == 3 && (!_previousXlocState.HasValue || _previousXlocState.Value != 3);
|
|
_previousXlocState = s;
|
|
|
|
if (!transitionedToReady || _hasAutoStartedOnce)
|
|
continue;
|
|
|
|
if (string.IsNullOrWhiteSpace(diag.CurrentActiveMap))
|
|
{
|
|
_logger.LogDebug("Auto-start localization skipped: no active map in diagnostics");
|
|
continue;
|
|
}
|
|
|
|
if (_xloc.LastLocalizationStopUtc.HasValue)
|
|
{
|
|
var elapsedMs = (DateTime.UtcNow - _xloc.LastLocalizationStopUtc.Value).TotalMilliseconds;
|
|
if (elapsedMs < cooldownMs)
|
|
{
|
|
_logger.LogDebug(
|
|
"Auto-start localization skipped: cooldown after stop ({ElapsedMs:F0}ms < {CooldownMs}ms)",
|
|
elapsedMs,
|
|
cooldownMs);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
_hasAutoStartedOnce = true;
|
|
|
|
_logger.LogInformation(
|
|
"XLOC READY with active map '{Map}'. Auto-starting localization...",
|
|
diag.CurrentActiveMap);
|
|
|
|
var ok = _xloc.StartLocalization();
|
|
if (!ok)
|
|
_logger.LogWarning("Auto-start localization failed (StartLocalization returned false)");
|
|
}
|
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
|
{
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error in XlocAutoLocalizationHostedService loop");
|
|
}
|
|
}
|
|
}
|
|
}
|