using NLog.Targets; using RobotNet.MapShares.Dtos; using RobotNet.RobotShares.OpenACS; using RobotNet.Shares; using System.Text.Json; namespace RobotNet.RobotManager.Services.OpenACS; public class TrafficACS(OpenACSManager OpenACSManager, IConfiguration Configuration, LoggerController Logger) { public bool Enable => OpenACSManager.TrafficEnable; private readonly double TrafficCheckingDistanceMin = Configuration.GetValue("TrafficConfig:CheckingDistanceMin", 3); public readonly double DeviationDistance = Configuration.GetValue("TrafficConfig:DeviationDistance", 0.5); private static readonly JsonSerializerOptions jsonSerializeOptions = new() { WriteIndented = true, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; public async Task> RequestIn(string robotId, string zoneId) { try { if (!OpenACSManager.TrafficEnable) return new(true, "Kết nối với hệ thống traffic ACS không được bật") { Data = true }; using var HttpClient = new HttpClient() { Timeout = TimeSpan.FromSeconds(15) }; var model = new TrafficACSRequestV2(robotId, zoneId, TrafficRequestType.IN.ToInOutString()); var response = await (await HttpClient.PostAsJsonAsync(OpenACSManager.TrafficURL, model)).Content.ReadFromJsonAsync() ?? throw new OpenACSException("Lỗi giao tiếp với hệ thống traffic ACS"); if (response.Body.AgvId != robotId) throw new OpenACSException($"Dữ liệu hệ thống traffic ACS agv_id trả về {response.Body.AgvId} không trùng với dữ liệu gửi đi {robotId}"); if (response.Body.TrafficZoneId != zoneId) throw new OpenACSException($"Dữ liệu hệ thống traffic ACS traffic_zone_id trả về {response.Body.TrafficZoneId} không trùng với dữ liệu gửi đi {zoneId}"); if (response.Body.InOut != TrafficRequestType.IN.ToInOutString()) throw new OpenACSException($"Dữ liệu hệ thống traffic ACS inout trả về {response.Body.InOut} không trùng với dữ liệu gửi đi in"); Logger.Info($"{robotId} yêu cầu vào traffic zone {zoneId} \nRequest: {JsonSerializer.Serialize(model, jsonSerializeOptions)}\n trả về kết quả: {JsonSerializer.Serialize(response, jsonSerializeOptions)}"); return new(true, "Yêu cầu vào traffic zone thành công") { Data = response.Body.Result == TrafficACSResult.GO }; } catch (OpenACSException ex) { Logger.Warning($"{robotId} request in xảy ra lỗi: {ex.Message}"); return new(false, ex.Message); } catch (Exception ex) { Logger.Warning($"{robotId} request In xảy ra lỗi: {ex.Message}"); return new(false, "Lỗi giao tiếp với hệ thống traffic ACS"); } } public async Task> RequestOut(string robotId, string zoneId) { try { if (!OpenACSManager.TrafficEnable) return new(true, "Kết nối với hệ thống traffic ACS không được bật") { Data = true}; using var HttpClient = new HttpClient() { Timeout = TimeSpan.FromSeconds(15) }; var model = new TrafficACSRequestV2(robotId, zoneId, TrafficRequestType.OUT.ToInOutString()); var response = await (await HttpClient.PostAsJsonAsync(OpenACSManager.TrafficURL, model)).Content.ReadFromJsonAsync() ?? throw new OpenACSException("Lỗi giao tiếp với hệ thống traffic ACS"); if (response.Body.AgvId != robotId) throw new OpenACSException($"Dữ liệu hệ thống traffic ACS agv_id trả về {response.Body.AgvId} không trùng với dữ liệu gửi đi {robotId}"); if (response.Body.TrafficZoneId != zoneId) throw new OpenACSException($"Dữ liệu hệ thống traffic ACS traffic_zone_id trả về {response.Body.TrafficZoneId} không trùng với dữ liệu gửi đi {zoneId}"); if (response.Body.InOut != TrafficRequestType.OUT.ToInOutString()) throw new OpenACSException($"Dữ liệu hệ thống traffic ACS inout trả về {response.Body.InOut} không trùng với dữ liệu gửi đi out"); Logger.Info($"{robotId} yêu cầu ra khỏi traffic zone {zoneId} \nRequest: {JsonSerializer.Serialize(model, jsonSerializeOptions)}\n trả về kết quả: {JsonSerializer.Serialize(response, jsonSerializeOptions)}"); return new(true, "Yêu cầu ra khỏi traffic zone thành công") { Data = response.Body.Result == TrafficACSResult.GO }; } catch (OpenACSException ex) { Logger.Warning($"{robotId} request out xảy ra lỗi: {ex.Message}"); return new(false, ex.Message); } catch (Exception ex) { Logger.Warning($"{robotId} request Out xảy ra lỗi: {ex.Message}"); return new(false, "Lỗi giao tiếp với hệ thống traffic ACS"); } } public Dictionary GetZones(Guid inNodeId, NodeDto[] nodes, Dictionary zones) { int inNodeIndex = Array.FindIndex(nodes, n => n.Id == inNodeId); if (inNodeId == Guid.Empty || (inNodeIndex != -1 && inNodeIndex < nodes.Length - 1)) { List baseNodes = []; List basezones = []; double distance = 0; int index = inNodeIndex != -1 ? inNodeIndex + 1 : 1; for (; index < nodes.Length; index++) { baseNodes.Add(nodes[index]); distance += Math.Sqrt(Math.Pow(nodes[index].X - nodes[index - 1].X, 2) + Math.Pow(nodes[index].Y - nodes[index - 1].Y, 2)); if (distance > TrafficCheckingDistanceMin) break; } Dictionary nodeZones = []; foreach (var node in baseNodes) { if (zones.TryGetValue(node.Id, out ZoneDto[]? zone) && zone is not null && zone.Length > 0) nodeZones.Add(node.Id, zone); else nodeZones.Add(node.Id, []); } return nodeZones; } else if (inNodeIndex == nodes.Length - 1) return []; else { Logger.Warning($"Không tìm thấy node {inNodeId} trong danh sách nodes hoặc node này."); return []; } } }