diff --git a/RobotApp.Client/Pages/Logs.razor b/RobotApp.Client/Pages/Logs.razor
index b4c5bef..fde3dc9 100644
--- a/RobotApp.Client/Pages/Logs.razor
+++ b/RobotApp.Client/Pages/Logs.razor
@@ -77,6 +77,13 @@
+
@code {
private DateTime DateLog = DateTime.Today;
diff --git a/RobotApp.Client/Pages/Logs.razor.css b/RobotApp.Client/Pages/Logs.razor.css
index 2a3ae7a..96663ec 100644
--- a/RobotApp.Client/Pages/Logs.razor.css
+++ b/RobotApp.Client/Pages/Logs.razor.css
@@ -23,7 +23,7 @@
.log-level {
display: inline-block;
- width: 46px;
+ width: 60px;
}
.log-head {
diff --git a/RobotApp.Client/Pages/RobotConfigManager.razor.cs b/RobotApp.Client/Pages/RobotConfigManager.razor.cs
index 45637ba..c71f006 100644
--- a/RobotApp.Client/Pages/RobotConfigManager.razor.cs
+++ b/RobotApp.Client/Pages/RobotConfigManager.razor.cs
@@ -560,10 +560,14 @@ public partial class RobotConfigManager
private async Task LoadConfig()
{
+ IsLoading = true;
+ StateHasChanged();
var response = await (await Http.PostAsync($"api/RobotConfigs/load", null)).Content.ReadFromJsonAsync();
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 Snackbar.Add("Config loaded", Severity.Success);
+
+ IsLoading = false;
StateHasChanged();
}
}
diff --git a/RobotApp/Services/MQTTClient.cs b/RobotApp/Services/MQTTClient.cs
index a1e6d48..95c697c 100644
--- a/RobotApp/Services/MQTTClient.cs
+++ b/RobotApp/Services/MQTTClient.cs
@@ -147,11 +147,11 @@ public class MQTTClient : IAsyncDisposable
MqttClient = MqttClientFactory.CreateMqttClient();
- //MqttClient.ApplicationMessageReceivedAsync -= OnMessageReceived;
+ MqttClient.ApplicationMessageReceivedAsync -= OnMessageReceived;
MqttClient.ApplicationMessageReceivedAsync += OnMessageReceived;
- //MqttClient.DisconnectedAsync -= OnDisconnected;
+ MqttClient.DisconnectedAsync -= OnDisconnected;
MqttClient.DisconnectedAsync += OnDisconnected;
- while (!cancellationToken.IsCancellationRequested)
+ while (!cancellationToken.IsCancellationRequested && !IsDisposed)
{
try
{
@@ -168,7 +168,11 @@ public class MQTTClient : IAsyncDisposable
{
Logger.Error($"Lỗi khi tạo MQTT client: {ex.Message}");
}
- await Task.Delay(3000, cancellationToken);
+ try
+ {
+ await Task.Delay(3000, cancellationToken);
+ }
+ catch { }
}
}
else throw new ObjectDisposedException(nameof(MQTTClient));
@@ -219,10 +223,10 @@ public class MQTTClient : IAsyncDisposable
var tlsOptions = new MqttClientTlsOptionsBuilder()
.UseTls(true)
.WithSslProtocols(System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13)
- //.WithCertificateValidationHandler(ValidateCertificates)
+ .WithCertificateValidationHandler(ValidateCertificates)
.WithClientCertificatesProvider(new MQTTClientCertificatesProvider(VDA5050Setting.CerFile, VDA5050Setting.KeyFile))
.Build();
- builder = builder.WithTlsOptions(tlsOptions);
+ builder = builder.WithTlsOptions(tlsOptions);
}
MqttClientOptions = builder.Build();
}
@@ -251,42 +255,42 @@ public class MQTTClient : IAsyncDisposable
{
//if (!IsDisposed)
//{
- if (MqttClient is null) throw new Exception("Kết nối tới broker chưa được khởi tạo nhưng đã yêu cầu subscribe");
- if (!MqttClient.IsConnected) throw new Exception("Kết nối tới broker chưa thành công nhưng đã yêu cầu subscribe");
+ if (MqttClient is null) throw new Exception("Kết nối tới broker chưa được khởi tạo nhưng đã yêu cầu subscribe");
+ if (!MqttClient.IsConnected) throw new Exception("Kết nối tới broker chưa thành công nhưng đã yêu cầu subscribe");
- while (!cancellationToken.IsCancellationRequested)
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ try
{
- try
+ var response = await MqttClient.SubscribeAsync(MqttClientSubscribeOptions, cancellationToken);
+ bool isSuccess = true;
+ foreach (var item in response.Items)
{
- var response = await MqttClient.SubscribeAsync(MqttClientSubscribeOptions, cancellationToken);
- bool isSuccess = true;
- foreach (var item in response.Items)
+ if (item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS0 ||
+ item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS1 ||
+ item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS2)
{
- if (item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS0 ||
- item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS1 ||
- item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS2)
- {
- Logger.Info($"Subscribe thành công cho topic: {item.TopicFilter.Topic} với QoS: {item.ResultCode}");
- }
- else
- {
- Logger.Warning($"Subscribe thất bại cho topic: {item.TopicFilter.Topic}. Lý do: {response.ReasonString}");
- isSuccess = false;
- break;
- }
+ Logger.Info($"Subscribe thành công cho topic: {item.TopicFilter.Topic} với QoS: {item.ResultCode}");
+ }
+ else
+ {
+ Logger.Warning($"Subscribe thất bại cho topic: {item.TopicFilter.Topic}. Lý do: {response.ReasonString}");
+ isSuccess = false;
+ break;
}
- if (isSuccess) break;
- }
- catch (Exception ex)
- {
- Logger.Error($"Lỗi khi subscribe: {ex.Message}");
- }
- if (!cancellationToken.IsCancellationRequested && !IsDisposed)
- {
- await Task.Delay(3000, cancellationToken);
}
+ if (isSuccess) break;
}
+ catch (Exception ex)
+ {
+ Logger.Error($"Lỗi khi subscribe: {ex.Message}");
+ }
+ if (!cancellationToken.IsCancellationRequested && !IsDisposed)
+ {
+ await Task.Delay(3000, cancellationToken);
+ }
+ }
//}
//else throw new ObjectDisposedException(nameof(MQTTClient));
}
diff --git a/RobotApp/Services/Robot/RobotConfiguration.cs b/RobotApp/Services/Robot/RobotConfiguration.cs
index e2fe8c4..e1886e8 100644
--- a/RobotApp/Services/Robot/RobotConfiguration.cs
+++ b/RobotApp/Services/Robot/RobotConfiguration.cs
@@ -57,8 +57,8 @@ public class RobotConfiguration(IServiceProvider ServiceProvider, Logger();
- await robotConnection.StopConnection();
robotConnection.StartConnection();
+ await Task.Delay(1000);
}
}
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 e3b8dd8..c3f6abd 100644
--- a/RobotApp/Services/Robot/RobotConnection.cs
+++ b/RobotApp/Services/Robot/RobotConnection.cs
@@ -3,19 +3,21 @@ using RobotApp.VDA5050;
using RobotApp.VDA5050.InstantAction;
using RobotApp.VDA5050.Order;
using System.Text.Json;
+using System.Threading;
namespace RobotApp.Services.Robot;
-public class RobotConnection(RobotConfiguration RobotConfiguration,
+public class RobotConnection(RobotConfiguration RobotConfiguration,
Logger Logger,
Logger MQTTClientLogger)
{
- private readonly VDA5050Setting VDA5050Setting = RobotConfiguration.VDA5050Setting;
private MQTTClient? MqttClient;
public bool IsConnected => MqttClient is not null && MqttClient.IsConnected;
public event Action? OrderUpdated;
public event Action? ActionUpdated;
+ private readonly SemaphoreSlim _connectionSemaphore = new(1, 1);
+ private CancellationTokenSource? _connectionCancel;
private void OrderChanged(string data)
@@ -50,7 +52,7 @@ public class RobotConnection(RobotConfiguration RobotConfiguration,
public async Task 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");
}
public void StartConnection()
@@ -58,16 +60,29 @@ public class RobotConnection(RobotConfiguration RobotConfiguration,
Task.Run(async () =>
{
await StartConnectionAsync(CancellationToken.None);
- Logger.Info("Robot đã kết nối tới Fleet Manager.");
+ if(IsConnected)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;
- MqttClient.InstanceActionsChanged += InstanceActionsChanged;
- await MqttClient.ConnectAsync(cancellationToken);
- await MqttClient.SubscribeAsync(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.InstanceActionsChanged += InstanceActionsChanged;
+ await MqttClient.ConnectAsync(_connectionCancel.Token);
+ if(MqttClient is not null) await MqttClient.SubscribeAsync(_connectionCancel.Token);
+ }
+ }
+ finally
+ {
+ _connectionSemaphore.Release();
+ }
}
public async Task StopConnection()