using WIDESEAWCS_QuartzJob; namespace WIDESEAWCS_Tasks { /// /// 输送线目标地址选择器 - 处理拘束机/插拔钉机的上下层请求 /// /// /// 核心职责: /// 1. 处理入库场景的目标地址选择 /// 2. 处理出库场景的目标地址选择 /// 3. 判断拘束机和插拔钉机的物料请求状态 /// 4. 协调输送线与上下层设备之间的物料流转 /// /// 拘束机和插拔钉机都有上下两层结构, /// 每层都有独立的物料请求和出料信号,需要分别处理。 /// public class ConveyorLineTargetAddressSelector { /// /// 拘束机名称常量 /// private const string ConstraintMachineName = "拘束机"; /// /// 插拔钉机名称常量 /// private const string PinMachineName = "插拔钉机"; /// /// 拘束机对应的点位编码列表 /// /// /// 当目标地址在这些编码中时,表示需要与拘束机交互。 /// private static readonly List ConstraintMachineCodes = new List { "10180", "20090" }; /// /// 插拔钉机对应的点位编码列表 /// /// /// 当目标地址在这些编码中时,表示需要与插拔钉机交互。 /// private static readonly List PinMachineCodes = new List { "10190", "20100" }; /// /// 处理入库场景的下一地址请求 /// /// /// 当入库任务执行到某个位置时调用此方法。 /// 判断目标设备是否需要物料或可以出料。 /// /// 输送线设备对象 /// 下一地址/目标设备编码 /// 当前子设备编码 public void HandleInboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode) { // 调用通用处理方法,isUpper = true 表示处理上层 HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, isUpper: true); } /// /// 处理出库场景的下一地址请求 /// /// /// 当出库任务执行到某个位置时调用此方法。 /// 判断目标设备是否需要物料或可以出料。 /// /// 输送线设备对象 /// 下一地址/目标设备编码 /// 当前子设备编码 public void HandleOutboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode) { // 调用通用处理方法,isUpper = false 表示处理下层 HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, isUpper: false); } /// /// 通用设备请求处理方法 /// /// /// 根据目标地址类型(拘束机/插拔钉机)调用相应的处理逻辑。 /// 处理上下层设备的物料请求和出料协调。 /// /// 输送线设备对象 /// 下一地址/目标设备编码 /// 当前子设备编码 /// 是否处理上层(true=上层,false=下层) private void HandleDeviceRequest(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode, bool isUpper) { // 获取全局设备列表 var devices = Storage.Devices; // 判断目标设备类型 if (ConstraintMachineCodes.Contains(nextAddress)) { // 拘束机处理分支 // 查找拘束机设备 ConstraintMachine? constraint = devices.OfType().FirstOrDefault(d => d.DeviceName == ConstraintMachineName); if (constraint == null) { // 未找到拘束机设备,直接返回 return; } // 处理拘束机的请求 ProcessDeviceRequest( conveyorLine, childDeviceCode, // 获取物料请求标志(上层或下层) getMaterialRequest: () => isUpper ? constraint.GetValue(ConstraintMachineDBName.MaterialRequestUpper) != 0 : constraint.GetValue(ConstraintMachineDBName.MaterialRequestLower) != 0, // 获取出料请求标志(上层或下层) getOutputRequest: () => isUpper ? constraint.GetValue(ConstraintMachineDBName.OutputRequestUpper) != 0 : constraint.GetValue(ConstraintMachineDBName.OutputRequestLower) != 0, // 设置输出就绪标志(上层或下层) setOutputReady: outputReq => { if (isUpper) { constraint.SetValue(ConstraintMachineDBName.ConstraintTrayOutputReadyUpper, outputReq ? 1 : 0); } else { constraint.SetValue(ConstraintMachineDBName.ConstraintTrayOutputReadyLower, outputReq ? 1 : 0); } }); } else if (PinMachineCodes.Contains(nextAddress)) { // 插拔钉机处理分支 // 查找插拔钉机设备 PinMachine? pinMachine = devices.OfType().FirstOrDefault(d => d.DeviceName == PinMachineName); if (pinMachine == null) { return; } // 处理插拔钉机的请求 ProcessDeviceRequest( conveyorLine, childDeviceCode, // 获取物料请求标志(上层或下层) getMaterialRequest: () => isUpper ? pinMachine.GetValue(PinMachineDBName.MaterialRequestUpper) != 0 : pinMachine.GetValue(PinMachineDBName.MaterialRequestLower) != 0, // 获取出料请求标志(上层或下层) getOutputRequest: () => isUpper ? pinMachine.GetValue(PinMachineDBName.OutputRequestUpper) != 0 : pinMachine.GetValue(PinMachineDBName.OutputRequestLower) != 0, // 设置输出就绪标志(上层或下层) setOutputReady: outputReq => { if (isUpper) { pinMachine.SetValue(PinMachineDBName.PlugPinTrayOutputReadyUpper, outputReq ? 1 : 0); } else { pinMachine.SetValue(PinMachineDBName.PlugPinTrayOutputReadyLower, outputReq ? 1 : 0); } }); } } /// /// 处理设备请求的核心逻辑 /// /// /// 根据物料请求和出料请求的状态: /// - 如果有物料请求,设置目标地址并发送 ACK /// - 如果有出料请求,设置设备的输出就绪标志 /// /// 输送线设备对象 /// 当前子设备编码 /// 获取物料请求状态的委托 /// 获取出料请求状态的委托 /// 设置输出就绪标志的委托 private static void ProcessDeviceRequest( CommonConveyorLine conveyorLine, string childDeviceCode, Func getMaterialRequest, Func getOutputRequest, Action setOutputReady) { // 获取物料请求状态 bool materialReq = getMaterialRequest(); // 获取出料请求状态 bool outputReq = getOutputRequest(); // 如果设备需要物料 if (materialReq) { // 设置目标地址为 1(表示有料进来) conveyorLine.SetValue(ConveyorLineDBNameNew.Target, 1, childDeviceCode); // 回复 ACK 确认信号 conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode); } else { // 设备不需要物料,设置输出就绪标志 // 通知设备可以继续出料 setOutputReady(outputReq); } } } }