using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.SignalR.Client; using RobotNet10.RobotApp.Client.Shared.Plc; namespace RobotNet10.RobotApp.Client.Clients; /// /// SignalR client để kết nối với PlcControllerHub (read-only) /// public class PlcControllerHubClient : IAsyncDisposable { private readonly HubConnection _hubConnection; private bool _disposed; public bool IsConnected => _hubConnection.State == HubConnectionState.Connected; public HubConnectionState ConnectionState => _hubConnection.State; /// /// Event fired when connection state changes /// public event Action? ConnectionStateChanged; public PlcControllerHubClient(NavigationManager navigationManager) { var hubUrl = navigationManager.ToAbsoluteUri("/hubs/plc/controller"); _hubConnection = new HubConnectionBuilder() .WithUrl(hubUrl) .WithAutomaticReconnect() .Build(); _hubConnection.Reconnecting += async (ex) => { ConnectionStateChanged?.Invoke(_hubConnection.State); await Task.CompletedTask; }; _hubConnection.Reconnected += async (id) => { ConnectionStateChanged?.Invoke(_hubConnection.State); await Task.CompletedTask; }; _hubConnection.Closed += async (ex) => { ConnectionStateChanged?.Invoke(_hubConnection.State); await Task.CompletedTask; }; } /// /// Connect to hub /// public async Task StartAsync() { if (_hubConnection.State == HubConnectionState.Disconnected) { await _hubConnection.StartAsync(); ConnectionStateChanged?.Invoke(_hubConnection.State); } } /// /// Disconnect from hub /// public async Task StopAsync() { if (_hubConnection.State != HubConnectionState.Disconnected) { await _hubConnection.StopAsync(); } } /// /// Get current status /// public async Task GetStatusAsync() { return await _hubConnection.InvokeAsync("GetStatus"); } public async ValueTask DisposeAsync() { if (_disposed) return; _disposed = true; await StopAsync(); await _hubConnection.DisposeAsync(); } }