This commit is contained in:
Đăng Nguyễn 2025-12-22 21:28:57 +07:00
parent 30732b4b9f
commit e4e135e35f
6 changed files with 75 additions and 45 deletions

View File

@ -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;

View File

@ -23,7 +23,7 @@
.log-level { .log-level {
display: inline-block; display: inline-block;
width: 46px; width: 60px;
} }
.log-head { .log-head {

View File

@ -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();
} }
} }

View File

@ -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);

View File

@ -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(); robotConnection.StartConnection();
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.");

View File

@ -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,7 +52,7 @@ 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 void StartConnection()
@ -58,16 +60,29 @@ public class RobotConnection(RobotConfiguration RobotConfiguration,
Task.Run(async () => Task.Run(async () =>
{ {
await StartConnectionAsync(CancellationToken.None); 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) public async Task StartConnectionAsync(CancellationToken cancellationToken)
{ {
MqttClient = new MQTTClient(RobotConfiguration.SerialNumber, VDA5050Setting, MQTTClientLogger); 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()