Files
annotations/Azaion.Common/Services/GpsMatcherClient.cs
T
Alex Bezdieniezhnykh bb6413c4f0 put default config if no config.json found
refactor Constants
2025-06-30 20:06:02 +03:00

142 lines
5.0 KiB
C#

using System.Diagnostics;
using System.IO;
using Azaion.Common.DTO;
using Azaion.Common.Events;
using MediatR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NetMQ;
using NetMQ.Sockets;
namespace Azaion.Common.Services;
public interface IGpsMatcherClient : IDisposable
{
Task StartMatching(StartMatchingEvent startEvent);
void Stop();
}
public class StartMatchingEvent
{
public string RouteDir { get; set; } = null!;
public string SatelliteImagesDir { get; set; } = null!;
public int ImagesCount { get; set; }
public GeoPoint GeoPoint { get; set; } = null!;
public int Altitude { get; set; } = 400;
public double CameraSensorWidth { get; set; } = 23.5;
public double CameraFocalLength { get; set; } = 24;
public override string ToString() =>
$"{RouteDir},{SatelliteImagesDir},{ImagesCount},{GeoPoint.Lat},{GeoPoint.Lon},{Altitude},{CameraSensorWidth},{CameraFocalLength}";
}
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, ILogger<GpsMatcherClient> logger)
{
_mediator = mediator;
_logger = logger;
try
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo
{
FileName = Constants.ExternalGpsDeniedPath,
Arguments = $"zeromq --rep {gpsConfig.Value.ZeroMqPort} --pub {gpsConfig.Value.ZeroMqReceiverPort}",
WorkingDirectory = Constants.EXTERNAL_GPS_DENIED_FOLDER,
CreateNoWindow = true
};
process.Start();
}
catch (Exception e)
{
_logger.LogError(e, e.ToString());
}
_requestAddress = $"tcp://{gpsConfig.Value.ZeroMqHost}:{gpsConfig.Value.ZeroMqPort}";
_requestSocket.Connect(_requestAddress);
_subscriberAddress = $"tcp://{gpsConfig.Value.ZeroMqHost}:{gpsConfig.Value.ZeroMqReceiverPort}";
_subscriberSocket.Connect(_subscriberAddress);
_subscriberSocket.Subscribe("");
_subscriberSocket.ReceiveReady += async (sender, e) => await ProcessClientCommand(sender, e);
_poller.Add(_subscriberSocket);
_poller.RunAsync();
}
private async Task ProcessClientCommand(object? sender, NetMQSocketEventArgs e)
{
while (e.Socket.TryReceiveFrameString(TimeSpan.FromMilliseconds(100), out var str))
{
try
{
if (string.IsNullOrEmpty(str))
continue;
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 != 6)
throw new Exception("Matching Result Failed");
var filename = Path.GetFileNameWithoutExtension(parts[1]);
await _mediator.Publish(new GPSMatcherResultEvent
{
Index = int.Parse(parts[0]),
Image = filename,
GeoPoint = new GeoPoint(double.Parse(parts[2]), double.Parse(parts[3])),
KeyPoints = int.Parse(parts[4]),
MatchType = Enum.TryParse<MatchTypeEnum>(parts[5], out var type) ? type : MatchTypeEnum.None
});
break;
}
}
catch (Exception ex)
{
_logger.LogError(ex, ex.Message);
}
}
}
public async Task StartMatching(StartMatchingEvent e)
{
_requestSocket.SendFrame(e.ToString());
_requestSocket.TryReceiveFrameString(TimeSpan.FromMilliseconds(300), out var response);
if (response != "OK")
{
_logger.LogError(response);
await _mediator.Publish(new SetStatusTextEvent(response ?? "", true));
}
}
public void Stop() => _requestSocket.SendFrame("STOP");
public void Dispose()
{
_poller.Stop();
_poller.Dispose();
_requestSocket.SendFrame("EXIT");
_requestSocket.Disconnect(_requestAddress);
_requestSocket.Dispose();
_subscriberSocket.Disconnect(_subscriberAddress);
_subscriberSocket.Dispose();
}
}