using System.Diagnostics; using Azaion.CommonSecurity; using Azaion.CommonSecurity.DTO; using MediatR; using Microsoft.Extensions.Options; using NetMQ; using NetMQ.Sockets; namespace Azaion.Common.Services; public interface IGpsMatcherClient : IDisposable { void 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 double Latitude { get; set; } public double Longitude { get; set; } 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},{Latitude},{Longitude},{Altitude},{CameraSensorWidth},{CameraFocalLength}"; } public class GpsMatcherClient : IGpsMatcherClient { private readonly IMediator _mediator; private readonly GpsDeniedClientConfig _gpsDeniedClientConfig; private string _requestAddress; private readonly RequestSocket _requestSocket = new(); private string _subscriberAddress; private readonly SubscriberSocket _subscriberSocket = new(); public GpsMatcherClient(IMediator mediator, IOptions gpsDeniedClientConfig) { _mediator = mediator; _gpsDeniedClientConfig = gpsDeniedClientConfig.Value; Start(); } private void Start(CancellationToken ct = default) { try { using var process = new Process(); process.StartInfo = new ProcessStartInfo { FileName = SecurityConstants.ExternalGpsDeniedPath, WorkingDirectory = SecurityConstants.EXTERNAL_GPS_DENIED_FOLDER //Arguments = $"-e {credentials.Email} -p {credentials.Password} -f {apiConfig.ResourcesFolder}", //RedirectStandardOutput = true, //RedirectStandardError = true, //CreateNoWindow = true }; process.OutputDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); }; process.ErrorDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); }; process.Start(); } catch (Exception e) { Console.WriteLine(e); //throw; } _requestAddress = $"tcp://{_gpsDeniedClientConfig.ZeroMqHost}:{_gpsDeniedClientConfig.ZeroMqPort}"; _requestSocket.Connect(_requestAddress); _subscriberAddress = $"tcp://{_gpsDeniedClientConfig.ZeroMqHost}:{_gpsDeniedClientConfig.ZeroMqSubscriberPort}"; _subscriberSocket.Connect(_subscriberAddress); _subscriberSocket.Subscribe(""); _subscriberSocket.ReceiveReady += async (_, e) => await ProcessClientCommand(e.Socket, ct); } private async Task ProcessClientCommand(NetMQSocket socket, CancellationToken ct) { while (socket.TryReceiveFrameString(TimeSpan.Zero, out var str)) { if (string.IsNullOrEmpty(str)) continue; switch (str) { case "FINISHED": await _mediator.Publish(new GPSMatcherFinishedEvent(), ct); break; case "OK": await _mediator.Publish(new GPSMatcherJobAcceptedEvent(), ct); break; default: var parts = str.Split(','); if (parts.Length != 5) throw new Exception("Matching Result Failed"); 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] }, ct); break; } } } public void StartMatching(StartMatchingEvent e) { _requestSocket.SendFrame(e.ToString()); } public void Stop() => _requestSocket.SendFrame("STOP"); public void Dispose() { _requestSocket.SendFrame("EXIT"); _requestSocket.Disconnect(_requestAddress); _requestSocket.Dispose(); _subscriberSocket.Disconnect(_subscriberAddress); _subscriberSocket.Dispose(); } }