@using RobotNet10.RobotApp.Client.Clients @using RobotNet10.RobotApp.Client.Shared.Modules @using MudBlazor Rotation Module @* Rotation Status Information *@ @if (rotationStatus != null) { Module Status State: @rotationStatus.State Ready: @rotationStatus.IsReady Current Angle: @($"{rotationStatus.CurrentAngle:F2}°") } @* Rotation Control Buttons *@ Rotation Controls @* Rotate to Absolute Angle *@ Go @* Rotate Offset *@ Offset @* Quick Rotation Buttons *@ -90° -45° +45° +90° @code { [Parameter, EditorRequired] public MotionHubClient HubClient { get; set; } = null!; [Parameter] public bool IsHubReady { get; set; } [Inject] private ISnackbar Snackbar { get; set; } = null!; private RotationModuleStatusDto? rotationStatus; private bool isLoading = false; private double targetAngle = 0; private double angleOffset = 0; private bool _previousIsHubReady = false; protected override async Task OnParametersSetAsync() { // Detect when IsHubReady changes from false to true if (IsHubReady && !_previousIsHubReady) { await RefreshStatus(); } _previousIsHubReady = IsHubReady; } public async Task RefreshStatus() { if (isLoading || !IsHubReady) return; try { isLoading = true; rotationStatus = await HubClient.GetRotationStatusAsync(); StateHasChanged(); } catch (Exception ex) { Snackbar.Add($"Error refreshing rotation status: {ex.Message}", Severity.Error); } finally { isLoading = false; } } private Color GetStateColor(string state) { return state switch { "Ready" => Color.Success, "Moving" => Color.Info, "Error" => Color.Error, "Homing" => Color.Warning, "Initializing" => Color.Warning, _ => Color.Default }; } private async Task RotateToAngle() { if (!IsHubReady || isLoading || rotationStatus?.IsReady != true) return; try { isLoading = true; Snackbar.Add($"Rotating to angle {targetAngle}°...", Severity.Info); await HubClient.RotateToAngleAsync(targetAngle); Snackbar.Add($"Rotate to angle {targetAngle}° command sent successfully", Severity.Success); await Task.Delay(500); await RefreshStatus(); } catch (Exception ex) { Snackbar.Add($"Error rotating to angle: {ex.Message}", Severity.Error); } finally { isLoading = false; StateHasChanged(); } } private async Task RotateOffset() { if (!IsHubReady || isLoading || rotationStatus?.IsReady != true) return; try { isLoading = true; var offsetText = angleOffset >= 0 ? $"+{angleOffset}°" : $"{angleOffset}°"; Snackbar.Add($"Rotating offset {offsetText}...", Severity.Info); await HubClient.RotateOffsetAsync(angleOffset); Snackbar.Add($"Rotate offset {offsetText} command sent successfully", Severity.Success); await Task.Delay(500); await RefreshStatus(); } catch (Exception ex) { Snackbar.Add($"Error rotating offset: {ex.Message}", Severity.Error); } finally { isLoading = false; StateHasChanged(); } } private async Task RotateOffsetQuick(double offset) { angleOffset = offset; await RotateOffset(); } }