udpate robot control

This commit is contained in:
Đăng Nguyễn 2025-12-22 20:25:22 +07:00
parent b2eeb8cb3f
commit 30732b4b9f
5 changed files with 111 additions and 69 deletions

View File

@ -8,6 +8,7 @@
@inject IJSRuntime JS @inject IJSRuntime JS
@inject IDialogService DialogService @inject IDialogService DialogService
@inject HttpClient Http @inject HttpClient Http
@inject ISnackbar Snackbar
<MudMainContent Class="pa-0 ma-0"> <MudMainContent Class="pa-0 ma-0">
<div style="height:100vh; overflow:hidden;"> <div style="height:100vh; overflow:hidden;">
@ -219,14 +220,49 @@
try try
{ {
var orderMsg = JsonSerializer.Deserialize<OrderMsg>(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( var response = await Http.PostAsJsonAsync(
"/api/order", "/api/order",
JsonSerializer.Deserialize<JsonElement>(OrderJson) JsonSerializer.Deserialize<OrderMsg>(OrderJson)
); );
sendSuccess = response.IsSuccessStatusCode; sendSuccess = response.IsSuccessStatusCode;
} }
catch(JsonException jsonEx)
{
Snackbar.Add($"Json to Order failed: {jsonEx.Message}", Severity.Warning);
}
catch catch
{ {
sendSuccess = false; sendSuccess = false;

View File

@ -268,7 +268,7 @@ public class OrderMessage
} }
).ToArray(); ).ToArray();
} }
public object ToSchemaObject() public OrderMsg ToSchemaObject()
{ {
// ================= SORT NODES BY UI SEQUENCE ================= // ================= SORT NODES BY UI SEQUENCE =================
var orderedNodes = Nodes var orderedNodes = Nodes
@ -277,50 +277,50 @@ public class OrderMessage
// ================= BUILD NODE OBJECTS ================= // ================= BUILD NODE OBJECTS =================
var nodeObjects = orderedNodes var nodeObjects = orderedNodes
.Select((n, index) => new .Select((n, index) => new Node
{ {
nodeId = n.NodeId, NodeId = n.NodeId,
sequenceId = index * 2, // ✅ NODE = EVEN SequenceId = index * 2, // ✅ NODE = EVEN
released = n.Released, Released = n.Released,
nodePosition = new NodePosition = new NodePosition
{ {
x = n.NodePosition.X, X = n.NodePosition.X,
y = n.NodePosition.Y, Y = n.NodePosition.Y,
theta = n.NodePosition.Theta, Theta = n.NodePosition.Theta,
allowedDeviationXY = n.NodePosition.AllowedDeviationXY, AllowedDeviationXY = n.NodePosition.AllowedDeviationXY,
allowedDeviationTheta = n.NodePosition.AllowedDeviationTheta, AllowedDeviationTheta = n.NodePosition.AllowedDeviationTheta,
mapId = string.IsNullOrWhiteSpace(n.NodePosition.MapId) MapId = string.IsNullOrWhiteSpace(n.NodePosition.MapId)
? "MAP_01" ? "MAP_01"
: n.NodePosition.MapId : n.NodePosition.MapId
}, },
actions = n.Actions? Actions = n.Actions?
.Select(a => new .Select(a => new VDA5050.InstantAction.Action
{ {
actionId = a.ActionId, ActionId = a.ActionId,
actionType = a.ActionType, ActionType = a.ActionType,
blockingType = a.BlockingType, BlockingType = a.BlockingType,
actionParameters = a.ActionParameters? ActionParameters = a.ActionParameters?
.Select(p => new .Select(p => new ActionParameter
{ {
key = p.Key, Key = p.Key,
value = p.Value Value = p.Value
}) })
.ToArray() .ToArray()
?? Array.Empty<object>() ?? []
}) })
.ToArray() .ToArray()
?? Array.Empty<object>() ?? []
}) })
.ToArray(); .ToArray();
// ================= BUILD EDGE OBJECTS ================= // ================= BUILD EDGE OBJECTS =================
var edgeObjects = Edges Edge[] edgeObjects = Edges
.Select<UiEdge, object>((e, index) => .Select((e, index) =>
{ {
int sequenceId = index * 2 + 1; // ✅ EDGE = ODD int sequenceId = index * 2 + 1; // ✅ EDGE = ODD
@ -339,24 +339,24 @@ public class OrderMessage
// ================================================= // =================================================
if (e.HasTrajectory && e.Trajectory != null) if (e.HasTrajectory && e.Trajectory != null)
{ {
return new return new Edge
{ {
baseEdge.edgeId, EdgeId = baseEdge.edgeId,
baseEdge.sequenceId, SequenceId = baseEdge.sequenceId,
baseEdge.released, Released= baseEdge.released,
baseEdge.startNodeId, StartNodeId= baseEdge.startNodeId,
baseEdge.endNodeId, EndNodeId= baseEdge.endNodeId,
trajectory = new Trajectory = new Trajectory
{ {
degree = e.Trajectory.Degree, Degree = e.Trajectory.Degree,
knotVector = e.Trajectory.KnotVector, KnotVector = e.Trajectory.KnotVector,
controlPoints = e.Trajectory.ControlPoints ControlPoints = e.Trajectory.ControlPoints
.Select(p => new { x = p.X, y = p.Y }) .Select(p => new ControlPoint { X = p.X, Y = p.Y , Weight = 1})
.ToArray() .ToArray()
}, },
actions = Array.Empty<object>() Actions = []
}; };
} }
@ -365,14 +365,15 @@ public class OrderMessage
// ================================================= // =================================================
if (e.Radius <= 0) if (e.Radius <= 0)
{ {
return new return new Edge
{ {
baseEdge.edgeId, EdgeId = baseEdge.edgeId,
baseEdge.sequenceId, SequenceId = baseEdge.sequenceId,
baseEdge.released, Released = baseEdge.released,
baseEdge.startNodeId, StartNodeId = baseEdge.startNodeId,
baseEdge.endNodeId, EndNodeId = baseEdge.endNodeId,
actions = Array.Empty<object>()
Actions = []
}; };
} }
@ -392,42 +393,41 @@ public class OrderMessage
e.Quadrant e.Quadrant
); );
return new return new Edge
{ {
baseEdge.edgeId, EdgeId = baseEdge.edgeId,
baseEdge.sequenceId, SequenceId = baseEdge.sequenceId,
baseEdge.released, Released = baseEdge.released,
baseEdge.startNodeId, StartNodeId = baseEdge.startNodeId,
baseEdge.endNodeId, EndNodeId = baseEdge.endNodeId,
trajectory = result.Trajectory, Actions = []
actions = Array.Empty<object>()
}; };
}) })
.ToArray(); .ToArray();
// ================= FINAL SCHEMA OBJECT ================= // ================= 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") ? DateTime.UtcNow.ToString("O")
: Timestamp, : Timestamp,
version = Version, Version = Version,
manufacturer = Manufacturer, Manufacturer = Manufacturer,
serialNumber = SerialNumber, SerialNumber = SerialNumber,
orderId = OrderId= Guid.NewGuid().ToString(), OrderId = OrderId= Guid.NewGuid().ToString(),
orderUpdateId = OrderUpdateId, OrderUpdateId = OrderUpdateId,
zoneSetId = string.IsNullOrWhiteSpace(ZoneSetId) ZoneSetId = string.IsNullOrWhiteSpace(ZoneSetId)
? null ? null
: ZoneSetId, : ZoneSetId,
nodes = nodeObjects, Nodes = nodeObjects,
edges = edgeObjects Edges = edgeObjects,
}; };
} }
} }

