| | |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core.LogHelper; |
| | | using WIDESEAWCS_Tasks.Workflow.Abstractions; |
| | | |
| | | namespace WIDESEAWCS_Tasks.Workflow |
| | | { |
| | | /// <summary> |
| | | /// 简单命令处理:仅迁移原 RobotMessageHandler 中的命令分支,不改变业务语义。 |
| | | /// 简单命令处理器 |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// 迁移原 RobotMessageHandler 中的简单命令分支,不改变业务语义。 |
| | | /// |
| | | /// 简单命令是指不需要额外参数的状态更新命令,如运行状态、模式切换等。 |
| | | /// 与前缀命令(需要解析位置参数)相对。 |
| | | /// |
| | | /// 处理完成后返回 true;无法识别的命令返回 false。 |
| | | /// </remarks> |
| | | public class RobotSimpleCommandHandler : IRobotSimpleCommandHandler |
| | | { |
| | | /// <summary> |
| | | /// 机器人任务处理器 |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// 用于处理 allpickfinished 和 allputfinished 命令时, |
| | | /// 调用任务入库和删除逻辑。 |
| | | /// </remarks> |
| | | private readonly RobotTaskProcessor _taskProcessor; |
| | | |
| | | public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor) |
| | | /// <summary> |
| | | /// Socket 网关 |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// 用于向客户端发送响应消息。 |
| | | /// </remarks> |
| | | private readonly ISocketClientGateway _socketClientGateway; |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | /// <param name="taskProcessor">任务处理器实例</param> |
| | | public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor, ISocketClientGateway socketClientGateway) |
| | | { |
| | | _taskProcessor = taskProcessor; |
| | | _socketClientGateway = socketClientGateway; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理简单命令 |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// 根据消息内容更新机器人的运行状态、模式、手臂对象等属性。 |
| | | /// 某些命令(如 allpickfinished、allputfinished)会触发实际的业务逻辑。 |
| | | /// |
| | | /// 命令列表: |
| | | /// - homing: 回零中 |
| | | /// - homed: 已回零 |
| | | /// - running: 运行中 |
| | | /// - pausing: 暂停中 |
| | | /// - warming: 预热中 |
| | | /// - emstoping: 急停中 |
| | | /// - picking: 取货中 |
| | | /// - puting: 放货中 |
| | | /// - runmode,1: 运行模式切换到手动 |
| | | /// - runmode,2: 运行模式切换到自动 |
| | | /// - controlmode,1: 控制模式切换到客户端控制 |
| | | /// - controlmode,2: 控制模式切换到其他 |
| | | /// - armobject,1: 手臂有物料 |
| | | /// - armobject,0: 手臂无物料 |
| | | /// - allpickfinished: 全部取货完成 |
| | | /// - allputfinished: 全部放货完成 |
| | | /// </remarks> |
| | | /// <param name="message">消息内容(小写形式)</param> |
| | | /// <param name="state">机器人当前状态(会被修改)</param> |
| | | /// <returns>是否成功处理;无法识别的命令返回 false</returns> |
| | | public async Task<bool> HandleAsync(string message, RobotSocketState state) |
| | | { |
| | | // 使用 switch 表达式进行模式匹配,提高可读性和性能 |
| | | switch (message) |
| | | { |
| | | // ==================== 运行状态命令 ==================== |
| | | |
| | | // 机器人正在回零 |
| | | case "homing": |
| | | state.OperStatus = "Homing"; |
| | | state.Homed = "Homing"; |
| | | return true; |
| | | |
| | | // 机器人已完成回零 |
| | | case "homed": |
| | | state.OperStatus = "Homed"; |
| | | state.Homed = "Homed"; |
| | | return true; |
| | | |
| | | case "picking": |
| | | state.CurrentAction = "Picking"; |
| | | return true; |
| | | |
| | | case "puting": |
| | | state.CurrentAction = "Putting"; |
| | | return true; |
| | | |
| | | case "allpickfinished": |
| | | { |
| | | state.CurrentAction = "AllPickFinished"; |
| | | var currentTask = state.CurrentTask; |
| | | if (currentTask == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; |
| | | if (robotTaskType == RobotTaskTypeEnum.SplitPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) |
| | | { |
| | | _taskProcessor.DeleteTask(currentTask.RobotTaskId); |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | case "allputfinished": |
| | | { |
| | | state.CurrentAction = "AllPutFinished"; |
| | | var currentTask = state.CurrentTask; |
| | | if (currentTask == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; |
| | | if (robotTaskType == RobotTaskTypeEnum.GroupPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) |
| | | { |
| | | _taskProcessor.DeleteTask(currentTask.RobotTaskId); |
| | | state.CurrentTask = null; |
| | | state.RobotTaskTotalNum = 0; |
| | | state.CellBarcode = new List<string>(); |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // 机器人正在运行 |
| | | case "running": |
| | | state.OperStatus = "Running"; |
| | | return true; |
| | | |
| | | // 机器人正在暂停 |
| | | case "pausing": |
| | | state.OperStatus = "Pausing"; |
| | | return true; |
| | | |
| | | // 机器人正在预热 |
| | | case "warming": |
| | | state.OperStatus = "Warming"; |
| | | return true; |
| | | |
| | | // 机器人正在急停 |
| | | case "emstoping": |
| | | state.OperStatus = "Emstoping"; |
| | | return true; |
| | | |
| | | // 机器人正在取货 |
| | | case "picking": |
| | | state.CurrentAction = "Picking"; |
| | | return true; |
| | | |
| | | // 机器人正在放货 |
| | | case "puting": |
| | | state.CurrentAction = "Putting"; |
| | | return true; |
| | | |
| | | // ==================== 全部完成命令 ==================== |
| | | |
| | | // 全部取货完成 |
| | | case "allpickfinished": |
| | | { |
| | | // 更新当前动作为"全部取货完成" |
| | | state.CurrentAction = "AllPickFinished"; |
| | | |
| | | // 获取当前关联的任务 |
| | | var currentTask = state.CurrentTask; |
| | | if (currentTask == null) |
| | | { |
| | | // 没有任务关联,返回 false |
| | | return false; |
| | | } |
| | | |
| | | // 判断任务类型 |
| | | var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; |
| | | |
| | | // 只有拆盘或换盘任务需要处理入库 |
| | | if (robotTaskType == RobotTaskTypeEnum.SplitPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | // 处理入库任务回传 |
| | | // useSourceAddress: true 表示使用源地址(拆盘/换盘场景) |
| | | if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) |
| | | { |
| | | // 入库成功,删除任务记录 |
| | | _taskProcessor.DeleteTask(currentTask.RobotTaskId); |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); |
| | | QuartzLogger.Info($"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // 全部放货完成 |
| | | case "allputfinished": |
| | | { |
| | | // 更新当前动作为"全部放货完成" |
| | | state.CurrentAction = "AllPutFinished"; |
| | | |
| | | // 获取当前关联的任务 |
| | | var currentTask = state.CurrentTask; |
| | | if (currentTask == null) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // 判断任务类型 |
| | | var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; |
| | | |
| | | // 只有组盘或换盘任务需要处理入库 |
| | | if (robotTaskType == RobotTaskTypeEnum.GroupPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) |
| | | { |
| | | // 处理入库任务回传 |
| | | // useSourceAddress: false 表示使用目标地址(组盘/换盘场景) |
| | | if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) |
| | | { |
| | | // 入库成功,删除任务记录 |
| | | _taskProcessor.DeleteTask(currentTask.RobotTaskId); |
| | | |
| | | // 清理状态,为下一个任务做准备 |
| | | state.CurrentTask = null; // 清除当前任务 |
| | | state.RobotTaskTotalNum = 0; // 重置任务计数 |
| | | state.CellBarcode = new List<string>(); // 清空条码列表 |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogger.Info($"发送消息:【Group,diskFinished】", state.RobotCrane.DeviceName); |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // ==================== 模式切换命令 ==================== |
| | | |
| | | // 运行模式切换为手动(模式1) |
| | | case "runmode,1": |
| | | state.RobotRunMode = 1; |
| | | return true; |
| | | |
| | | // 运行模式切换为自动(模式2) |
| | | case "runmode,2": |
| | | state.RobotRunMode = 2; |
| | | return true; |
| | | |
| | | // 控制模式切换为客户端控制(模式1) |
| | | case "controlmode,1": |
| | | state.RobotControlMode = 1; |
| | | return true; |
| | | |
| | | // 控制模式切换为其他(模式2) |
| | | case "controlmode,2": |
| | | state.RobotControlMode = 2; |
| | | return true; |
| | | |
| | | // ==================== 手臂对象命令 ==================== |
| | | |
| | | // 手臂有物料(抓取到货物) |
| | | case "armobject,1": |
| | | state.RobotArmObject = 1; |
| | | return true; |
| | | |
| | | // 手臂无物料(手臂空闲) |
| | | case "armobject,0": |
| | | state.RobotArmObject = 0; |
| | | return true; |
| | | |
| | | // ==================== 默认情况 ==================== |
| | | |
| | | // 无法识别的命令,返回 false |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |