diff --git a/RobotApp.Client/Pages/Order/OrderMess.razor b/RobotApp.Client/Pages/Order/OrderMess.razor index 5f13060..28b8bfa 100644 --- a/RobotApp.Client/Pages/Order/OrderMess.razor +++ b/RobotApp.Client/Pages/Order/OrderMess.razor @@ -8,6 +8,7 @@ @inject IJSRuntime JS @inject IDialogService DialogService @inject HttpClient Http +@inject ISnackbar Snackbar
@@ -219,14 +220,49 @@ try { + var orderMsg = JsonSerializer.Deserialize(OrderJson); + if (orderMsg is null) + { + Snackbar.Add("Unable to convert JSON to Order", Severity.Warning); + return; + } + if (orderMsg.Nodes.Length < 1) + { + Snackbar.Add("The order must contain at least one node (number of nodes > 0)", Severity.Warning); + return; + } + if (orderMsg.Nodes.Length - 1 != orderMsg.Edges.Length) + { + Snackbar.Add("Order must have a number of edges equal to the number of nodes minus 1", Severity.Warning); + return; + } + + foreach(var edge in orderMsg.Edges) + { + if (!orderMsg.Nodes.Any(n => n.NodeId == edge.StartNodeId)) + { + Snackbar.Add($"The edge {edge.EdgeId} references a startNodeId {edge.StartNodeId} that does not exist in the list of nodes", Severity.Warning); + return; + } + if (!orderMsg.Nodes.Any(n => n.NodeId == edge.EndNodeId)) + { + Snackbar.Add($"The edge {edge.EdgeId} references a startNodeId {edge.EndNodeId} that does not exist in the list of nodes", Severity.Warning); + return; + } + } + var response = await Http.PostAsJsonAsync( "/api/order", - JsonSerializer.Deserialize(OrderJson) + JsonSerializer.Deserialize(OrderJson) ); sendSuccess = response.IsSuccessStatusCode; } + catch(JsonException jsonEx) + { + Snackbar.Add($"Json to Order failed: {jsonEx.Message}", Severity.Warning); + } catch { sendSuccess = false; diff --git a/RobotApp.Client/Services/UiEdge.cs b/RobotApp.Client/Services/UiEdge.cs index 048d3dc..41bab21 100644 --- a/RobotApp.Client/Services/UiEdge.cs +++ b/RobotApp.Client/Services/UiEdge.cs @@ -268,7 +268,7 @@ public class OrderMessage } ).ToArray(); } - public object ToSchemaObject() + public OrderMsg ToSchemaObject() { // ================= SORT NODES BY UI SEQUENCE ================= var orderedNodes = Nodes @@ -277,50 +277,50 @@ public class OrderMessage // ================= BUILD NODE OBJECTS ================= var nodeObjects = orderedNodes - .Select((n, index) => new + .Select((n, index) => new Node { - nodeId = n.NodeId, - sequenceId = index * 2, // ✅ NODE = EVEN - released = n.Released, + NodeId = n.NodeId, + SequenceId = index * 2, // ✅ NODE = EVEN + Released = n.Released, - nodePosition = new + NodePosition = new NodePosition { - x = n.NodePosition.X, - y = n.NodePosition.Y, - theta = n.NodePosition.Theta, + X = n.NodePosition.X, + Y = n.NodePosition.Y, + Theta = n.NodePosition.Theta, - allowedDeviationXY = n.NodePosition.AllowedDeviationXY, - allowedDeviationTheta = n.NodePosition.AllowedDeviationTheta, + AllowedDeviationXY = n.NodePosition.AllowedDeviationXY, + AllowedDeviationTheta = n.NodePosition.AllowedDeviationTheta, - mapId = string.IsNullOrWhiteSpace(n.NodePosition.MapId) + MapId = string.IsNullOrWhiteSpace(n.NodePosition.MapId) ? "MAP_01" : n.NodePosition.MapId }, - actions = n.Actions? - .Select(a => new + Actions = n.Actions? + .Select(a => new VDA5050.InstantAction.Action { - actionId = a.ActionId, - actionType = a.ActionType, - blockingType = a.BlockingType, + ActionId = a.ActionId, + ActionType = a.ActionType, + BlockingType = a.BlockingType, - actionParameters = a.ActionParameters? - .Select(p => new + ActionParameters = a.ActionParameters? + .Select(p => new ActionParameter { - key = p.Key, - value = p.Value + Key = p.Key, + Value = p.Value }) .ToArray() - ?? Array.Empty() + ?? [] }) .ToArray() - ?? Array.Empty() + ?? [] }) .ToArray(); // ================= BUILD EDGE OBJECTS ================= - var edgeObjects = Edges - .Select((e, index) => + Edge[] edgeObjects = Edges + .Select((e, index) => { int sequenceId = index * 2 + 1; // ✅ EDGE = ODD @@ -339,24 +339,24 @@ public class OrderMessage // ================================================= if (e.HasTrajectory && e.Trajectory != null) { - return new + return new Edge { - baseEdge.edgeId, - baseEdge.sequenceId, - baseEdge.released, - baseEdge.startNodeId, - baseEdge.endNodeId, + EdgeId = baseEdge.edgeId, + SequenceId = baseEdge.sequenceId, + Released= baseEdge.released, + StartNodeId= baseEdge.startNodeId, + EndNodeId= baseEdge.endNodeId, - trajectory = new + Trajectory = new Trajectory { - degree = e.Trajectory.Degree, - knotVector = e.Trajectory.KnotVector, - controlPoints = e.Trajectory.ControlPoints - .Select(p => new { x = p.X, y = p.Y }) + Degree = e.Trajectory.Degree, + KnotVector = e.Trajectory.KnotVector, + ControlPoints = e.Trajectory.ControlPoints + .Select(p => new ControlPoint { X = p.X, Y = p.Y , Weight = 1}) .ToArray() }, - actions = Array.Empty() + Actions = [] }; } @@ -365,14 +365,15 @@ public class OrderMessage // ================================================= if (e.Radius <= 0) { - return new + return new Edge { - baseEdge.edgeId, - baseEdge.sequenceId, - baseEdge.released, - baseEdge.startNodeId, - baseEdge.endNodeId, - actions = Array.Empty() + EdgeId = baseEdge.edgeId, + SequenceId = baseEdge.sequenceId, + Released = baseEdge.released, + StartNodeId = baseEdge.startNodeId, + EndNodeId = baseEdge.endNodeId, + + Actions = [] }; } @@ -392,42 +393,41 @@ public class OrderMessage e.Quadrant ); - return new + return new Edge { - baseEdge.edgeId, - baseEdge.sequenceId, - baseEdge.released, - baseEdge.startNodeId, - baseEdge.endNodeId, + EdgeId = baseEdge.edgeId, + SequenceId = baseEdge.sequenceId, + Released = baseEdge.released, + StartNodeId = baseEdge.startNodeId, + EndNodeId = baseEdge.endNodeId, - trajectory = result.Trajectory, - actions = Array.Empty() + Actions = [] }; }) .ToArray(); // ================= FINAL SCHEMA OBJECT ================= - return new + return new OrderMsg { - headerId = HeaderId++, + HeaderId = (uint)HeaderId++, - timestamp = string.IsNullOrWhiteSpace(Timestamp) + Timestamp = string.IsNullOrWhiteSpace(Timestamp) ? DateTime.UtcNow.ToString("O") : Timestamp, - version = Version, - manufacturer = Manufacturer, - serialNumber = SerialNumber, + Version = Version, + Manufacturer = Manufacturer, + SerialNumber = SerialNumber, - orderId = OrderId= Guid.NewGuid().ToString(), - orderUpdateId = OrderUpdateId, + OrderId = OrderId= Guid.NewGuid().ToString(), + OrderUpdateId = OrderUpdateId, - zoneSetId = string.IsNullOrWhiteSpace(ZoneSetId) + ZoneSetId = string.IsNullOrWhiteSpace(ZoneSetId) ? null : ZoneSetId, - nodes = nodeObjects, - edges = edgeObjects + Nodes = nodeObjects, + Edges = edgeObjects, }; } } diff --git a/RobotApp/Services/Robot/RobotConfiguration.cs b/RobotApp/Services/Robot/RobotConfiguration.cs index 4f3c0f0..e2fe8c4 100644 --- a/RobotApp/Services/Robot/RobotConfiguration.cs +++ b/RobotApp/Services/Robot/RobotConfiguration.cs @@ -58,7 +58,7 @@ public class RobotConfiguration(IServiceProvider ServiceProvider, Logger(); await robotConnection.StopConnection(); - _ = Task.Run(async () => await robotConnection.StartConnection(CancellationToken.None)); + robotConnection.StartConnection(); } } else throw new Exception("Chưa có cấu hình VDA5050."); diff --git a/RobotApp/Services/Robot/RobotConnection.cs b/RobotApp/Services/Robot/RobotConnection.cs index cf3cbed..e3b8dd8 100644 --- a/RobotApp/Services/Robot/RobotConnection.cs +++ b/RobotApp/Services/Robot/RobotConnection.cs @@ -53,8 +53,15 @@ public class RobotConnection(RobotConfiguration RobotConfiguration, if (MqttClient is not null && MqttClient.IsConnected) return await MqttClient.PublishAsync($"{VDA5050Setting.TopicPrefix}/{VDA5050Setting.Manufacturer}/{RobotConfiguration.SerialNumber}/{topic}", data); return new(false, "Chưa có kết nối tới broker"); } - - public async Task StartConnection(CancellationToken cancellationToken) + public void StartConnection() + { + Task.Run(async () => + { + await StartConnectionAsync(CancellationToken.None); + Logger.Info("Robot đã kết nối tới Fleet Manager."); + }); + } + public async Task StartConnectionAsync(CancellationToken cancellationToken) { MqttClient = new MQTTClient(RobotConfiguration.SerialNumber, VDA5050Setting, MQTTClientLogger); MqttClient.OrderChanged += OrderChanged; diff --git a/RobotApp/Services/Robot/RobotControllerInitialize.cs b/RobotApp/Services/Robot/RobotControllerInitialize.cs index 022bc75..79c9bd7 100644 --- a/RobotApp/Services/Robot/RobotControllerInitialize.cs +++ b/RobotApp/Services/Robot/RobotControllerInitialize.cs @@ -39,8 +39,7 @@ public partial class RobotController ConnectionManager.OrderUpdated += NewOrderUpdated; ConnectionManager.ActionUpdated += NewInstantActionUpdated; - await ConnectionManager.StartConnection(cancellationToken); - Logger.Info("Robot đã kết nối tới Fleet Manager."); + ConnectionManager.StartConnection(); StateManager.TransitionTo(SystemStateType.Standby); if (!RobotConfiguration.IsSimulation)