# 堆垛机 TargetAddress 输送线站台空闲检查 实施计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 在 `StackerCraneTaskSelector.TrySelectOutboundTask` 中新增 `TargetAddress` 输送线站台空闲检查(CV_State == 2 表示空闲),不可用则返回 null。 **Architecture:** 在 `StackerCraneTaskSelector` 类中新增 `IsTargetAddressConveyorStationAvailable` 私有方法,通过 `_routerService.QueryNextRoute` 获取路由信息,从 `Storage.Devices` 找到输送线设备,调用 `GetValue` 读取 `CV_State` 判断是否空闲。 **Tech Stack:** C# / .NET 6+,SqlSugar ORM,Serilog --- ## 涉及文件 - 修改: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs` --- ## Task 1: 新增 IsTargetAddressConveyorStationAvailable 方法 **Files:** - Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs` - [ ] **Step 1: 确认现有 using 命名空间** 打开 `StackerCraneTaskSelector.cs`,检查是否已包含以下 using: - `WIDESEAWCS_QuartzJob.ConveyorLine.Enum.ConveyorLineStatus` - `WIDESEAWCS_Model.Models.Dt_Router` 如缺少,添加: ```csharp using WIDESEAWCS_QuartzJob.ConveyorLine.Enum; using WIDESEAWCS_Model.Models; ``` - [ ] **Step 2: 在类末尾(`IsOutTaskStationAvailable` 方法之后,`}` 之前)新增方法** ```csharp /// /// 判断 TargetAddress 输送线站台是否空闲 /// /// 出库任务 /// 站台空闲(CV_State == 2)返回 true 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; } ``` - [ ] **Step 3: Commit** ```bash git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs git commit -m "feat(StackerCraneTaskSelector): 新增 TargetAddress 输送线站台空闲检查方法 IsTargetAddressConveyorStationAvailable 通过路由查找输送线设备,读取 CV_State 判断是否空闲(CV_State == 2) Co-Authored-By: Claude Opus 4.7 " ``` --- ## Task 2: 在 TrySelectOutboundTask 中调用新方法 **Files:** - Modify: `WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs` - [ ] **Step 1: 找到 TrySelectOutboundTask 方法中的 return 语句** 当前方法末尾(line ~210): ```csharp return IsOutTaskStationAvailable(taskAfterTransferCheck) ? taskAfterTransferCheck : null; ``` - [ ] **Step 2: 在 return 语句之前插入 TargetAddress 检查逻辑** 在 `return IsOutTaskStationAvailable(...)` 之前插入: ```csharp // 判断 TargetAddress 输送线站台是否空闲 if (!IsTargetAddressConveyorStationAvailable(taskAfterTransferCheck)) { return null; } ``` 修改后: ```csharp // 判断 TargetAddress 输送线站台是否空闲 if (!IsTargetAddressConveyorStationAvailable(taskAfterTransferCheck)) { return null; } // 判断出库站台是否可用 return IsOutTaskStationAvailable(taskAfterTransferCheck) ? taskAfterTransferCheck : null; ``` - [ ] **Step 3: 验证修改位置正确** 确认修改后的 `TrySelectOutboundTask` 方法末尾逻辑为: ```csharp // 判断 TargetAddress 输送线站台是否空闲 if (!IsTargetAddressConveyorStationAvailable(taskAfterTransferCheck)) { return null; } // 判断出库站台是否可用 return IsOutTaskStationAvailable(taskAfterTransferCheck) ? taskAfterTransferCheck : null; ``` - [ ] **Step 4: Commit** ```bash git add WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs git commit -m "feat(StackerCraneTaskSelector): 在 TrySelectOutboundTask 中调用 TargetAddress 站台空闲检查 检查顺序:先检查 NextAddress 出库站台,再检查 TargetAddress 输送线站台 若 TargetAddress 站台不空闲(CV_State != 2),任务不可选 Co-Authored-By: Claude Opus 4.7 " ``` --- ## Task 3: 验证构建 - [ ] **Step 1: 执行构建验证** ```bash cd D:/Git/ShanMeiXinNengYuan/Code dotnet build WCS/WIDESEAWCS_Server/WIDESEAWCS_Server.sln ``` 预期:无编译错误 - [ ] **Step 2: 如有错误,分析并修复** 常见错误: - 缺少 using → 添加命名空间 - 类型转换异常 → 确认设备类型为 `CommonConveyorLine` - 方法未找到 → 确认方法签名正确 --- ## 验证清单 - [ ] `IsTargetAddressConveyorStationAvailable` 方法已添加在 `IsOutTaskStationAvailable` 方法之后 - [ ] `TrySelectOutboundTask` 方法在判断 `IsOutTaskStationAvailable` 之前,先判断 `IsTargetAddressConveyorStationAvailable` - [ ] 新增方法包含完整的日志记录(Warn 和 Info) - [ ] `CV_State == 2` 作为空闲判断条件 - [ ] `task.TargetAddress` 直接作为 `GetValue` 的设备子编号 - [ ] 构建通过,无编译错误 - [ ] 已提交两个 commit(方法新增 + 调用点)