Files
ulapp/FieldLogger/Services/PointLogger.cs

74 lines
2.6 KiB
C#

using FieldLogger.Models;
using FieldLogger.Services.Data;
using FieldLogger.Services.Sync;
using Microsoft.Extensions.Logging;
namespace FieldLogger.Services;
/// <summary>
/// Joins UM receiver log packets with the current GNSS fix and persists them
/// under the active job. Runs for the lifetime of the app.
/// </summary>
public sealed class PointLogger
{
private readonly UmReceiverService _locator;
private readonly MaglinkService _gps;
private readonly AppDatabase _database;
private readonly SettingsService _settings;
private readonly IMqttSyncService _sync;
private readonly ILogger<PointLogger> _logger;
/// <summary>Raised (on the UI thread) after a point is saved.</summary>
public event EventHandler<LoggedPoint>? PointSaved;
/// <summary>Raised when a packet arrives but no active job is selected, so the point was dropped.</summary>
public event EventHandler? PacketIgnoredNoJob;
public PointLogger(UmReceiverService locator, MaglinkService gps, AppDatabase database,
SettingsService settings, IMqttSyncService sync, ILogger<PointLogger> logger)
{
_locator = locator;
_gps = gps;
_database = database;
_settings = settings;
_sync = sync;
_logger = logger;
_locator.PacketReceived += OnPacketReceived;
}
private void OnPacketReceived(object? sender, UmLogPacket packet)
{
_ = HandlePacketAsync(packet);
}
private async Task HandlePacketAsync(UmLogPacket packet)
{
try
{
var jobId = _settings.ActiveJobId;
if (jobId is null)
{
_logger.LogWarning("Log packet received but no active job; point dropped");
MainThread.BeginInvokeOnMainThread(() => PacketIgnoredNoJob?.Invoke(this, EventArgs.Empty));
return;
}
var fix = _gps.FreshFix();
var point = LoggedPoint.From(jobId.Value, packet, _locator.DeviceInfo, fix, _gps.DeviceInfo);
point.SyncPointId = Guid.CreateVersion7().ToString();
await _database.AddPointAsync(point);
await _sync.PublishPointAsync(point);
_logger.LogInformation(
"Point {Id}/{SyncPointId} saved to job {JobId} (gps valid: {GpsValid}, sync error: {SyncError})",
point.Id, point.SyncPointId, jobId, point.GpsValid, point.SyncError);
MainThread.BeginInvokeOnMainThread(() => PointSaved?.Invoke(this, point));
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to save logged point");
}
}
}