using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using RobotNet10.FleetManager.Data; using RobotNet10.FleetManager.Services; using RobotNet10.FleetManager.Services.RobotManager; using RobotNet10.FleetManager.Services.RobotManager.Models; using RobotNet10.FleetManager.Shared.Models; using RobotNet10.MapManager.Services; using RobotNet10.Shared; namespace RobotNet10.FleetManager.Controllers; [Route("api/[controller]")] [ApiController] [AllowAnonymous] public class RobotManagerController(IRobotService RobotService, ILayoutDataService LayoutManager, IRobotManagerService RobotManager, Services.Logger Logger) : ControllerBase { [HttpPost] [Route("MoveToNode")] public async Task MoveToNode([FromBody] RobotMoveToNodeModel model) { try { if (string.IsNullOrEmpty(model.NodeName)) return new(false, "NodeName cannot be empty.."); var robot = await RobotService.GetByRobotIdAsync(model.RobotId); if (robot is null) return new(false, "RobotId does not exist."); if (robot.MapId is null || robot.MapId == Guid.Empty) return new(false, "The robot has not been assigned a map."); var robotController = RobotManager.GetRobotController(model.RobotId); if (robotController is null || !robotController.IsOnline) return new(false, "The robot is not online."); if (robotController.Data is null || robotController.Data.State is null) return new(false, "The robot is broken connection."); var map = await LayoutManager.GetLayoutDataAsync(robot.MapId ?? Guid.Empty); var node = map.Nodes.FirstOrDefault(n => n.NodeName == model.NodeName && n.LevelId == map.LayoutLevelId); if (node is null) return new(false, "This Node does not exist."); if (!robotController.IsReady) return new(false, "The robot is busy."); var move = await robotController.MoveToNodeAsync(model.NodeName, model.LastAngle); if (move.IsSuccess) return new(true); Logger.Warning($"RobotManager API: MoveToNode for robot {model.RobotId} to node {model.NodeName} failed: {move.Message}"); return new(false, "Request failed."); } catch (Exception ex) { Logger.Error($"RobotManager API: MoveToNode for robot {model.RobotId} to node {model.NodeName} error: {ex.Message}"); return new(false, "An error occurred."); } } [HttpDelete] [Route("MoveToNode/{robotId}")] public async Task Cancel(string robotId) { try { var robot = await RobotService.GetByRobotIdAsync(robotId); if (robot is null) return new(false, "RobotId does not exist."); var robotController = RobotManager.GetRobotController(robotId); if (robotController is null || !robotController.IsOnline) return new(false, "The robot is not online."); if (robotController.Data is null || robotController.Data.State is null) return new(false, "The robot is broken connection."); var cancel = await robotController.CancelOrderAsync(); if (cancel.IsSuccess) return new(true); Logger.Warning($"RobotManager API: Cancel order for robot {robotId} failed: {cancel.Message}"); return new(false, "Request failed."); } catch (Exception ex) { Logger.Error($"RobotManager API: Cancel order for robot {robotId} error: {ex.Message}"); return new(false, "An error occurred."); } } [HttpPost] [Route("InstantActions")] public async Task InstantAction([FromBody] RobotInstantActionModel model) { try { var robot = await RobotService.GetByRobotIdAsync(model.RobotId); if (robot is null) return new(false, "RobotId does not exist."); if (robot.MapId is null || robot.MapId == Guid.Empty) return new(false, "The robot has not been assigned a map."); var robotController = RobotManager.GetRobotController(model.RobotId); if (robotController is null || !robotController.IsOnline) return new(false, "The robot is not online."); if (robotController.Data is null || robotController.Data.State is null) return new(false, "The robot is broken connection."); var instantAction = await robotController.SendInstantActionAsync(model.Action); if (instantAction.IsSuccess) return new(true); Logger.Warning($"RobotManager API: Send instant action for robot {model.RobotId} failed: {instantAction.Message}"); return new(false, "Request failed."); } catch (Exception ex) { Logger.Error($"RobotManager API: Send instant action for robot {model.RobotId}, action type {model.Action.ActionType} error: {ex.Message}"); return new(false, "An error occurred."); } } [HttpGet] [Route("State/{robotId}")] public async Task> GetState(string robotId) { try { var robot = await RobotService.GetByRobotIdAsync(robotId); if (robot is null) return new(false, null, "RobotId does not exist."); if (robot.MapId is null || robot.MapId == Guid.Empty) return new(false, null, "The robot has not been assigned a map."); var robotController = RobotManager.GetRobotController(robotId); if (robotController is null || !robotController.IsOnline) return new(false, null, "The robot is not online."); if (robotController.Data is null || robotController.Data.State is null) return new(false, null, "The robot is broken connection."); return new(true, robotController.Data, ""); } catch (Exception ex) { Logger.Error($"RobotManager API: GetState for robot {robotId} error: {ex.Message}"); return new(false, null, "An error occurred."); } } [HttpGet] [Route("OnlineStatus/{robotId}")] public async Task> GetOnlineStatus(string robotId) { try { var robot = await RobotService.GetByRobotIdAsync(robotId); if (robot is null) return new(false, false, "RobotId does not exist."); var robotController = RobotManager.GetRobotController(robotId); var isOnline = robotController?.IsOnline ?? false; return new(true, isOnline, ""); } catch (Exception ex) { Logger.Error($"RobotManager API: GetOnlineStatus for robot {robotId} error: {ex.Message}"); return new(false, false, "An error occurred."); } } }