@page "/motion/manualcontrol" @rendermode InteractiveWebAssemblyNoPrerender @implements IAsyncDisposable @using RobotNet10.RobotApp.Client.Clients @using RobotNet10.RobotApp.Client.Components.Motion @using RobotNet10.RobotApp.Client.Shared.Motion @using Microsoft.AspNetCore.SignalR.Client @using MudBlazor Manual Control @* Disconnected Overlay *@ MotionHub Disconnected Waiting for connection... @* 4 Cards Grid *@ @* Card 1: Manual Control *@ @* Card 2: Odometry (from OdometryService → XLOC) *@ @* Card 3: Lift Module *@ @* Card 4: Rotation Module *@ @code { [Inject] private MotionHubClient MotionHubClientInjected { get; set; } = null!; [Inject] private OdometryHubClient OdometryHubClientInjected { get; set; } = null!; [Inject] private ISnackbar Snackbar { get; set; } = null!; private MotionHubClient motionHubClient = null!; private bool isHubReady = false; private OdometryHubClient odometryHubClient = null!; private bool odometryHubReady = false; private OdometryDto? currentOdometry; protected override async Task OnInitializedAsync() { motionHubClient = MotionHubClientInjected; odometryHubClient = OdometryHubClientInjected; // Subscribe to connection state changes motionHubClient.ConnectionStateChanged += OnConnectionStateChanged; odometryHubClient.ConnectionStateChanged += OnOdometryConnectionStateChanged; odometryHubClient.OdometryReceived += OnOdometryReceived; try { await motionHubClient.StartAsync(); isHubReady = motionHubClient.IsConnected; // Wait a bit for connection to establish await Task.Delay(500); isHubReady = motionHubClient.IsConnected; await odometryHubClient.StartAsync(); odometryHubReady = odometryHubClient.IsConnected; if (odometryHubReady) { currentOdometry = await odometryHubClient.GetCurrentOdometryAsync(); } } catch (Exception ex) { Snackbar.Add($"Error initializing: {ex.Message}", Severity.Error); isHubReady = false; } } private void OnConnectionStateChanged(HubConnectionState state) { isHubReady = state == HubConnectionState.Connected; InvokeAsync(StateHasChanged); } private void OnOdometryConnectionStateChanged(HubConnectionState state) { odometryHubReady = state == HubConnectionState.Connected; InvokeAsync(StateHasChanged); } private void OnOdometryReceived(OdometryDto dto) { currentOdometry = dto; InvokeAsync(StateHasChanged); } public async ValueTask DisposeAsync() { if (motionHubClient != null) { motionHubClient.ConnectionStateChanged -= OnConnectionStateChanged; } if (odometryHubClient != null) { odometryHubClient.ConnectionStateChanged -= OnOdometryConnectionStateChanged; odometryHubClient.OdometryReceived -= OnOdometryReceived; } await ValueTask.CompletedTask; } }