| | |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | | using WIDESEAWCS_Tasks.SocketServer; |
| | | using WIDESEAWCS_Tasks.Workflow.Abstractions; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | | /// <summary> |
| | | /// 机械手任务处理器 - 负责机械手任务执行和处理 |
| | | /// 机器人任务处理器:负责任务获取、下发、入库任务回传及库存 DTO 构建。 |
| | | /// </summary> |
| | | public class RobotTaskProcessor |
| | | { |
| | | private readonly TcpSocketServer _tcpSocket; |
| | | // 通过网关访问 Socket,避免业务层直接依赖 TcpSocketServer。 |
| | | private readonly ISocketClientGateway _socketClientGateway; |
| | | private readonly RobotStateManager _stateManager; |
| | | private readonly IRobotTaskService _robotTaskService; |
| | | private readonly ITaskService _taskService; |
| | | private readonly HttpClientHelper _httpClientHelper; |
| | | |
| | | public RobotTaskProcessor( |
| | | TcpSocketServer tcpSocket, |
| | | ISocketClientGateway socketClientGateway, |
| | | RobotStateManager stateManager, |
| | | IRobotTaskService robotTaskService, |
| | | ITaskService taskService, |
| | | HttpClientHelper httpClientHelper) |
| | | { |
| | | _tcpSocket = tcpSocket; |
| | | _socketClientGateway = socketClientGateway; |
| | | _stateManager = stateManager; |
| | | _robotTaskService = robotTaskService; |
| | | _taskService = taskService; |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取机械手任务 |
| | | /// 按设备编码获取当前机器人任务。 |
| | | /// </summary> |
| | | public Dt_RobotTask? GetTask(RobotCraneDevice robotCrane) |
| | | { |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取机械手任务 |
| | | /// 删除机器人任务。 |
| | | /// </summary> |
| | | public bool? DeleteTask(int ID) |
| | | { |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 发送机械手取货命令 |
| | | /// 下发取货指令(Pickbattery)到机器人客户端。 |
| | | /// </summary> |
| | | public async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state) |
| | | { |
| | | string taskString = $"Pickbattery,{task.RobotSourceAddress}"; |
| | | // 发送任务指令 |
| | | bool result = await _tcpSocket.SendToClientAsync(state.IPAddress, taskString); |
| | | bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString); |
| | | if (result) |
| | | { |
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); |
| | | state.CurrentTask = task; |
| | | |
| | | // 更新缓存中的状态(使用安全更新防止并发覆盖) |
| | | // 保持原语义:仅在状态安全写入成功后再更新任务状态。 |
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) |
| | | { |
| | | await _robotTaskService.UpdateRobotTaskAsync(task); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理入库任务 |
| | | /// 处理入库任务回传(拆盘/组盘/换盘场景)。 |
| | | /// </summary> |
| | | public async Task<bool> HandleInboundTaskAsync(RobotSocketState state, bool useSourceAddress) |
| | | { |
| | |
| | | string SourceAddress = currentTask.RobotTargetAddressLineCode; |
| | | string TargetAddress = currentTask.RobotSourceAddressLineCode; |
| | | string PalletCode = string.Empty; |
| | | // 直接转换为枚举类型进行比较 |
| | | var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; |
| | | |
| | | if (useSourceAddress) |
| | |
| | | PalletType = 1, |
| | | TaskType = taskType |
| | | }; |
| | | |
| | | var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.CreateTaskInboundAsync), taskDto.ToJson()); |
| | | if (!result.Data.Status && result.IsSuccess) |
| | | { |
| | |
| | | |
| | | WMSTaskDTO taskDTO = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data.ToJson() ?? string.Empty) ?? new WMSTaskDTO(); |
| | | var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO }); |
| | | if (!content.Status) return false; |
| | | if (!content.Status) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | var taskInfo = JsonConvert.DeserializeObject<Dt_Task>(content.Data.ToJson() ?? string.Empty) ?? new Dt_Task(); |
| | | |
| | | string sourceAddress = taskDTO.SourceAddress; |
| | | |
| | | IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceAddress)); |
| | |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 构建库存DTO |
| | | /// 构建库存回传 DTO。 |
| | | /// </summary> |
| | | public static StockDTO BuildStockDTO(RobotSocketState state, int[] positions) |
| | | { |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 调用拆盘API |
| | | /// 调用拆盘 API。 |
| | | /// </summary> |
| | | public HttpResponseResult<WebResponseContent> PostSplitPalletAsync(StockDTO stockDTO) |
| | | { |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 调用组盘或换盘API |
| | | /// 调用组盘/换盘 API。 |
| | | /// </summary> |
| | | public HttpResponseResult<WebResponseContent> PostGroupPalletAsync(string configKey, StockDTO stockDTO) |
| | | { |