| | |
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 按任务编号获取机器人任务
|
| | | /// </summary>
|
| | | /// <remarks>
|
| | | /// 用于 RobotJob 快速查找执行中的任务,避免全表扫描。
|
| | | /// 优先通过状态中缓存的 CurrentTaskNum 定位任务。
|
| | | /// </remarks>
|
| | | /// <param name="taskNum">机器人任务编号</param>
|
| | | /// <returns>匹配的任务对象,如果没有则返回 null</returns>
|
| | | public Dt_RobotTask? GetTaskByNum(int taskNum)
|
| | | {
|
| | | return _robotTaskService.Repository.QueryFirst(x => x.RobotTaskNum == taskNum);
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 按设备编码获取当前机器人的执行中任务
|
| | | /// </summary>
|
| | | /// <remarks>
|
| | |
| | |
|
| | | // 将任务关联到状态对象
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (isScanNG)
|
| | | {
|
| | |
| | |
|
| | | // 将任务关联到状态对象
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | |
|
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | | {
|
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | | {
|
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | | // 通道/位置编号
|
| | | Channel = x,
|
| | |
|
| | | // 电池条码:如果状态中有条码列表,取对应位置的条码;否则为空
|
| | | // 电池条码:使用当前批次条码列表,取对应位置的条码;否则为空
|
| | | //CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : ""
|
| | | CellBarcode = !state.CellBarcode.IsNullOrEmpty() ? state.CellBarcode[idx].ToString() ?? string.Empty : string.Empty
|
| | | CellBarcode = !state.CurrentBatchBarcodes.IsNullOrEmpty() ? state.CurrentBatchBarcodes[idx].ToString() ?? string.Empty : string.Empty
|
| | | })
|
| | | .ToList()
|
| | | };
|
| | | }
|
| | | /// <summary>
|
| | | /// 构建库存回传 DTO
|
| | | /// </summary>
|
| | | /// <remarks>
|
| | | /// 用于拆盘和组盘操作时,向 WMS 回传库存信息。
|
| | | /// DTO 包含源货位、目标货位、托盘码以及每个位置的电池条码。
|
| | | /// </remarks>
|
| | | /// <param name="state">机器人当前状态</param>
|
| | | /// <param name="positions">电池位置数组</param>
|
| | | /// <returns>构建好的库存 DTO</returns>
|
| | | public static StockDTO BuildStockDTO1(RobotSocketState state, int[] positions)
|
| | | {
|
| | | return new StockDTO
|
| | | {
|
| | | // 源输送线编号
|
| | | SourceLineNo = state.CurrentTask.RobotSourceAddressLineCode,
|
| | |
|
| | | // 源托盘号
|
| | | SourcePalletNo = state.CurrentTask.RobotSourceAddressPalletCode,
|
| | |
|
| | | // 目标托盘号
|
| | | TargetPalletNo = state.CurrentTask.RobotTargetAddressPalletCode,
|
| | |
|
| | | // 目标输送线编号
|
| | | TargetLineNo = state.CurrentTask.RobotTargetAddressLineCode,
|
| | |
|
| | | // 巷道编号(机器人名称)
|
| | | Roadway = state.CurrentTask.RobotRoadway,
|
| | |
|
| | | // 电池位置详情列表
|
| | | // 过滤掉位置为 0 或负数的无效数据
|
| | | // 按位置编号排序
|
| | | // 为每个位置生成对应的库存详情
|
| | | Details = positions
|
| | | .Where(x => x > 0) // 过滤无效位置
|
| | | .OrderBy(x => x) // 按位置排序
|
| | | .Select((x, idx) => new StockDetailDTO
|
| | | {
|
| | | // 数量:如果已有任务总数,使用任务总数+当前位置数;否则只使用当前位置数
|
| | | Quantity = 1,
|
| | |
|
| | | // 通道/位置编号
|
| | | Channel = x,
|
| | |
|
| | | // 电池条码:取当前批次条码列表的最后 N 个(N = 有效位置数)
|
| | | CellBarcode = !state.CurrentBatchBarcodes.IsNullOrEmpty() ? state.CurrentBatchBarcodes[^(positions.Count(p => p > 0) - idx)].ToString() ?? string.Empty : string.Empty
|
| | | })
|
| | | .ToList()
|
| | | };
|
| | | }
|
| | | /// <summary>
|
| | | /// 调用拆盘 API
|
| | | /// </summary>
|