Files
I150/srcs/RobotNet10/RobotApp/RobotNet10.RobotApp.Client/Clients/OdometryHubClient.cs
2026-07-03 16:37:12 +07:00

91 lines
2.8 KiB
C#

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR.Client;
using RobotNet10.RobotApp.Client.Shared.Motion;
namespace RobotNet10.RobotApp.Client.Clients;
/// <summary>
/// SignalR client kết nối tới OdometryHub - hiển thị odom (pose + velocity) realtime
/// </summary>
public class OdometryHubClient : IAsyncDisposable
{
private readonly HubConnection _hubConnection;
private bool _disposed;
/// <summary>
/// Sự kiện nhận odometry mới (broadcast từ server ~10 Hz)
/// </summary>
public event Action<OdometryDto>? OdometryReceived;
/// <summary>
/// Trạng thái kết nối thay đổi
/// </summary>
public event Action<HubConnectionState>? ConnectionStateChanged;
public bool IsConnected => _hubConnection.State == HubConnectionState.Connected;
public HubConnectionState ConnectionState => _hubConnection.State;
public OdometryHubClient(NavigationManager navigationManager)
{
var hubUrl = navigationManager.ToAbsoluteUri("/hubs/odometry");
_hubConnection = new HubConnectionBuilder()
.WithUrl(hubUrl)
.WithAutomaticReconnect()
.Build();
_hubConnection.On<OdometryDto>("ReceiveOdometry", dto => OdometryReceived?.Invoke(dto));
_hubConnection.Reconnecting += _ =>
{
ConnectionStateChanged?.Invoke(_hubConnection.State);
return Task.CompletedTask;
};
_hubConnection.Reconnected += _ =>
{
ConnectionStateChanged?.Invoke(_hubConnection.State);
return Task.CompletedTask;
};
_hubConnection.Closed += _ =>
{
ConnectionStateChanged?.Invoke(_hubConnection.State);
return Task.CompletedTask;
};
}
public async Task StartAsync()
{
if (_hubConnection.State == HubConnectionState.Disconnected)
{
await _hubConnection.StartAsync();
ConnectionStateChanged?.Invoke(_hubConnection.State);
}
}
public async Task StopAsync()
{
if (_hubConnection.State != HubConnectionState.Disconnected)
{
await _hubConnection.StopAsync();
ConnectionStateChanged?.Invoke(_hubConnection.State);
}
}
/// <summary>
/// Lấy odometry hiện tại (on-demand)
/// </summary>
public async Task<OdometryDto?> GetCurrentOdometryAsync()
{
return await _hubConnection.InvokeAsync<OdometryDto?>("GetCurrentOdometry");
}
public async ValueTask DisposeAsync()
{
if (_disposed)
return;
_disposed = true;
await StopAsync();
await _hubConnection.DisposeAsync();
GC.SuppressFinalize(this);
}
}