diff --git a/RobotApp.Client/Pages/Order/EdgesPanel.razor b/RobotApp.Client/Pages/Order/EdgesPanel.razor index fb62c5a..6f6920d 100644 --- a/RobotApp.Client/Pages/Order/EdgesPanel.razor +++ b/RobotApp.Client/Pages/Order/EdgesPanel.razor @@ -141,8 +141,7 @@ [Parameter] public OrderMessage Order { get; set; } = default!; [Parameter] public EventCallback OnAddEdge { get; set; } - [Parameter] public EventCallback OnRemoveEdge { get; set; } - [Parameter] public EventCallback OnApplyCurve { get; set; } + [Parameter] public EventCallback OnRemoveEdge { get; set; } [Parameter] public EventCallback OnOrderChanged { get; set; } @@ -158,15 +157,9 @@ await OnOrderChanged.InvokeAsync(); } - private async Task RemoveEdgeAsync(UiEdge edge) + private async Task RemoveEdgeAsync(VDA5050.Order.Edge edge) { await OnRemoveEdge.InvokeAsync(edge); await OnOrderChanged.InvokeAsync(); } - - private async Task ApplyCurveAsync(UiEdge edge) - { - await OnApplyCurve.InvokeAsync(edge); - await OnOrderChanged.InvokeAsync(); - } } diff --git a/RobotApp.Client/Pages/Order/ImportOrderDialog.razor b/RobotApp.Client/Pages/Order/ImportOrderDialog.razor index 007bee4..3ba8b6e 100644 --- a/RobotApp.Client/Pages/Order/ImportOrderDialog.razor +++ b/RobotApp.Client/Pages/Order/ImportOrderDialog.razor @@ -132,17 +132,17 @@ try { - using var doc = JsonDocument.Parse(JsonText); - var root = doc.RootElement; - - // ===== BASIC STRUCTURE CHECK ===== - if (!root.TryGetProperty("nodes", out _) || - !root.TryGetProperty("edges", out _)) + var order = JsonSerializer.Deserialize(JsonText, new JsonSerializerOptions { - throw new Exception("Missing 'nodes' or 'edges' field."); + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }); + if(order is null) + { + ShowWarning = true; + ErrorMessage = "Can not convert file to Order message"; + return; } - - var order = OrderMessage.FromSchemaObject(root); ValidateOrder(order); MudDialog.Close(DialogResult.Ok(order)); @@ -160,15 +160,15 @@ } // ================= DOMAIN VALIDATION ================= - private void ValidateOrder(OrderMessage order) + private void ValidateOrder(OrderMsg order) { - if (order.Nodes.Count == 0) + if (order.Nodes.Length == 0) throw new Exception("Order must contain at least one node."); - if (order.Nodes.Count != order.Edges.Count + 1) + if (order.Nodes.Length != order.Edges.Length + 1) throw new Exception( - $"Invalid path structure: Nodes count ({order.Nodes.Count}) " + - $"must equal Edges count + 1 ({order.Edges.Count + 1})." + $"Invalid path structure: Nodes count ({order.Nodes.Length}) " + + $"must equal Edges count + 1 ({order.Edges.Length + 1})." ); var nodeIds = order.Nodes diff --git a/RobotApp.Client/Pages/Order/JsonOutputPanel.razor b/RobotApp.Client/Pages/Order/JsonOutputPanel.razor index 11ba185..fbd2f25 100644 --- a/RobotApp.Client/Pages/Order/JsonOutputPanel.razor +++ b/RobotApp.Client/Pages/Order/JsonOutputPanel.razor @@ -6,14 +6,14 @@
- @* Import JSON - *@ + @@ -99,9 +98,9 @@ var result = await dialog.Result; - if (!result.Canceled && result.Data is OrderMessage imported) + if (result is not null && !result.Canceled && result.Data is OrderMsg imported) { - Order = imported; + Order.Import(imported); RebuildOrderJson(); StateHasChanged(); } @@ -149,7 +148,7 @@ ? Order.Nodes[1].NodeId : start; // 👈 1 node thì start = end - Order.Edges.Add(new UiEdge + Order.Edges.Add(new VDA5050.Order.Edge { EdgeId = $"EDGE_{Order.Edges.Count + 1}", StartNodeId = start, @@ -158,25 +157,10 @@ } - void RemoveEdge(UiEdge edge) + void RemoveEdge(VDA5050.Order.Edge edge) { Order.Edges.Remove(edge); } - - void ApplyCurve(UiEdge edge) - { - if (edge.Radius <= 0 || edge.Expanded) return; - - var startNode = Order.Nodes.First(n => n.NodeId == edge.StartNodeId); - var newNode = OrderMessage.CreateCurveNode(startNode, edge); - - Order.Nodes.Add(newNode); - edge.EndNodeId = newNode.NodeId; - edge.MarkExpanded(); // ✅ - - ResequenceNodes(); - } - // ================= ACTION ================= void AddAction(Node node) { diff --git a/RobotApp.Client/Services/UiEdge.cs b/RobotApp.Client/Services/UiEdge.cs index e54dd1c..37fadd7 100644 --- a/RobotApp.Client/Services/UiEdge.cs +++ b/RobotApp.Client/Services/UiEdge.cs @@ -2,6 +2,7 @@ using RobotApp.VDA5050.Order; using System.Text.Json; using System.Text.Json.Serialization; +using System.Xml.Linq; namespace RobotApp.Client.Services; @@ -126,7 +127,7 @@ public static class QuarterGeometry // ====================================================== public class OrderMessage { - public int HeaderId { get; set; } + public uint HeaderId { get; set; } public string Timestamp { get; set; } = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); public string Version { get; set; } = "2.1.0"; public string Manufacturer { get; set; } = "PhenikaaX"; @@ -135,139 +136,9 @@ public class OrderMessage public int OrderUpdateId { get; set; } public string? ZoneSetId { get; set; } - public List Nodes { get; set; } = new(); - public List Edges { get; set; } = new(); - public static Node CreateCurveNode(Node startNode, UiEdge edge) - { - var A = new Point( - startNode.NodePosition.X, - startNode.NodePosition.Y - ); + public List Nodes { get; set; } = []; + public List Edges { get; set; } = []; - var result = QuarterGeometry.BuildQuarterTrajectory( - A, - edge.Radius, - edge.Quadrant - ); - - return new Node - { - NodeId = $"NODE_C{Guid.NewGuid():N}".Substring(0, 12), - Released = true, - NodePosition = new NodePosition - { - X = result.EndPoint.X, - Y = result.EndPoint.Y, - Theta = startNode.NodePosition.Theta, - MapId = startNode.NodePosition.MapId - } - }; - } - public static OrderMessage FromSchemaObject(JsonElement root) - { - var order = new OrderMessage - { - HeaderId = root.GetProperty("headerId").GetInt32(), - Timestamp = root.GetProperty("timestamp").GetString(), - Version = root.GetProperty("version").GetString(), - Manufacturer = root.GetProperty("manufacturer").GetString(), - SerialNumber = root.GetProperty("serialNumber").GetString(), - OrderId = root.GetProperty("orderId").GetString(), - OrderUpdateId = root.GetProperty("orderUpdateId").GetInt32() - }; - - // ================= NODES ================= - foreach (var n in root.GetProperty("nodes").EnumerateArray()) - { - var node = new Node - { - NodeId = n.GetProperty("nodeId").GetString()!, - SequenceId = n.GetProperty("sequenceId").GetInt32(), - Released = n.GetProperty("released").GetBoolean(), - - NodePosition = new NodePosition - { - X = n.GetProperty("nodePosition").GetProperty("x").GetDouble(), - Y = n.GetProperty("nodePosition").GetProperty("y").GetDouble(), - Theta = n.GetProperty("nodePosition").GetProperty("theta").GetDouble(), - AllowedDeviationXY = n.GetProperty("nodePosition").GetProperty("allowedDeviationXY").GetDouble(), - AllowedDeviationTheta = n.GetProperty("nodePosition").GetProperty("allowedDeviationTheta").GetDouble(), - MapId = n.GetProperty("nodePosition").GetProperty("mapId").GetString() - }, - - Actions = ParseActions(n) - }; - - order.Nodes.Add(node); - } - - foreach (var e in root.GetProperty("edges").EnumerateArray()) - { - var edge = new UiEdge - { - EdgeId = e.GetProperty("edgeId").GetString()!, - SequenceId = e.GetProperty("sequenceId").GetInt32(), - Released = e.GetProperty("released").GetBoolean(), - StartNodeId = e.GetProperty("startNodeId").GetString()!, - EndNodeId = e.GetProperty("endNodeId").GetString()!, - }; - - // ===== IMPORT TRAJECTORY ===== - if (e.TryGetProperty("trajectory", out var traj)) - { - edge.HasTrajectory = true; - edge.Trajectory = new UiTrajectory - { - Degree = traj.GetProperty("degree").GetInt32(), - KnotVector = traj.GetProperty("knotVector") - .EnumerateArray() - .Select(x => x.GetDouble()) - .ToArray(), - - ControlPoints = traj.GetProperty("controlPoints") - .EnumerateArray() - .Select(p => new Point( - p.GetProperty("x").GetDouble(), - p.GetProperty("y").GetDouble() - )) - .ToList() - }; - - // 🔥 IMPORTED CURVE → LOCK APPLY - edge.MarkExpanded(); - } - - order.Edges.Add(edge); - } - - return order; - } - - // ================= ACTION PARSER ================= - private static VDA5050.InstantAction.Action[] ParseActions(JsonElement parent) - { - if (!parent.TryGetProperty("actions", out var acts)) - return Array.Empty(); - - return acts.EnumerateArray().Select(a => - new VDA5050.InstantAction.Action - { - ActionId = a.GetProperty("actionId").GetString(), - ActionType = a.GetProperty("actionType").GetString(), - BlockingType = a.GetProperty("blockingType").GetString(), - - ActionParameters = a.TryGetProperty("actionParameters", out var ps) - ? ps.EnumerateArray() - .Select(p => new ActionParameter - { - Key = p.GetProperty("key").GetString(), - Value = p.GetProperty("value").GetString() - }) - .ToArray() - : Array.Empty() - } - ).ToArray(); - } public OrderMsg ToSchemaObject() { // ================= SORT NODES BY UI SEQUENCE ================= @@ -337,7 +208,7 @@ public class OrderMessage // ================================================= // 1️⃣ IMPORTED TRAJECTORY // ================================================= - if (e.HasTrajectory && e.Trajectory != null) + if (e.Trajectory != null) { return new Edge { @@ -360,39 +231,6 @@ public class OrderMessage }; } - // ================================================= - // 2️⃣ STRAIGHT EDGE - // ================================================= - if (e.Radius <= 0) - { - return new Edge - { - EdgeId = baseEdge.edgeId, - SequenceId = baseEdge.sequenceId, - Released = baseEdge.released, - StartNodeId = baseEdge.startNodeId, - EndNodeId = baseEdge.endNodeId, - - Actions = [] - }; - } - - // ================================================= - // 3️⃣ GENERATED CURVE (EDITOR) - // ================================================= - var startNode = orderedNodes.First(n => n.NodeId == e.StartNodeId); - - var A = new Point( - startNode.NodePosition.X, - startNode.NodePosition.Y - ); - - var result = QuarterGeometry.BuildQuarterTrajectory( - A, - e.Radius, - e.Quadrant - ); - return new Edge { EdgeId = baseEdge.edgeId, @@ -428,6 +266,20 @@ public class OrderMessage Edges = edgeObjects, }; } + + public void Import(OrderMsg order) + { + HeaderId = order.HeaderId; + Timestamp = order.Timestamp; + Version = order.Version; + Manufacturer = order.Manufacturer; + SerialNumber = order.SerialNumber; + OrderId = order.OrderId; + ZoneSetId = order.ZoneSetId; + OrderUpdateId = order.OrderUpdateId; + Nodes = [.. order.Nodes]; + Edges = [.. order.Edges]; + } } // ====================================================== diff --git a/RobotApp/Services/Robot/RobotOrderController.cs b/RobotApp/Services/Robot/RobotOrderController.cs index 2fdc973..64f24ef 100644 --- a/RobotApp/Services/Robot/RobotOrderController.cs +++ b/RobotApp/Services/Robot/RobotOrderController.cs @@ -479,6 +479,7 @@ public class RobotOrderController(INavigation NavigationManager, var edges = NewOrderEdges.ToList().GetRange(lastNodeIndex + 1, nodes.Count - 1); for (int i = 0; i < nodes.Count - 1; i++) { + if (edges[i] is null) return (NodeStates, [.. pathEdges]); pathEdges.Add(new() { StartX = nodes[i].NodePosition.X, @@ -489,7 +490,7 @@ public class RobotOrderController(INavigation NavigationManager, ControlPoint1Y = edges[i].Trajectory is not null && edges[i].Trajectory.ControlPoints.Length > 2 ? edges[i].Trajectory.ControlPoints[1].Y : 0, ControlPoint2X = edges[i].Trajectory is not null && edges[i].Trajectory.ControlPoints.Length > 3 ? edges[i].Trajectory.ControlPoints[2].X : 0, ControlPoint2Y = edges[i].Trajectory is not null && edges[i].Trajectory.ControlPoints.Length > 3 ? edges[i].Trajectory.ControlPoints[2].Y : 0, - Degree = edges[i].Trajectory.Degree, + Degree = edges[i].Trajectory is null ? 1 : edges[i].Trajectory.Degree, }); } }