wanshenmean
11 小时以前 c9a1df9c19a64844d05d120ff171f523d77e7823
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -1,10 +1,12 @@
using MapsterMapper;
using Serilog;
using System.Threading.Tasks;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_Tasks
@@ -47,6 +49,11 @@
        private readonly IMapper _mapper;
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger _logger;
        /// <summary>
        /// 输送线任务过滤器
        /// </summary>
        /// <remarks>
@@ -69,16 +76,18 @@
        /// <param name="taskExecuteDetailService">任务执行明细服务</param>
        /// <param name="routerService">路由服务</param>
        /// <param name="mapper">对象映射器</param>
        public ConveyorLineDispatchHandler(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper)
        /// <param name="logger">日志记录器</param>
        public ConveyorLineDispatchHandler(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper, ILogger logger)
        {
            _taskService = taskService;
            _taskExecuteDetailService = taskExecuteDetailService;
            _routerService = routerService;
            _mapper = mapper;
            _logger = logger;
            // 初始化任务过滤器和目标地址选择器
            _taskFilter = new ConveyorLineTaskFilter(taskService);
            _targetAddressSelector = new ConveyorLineTargetAddressSelector();
            _taskFilter = new ConveyorLineTaskFilter(taskService, _logger);
            _targetAddressSelector = new ConveyorLineTargetAddressSelector(_logger);
        }
        /// <summary>
@@ -96,6 +105,7 @@
        {
            // 清除任务号,表示当前空闲
            conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, 0, childDeviceCode);
            QuartzLogHelper.LogDebug(_logger, $"HeartBeat:子设备 {childDeviceCode} 心跳", conveyorLine.DeviceCode);
        }
        /// <summary>
@@ -114,6 +124,8 @@
        /// <param name="childDeviceCode">子设备编码</param>
        public void RequestInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode)
        {
            QuartzLogHelper.LogInfo(_logger, $"请求入库,子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            // 向 WMS 请求新任务(基于条码)
            if (_taskFilter.RequestWmsTask(command.Barcode, childDeviceCode))
            {
@@ -132,6 +144,8 @@
                    // 更新任务状态到下一阶段
                    _taskService.UpdateTaskStatusToNext(task);
                    QuartzLogHelper.LogInfo(_logger, $"入库任务已下发,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
                }
            }
        }
@@ -152,20 +166,48 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task == null)
            {
                QuartzLogHelper.LogDebug(_logger, $"RequestInNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode);
                return;
            }
            // 如果不是空托盘任务,处理目标地址(与拘束机/插拔钉机交互)
            if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            QuartzLogHelper.LogInfo(_logger, $"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            bool isEmptyTask = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty;
            // 确定目标地址
            string targetAddress;
            if (isEmptyTask)
            {
                _targetAddressSelector.HandleInboundNextAddress(conveyorLine, task.NextAddress, childDeviceCode);
                targetAddress = "2125";
                QuartzLogHelper.LogDebug(_logger, $"子设备: {childDeviceCode},入库下一目标地址: {2125}", conveyorLine.DeviceCode);
            }
            else
            {
                Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress);
                if (routers == null) throw new Exception($"未找到设备路由信息");
                targetAddress = routers.ChildPosi;
            }
            // 更新任务当前位置
            _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
            // 处理目标地址:ChildPosi == "2125" 时跳过 HandleInboundNextAddress
            if (targetAddress == "2125")
            {
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, "2125", childDeviceCode);
            }
            else if (!_targetAddressSelector.HandleInboundNextAddress(conveyorLine, targetAddress, childDeviceCode))
            {
                return;
            }
            // 设置 WCS_STB 标志,表示 WCS 已处理
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_STB, 1, childDeviceCode);
            // 更新任务当前位置和 WCS_ACK
            if (isEmptyTask)
            {
                _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress, "2125");
            }
            else
            {
                _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
            }
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
        }
        /// <summary>
@@ -184,12 +226,13 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task != null)
            {
                // 回复 ACK 确认
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
                // 更新任务状态到下一阶段(通常是完成)
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                Console.Out.WriteLine(content.Serialize());
                if (_taskService.UpdateTaskStatusToNext(task).Status)
                {
                    // 回复 ACK 确认
                    conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                    QuartzLogHelper.LogInfo(_logger, $"入库完成,任务号: {task.TaskNum},子设备:{childDeviceCode}", conveyorLine.DeviceCode);
                }
            }
        }
