using Newtonsoft.Json; using WIDESEA_Core; using WIDESEAWCS_Common; using WIDESEAWCS_Common.HttpEnum; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_DTO.Stock; using WIDESEAWCS_DTO.TaskInfo; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_Tasks.Workflow.Abstractions; namespace WIDESEAWCS_Tasks { /// /// 机器人任务处理器:负责任务获取、下发、入库任务回传及库存 DTO 构建。 /// public class RobotTaskProcessor { // 通过网关访问 Socket,避免业务层直接依赖 TcpSocketServer。 private readonly ISocketClientGateway _socketClientGateway; private readonly RobotStateManager _stateManager; private readonly IRobotTaskService _robotTaskService; private readonly ITaskService _taskService; private readonly HttpClientHelper _httpClientHelper; public RobotTaskProcessor( ISocketClientGateway socketClientGateway, RobotStateManager stateManager, IRobotTaskService robotTaskService, ITaskService taskService, HttpClientHelper httpClientHelper) { _socketClientGateway = socketClientGateway; _stateManager = stateManager; _robotTaskService = robotTaskService; _taskService = taskService; _httpClientHelper = httpClientHelper; } /// /// 按设备编码获取当前机器人任务。 /// public Dt_RobotTask? GetTask(RobotCraneDevice robotCrane) { return _robotTaskService.QueryRobotCraneTask(robotCrane.DeviceCode); } /// /// 删除机器人任务。 /// public bool? DeleteTask(int ID) { return _robotTaskService.Repository.DeleteDataById(ID); } /// /// 下发取货指令(Pickbattery)到机器人客户端。 /// public async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state) { string taskString = $"Pickbattery,{task.RobotSourceAddress}"; 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); } } } /// /// 处理入库任务回传(拆盘/组盘/换盘场景)。 /// public async Task HandleInboundTaskAsync(RobotSocketState state, bool useSourceAddress) { var currentTask = state.CurrentTask; if (currentTask == null) { return false; } string roadway = currentTask.RobotSourceAddressLineCode; int warehouseId = currentTask.RobotRoadway == "ZYRB1" ? 1 : currentTask.RobotRoadway == "HPRB001" ? 2 : 3; int taskType = 0; string SourceAddress = currentTask.RobotTargetAddressLineCode; string TargetAddress = currentTask.RobotSourceAddressLineCode; string PalletCode = string.Empty; var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; if (useSourceAddress) { switch (robotTaskType) { case RobotTaskTypeEnum.GroupPallet: return false; case RobotTaskTypeEnum.ChangePallet: case RobotTaskTypeEnum.SplitPallet: taskType = TaskTypeEnum.InEmpty.GetHashCode(); PalletCode = currentTask.RobotSourceAddressPalletCode; break; } } else { switch (robotTaskType) { case RobotTaskTypeEnum.ChangePallet: case RobotTaskTypeEnum.GroupPallet: taskType = TaskTypeEnum.Inbound.GetHashCode(); PalletCode = currentTask.RobotTargetAddressPalletCode; break; case RobotTaskTypeEnum.SplitPallet: return true; } } CreateTaskDto taskDto = new CreateTaskDto { PalletCode = PalletCode, SourceAddress = SourceAddress ?? string.Empty, TargetAddress = TargetAddress ?? string.Empty, Roadway = roadway, WarehouseId = warehouseId, PalletType = 1, TaskType = taskType }; var result = _httpClientHelper.Post(nameof(ConfigKey.CreateTaskInboundAsync), taskDto.ToJson()); if (!result.Data.Status && result.IsSuccess) { return false; } WMSTaskDTO taskDTO = JsonConvert.DeserializeObject(result.Data.Data.ToJson() ?? string.Empty) ?? new WMSTaskDTO(); var content = _taskService.ReceiveWMSTask(new List { taskDTO }); if (!content.Status) { return false; } var taskInfo = JsonConvert.DeserializeObject(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)); if (device != null) { CommonConveyorLine conveyorLine = (CommonConveyorLine)device; conveyorLine.SetValue(ConveyorLineDBNameNew.Target, taskInfo.NextAddress, sourceAddress); conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, taskInfo.TaskNum, sourceAddress); conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_STB, 1, sourceAddress); if (_taskService.UpdateTaskStatusToNext(taskInfo).Status) { return true; } } return false; } /// /// 构建库存回传 DTO。 /// public static StockDTO BuildStockDTO(RobotSocketState state, int[] positions) { return new StockDTO { SourceLineNo = state.CurrentTask.RobotSourceAddressLineCode, SourcePalletNo = state.CurrentTask.RobotSourceAddressPalletCode, TargetPalletNo = state.CurrentTask.RobotTargetAddressPalletCode, TargetLineNo = state.CurrentTask.RobotTargetAddressLineCode, Details = positions .Where(x => x > 0) .OrderBy(x => x) .Select((x, idx) => new StockDetailDTO { Quantity = state.RobotTaskTotalNum > 0 ? state.RobotTaskTotalNum + positions.Length : positions.Length, Channel = x, CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : "" }) .ToList() }; } /// /// 调用拆盘 API。 /// public HttpResponseResult PostSplitPalletAsync(StockDTO stockDTO) { return _httpClientHelper.Post(nameof(ConfigKey.SplitPalletAsync), stockDTO.ToJson()); } /// /// 调用组盘/换盘 API。 /// public HttpResponseResult PostGroupPalletAsync(string configKey, StockDTO stockDTO) { return _httpClientHelper.Post(configKey, stockDTO.ToJson()); } } }