using FieldLogger.Models; using FieldLogger.Services.Data; using FieldLogger.Services.Sync; using Microsoft.Extensions.Logging; namespace FieldLogger.Services; /// /// Joins UM receiver log packets with the current GNSS fix and persists them /// under the active job. Runs for the lifetime of the app. /// 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 _logger; /// Raised (on the UI thread) after a point is saved. public event EventHandler? PointSaved; /// Raised when a packet arrives but no active job is selected, so the point was dropped. public event EventHandler? PacketIgnoredNoJob; public PointLogger(UmReceiverService locator, MaglinkService gps, AppDatabase database, SettingsService settings, IMqttSyncService sync, ILogger 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"); } } }