@@ -206,27 +249,65 @@
        /// <param name="conveyorLine">输送线设备对象</param>
        /// <param name="command">PLC 命令数据</param>
        /// <param name="childDeviceCode">子设备编码</param>
        public void RequestOutbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode)
        public Task RequestOutbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode)
        {
            // 查询待处理任务
            Dt_Task? task = _taskFilter.QueryPendingTask(conveyorLine.DeviceCode, childDeviceCode);
            if (task != null)
            if (task == null) return Task.CompletedTask;
            // 确定目标地址:空托盘任务使用 "2201",其他任务使用 NextAddress
            var isEmptyTask = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty;
            var targetAddress = task.CurrentAddress == "2217" ? (isEmptyTask ? "2201" : task.NextAddress) : task.NextAddress;
            // 处理特殊地址 2217,需要调用目标地址选择器
            if (task.CurrentAddress == "2217" && !_targetAddressSelector.HandleOutboundNextAddress(conveyorLine, targetAddress, childDeviceCode))
            {
                // 设置任务号
                conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, task.TaskNum, childDeviceCode);
                // 设置托盘条码
                conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
                // 设置目标地址
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, task.NextAddress, childDeviceCode);
                // 回复 ACK 确认
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
                // 更新任务状态
                _taskService.UpdateTaskStatusToNext(task);
                return Task.CompletedTask; ;
            }
            // 设置任务号、托盘条码、目标地址、WCS_ACK
            var isTaskNoSet = conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, task.TaskNum, childDeviceCode);
            Thread.Sleep(100); // 确保 PLC 能正确读取任务号后再写入条码
            var isPalletSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
            bool isTargetSet = true;
            if (targetAddress == "2217" && !isEmptyTask)
            {
                QuartzLogHelper.LogDebug(_logger, $"子设备: {childDeviceCode},出库目标地址: {targetAddress}", conveyorLine.DeviceCode);
                Thread.Sleep(100); // 确保 PLC 能正确读取任务号后再写入条码
                isTargetSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Target, targetAddress, childDeviceCode);
            }
            if (!isTargetSet || !isTaskNoSet || !isPalletSet)
            {
                QuartzLogHelper.LogError(_logger, $"RequestOutbound:下发出库任务失败,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
                return Task.CompletedTask;
            }
            bool isWmsResult = false;
            // 更新任务状态或位置
            if (isEmptyTask && task.NextAddress == "2217")
            {
                task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
                task.NextAddress = "2201";
                isWmsResult = _taskService.Repository.UpdateData(task);
            }
            else
            {
                isWmsResult = _taskService.UpdateTaskStatusToNext(task).Status;
            }
            if(!isWmsResult)
            {
                QuartzLogHelper.LogError(_logger, $"RequestOutbound:更新任务状态失败,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
                return Task.CompletedTask;
            }
            Thread.Sleep(100); // 确保 PLC 能正确读取任务号后再写入条码
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
            QuartzLogHelper.LogInfo(_logger, "RequestOutbound:出库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"出库任务已下发,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
            return Task.CompletedTask;
        }
        /// <summary>
@@ -234,7 +315,6 @@
        /// </summary>
        /// <remarks>
        /// 当出库任务执行到某个中间站点时调用。
        /// 根据下一地址判断是否需要与拘束机/插拔钉机等设备交互。
        /// </remarks>
        /// <param name="conveyorLine">输送线设备对象</param>
        /// <param name="command">PLC 命令数据</param>
@@ -245,20 +325,26 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task == null)
            {
                QuartzLogHelper.LogDebug(_logger, $"RequestOutNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode);
                return;
            }
            QuartzLogHelper.LogInfo(_logger, $"RequestOutNextAddress:出库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            // 如果不是空托盘任务,处理目标地址
            if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            {
                _targetAddressSelector.HandleOutboundNextAddress(conveyorLine, task.NextAddress, childDeviceCode);
            }
            //if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            //{
            Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress);
            if (routers == null) throw new Exception($"未找到设备路由信息");
            _targetAddressSelector.HandleOutboundNextAddress(conveyorLine, routers.ChildPosi, childDeviceCode);
            //}
            // 更新任务当前位置
            _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
            // 回复 ACK 确认
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
        }
        /// <summary>
@@ -277,13 +363,17 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task != null)
            {
                // 回复 ACK 确认
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
                // 更新任务状态到下一阶段(通常是完成)
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                Console.Out.WriteLine(content.Serialize());
                if (content.Status)
                {
                    // 回复 ACK 确认
                    conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                }
                QuartzLogHelper.LogInfo(_logger, $"出库完成,完成结果:{content.Status},任务号: {task.TaskNum},错误消息:{content.Message}", conveyorLine.DeviceCode);
            }
        }
    }
}
}