Compare commits
2 Commits
b2eeb8cb3f
...
e4e135e35f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4e135e35f | ||
|
|
30732b4b9f |
|
|
@ -77,6 +77,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.ScrollToBottom = (element) => {
|
||||||
|
if (element) {
|
||||||
|
element.scrollTop = element.scrollHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private DateTime DateLog = DateTime.Today;
|
private DateTime DateLog = DateTime.Today;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
.log-level {
|
.log-level {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 46px;
|
width: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-head {
|
.log-head {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -560,10 +560,14 @@ public partial class RobotConfigManager
|
||||||
|
|
||||||
private async Task LoadConfig()
|
private async Task LoadConfig()
|
||||||
{
|
{
|
||||||
|
IsLoading = true;
|
||||||
|
StateHasChanged();
|
||||||
var response = await (await Http.PostAsync($"api/RobotConfigs/load", null)).Content.ReadFromJsonAsync<MessageResult>();
|
var response = await (await Http.PostAsync($"api/RobotConfigs/load", null)).Content.ReadFromJsonAsync<MessageResult>();
|
||||||
if (response is null) Snackbar.Add("Failed to load config", Severity.Warning);
|
if (response is null) Snackbar.Add("Failed to load config", Severity.Warning);
|
||||||
else if (!response.IsSuccess) Snackbar.Add(response.Message ?? "Failed to load config", Severity.Warning);
|
else if (!response.IsSuccess) Snackbar.Add(response.Message ?? "Failed to load config", Severity.Warning);
|
||||||
else Snackbar.Add("Config loaded", Severity.Success);
|
else Snackbar.Add("Config loaded", Severity.Success);
|
||||||
|
|
||||||
|
IsLoading = false;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,11 +147,11 @@ public class MQTTClient : IAsyncDisposable
|
||||||
|
|
||||||
MqttClient = MqttClientFactory.CreateMqttClient();
|
MqttClient = MqttClientFactory.CreateMqttClient();
|
||||||
|
|
||||||
//MqttClient.ApplicationMessageReceivedAsync -= OnMessageReceived;
|
MqttClient.ApplicationMessageReceivedAsync -= OnMessageReceived;
|
||||||
MqttClient.ApplicationMessageReceivedAsync += OnMessageReceived;
|
MqttClient.ApplicationMessageReceivedAsync += OnMessageReceived;
|
||||||
//MqttClient.DisconnectedAsync -= OnDisconnected;
|
MqttClient.DisconnectedAsync -= OnDisconnected;
|
||||||
MqttClient.DisconnectedAsync += OnDisconnected;
|
MqttClient.DisconnectedAsync += OnDisconnected;
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested && !IsDisposed)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -168,8 +168,12 @@ public class MQTTClient : IAsyncDisposable
|
||||||
{
|
{
|
||||||
Logger.Error($"Lỗi khi tạo MQTT client: {ex.Message}");
|
Logger.Error($"Lỗi khi tạo MQTT client: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
await Task.Delay(3000, cancellationToken);
|
await Task.Delay(3000, cancellationToken);
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else throw new ObjectDisposedException(nameof(MQTTClient));
|
else throw new ObjectDisposedException(nameof(MQTTClient));
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +223,7 @@ public class MQTTClient : IAsyncDisposable
|
||||||
var tlsOptions = new MqttClientTlsOptionsBuilder()
|
var tlsOptions = new MqttClientTlsOptionsBuilder()
|
||||||
.UseTls(true)
|
.UseTls(true)
|
||||||
.WithSslProtocols(System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13)
|
.WithSslProtocols(System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13)
|
||||||
//.WithCertificateValidationHandler(ValidateCertificates)
|
.WithCertificateValidationHandler(ValidateCertificates)
|
||||||
.WithClientCertificatesProvider(new MQTTClientCertificatesProvider(VDA5050Setting.CerFile, VDA5050Setting.KeyFile))
|
.WithClientCertificatesProvider(new MQTTClientCertificatesProvider(VDA5050Setting.CerFile, VDA5050Setting.KeyFile))
|
||||||
.Build();
|
.Build();
|
||||||
builder = builder.WithTlsOptions(tlsOptions);
|
builder = builder.WithTlsOptions(tlsOptions);
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,8 @@ public class RobotConfiguration(IServiceProvider ServiceProvider, Logger<RobotCo
|
||||||
if (IsReady)
|
if (IsReady)
|
||||||
{
|
{
|
||||||
var robotConnection = scope.ServiceProvider.GetRequiredService<RobotConnection>();
|
var robotConnection = scope.ServiceProvider.GetRequiredService<RobotConnection>();
|
||||||
await robotConnection.StopConnection();
|
robotConnection.StartConnection();
|
||||||
_ = Task.Run(async () => await robotConnection.StartConnection(CancellationToken.None));
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else throw new Exception("Chưa có cấu hình VDA5050.");
|
else throw new Exception("Chưa có cấu hình VDA5050.");
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using RobotApp.VDA5050;
|
||||||
using RobotApp.VDA5050.InstantAction;
|
using RobotApp.VDA5050.InstantAction;
|
||||||
using RobotApp.VDA5050.Order;
|
using RobotApp.VDA5050.Order;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace RobotApp.Services.Robot;
|
namespace RobotApp.Services.Robot;
|
||||||
|
|
||||||
|
|
@ -10,12 +11,13 @@ public class RobotConnection(RobotConfiguration RobotConfiguration,
|
||||||
Logger<RobotConnection> Logger,
|
Logger<RobotConnection> Logger,
|
||||||
Logger<MQTTClient> MQTTClientLogger)
|
Logger<MQTTClient> MQTTClientLogger)
|
||||||
{
|
{
|
||||||
private readonly VDA5050Setting VDA5050Setting = RobotConfiguration.VDA5050Setting;
|
|
||||||
private MQTTClient? MqttClient;
|
private MQTTClient? MqttClient;
|
||||||
|
|
||||||
public bool IsConnected => MqttClient is not null && MqttClient.IsConnected;
|
public bool IsConnected => MqttClient is not null && MqttClient.IsConnected;
|
||||||
public event Action<OrderMsg>? OrderUpdated;
|
public event Action<OrderMsg>? OrderUpdated;
|
||||||
public event Action<InstantActionsMsg>? ActionUpdated;
|
public event Action<InstantActionsMsg>? ActionUpdated;
|
||||||
|
private readonly SemaphoreSlim _connectionSemaphore = new(1, 1);
|
||||||
|
private CancellationTokenSource? _connectionCancel;
|
||||||
|
|
||||||
|
|
||||||
private void OrderChanged(string data)
|
private void OrderChanged(string data)
|
||||||
|
|
@ -50,17 +52,37 @@ public class RobotConnection(RobotConfiguration RobotConfiguration,
|
||||||
|
|
||||||
public async Task<MessageResult> Publish(string topic, string data)
|
public async Task<MessageResult> Publish(string topic, string data)
|
||||||
{
|
{
|
||||||
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($"{RobotConfiguration.VDA5050Setting.TopicPrefix}/{RobotConfiguration.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)
|
|
||||||
{
|
{
|
||||||
MqttClient = new MQTTClient(RobotConfiguration.SerialNumber, VDA5050Setting, MQTTClientLogger);
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await StartConnectionAsync(CancellationToken.None);
|
||||||
|
if(IsConnected)Logger.Info("Robot đã kết nối tới Fleet Manager.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public async Task StartConnectionAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await StopConnection();
|
||||||
|
_connectionCancel?.Cancel();
|
||||||
|
if (_connectionSemaphore.Wait(1000, cancellationToken))
|
||||||
|
{
|
||||||
|
_connectionCancel = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||||
|
MqttClient = new MQTTClient(RobotConfiguration.SerialNumber, RobotConfiguration.VDA5050Setting, MQTTClientLogger);
|
||||||
MqttClient.OrderChanged += OrderChanged;
|
MqttClient.OrderChanged += OrderChanged;
|
||||||
MqttClient.InstanceActionsChanged += InstanceActionsChanged;
|
MqttClient.InstanceActionsChanged += InstanceActionsChanged;
|
||||||
await MqttClient.ConnectAsync(cancellationToken);
|
await MqttClient.ConnectAsync(_connectionCancel.Token);
|
||||||
await MqttClient.SubscribeAsync(cancellationToken);
|
if(MqttClient is not null) await MqttClient.SubscribeAsync(_connectionCancel.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_connectionSemaphore.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StopConnection()
|
public async Task StopConnection()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user