xiazhengtongxue
2026-03-19 bfcd7f5b405e431a5c07fe3fa77d74c892d4e66b
ÏîÄ¿´úÂë/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WMSCruJob.cs
@@ -40,135 +40,135 @@
    {
        private readonly ILogger<WMSCruJob> _logger;
        private Timer _timer;
        private Timer _timer2;
        private readonly ITaskService _taskService;
        private readonly ILocationInfoService _locationInfoService;
        private readonly IStockInfoService _stockInfoService;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        public WMSCruJob(ILogger<WMSCruJob> logger, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, ILocationInfoService locationInfoService,
            ITaskService taskService)
        {
            _logger = logger;
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
            _locationInfoService = locationInfoService;
            _taskService=taskService;
        }
        private static readonly object _taskProcessLock = new object();
        private const int TASK_PROCESS_TIMEOUT = 1000; // 2秒超时
        private readonly Queue<int> _deviceQueueSC = new Queue<int>();
        public Task StartAsync(CancellationToken cancellationToken)
        {
            _timer = new Timer(DoWorkWheel, null, TimeSpan.Zero, TimeSpan.FromSeconds(3));
            // åˆå§‹åŒ–设备队列(1-5)
            for (int i = 1; i <= 5; i++)
            {
                _deviceQueueSC.Enqueue(i);
            }
            _timer = new Timer(SCProcessNextDevice, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));
            //_timer2 = new Timer(PLCDoDeciceWork, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
            return Task.CompletedTask;
        }
        private void DoWorkWheel(object state)
        //堆垛机队列
        private void SCProcessNextDevice(object state)
        {
            // å®šä¹‰çŠ¶æ€å¸¸é‡ï¼Œé¿å…é­”æ³•æ•°å­—
            const int PLC_IN_FINISH = (int)InTaskStatusEnum.PLC_InFinish;
            const int OUT_NEW = (int)OutTaskStatusEnum.OutNew;
            const int SC_OUT_FINISH = (int)OutTaskStatusEnum.SC_OutFinish;
            const int SC_IN_EXECUTING = (int)InTaskStatusEnum.SC_IntExecuting;
            const int SC_OUT_EXECUTING = (int)OutTaskStatusEnum.SC_OutExecuting;
            const int RELOCATION_EXECUTING = (int)RelocationTaskStatusEnum.RelocationExecuting;
            const int PLC_OUT_EXECUTING = (int)OutTaskStatusEnum.PLC_OutExecuting;
            // èŽ·å–å½“å‰ä»»åŠ¡æ•°æ®
            List<Dt_Task> allTasks = _taskService.Repository.QueryData();
            // èŽ·å–å··é“è¶…è¿‡3个任务的路段
            HashSet<string> excludedRoadways = allTasks
                .Where(x => x.NumberSsuances > 3)
                .Select(x => x.Roadway)
                .Distinct()
                .ToHashSet();
            // è¿‡æ»¤éœ€è¦å¤„理的任务
            List<Dt_Task> tasksToProcess = allTasks
                .Where(x =>
                    (x.TaskStatus == PLC_IN_FINISH ||
                     x.TaskStatus == OUT_NEW ||
                     x.TaskStatus == SC_OUT_FINISH) &&
                    !excludedRoadways.Contains(x.Roadway))
                .ToList();
            // æŒ‰çŠ¶æ€åˆ†ç»„å¤„ç†ï¼Œå‡å°‘é‡å¤æŸ¥è¯¢
            ProcessInAndNewTasks(tasksToProcess, allTasks, excludedRoadways);   //下发堆垛机
            ProcessOutFinishTasks(tasksToProcess, allTasks);    //下发输送线任务
        }
        private void ProcessInAndNewTasks(List<Dt_Task> tasksToProcess, List<Dt_Task> allTasks, HashSet<string> excludedRoadways)
        {
            const int PLC_IN_FINISH = (int)InTaskStatusEnum.PLC_InFinish;
            const int OUT_NEW = (int)OutTaskStatusEnum.OutNew;
            const int SC_IN_EXECUTING = (int)InTaskStatusEnum.SC_IntExecuting;
            const int SC_OUT_EXECUTING = (int)OutTaskStatusEnum.SC_OutExecuting;
            const int RELOCATION_EXECUTING = (int)RelocationTaskStatusEnum.RelocationExecuting;
            const int RELOCCATION_NEW = (int)RelocationTaskStatusEnum.RelocationNew;
            var inAndNewTasks = tasksToProcess
                .Where(x => x.TaskStatus == PLC_IN_FINISH || x.TaskStatus == OUT_NEW).OrderBy(x=>x.CreateDate)
                .ToList();
            foreach (var task in inAndNewTasks)
            if (!Monitor.TryEnter(_taskProcessLock, TASK_PROCESS_TIMEOUT)) return;
            try
            {
                // æ£€æŸ¥åŒä¸€å··é“是否有正在执行的任务
                bool hasExecutingTask = allTasks.Any(x =>
                    x.TaskId != task.TaskId &&
                    x.Roadway == task.Roadway &&
                    (x.TaskStatus == SC_IN_EXECUTING ||
                     x.TaskStatus == SC_OUT_EXECUTING ||
                     x.TaskStatus == RELOCATION_EXECUTING));
                if (_deviceQueueSC.Count == 0)
                    return;
                if (hasExecutingTask)
                    continue;
                int deviceId = _deviceQueueSC.Dequeue();
                //判断是否需要移库
                WebResponseContent webResponse=JudgmentIsRelocations(task);
                if (!webResponse.Status) continue;
                // ä¸‹å‘堆垛机任务
                WCSginseng result = _taskService.SC_IssueTasks(
                    task.TaskId,
                    int.Parse(task.Roadway),
                    task.TaskNum,
                    task.PalletCode,
                    int.Parse(task.PalletType),
                    task.CurrentAddress,
                    task.NextAddress,
                    task.TargetAddress);
                UpdateTaskStatus(task, result,
                    successStatus: task.TaskStatus == PLC_IN_FINISH ? SC_IN_EXECUTING : SC_OUT_EXECUTING,1);
                try
                {
                    SCDoDeviceWork(deviceId);
                    _deviceQueueSC.Enqueue(deviceId);
                    PLCDoDeciceWork();
                }
                catch (Exception ex)
                {
                    _deviceQueueSC.Enqueue(deviceId);
                    Console.WriteLine($"设备 {deviceId} æ‰§è¡Œå¤±è´¥: {ex.Message}");
                }
            }
            finally
            {
                Monitor.Exit(_taskProcessLock);
            }
        }
        private void ProcessOutFinishTasks(List<Dt_Task> tasksToProcess, List<Dt_Task> allTasks)
        //执行方法
        private void SCDoDeviceWork(int deviceId)
        {
            const int SC_OUT_FINISH = (int)OutTaskStatusEnum.SC_OutFinish;
            const int PLC_OUT_EXECUTING = (int)OutTaskStatusEnum.PLC_OutExecuting;
            var outFinishTasks = tasksToProcess
                .Where(x => x.TaskStatus == SC_OUT_FINISH)
                .ToList();
            foreach (var task in outFinishTasks)
            const int PLC_IN_FINISH = (int)InTaskStatusEnum.PLC_InFinish;
            const int SC_IN_EXECUTING = (int)InTaskStatusEnum.SC_IntExecuting;
            const int SC_OUT_EXECUTING = (int)OutTaskStatusEnum.SC_OutExecuting;
            try
            {
                // æ£€æŸ¥åŒä¸€å··é“是否有其他已完成的任务
                bool hasOtherFinishTask = allTasks.Any(x =>
                    x.Roadway == task.Roadway &&
                    x.TaskStatus == SC_OUT_FINISH &&
                    x.TaskId != task.TaskId);
                //判断当前堆垛机是否有执行任务
                if (_taskService.CurrentTaskProgress(deviceId.ToString())) return;
                // èŽ·å–å½“å‰å †åž›æœºä»»åŠ¡
                List<Dt_Task> taskList = _taskService.GetaskQueue(deviceId.ToString());
                if (taskList.Count == 0) return;
                if (hasOtherFinishTask)
                    continue;
                foreach (Dt_Task task in taskList)
                {
                    WebResponseContent webResponse = JudgmentIsRelocations(task);
                    if (!webResponse.Status)
                    {
                        WriteLog.Write_Log("WMS_移库故障", $"移库返回失败内容", "失败", $"移库失败,原因:{webResponse.Message}");
                        return;
                    }
                // ä¸‹å‘PLC任务
                WCSginseng result = _taskService.PLC_IssueTasks(
                    task.TaskId,
                    int.Parse(task.Roadway),
                    task.TaskNum,
                    task.PalletCode,
                    int.Parse(task.PalletType),
                    task.CurrentAddress,
                    task.NextAddress,
                    "");
                    WCSginseng result = _taskService.SC_IssueTasks(
                        task.TaskId,
                        int.Parse(task.Roadway),
                        task.TaskNum,
                        task.PalletCode,
                        int.Parse(task.PalletType),
                        task.CurrentAddress,
                        task.NextAddress,
                        task.TargetAddress);
                UpdateTaskStatus(task, result, PLC_OUT_EXECUTING,2);
                    UpdateTaskStatus(task, result,
                        successStatus: task.TaskStatus == PLC_IN_FINISH ? SC_IN_EXECUTING : SC_OUT_EXECUTING, 1);
                    return;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"任务处理异常:{ex.Message}");
            }
        }
        private void PLCDoDeciceWork()
        {
            try
            {
                // èŽ·å–å½“å‰ä»»åŠ¡æ•°æ®
                List<Dt_Task> allTasks = _taskService.GetaskQueuePLC();
                if (allTasks.Count == 0) return;
                foreach (var task in allTasks)
                {
                    // ä¸‹å‘PLC任务
                    WCSginseng result = _taskService.PLC_IssueTasks(task.TaskId, task.WarehouseId, task.TaskNum, task.PalletCode, int.Parse(task.PalletType), task.CurrentAddress, task.NextAddress, "");
                    UpdateTaskStatus(task, result, (int)OutTaskStatusEnum.PLC_OutExecuting, 2);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"堆垛机完成,下发输送线执行任务失败! åŽŸå› : {ex.Message}");
            }
        }
        //修改状态
        private void UpdateTaskStatus(Dt_Task task, WCSginseng result, int successStatus,int statype)
        {
            if (result.IsSuccess)
@@ -177,7 +177,7 @@
                task.TaskStatus = successStatus;
                if(task.TaskStatus== (int)OutTaskStatusEnum.SC_OutExecuting)
                {
                    string Result = MesOutTaskStatusEnum.出库开始.GetDescription();
                    string Result = MesOutTaskStatusEnum.Start.GetDescription();
                    //调取上游系统反馈开始任务
                    _taskService.OutStoreDocCallback(task.TaskNum,Result, "操作成功");
                }
@@ -185,12 +185,14 @@
            else
            {
                task.Remark = result.Message;
                task.NumberSsuances++;
                //task.NumberSsuances++;
            }
            _taskService.Repository.UpdateData(task);
        }
        public Task StopAsync(CancellationToken cancellationToken)
        {
@@ -201,165 +203,6 @@
        public void Dispose()
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// åˆ¤æ–­å··é“内移库
        /// </summary>
        /// <param name="TaskNum"></param>
        /// <param name="SourceAddress"></param>
        /// <returns></returns>
        public WebResponseContent JudgmentIsRelocations(Dt_Task dt_Task)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                string Locationcodeadd = dt_Task.TaskType == (int)TaskTypeEnum.Inbound ? dt_Task.NextAddress : dt_Task.CurrentAddress;
                Dt_LocationInfo dt_Location = _locationInfoService.Repository.QueryData(x => x.LocationCode == Locationcodeadd).FirstOrDefault();
                if (dt_Location.Depth == 1 || dt_Location.RoadwayNo == "5") return content.OK();
                int locrow = judgmentRow(dt_Location.RoadwayNo, dt_Location.Row);
                Dt_LocationInfo shallowLocation = _locationInfoService.Repository.QueryData(x => x.RoadwayNo == dt_Location.RoadwayNo && x.Row == locrow && x.Layer == dt_Location.Layer && x.Column == dt_Location.Column).FirstOrDefault();
                if (shallowLocation.LocationStatus == (int)LocationStatusEnum.Free) return content.OK();
                if (shallowLocation.LocationStatus != (int)(int)LocationStatusEnum.InStock) return content.Error();
                //判断是否有移库任务
                var TransferTask = _taskService.Repository.QueryData(x=>x.TaskStatus== (int)RelocationTaskStatusEnum.RelocationNew && x.CurrentAddress== shallowLocation.LocationCode).FirstOrDefault();
                if(TransferTask != null)
                {
                    //进行下发给堆垛机任务
                    WCSginseng result = _taskService.SC_IssueTasks(
                        TransferTask.TaskId,
                        int.Parse(TransferTask.Roadway),
                        TransferTask.TaskNum,
                        TransferTask.PalletCode,
                        int.Parse(TransferTask.PalletType),
                        TransferTask.CurrentAddress,
                        TransferTask.NextAddress,
                        TransferTask.TargetAddress);
                    if (result.IsSuccess)
                    {
                        return content.OK();
                    }
                    else
                    {
                        WriteLog.GetLog("判断巷道内移库").Write($"下发堆垛机任务失败,原因:{result.Message}", $"生成移库任务:GenerateTransferTask");
                        return content.Error();
                    }
                }
                //生成移库任务,进行下发
                return content =GenerateTransferTask(shallowLocation.LocationCode);
            }
            catch (Exception ex)
            {
                WriteLog.GetLog("判断巷道内移库").Write($"判断移库失败,原因:{ex.Message}", $"判断巷道内移库方法:JudgmentIsRelocations");
                return content.Error();
            }
        }
        private int judgmentRow(string RoadwayNo,int locrow)
        {
            if (RoadwayNo == "1" || RoadwayNo == "3")
            {
                return locrow == 1 ? 2 : 3;
            }
            else if (RoadwayNo == "2" || RoadwayNo == "4")
            {
                return locrow == 5 ? 6 : 7;
            }
            else
            {
                return 0;
            }
        }
        public WebResponseContent GenerateTransferTask(string shallowLocation)
        {
            WebResponseContent webResponse=new WebResponseContent();
            try
            {
                Dt_LocationInfo OriginalLocation = _locationInfoService.Repository.QueryData(x => x.LocationCode == shallowLocation).FirstOrDefault();
                Dt_StockInfo dt_StockInfo = _stockInfoService.Repository.QueryData(x => x.LocationCode == shallowLocation).FirstOrDefault();
                Dt_LocationInfo newLocation = _locationInfoService.GetLocation(OriginalLocation.RoadwayNo, OriginalLocation.LocationType);
                List<Dt_LocationInfo> dt_Locations = new List<Dt_LocationInfo>();
                MES_parameter mES_Parame = _taskService.ApplicationChangeStorageLocation(dt_StockInfo.PalletCode, OriginalLocation.LocationCode, newLocation.LocationCode);
                if (mES_Parame != null)
                {
                    if (mES_Parame.Result == "Y")
                    {
                        //进行生成任务,下发任务至MES
                        Dt_Task task = new Dt_Task();
                        task.TaskNum = "0";
                        task.PalletCode = dt_StockInfo.PalletCode;
                        task.PalletType = dt_StockInfo.PalletType;
                        task.Roadway = OriginalLocation.RoadwayNo;
                        task.TaskType = (int)TaskTypeEnum.Relocation;
                        task.TaskStatus = (int)RelocationTaskStatusEnum.RelocationNew;
                        task.SourceAddress = OriginalLocation.LocationCode;
                        task.TargetAddress = newLocation.LocationCode;
                        task.CurrentAddress = OriginalLocation.LocationCode;
                        task.NextAddress = newLocation.LocationCode;
                        task.WarehouseId = OriginalLocation.WarehouseId;
                        task.OrderNo = "";
                        task.Grade = 1;
                        task.Creater = "MES";
                        task.CreateDate = DateTime.Now;
                        OriginalLocation.LocationStatus = (int)LocationStatusEnum.Lock;
                        newLocation.LocationStatus = (int)LocationStatusEnum.Lock;
                        dt_StockInfo.StockStatus = (int)StockStatusEmun.移库锁定;
                        dt_Locations.Add(OriginalLocation);
                        dt_Locations.Add(newLocation);
                        _unitOfWorkManage.BeginTran();
                        _taskService.AddData(task);
                        _locationInfoService.UpdateData(dt_Locations);
                        _stockInfoService.UpdateData(dt_StockInfo);
                        //_stockInfoService.Repository.AddData(dt_StockInfo);
                        _unitOfWorkManage.CommitTran();
                        //进行下发给堆垛机任务
                        WCSginseng result = _taskService.SC_IssueTasks(
                            task.TaskId,
                            int.Parse(task.Roadway),
                            task.TaskNum,
                            task.PalletCode,
                            int.Parse(task.PalletType),
                            task.CurrentAddress,
                            task.NextAddress,
                            task.TargetAddress);
                        if (result.IsSuccess)
                        {
                            return webResponse.OK();
                        }
                        else
                        {
                            WriteLog.GetLog("判断巷道内移库").Write($"下发堆垛机任务失败,原因:{result.Message}", $"生成移库任务:GenerateTransferTask");
                            return webResponse.Error();
                        }
                    }
                    else
                    {
                        WriteLog.GetLog("判断巷道内移库").Write($"申请储位异动,MES不允许移动", $"生成移库任务:GenerateTransferTask");
                        return webResponse.Error();
                    }
                }
                else
                {
                    WriteLog.GetLog("判断巷道内移库").Write($"申请储位异动,MES返回为空", $"生成移库任务:GenerateTransferTask");
                    return webResponse.Error();
                }
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                WriteLog.GetLog("判断巷道内移库").Write($"生成移库任务失败:{ex.Message}", $"生成移库任务:GenerateTransferTask");
                return webResponse.Error();
            }
        }
    }
}