编辑 | blame | 历史 | 原始文档

堆垛机出库任务 TargetAddress 不可用时继续搜索 设计文档

1. 背景与目标

StackerCraneTaskSelector.SelectTask 方法中,当 TrySelectOutboundTaskTargetAddress 输送线站台不空闲(CV_State != 2)而返回 null 时,需要继续搜索其他可选的出库任务,而不是直接返回 null 或仅尝试不同 NextAddress 的任务。

2. 设计方案

2.1 搜索顺序

当 TargetAddress 不可用时,按以下顺序搜索备选任务:

  1. 同 NextAddress 的其他任务 - 查询与当前任务 NextAddress 相同的其他出库任务,尝试其 TargetAddress 是否可用
  2. 不同 NextAddress 的任务 - 查询其他站台(N extAddress 不同)的出库任务(现有逻辑)

2.2 代码修改

SelectTask 方法中,TrySelectOutboundTask(candidateTask) 返回 null 之后、现有备选任务循环之前,插入同 NextAddress 任务搜索逻辑:

// 尝试选择出库任务
Dt_Task? selectedTask = TrySelectOutboundTask(candidateTask);
if (selectedTask != null)
{
    return selectedTask;
}

// ===== TargetAddress 不可用时,先尝试同 NextAddress 的其他任务 =====
// 查询与当前任务 NextAddress 相同的其他出库任务
var sameStationTasks = _taskService
    .QueryStackerCraneOutTasks(deviceCode, new List<string> { candidateTask.NextAddress })
    .Where(x => x.TaskId != candidateTask.TaskId)
    .ToList();

foreach (var sameStationTask in sameStationTasks)
{
    selectedTask = TrySelectOutboundTask(sameStationTask);
    if (selectedTask != null)
    {
        QuartzLogHelper.LogDebug(_logger, $"选中同站台备选出库任务,任务号: {selectedTask.TaskNum}", commonStackerCrane.DeviceName);
        return selectedTask;
    }
}

// ===== 同 NextAddress 无可用任务,尝试不同 NextAddress 的任务(现有逻辑)=====
var otherOutStationCodes = _routerService
    .QueryNextRoutes(deviceCode, candidateTask.NextAddress, candidateTask.TaskType)
    .Select(x => x.ChildPosi)
    .ToList();

var tasks = _taskService.QueryStackerCraneOutTasks(deviceCode, otherOutStationCodes);
foreach (var alternativeTask in tasks)
{
    selectedTask = TrySelectOutboundTask(alternativeTask);
    if (selectedTask != null)
    {
        QuartzLogHelper.LogDebug(_logger, $"选中备选出库任务,任务号: {selectedTask.TaskNum}", commonStackerCrane.DeviceName);
        return selectedTask;
    }
}

2.3 无需新增方法

利用现有的 QueryStackerCraneOutTasks(deviceCode, stationCodes) 方法,传入单站台列表即可查询同 NextAddress 的任务。过滤掉当前任务(TaskId 不同)避免重复尝试。

2.4 流程图

SelectTask
    ↓
TrySelectOutboundTask(candidateTask)
    ↓
TargetAddress 可用?否 → 返回 null
    ↓
查询同 NextAddress 的其他出库任务
    ↓
遍历同站台任务
  → TrySelectOutboundTask(task) → 可用 → 返回任务
  → 不可用 → 继续下一个
    ↓
同 NextAddress 无可用任务
    ↓
查询不同 NextAddress 的出库任务(现有逻辑)
    ↓
遍历 → 返回可用任务 / 无可用 → 返回 null

3. 涉及的命名空间

无需新增 using,现有方法签名已满足。

4. 风险与约束

  • TaskId 作为唯一标识用于过滤已尝试任务,假设任务表中无重复 TaskId
  • QueryStackerCraneOutTasks 返回的任务列表需要考虑排序(如果有业务规则决定优先级)
  • 如果同 NextAddress 有大量任务,可能增加选择延迟