fix bugs with UI for gps denied

This commit is contained in:
Alex Bezdieniezhnykh
2025-05-30 02:09:15 +03:00
parent d87ddb5f6a
commit b345137f16
10 changed files with 143 additions and 85 deletions
@@ -0,0 +1,10 @@
using System.Windows.Media;
using MediatR;
namespace Azaion.Common.Events;
public class SetStatusTextEvent(string text, Color? color = null) : INotification
{
public string Text { get; set; } = text;
public Color? Color { get; set; } = color;
}
@@ -0,0 +1,14 @@
using MediatR;
namespace Azaion.Common.Services;
public class GPSMatcherEventHandler(IGpsMatcherService gpsMatcherService) :
INotificationHandler<GPSMatcherResultEvent>,
INotificationHandler<GPSMatcherFinishedEvent>
{
public async Task Handle(GPSMatcherResultEvent result, CancellationToken cancellationToken) =>
await gpsMatcherService.SetGpsResult(result, cancellationToken);
public async Task Handle(GPSMatcherFinishedEvent notification, CancellationToken cancellationToken) =>
await gpsMatcherService.FinishGPS(notification, cancellationToken);
}
+8 -11
View File
@@ -1,9 +1,7 @@
using System.IO;
using Azaion.CommonSecurity;
using Azaion.CommonSecurity.DTO;
using MediatR;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
namespace Azaion.Common.Services;
@@ -11,12 +9,11 @@ public interface IGpsMatcherService
{
Task RunGpsMatching(string userRouteDir, double initialLatitude, double initialLongitude, CancellationToken detectToken = default);
void StopGpsMatching();
Task SetGpsResult(GPSMatcherResultEvent result, CancellationToken detectToken = default);
Task FinishGPS(GPSMatcherFinishedEvent notification, CancellationToken cancellationToken);
}
public class GpsMatcherService(IGpsMatcherClient gpsMatcherClient, ISatelliteDownloader satelliteTileDownloader, IOptions<DirectoriesConfig> dirConfig)
: IGpsMatcherService,
INotificationHandler<GPSMatcherResultEvent>,
INotificationHandler<GPSMatcherFinishedEvent>
public class GpsMatcherService(IGpsMatcherClient gpsMatcherClient, ISatelliteDownloader satelliteTileDownloader, IOptions<DirectoriesConfig> dirConfig) : IGpsMatcherService
{
private readonly DirectoriesConfig _dirConfig = dirConfig.Value;
private const int ZOOM_LEVEL = 18;
@@ -63,7 +60,7 @@ public class GpsMatcherService(IGpsMatcherClient gpsMatcherClient, ISatelliteDow
{
var filename = Path.GetFileName(fullName);
File.Copy(Path.Combine(_userRouteDir, filename), Path.Combine(_routeDir, filename));
return new { Filename = filename, Index = startIndex + index };
return new { Filename = Path.GetFileNameWithoutExtension(fullName), Index = startIndex + index };
})
.ToDictionary(x => x.Filename, x => x.Index);
@@ -83,16 +80,16 @@ public class GpsMatcherService(IGpsMatcherClient gpsMatcherClient, ISatelliteDow
gpsMatcherClient.Stop();
}
public Task Handle(GPSMatcherResultEvent result, CancellationToken cancellationToken)
public async Task SetGpsResult(GPSMatcherResultEvent result, CancellationToken detectToken = default)
{
_currentIndex = _currentRouteImages[result.Image];
_currentRouteImages.Remove(result.Image);
_currentLat = result.Latitude;
_currentLon = result.Longitude;
_currentIndex = _currentRouteImages[result.Image];
return Task.CompletedTask;
await Task.CompletedTask;
}
public async Task Handle(GPSMatcherFinishedEvent notification, CancellationToken cancellationToken)
public async Task FinishGPS(GPSMatcherFinishedEvent notification, CancellationToken cancellationToken)
{
if (_currentRouteImages.Count == 0 && _currentIndex < _allRouteImages.Count)
await StartMatchingRound(_currentIndex);
+44 -29
View File
@@ -1,7 +1,9 @@
using System.Diagnostics;
using System.IO;
using Azaion.CommonSecurity;
using Azaion.CommonSecurity.DTO;
using MediatR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NetMQ;
using NetMQ.Sockets;
@@ -32,15 +34,17 @@ public class StartMatchingEvent
public class GpsMatcherClient : IGpsMatcherClient
{
private readonly IMediator _mediator;
private readonly ILogger<GpsMatcherClient> _logger;
private readonly string _requestAddress;
private readonly RequestSocket _requestSocket = new();
private readonly string _subscriberAddress;
private readonly SubscriberSocket _subscriberSocket = new();
private readonly NetMQPoller _poller = new();
public GpsMatcherClient(IMediator mediator, IOptions<GpsDeniedClientConfig> gpsConfig)
public GpsMatcherClient(IMediator mediator, IOptions<GpsDeniedClientConfig> gpsConfig, ILogger<GpsMatcherClient> logger)
{
_mediator = mediator;
_logger = logger;
try
{
using var process = new Process();
@@ -67,41 +71,52 @@ public class GpsMatcherClient : IGpsMatcherClient
_requestAddress = $"tcp://{gpsConfig.Value.ZeroMqHost}:{gpsConfig.Value.ZeroMqPort}";
_requestSocket.Connect(_requestAddress);
_subscriberAddress = $"tcp://{gpsConfig.Value.ZeroMqHost}:{gpsConfig.Value.ZeroMqSubscriberPort}";
_subscriberAddress = $"tcp://{gpsConfig.Value.ZeroMqHost}:{gpsConfig.Value.ZeroMqReceiverPort}";
_subscriberSocket.Connect(_subscriberAddress);
_subscriberSocket.Subscribe("");
_subscriberSocket.ReceiveReady += async (_, e) => await ProcessClientCommand(e.Socket);
_subscriberSocket.ReceiveReady += async (sender, e) => await ProcessClientCommand(sender, e);
_poller.Add(_subscriberSocket);
_poller.RunAsync();
}
private async Task ProcessClientCommand(NetMQSocket socket)
private async Task ProcessClientCommand(object? sender, NetMQSocketEventArgs e)
{
while (socket.TryReceiveFrameString(TimeSpan.Zero, out var str))
while (e.Socket.TryReceiveFrameString(TimeSpan.FromMilliseconds(100), out var str))
{
if (string.IsNullOrEmpty(str))
continue;
switch (str)
try
{
case "FINISHED":
await _mediator.Publish(new GPSMatcherFinishedEvent());
break;
case "OK":
await _mediator.Publish(new GPSMatcherJobAcceptedEvent());
break;
default:
var parts = str.Split(',');
if (parts.Length != 5)
throw new Exception("Matching Result Failed");
if (string.IsNullOrEmpty(str))
continue;
await _mediator.Publish(new GPSMatcherResultEvent
{
Index = int.Parse(parts[0]),
Image = parts[1],
Latitude = double.Parse(parts[2]),
Longitude = double.Parse(parts[3]),
MatchType = parts[4]
});
break;
switch (str)
{
case "FINISHED":
await _mediator.Publish(new GPSMatcherFinishedEvent());
break;
case "OK":
await _mediator.Publish(new GPSMatcherJobAcceptedEvent());
break;
default:
var parts = str.Split(',');
if (parts.Length != 5)
throw new Exception("Matching Result Failed");
var filename = Path.GetFileNameWithoutExtension(parts[1]);
await _mediator.Publish(new GPSMatcherResultEvent
{
Index = int.Parse(parts[0]),
Image = filename,
Latitude = double.Parse(parts[2]),
Longitude = double.Parse(parts[3]),
MatchType = parts[4]
});
break;
}
}
catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
}
}
}
+10 -3
View File
@@ -5,9 +5,11 @@ using System.Net.Http;
using System.Net.Http.Json;
using Azaion.Common.DTO;
using Azaion.Common.DTO.Config;
using Azaion.Common.Events;
using Azaion.Common.Extensions;
using Azaion.CommonSecurity;
using Azaion.CommonSecurity.DTO;
using MediatR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
@@ -26,7 +28,8 @@ public class SatelliteDownloader(
ILogger<SatelliteDownloader> logger,
IOptions<MapConfig> mapConfig,
IOptions<DirectoriesConfig> directoriesConfig,
IHttpClientFactory httpClientFactory)
IHttpClientFactory httpClientFactory,
IMediator mediator)
: ISatelliteDownloader
{
private const int INPUT_TILE_SIZE = 256;
@@ -45,15 +48,19 @@ public class SatelliteDownloader(
public async Task GetTiles(double centerLat, double centerLon, double radiusM, int zoomLevel, CancellationToken token = default)
{
await mediator.Publish(new SetStatusTextEvent($"Завантажується супутникові зображення по координатах: центр: lat: {centerLat:F3} lon: {centerLon:F3} квадрат {radiusM}м * {radiusM}м, zoom: {zoomLevel}..."), token);
//empty Satellite directory
if (Directory.Exists(_satDirectory))
Directory.Delete(_satDirectory, true);
Directory.CreateDirectory(_satDirectory);
var downloadTilesResult = await DownloadTiles(centerLat, centerLon, radiusM, zoomLevel, token);
await mediator.Publish(new SetStatusTextEvent("Завершено! Склеюється в 1 зображення..."), token);
var image = ComposeTiles(downloadTilesResult.Tiles, token);
if (image != null)
await SplitToTiles(image, downloadTilesResult, token);
if (image == null)
return;
await mediator.Publish(new SetStatusTextEvent("Розбиття на малі зображення для опрацювання..."), token);
await SplitToTiles(image, downloadTilesResult, token);
}
private async Task SplitToTiles(Image<Rgba32> image, DownloadTilesResult bounds, CancellationToken token = default)