From e4e135e35f548a1a158c2c1421d3ec5be06440f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=C4=83ng=20Nguy=E1=BB=85n?= Date: Mon, 22 Dec 2025 21:28:57 +0700 Subject: [PATCH] update --- RobotApp.Client/Pages/Logs.razor | 7 ++ RobotApp.Client/Pages/Logs.razor.css | 2 +- .../Pages/RobotConfigManager.razor.cs | 4 ++ RobotApp/Services/MQTTClient.cs | 72 ++++++++++--------- RobotApp/Services/Robot/RobotConfiguration.cs | 2 +- RobotApp/Services/Robot/RobotConnection.cs | 33 ++++++--- 6 files changed, 75 insertions(+), 45 deletions(-) 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()