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
}