using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; using RobotNet10.RobotApp.Client.Shared.Motion; using RobotNet10.RobotApp.Client.Shared.Modules; using RobotNet10.RobotApp.Motion; using RobotNet10.RobotApp.Modules; namespace RobotNet10.RobotApp.Hubs; /// /// SignalR Hub thống nhất cho tất cả các chức năng Motion: /// - ManualControl (điều khiển thủ công qua RF Handle) /// - Odometry (ước lượng vị trí robot) /// - LiftModule (điều khiển nâng hạ) /// - RotationModule (điều khiển xoay) /// [AllowAnonymous] public class MotionHub( ManualControlService manualControlService, IOdometryEstimator odometryEstimator, ILiftModule liftModule, IRotationModule rotationModule) : Hub { #region Manual Control /// /// Lấy trạng thái hiện tại của ManualControlService /// public Task GetStatus() { var status = manualControlService.CurrentRfHandleStatus; var twist = manualControlService.CurrentTwist; return Task.FromResult(new ManualControlStatusDto { State = manualControlService.State.ToString(), IsEnabled = manualControlService.State == ManualControlState.Maintenance || manualControlService.State == ManualControlState.Override, CurrentLinearVelocity = twist.Linear.X, CurrentAngularVelocity = twist.Angular.Z, RfHandleStatus = status != null ? new RfHandleStatusDto { Heartbeat = status.Heartbeat, Ready = status.Ready, Locked = status.Locked, EStop = status.EStop, Enable = status.Enable, Speed = status.Speed, Linear = status.Linear, Angular = status.Angular, Mode = status.Mode, LastUpdateTime = status.LastUpdateTime } : null }); } /// /// Start manual control update loop /// public Task Enable() { manualControlService.Start(); return Task.CompletedTask; } /// /// Stop manual control update loop /// public Task Disable() { manualControlService.Stop(); return Task.CompletedTask; } #endregion #region Odometry /// /// Lấy pose hiện tại của robot (odometry) /// public OdometryDto GetCurrentPose() { var pose = odometryEstimator.CurrentPose; var frequency = odometryEstimator.UpdateFrequency; return pose.ToOdometryDto(frequency); } /// /// Reset odometry về vị trí ban đầu /// public void ResetOdometry() => odometryEstimator.ResetOdometry(); /// /// Reset odometry về một pose cụ thể /// public void ResetOdometryPose(OdometryDto dto) { if (dto != null) { odometryEstimator.ResetOdometry(dto.ToPose()); } } #endregion #region Lift Module /// /// Lấy trạng thái hiện tại của LiftModule /// public async Task GetLiftStatus() { var position = await liftModule.GetCurrentPositionAsync(); return new LiftModuleStatusDto { State = liftModule.State.ToString(), IsReady = liftModule.IsReady, CurrentPosition = position }; } /// /// Lấy vị trí hiện tại của Lift /// public async Task GetLiftCurrentPosition() { return await liftModule.GetCurrentPositionAsync(); } /// /// Nâng lên /// public async Task LiftUp() { await liftModule.LiftUpAsync(); } /// /// Hạ xuống /// public async Task LiftDown() { await liftModule.LiftDownAsync(); } /// /// Dừng nâng/hạ (khi đang di chuyển) /// public async Task LiftStop() { await liftModule.LiftStopAsync(); } /// /// Di chuyển đến vị trí cụ thể /// public async Task LiftToPosition(int position) { await liftModule.LiftToPositionAsync(position); } /// /// Kiểm tra Lift module đã homed chưa /// public async Task IsLiftHomed() { return await liftModule.IsHomedAsync(); } /// /// Thực hiện homing thủ công cho LiftModule /// public async Task LiftHome() { await liftModule.HomeAsync(); } #endregion #region Rotation Module /// /// Lấy trạng thái hiện tại của RotationModule /// public async Task GetRotationStatus() { var angle = await rotationModule.GetCurrentAngleAsync(); return new RotationModuleStatusDto { State = rotationModule.State.ToString(), IsReady = rotationModule.IsReady, CurrentAngle = angle }; } /// /// Lấy góc hiện tại /// public async Task GetRotationCurrentAngle() { return await rotationModule.GetCurrentAngleAsync(); } /// /// Xoay đến góc cụ thể (absolute) /// public async Task RotateToAngle(double angleDegrees) { await rotationModule.RotateToAngleAsync(angleDegrees); } /// /// Xoay một góc offset (relative) /// public async Task RotateOffset(double angleOffsetDegrees) { await rotationModule.RotateOffsetAsync(angleOffsetDegrees); } /// /// Kiểm tra Rotation module đã homed chưa /// public async Task IsRotationHomed() { return await rotationModule.IsHomedAsync(); } #endregion }