View File

@ -58,7 +58,7 @@ public class RobotConfiguration(IServiceProvider ServiceProvider, Logger<RobotCo
{ {
var robotConnection = scope.ServiceProvider.GetRequiredService<RobotConnection>(); var robotConnection = scope.ServiceProvider.GetRequiredService<RobotConnection>();
await robotConnection.StopConnection(); 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."); else throw new Exception("Chưa có cấu hình VDA5050.");

View File

@ -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); 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"); return new(false, "Chưa có kết nối tới broker");
} }
public void StartConnection()
public async Task StartConnection(CancellationToken cancellationToken) {
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 = new MQTTClient(RobotConfiguration.SerialNumber, VDA5050Setting, MQTTClientLogger);
MqttClient.OrderChanged += OrderChanged; MqttClient.OrderChanged += OrderChanged;

View File

@ -39,8 +39,7 @@ public partial class RobotController
ConnectionManager.OrderUpdated += NewOrderUpdated; ConnectionManager.OrderUpdated += NewOrderUpdated;
ConnectionManager.ActionUpdated += NewInstantActionUpdated; ConnectionManager.ActionUpdated += NewInstantActionUpdated;
await ConnectionManager.StartConnection(cancellationToken); ConnectionManager.StartConnection();
Logger.Info("Robot đã kết nối tới Fleet Manager.");
StateManager.TransitionTo(SystemStateType.Standby); StateManager.TransitionTo(SystemStateType.Standby);
if (!RobotConfiguration.IsSimulation) if (!RobotConfiguration.IsSimulation)