# 堆垛机出库任务 TargetAddress 输送线站台空闲检查 设计文档 ## 1. 背景与目标 在 `StackerCraneTaskSelector.TrySelectOutboundTask` 方法中,当前只检查出库站台的 `NextAddress` 是否可用(`IsOutTaskStationAvailable`)。需求:增加对 `TargetAddress` 输送线站台的空闲状态检查。只有当 `TargetAddress` 输送线站台空闲(`CV_State == 2`)时,才认为该出库任务真正可选。 ## 2. 设计方案 ### 2.1 新增私有方法 在 `StackerCraneTaskSelector` 类中新增方法 `IsTargetAddressConveyorStationAvailable`: ```csharp /// /// 判断 TargetAddress 输送线站台是否空闲 /// /// 出库任务 /// 站台空闲返回 true,否则返回 false private bool IsTargetAddressConveyorStationAvailable([NotNull] Dt_Task task) { // 确定任务类型 int taskType = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty ? StackerCraneConst.EmptyPalletTaskType : task.TaskType; // 通过路由查找 TargetAddress 对应的设备信息 Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.TargetAddress, taskType); if (router == null) { QuartzLogHelper.LogWarn(_logger, "IsTargetAddressConveyorStationAvailable:未找到 TargetAddress 路由信息,TargetAddress: {TargetAddress},任务号: {TaskNum}", $"IsTargetAddressConveyorStationAvailable:未找到 TargetAddress 路由信息,TargetAddress: {task.TargetAddress}", task.Roadway, task.TargetAddress, task.TaskNum); return false; } // 查找输送线设备 IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == router.ChildPosiDeviceCode); if (device == null) { QuartzLogHelper.LogWarn(_logger, "IsTargetAddressConveyorStationAvailable:未找到输送线设备,ChildPosiDeviceCode: {ChildPosiDeviceCode},任务号: {TaskNum}", $"IsTargetAddressConveyorStationAvailable:未找到输送线设备,ChildPosiDeviceCode: {router.ChildPosiDeviceCode}", task.Roadway, router.ChildPosiDeviceCode, task.TaskNum); return false; } // 转换为输送线设备 CommonConveyorLine conveyorLine = (CommonConveyorLine)device; // 读取 CV_State,CV_State == 2 表示空闲 byte cvState = conveyorLine.GetValue(ConveyorLineStatus.CV_State, task.TargetAddress); bool isAvailable = cvState == 2; QuartzLogHelper.LogInfo(_logger, "IsTargetAddressConveyorStationAvailable:TargetAddress: {TargetAddress},CV_State: {CV_State},是否空闲: {IsAvailable},任务号: {TaskNum}", $"IsTargetAddressConveyorStationAvailable:TargetAddress: {task.TargetAddress},CV_State: {cvState},是否空闲: {isAvailable}", task.Roadway, task.TargetAddress, cvState, isAvailable, task.TaskNum); return isAvailable; } ``` ### 2.2 调用点修改 在 `TrySelectOutboundTask` 方法中,在 `return IsOutTaskStationAvailable(taskAfterTransferCheck) ? taskAfterTransferCheck : null;` 之前插入: ```csharp // 判断 TargetAddress 输送线站台是否空闲 if (!IsTargetAddressConveyorStationAvailable(taskAfterTransferCheck)) { return null; } ``` ### 2.3 流程图 ``` 出库任务进入 TrySelectOutboundTask ↓ 移库检查(_transferCheck) ↓ 是否移库任务?是 → 返回任务 ↓(否) IsOutTaskStationAvailable(NextAddress 出库站台) → 不可用 → 返回 null ↓(可用) IsTargetAddressConveyorStationAvailable(TargetAddress 输送线站台) → 不可用 → 返回 null ↓(可用,即 CV_State == 2) 返回任务 ``` ## 3. 涉及的命名空间 新增方法需要 using: - `WIDESEAWCS_QuartzJob.ConveyorLine.Enum.ConveyorLineStatus`(`ConveyorLineStatus.CV_State` 枚举) - `WIDESEAWCS_Model.Models.Dt_Router`(路由实体) - `WIDESEAWCS_Core.Storage`(设备存储) ## 4. 风险与约束 - `CV_State == 2` 表示空闲是业务约定,需与 PLC 侧协议保持一致 - 如设备未连接或协议配置缺失,`GetValue` 会抛出异常,当前设计让异常向上传播,调用方通过 try-catch 兜底