|  |  | 
 |  |  | using Autofac.Core; | 
 |  |  | using HslCommunication; | 
 |  |  | using Mapster; | 
 |  |  | using Newtonsoft.Json; | 
 |  |  | using Quartz; | 
 |  |  | using System.Diagnostics.CodeAnalysis; | 
 |  |  | using System.Text; | 
 |  |  | using WIDESEAWCS_BasicInfoRepository; | 
 |  |  | using WIDESEAWCS_Common; | 
 |  |  | using WIDESEAWCS_Common.TaskEnum; | 
 |  |  | using WIDESEAWCS_Core.Caches; | 
 |  |  | using WIDESEAWCS_Core.Helper; | 
 |  |  | using WIDESEAWCS_DTO.MOM; | 
 |  |  | using WIDESEAWCS_Core.HttpContextUser; | 
 |  |  | using WIDESEAWCS_IProcessRepository; | 
 |  |  | using WIDESEAWCS_ISystemServices; | 
 |  |  | using WIDESEAWCS_ITaskInfo_HtyRepository; | 
 |  |  | using WIDESEAWCS_ITaskInfoRepository; | 
 |  |  | using WIDESEAWCS_ITaskInfoService; | 
 |  |  | using WIDESEAWCS_Model; | 
 |  |  | using WIDESEAWCS_Model.Models; | 
 |  |  | using WIDESEAWCS_QuartzJob; | 
 |  |  | using WIDESEAWCS_QuartzJob.DeviceBase; | 
 |  |  | using WIDESEAWCS_QuartzJob.Models; | 
 |  |  | using WIDESEAWCS_QuartzJob.Service; | 
 |  |  | using WIDESEAWCS_QuartzJob.StackerCrane.Enum; | 
 |  |  | using WIDESEAWCS_SignalR; | 
 |  |  | using WIDESEAWCS_Tasks.ConveyorLineJob; | 
 |  |  | using WIDESEAWCS_Tasks.StackerCraneJob; | 
 |  |  |  | 
 |  |  | namespace WIDESEAWCS_Tasks | 
 |  |  | 
 |  |  |         private readonly ITaskRepository _taskRepository; | 
 |  |  |         private readonly IRouterService _routerService; | 
 |  |  |         private readonly IProcessRepository _processRepository; | 
 |  |  |         private readonly ICacheService _cacheService; | 
 |  |  |         private readonly INoticeService _noticeService; | 
 |  |  |         private readonly IDt_StationManagerRepository _stationManagerRepository; | 
 |  |  |         private readonly ITask_HtyRepository _htyRepository; | 
 |  |  |         private readonly ISys_ConfigService _sys_ConfigService; | 
 |  |  |         private static List<string>? userTokenIds; | 
 |  |  |         private static List<int>? userIds; | 
 |  |  |  | 
 |  |  |         public CommonStackerCraneJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, ITaskRepository taskRepository, IRouterService routerService, IProcessRepository processRepository) | 
 |  |  |         public CommonStackerCraneJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, ITaskRepository taskRepository, IRouterService routerService, IProcessRepository processRepository, ICacheService cacheService, INoticeService noticeService, IDt_StationManagerRepository stationManagerRepository, ITask_HtyRepository htyRepository, ISys_ConfigService sys_ConfigService) | 
 |  |  |         { | 
 |  |  |             _taskService = taskService; | 
 |  |  |             _taskExecuteDetailService = taskExecuteDetailService; | 
 |  |  |             _taskRepository = taskRepository; | 
 |  |  |             _routerService = routerService; | 
 |  |  |             _processRepository = processRepository; | 
 |  |  |             _cacheService = cacheService; | 
 |  |  |             _noticeService = noticeService; | 
 |  |  |             _stationManagerRepository = stationManagerRepository; | 
 |  |  |             _htyRepository = htyRepository; | 
 |  |  |             _sys_ConfigService = sys_ConfigService; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public Task Execute(IJobExecutionContext context) | 
 |  |  |         { | 
 |  |  |             try | 
 |  |  |             { | 
 |  |  |                 // speStackerCrane.GetStackerCraneStatus<StackerCraneAutoStatus>(); | 
 |  |  |                 // speStackerCrane.GetStackerCraneStatus<StackerCraneWorkStatus>(); | 
 |  |  |                 // speStackerCrane.GetStackerCraneStatus<StackerCraneStatus>(); | 
 |  |  |  | 
 |  |  |                 CommonStackerCrane commonStackerCrane = (CommonStackerCrane)context.JobDetail.JobDataMap.Get("JobParams"); | 
 |  |  |                 if (commonStackerCrane != null) | 
 |  |  |                 { | 
 |  |  |                     //EqptAlive(commonStackerCrane); | 
 |  |  |                     //Console.Out.WriteLine(commonStackerCrane.DeviceName); | 
 |  |  |                     if (!commonStackerCrane.IsEventSubscribed) | 
 |  |  |                     { | 
 |  |  |                         commonStackerCrane.StackerCraneTaskCompletedEventHandler += CommonStackerCrane_StackerCraneTaskCompletedEventHandler;//订阅任务完成事件 | 
 |  |  | 
 |  |  |                                 StackerCraneTaskCommand? stackerCraneTaskCommand = ConvertToStackerCraneTaskCommand(task); | 
 |  |  |                                 if (stackerCraneTaskCommand != null) | 
 |  |  |                                 { | 
 |  |  |                                     bool sendFlag = commonStackerCrane.SendCommand(stackerCraneTaskCommand); | 
 |  |  |                                     if (sendFlag) | 
 |  |  |                                     var taskNum = commonStackerCrane.GetValue<StackerCraneDBName, int>(StackerCraneDBName.TaskNum); | 
 |  |  |                                     //var taskBarCode = commonStackerCrane.GetValue<StackerCraneDBName, string>(StackerCraneDBName.Barcode); | 
 |  |  |                                     ConsoleHelper.WriteColorLine($"【{commonStackerCrane.DeviceName}】堆垛机任务号:【{taskNum}】任务任务号:【{task.TaskNum}】", ConsoleColor.DarkBlue); | 
 |  |  |                                     if (taskNum == 0) | 
 |  |  |                                     { | 
 |  |  |                                         commonStackerCrane.LastTaskType = task.TaskType; | 
 |  |  |                                         _taskService.UpdateTaskStatusToNext(task.TaskNum); | 
 |  |  |                                         ConsoleHelper.WriteColorLine($"【{commonStackerCrane.DeviceName}】任务号为【{0}】,任务号不一致可以下发任务", ConsoleColor.DarkBlue); | 
 |  |  |  | 
 |  |  |                                         Thread.Sleep(1000); | 
 |  |  |                                         bool sendFlag = commonStackerCrane.SendCommand(stackerCraneTaskCommand); | 
 |  |  |                                         if (sendFlag) | 
 |  |  |                                         { | 
 |  |  |                                             StringBuilder builder = new StringBuilder(); | 
 |  |  |                                             builder.AppendLine(); | 
 |  |  |                                             builder.AppendLine($"【{commonStackerCrane.DeviceName}】堆垛机状态:【{commonStackerCrane.StackerCraneStatusDes}】,时间:【{DateTime.Now}】"); | 
 |  |  |                                             builder.AppendLine($"【{commonStackerCrane.DeviceName}】手自动状态:【{commonStackerCrane.StackerCraneAutoStatusDes}】,时间:【{DateTime.Now}】"); | 
 |  |  |                                             builder.AppendLine($"【{commonStackerCrane.DeviceName}】作业状态:【{commonStackerCrane.StackerCraneWorkStatusDes}】,时间:【{DateTime.Now}】"); | 
 |  |  |                                             builder.AppendLine($"【{commonStackerCrane.DeviceName}】下发任务成功,【{JsonConvert.SerializeObject(stackerCraneTaskCommand, Formatting.Indented)}】"); | 
 |  |  |                                             builder.AppendLine($"时间:【{DateTime.Now}】"); | 
 |  |  |                                             builder.AppendLine(); | 
 |  |  |                                             ConsoleHelper.WriteColorLine(builder, ConsoleColor.Blue); | 
 |  |  |                                             commonStackerCrane.LastTaskType = task.TaskType; | 
 |  |  |                                             _taskService.UpdateTaskStatusToNext(task.TaskNum); | 
 |  |  |                                         } | 
 |  |  |                                     } | 
 |  |  |                                     else | 
 |  |  |                                     { | 
 |  |  |                                         ConsoleHelper.WriteColorLine($"【{commonStackerCrane.DeviceName}】任务号不为【{0}】,不可以下发任务", ConsoleColor.DarkBlue); | 
 |  |  |                                     } | 
 |  |  |                                 } | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     #region 调用事件总线通知前端 | 
 |  |  |  | 
 |  |  |                     var tokenInfos = _cacheService.Get<List<UserInfo>>("Cache_UserToken"); | 
 |  |  |                     if (tokenInfos != null && tokenInfos.Any()) | 
 |  |  |                     { | 
 |  |  |                         var userTokenIds = tokenInfos?.Select(x => x.Token_ID).ToList(); | 
 |  |  |                         var userIds = tokenInfos?.Select(x => x.UserId).ToList(); | 
 |  |  |  | 
 |  |  |                         object obj = new | 
 |  |  |                         { | 
 |  |  |                             commonStackerCrane.StackerCraneStatusDes, | 
 |  |  |                             commonStackerCrane.StackerCraneAutoStatusDes, | 
 |  |  |                             commonStackerCrane.StackerCraneWorkStatusDes, | 
 |  |  |                             commonStackerCrane.DeviceCode, | 
 |  |  |                             commonStackerCrane.DeviceName, | 
 |  |  |                             commonStackerCrane.CurrentTaskNum, | 
 |  |  |                             commonStackerCrane.LastTaskNum, | 
 |  |  |                         }; | 
 |  |  |                         _noticeService.StackerData(userIds?.FirstOrDefault(), userTokenIds, new { commonStackerCrane.DeviceName, data = obj }); | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     #endregion 调用事件总线通知前端 | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             catch (Exception ex) | 
 |  |  |             { | 
 |  |  |                 WriteError("CommonConveyorLineJob", "test", ex); | 
 |  |  |                 ConsoleHelper.WriteErrorLine($"{ex.Message}"); | 
 |  |  |                 //Console.WriteLine(nameof(CommonStackerCraneJob) + ":" + ex.ToString()); | 
 |  |  |             } | 
 |  |  |             //WriteDebug("CommonConveyorLineJob", "test"); | 
 |  |  | 
 |  |  |             { | 
 |  |  |                 if (commonStackerCrane.GetValue<StackerCraneDBName, short>(StackerCraneDBName.WorkType) != 5) | 
 |  |  |                 { | 
 |  |  |                     //Console.Out.WriteLine("TaskCompleted" + e.TaskNum); | 
 |  |  |                     ConsoleHelper.WriteColorLine($"【{commonStackerCrane.DeviceName}】任务完成,任务号:【{e.TaskNum}】", ConsoleColor.Blue); | 
 |  |  |                     _taskService.StackCraneTaskCompleted(e.TaskNum); | 
 |  |  |                     commonStackerCrane.SetValue(StackerCraneDBName.WorkType, 5); | 
 |  |  |                     ConsoleHelper.WriteColorLine($"【{commonStackerCrane.DeviceName}】堆垛机作业状态:【{(int)commonStackerCrane.StackerCraneWorkStatusValue}】时间【{DateTime.Now}】", ConsoleColor.Magenta); | 
 |  |  |  | 
 |  |  |                     string str = $"【{commonStackerCrane.DeviceName}】任务完成,任务号:【{e.TaskNum}】时间【{DateTime.Now}】"; | 
 |  |  |                     WriteInfo(commonStackerCrane.DeviceName, str); | 
 |  |  |                     ConsoleHelper.WriteColorLine(str, ConsoleColor.Blue); | 
 |  |  |                     var task = _taskRepository.QueryFirst(x => x.TaskNum == e.TaskNum); | 
 |  |  |  | 
 |  |  |                     if (task == null) commonStackerCrane.SetValue(StackerCraneDBName.WorkType, 5); | 
 |  |  |  | 
 |  |  |                     if (commonStackerCrane.DeviceCode.Contains("GW") && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup) | 
 |  |  |                     { | 
 |  |  |                         var station = _stationManagerRepository.QueryFirst(x => x.stationChildCode == task.TargetAddress); | 
 |  |  |  | 
 |  |  |                         IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == station.stationPLC); | 
 |  |  |                         if (device != null) | 
 |  |  |                         { | 
 |  |  |                             CommonConveyorLine_GW conveyorLine = (CommonConveyorLine_GW)device; | 
 |  |  |                             var isResult = conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, task.PalletCode, task.TargetAddress); | 
 |  |  |                             if (!isResult) | 
 |  |  |                             { | 
 |  |  |                                 var result = conveyorLine.GetValue<ConveyorLineDBName_After, string>(ConveyorLineDBName_After.ConveyorLineBarcode, task.TargetAddress); | 
 |  |  |                                 if (result != task.PalletCode) | 
 |  |  |                                 { | 
 |  |  |                                     conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineBarcode, task.PalletCode, task.TargetAddress); | 
 |  |  |                                 } | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                         else | 
 |  |  |                             return; | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     var content = _taskService.StackCraneTaskCompleted(e.TaskNum); | 
 |  |  |                     if (commonStackerCrane.DeviceCode.Contains("CH") && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) | 
 |  |  |                     { | 
 |  |  |                         task = _taskRepository.QueryFirst(x => x.TaskNum == e.TaskNum); | 
 |  |  |                         Dt_Task? newTask = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress); | 
 |  |  |                         _taskService.UpdateData(newTask); | 
 |  |  |                     } | 
 |  |  |                     if ((task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup && (task.TargetAddress == "002-021-001" || task.TargetAddress == "001-021-001"))|| task.TaskType == (int)TaskOutboundTypeEnum.OutFireAlarm) | 
 |  |  |                     { | 
 |  |  |                         var TASKHTY = task.Adapt<Dt_Task_Hty>(); | 
 |  |  |                         _taskRepository.DeleteData(task); | 
 |  |  |                         _htyRepository.AddData(TASKHTY); | 
 |  |  |                     } | 
 |  |  |                     var isWorkType = commonStackerCrane.SetValue(StackerCraneDBName.WorkType, 5); | 
 |  |  |                     str = $"{commonStackerCrane.DeviceName}】WMS|WCS任务完成:【{content.Status}】,堆垛机完成信号写入:【{isWorkType}】,任务号:【{e.TaskNum}】时间【{DateTime.Now}】"; | 
 |  |  |                     WriteInfo(commonStackerCrane.DeviceName, str); | 
 |  |  |                     ConsoleHelper.WriteColorLine(str, ConsoleColor.Blue); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  | 
 |  |  |         private Dt_Task? GetTask(CommonStackerCrane commonStackerCrane) | 
 |  |  |         { | 
 |  |  |             Dt_Task task; | 
 |  |  |             task = _taskService.QueryOutFireAlarmTask(commonStackerCrane.DeviceCode); | 
 |  |  |             if (task != null) | 
 |  |  |             { | 
 |  |  |                 return task; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (commonStackerCrane.LastTaskType == null) | 
 |  |  |             { | 
 |  |  |                 task = _taskService.QueryStackerCraneTask(commonStackerCrane.DeviceCode); | 
 |  |  |             } | 
 |  |  |             else | 
 |  |  |             { | 
 |  |  |                 if (commonStackerCrane.LastTaskType.GetValueOrDefault().GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup) | 
 |  |  |                 var lastTaskTypeGroup = commonStackerCrane.LastTaskType.GetValueOrDefault().GetTaskTypeGroup(); | 
 |  |  |                 if (lastTaskTypeGroup == TaskTypeGroup.OutbondGroup) | 
 |  |  |                 { | 
 |  |  |                     task = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode); | 
 |  |  |                     if (task == null) | 
 |  |  | 
 |  |  |  | 
 |  |  |             if (task != null && task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup) | 
 |  |  |             { | 
 |  |  |                 if (OutTaskStationIsOccupied(task) != null) | 
 |  |  |                 // 检查当前出库任务站台是否允许放货 | 
 |  |  |                 var occupiedStation = OutTaskStationIsOccupied(task); | 
 |  |  |                 if (occupiedStation == null) | 
 |  |  |                 { | 
 |  |  |                     // 如果当前出库任务站台不允许放货,排除当前任务,查找其他出库任务 | 
 |  |  |  | 
 |  |  |                     var log = $"任务号:【{task.TaskNum}】出库地址:【{task.NextAddress}】不允许放货"; | 
 |  |  |                     ConsoleHelper.WriteErrorLine(log); | 
 |  |  |  | 
 |  |  |                     _noticeService.Logs(userTokenIds, new { commonStackerCrane.DeviceName, log = log, time = DateTime.Now.ToString("G"), color = "red" }); | 
 |  |  |                     WriteInfo(commonStackerCrane.DeviceName, log); | 
 |  |  |  | 
 |  |  |                     task = FindAnotherOutboundTask(commonStackerCrane.DeviceCode, task.TaskId); | 
 |  |  |  | 
 |  |  |                     if (task == null) | 
 |  |  |                     { | 
 |  |  |                         task = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     return task; | 
 |  |  |                 } | 
 |  |  |                 //else | 
 |  |  |                 //{ | 
 |  |  |                 //    List<string> otherOutStaionCodes = _routerService.QueryNextRoutes(commonStackerCrane.DeviceCode, task.NextAddress).Select(x => x.ChildPosi).ToList(); | 
 |  |  |                 //    List<Dt_Task> tasks = _taskService.QueryStackerCraneOutTasks(commonStackerCrane.DeviceCode, otherOutStaionCodes); | 
 |  |  |                 //    foreach (var item in tasks) | 
 |  |  |                 //    { | 
 |  |  |                 //        if (OutTaskStationIsOccupied(task) != null) | 
 |  |  |                 //        { | 
 |  |  |                 //            return task; | 
 |  |  |                 //        } | 
 |  |  |                 //    } | 
 |  |  |                 //    task = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode); | 
 |  |  |                 //} | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |             else if (task == null) | 
 |  |  |             { | 
 |  |  |                 task = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             return task; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  | 
 |  |  |             { | 
 |  |  |                 if (router != null) | 
 |  |  |                 { | 
 |  |  |  | 
 |  |  |                     IDevice? device = null; | 
 |  |  |                     if (task.Roadway.Contains("CW")) | 
 |  |  |                     { | 
 |  |  |                         device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == router.ChildPosiDeviceCode); | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     else | 
 |  |  |                     { | 
 |  |  |                         device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == "1015"); | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     if (device != null) | 
 |  |  |                     { | 
 |  |  |                         CommonConveyorLine_GW conveyorLine = (CommonConveyorLine_GW)device; | 
 |  |  |                         if (conveyorLine.IsOccupied(task.NextAddress))//出库站台未被占用 | 
 |  |  |                         if (device != null) | 
 |  |  |                         { | 
 |  |  |                             return task; | 
 |  |  |                             CommonConveyorLine_GW conveyorLine = (CommonConveyorLine_GW)device; | 
 |  |  |                             if (conveyorLine.IsOccupied(task.NextAddress))//出库站台未被占用 | 
 |  |  |                             { | 
 |  |  |                                 return task; | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                     else | 
 |  |  |                     { | 
 |  |  |                         _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{task.TargetAddress}】对应的通讯对象,无法判断出库站台是否被占用"); | 
 |  |  |                         else | 
 |  |  |                         { | 
 |  |  |                             _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{task.NextAddress}】对应的通讯对象,无法判断出库站台是否被占用"); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法校验站台"); | 
 |  |  |                     IDevice? device = null; | 
 |  |  |                     if (task.Roadway.Contains("GW")) | 
 |  |  |                     { | 
 |  |  |                         device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == "1015"); | 
 |  |  |                         if (device != null) | 
 |  |  |                         { | 
 |  |  |                             CommonConveyorLine_GW conveyorLine = (CommonConveyorLine_GW)device; | 
 |  |  |                             if (conveyorLine.IsOccupied(task.TargetAddress))//出库站台未被占用 | 
 |  |  |                             { | 
 |  |  |                                 return task; | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                         else | 
 |  |  |                         { | 
 |  |  |                             _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{task.TargetAddress}】对应的通讯对象,无法判断出库站台是否被占用"); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                     //_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.TargetAddress}】信息,无法校验站台"); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             else | 
 |  |  |             { | 
 |  |  |                 //Dt_Router? router = _routerService.QueryNextRoutes(task.Roadway, task.NextAddress).FirstOrDefault(); | 
 |  |  |                 if (router != null) | 
 |  |  |                 if ((task.NextAddress == ("002-021-001") || task.NextAddress == ("001-021-001")) && task.Roadway.Contains("JZ")) | 
 |  |  |                 { | 
 |  |  |                     IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == router.ChildPosiDeviceCode); | 
 |  |  |                     if (device != null) | 
 |  |  |                     return task; | 
 |  |  |                 } | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     //Dt_Router? router = _routerService.QueryNextRoutes(task.Roadway, task.NextAddress).FirstOrDefault(); | 
 |  |  |                     if (router != null) | 
 |  |  |                     { | 
 |  |  |                         CommonConveyorLine conveyorLine = (CommonConveyorLine)device; | 
 |  |  |                         if (conveyorLine.IsOccupied(router.ChildPosi))//出库站台未被占用 | 
 |  |  |                         IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == router.ChildPosiDeviceCode); | 
 |  |  |                         if (device != null) | 
 |  |  |                         { | 
 |  |  |                             return task; | 
 |  |  |                             CommonConveyorLine conveyorLine = (CommonConveyorLine)device; | 
 |  |  |                             if (conveyorLine.IsOccupiedx(router.ChildPosi))//出库站台未被占用 | 
 |  |  |                             { | 
 |  |  |                                 return task; | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                         else | 
 |  |  |                         { | 
 |  |  |                             _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{router.ChildPosiDeviceCode}】对应的通讯对象,无法判断出库站台是否被占用"); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                     else | 
 |  |  |                     { | 
 |  |  |                         _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{router.ChildPosiDeviceCode}】对应的通讯对象,无法判断出库站台是否被占用"); | 
 |  |  |                         _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法校验站台"); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法校验站台"); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             return null; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         /// <summary> | 
 |  |  |         /// 查找其他出库任务的辅助方法(排除指定任务ID的任务) | 
 |  |  |         /// </summary> | 
 |  |  |         /// <param name="deviceCode">设备代码</param> | 
 |  |  |         /// <param name="excludedTaskId">要排除的任务ID</param> | 
 |  |  |         /// <returns></returns> | 
 |  |  |         private Dt_Task? FindAnotherOutboundTask(string deviceCode, int excludedTaskId) | 
 |  |  |         { | 
 |  |  |             // 先获取所有符合条件(排除指定任务ID)的出库任务列表 | 
 |  |  |             var allOutboundTasks = _taskService.QueryAllOutboundTasks(deviceCode); | 
 |  |  |             var availableTasks = allOutboundTasks?.Where(t => excludedTaskId != t.TaskId && t.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup).ToList(); | 
 |  |  |  | 
 |  |  |             if (availableTasks == null || availableTasks.Count == 0) | 
 |  |  |             { | 
 |  |  |                 return null; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             // 遍历可用任务列表,检查任务站台是否允许放货,找到第一个允许放货的任务就返回 | 
 |  |  |             foreach (var candidateTask in availableTasks) | 
 |  |  |             { | 
 |  |  |                 var occupiedStation = OutTaskStationIsOccupied(candidateTask); | 
 |  |  |                 if (occupiedStation != null) | 
 |  |  |                 { | 
 |  |  |                     return candidateTask; | 
 |  |  |                 } | 
 |  |  |                 var log = $"任务号:【{candidateTask.TaskNum}】出库地址:【{candidateTask.NextAddress}】不允许放货"; | 
 |  |  |                 ConsoleHelper.WriteErrorLine(log); | 
 |  |  |  | 
 |  |  |                 _noticeService.Logs(userTokenIds, new { deviceCode, log = log, time = DateTime.Now.ToString("G"), color = "red" }); | 
 |  |  |                 WriteInfo(deviceCode, log); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             return null; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  | 
 |  |  |             stackerCraneTaskCommand.StartCommand = 1; | 
 |  |  |             if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.InboundGroup)//判断是否是入库任务 | 
 |  |  |             { | 
 |  |  |                 List<Dt_Router> routers = _routerService.QueryNextRoutes(task.CurrentAddress, task.Roadway); | 
 |  |  |                 if (routers.Count > 0) | 
 |  |  |                 var value = _sys_ConfigService.GetByConfigKey(CateGoryConst.CONFIG_SYS_InStation, SysConfigKeyConst.JZNGInBoundStation).ConfigValue; | 
 |  |  |                 var valueList = value.Split(',').ToList(); | 
 |  |  |                 if ((valueList.Contains(task.SourceAddress)) && task.Roadway.Contains("JZ")) | 
 |  |  |                 { | 
 |  |  |                     stackerCraneTaskCommand.StartRow = Convert.ToInt16(routers.FirstOrDefault().SrmRow); | 
 |  |  |                     stackerCraneTaskCommand.StartColumn = Convert.ToInt16(routers.FirstOrDefault().SrmColumn); | 
 |  |  |                     stackerCraneTaskCommand.StartLayer = Convert.ToInt16(routers.FirstOrDefault().SrmLayer); | 
 |  |  |  | 
 |  |  |                     string[] souredCodes = task.CurrentAddress.Split("-"); | 
 |  |  |                     if (souredCodes.Length == 3) | 
 |  |  |                     { | 
 |  |  |                         stackerCraneTaskCommand.StartRow = Convert.ToInt16(souredCodes[0]); | 
 |  |  |                         stackerCraneTaskCommand.StartColumn = Convert.ToInt16(souredCodes[1]); | 
 |  |  |                         stackerCraneTaskCommand.StartLayer = Convert.ToInt16(souredCodes[2]); | 
 |  |  |                     } | 
 |  |  |                     else | 
 |  |  |                     { | 
 |  |  |                         //数据配置错误 | 
 |  |  |                         _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"入库任务起点错误,起点:【{task.CurrentAddress}】"); | 
 |  |  |                         return null; | 
 |  |  |                     } | 
 |  |  |                     string[] targetCodes = task.NextAddress.Split("-"); | 
 |  |  |                     if (targetCodes.Length == 3) | 
 |  |  |                     { | 
 |  |  | 
 |  |  |                 } | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法获取对应的堆垛机取货站台信息"); | 
 |  |  |                     return null; | 
 |  |  |                     List<Dt_Router> routers = _routerService.QueryNextRoutes(task.CurrentAddress, task.Roadway); | 
 |  |  |                     if (routers.Count > 0) | 
 |  |  |                     { | 
 |  |  |                         stackerCraneTaskCommand.StartRow = Convert.ToInt16(routers.FirstOrDefault().SrmRow); | 
 |  |  |                         stackerCraneTaskCommand.StartColumn = Convert.ToInt16(routers.FirstOrDefault().SrmColumn); | 
 |  |  |                         stackerCraneTaskCommand.StartLayer = Convert.ToInt16(routers.FirstOrDefault().SrmLayer); | 
 |  |  |  | 
 |  |  |                         string[] targetCodes = task.NextAddress.Split("-"); | 
 |  |  |                         if (targetCodes.Length == 3) | 
 |  |  |                         { | 
 |  |  |                             stackerCraneTaskCommand.EndRow = Convert.ToInt16(targetCodes[0]) % 2 != 0 ? (short)1 : (short)2; | 
 |  |  |                             stackerCraneTaskCommand.EndColumn = Convert.ToInt16(targetCodes[1]); | 
 |  |  |                             stackerCraneTaskCommand.EndLayer = Convert.ToInt16(targetCodes[2]); | 
 |  |  |                         } | 
 |  |  |                         else | 
 |  |  |                         { | 
 |  |  |                             //数据配置错误 | 
 |  |  |                             _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"入库任务终点错误,起点:【{task.NextAddress}】"); | 
 |  |  |                             return null; | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                     else | 
 |  |  |                     { | 
 |  |  |                         _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法获取对应的堆垛机取货站台信息"); | 
 |  |  |                         return null; | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             else if (task.TaskType.GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup) | 
 |  |  |             { | 
 |  |  |                 if (task.Roadway.Contains("GW")) | 
 |  |  |                 if (task.Roadway.Contains("GW")|| task.TaskType == (int)TaskOutboundTypeEnum.OutFireAlarm) | 
 |  |  |                 { | 
 |  |  |                     string[] endCodes = task.NextAddress.Split("-"); | 
 |  |  |                     stackerCraneTaskCommand.EndRow = Convert.ToInt16(endCodes[0]); | 
 |  |  | 
 |  |  |                 } | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     List<Dt_Router> routers = _routerService.QueryNextRoutes(task.Roadway, task.TargetAddress); | 
 |  |  |                     if (routers.Count > 0) | 
 |  |  |                     if (((task.TargetAddress == "002-021-001" || task.TargetAddress == "001-021-001") && task.Roadway.Contains("JZ")) || task.TaskType == (int)TaskOutboundTypeEnum.OutFireAlarm) | 
 |  |  |                     { | 
 |  |  |                         stackerCraneTaskCommand.EndRow = Convert.ToInt16(routers.FirstOrDefault().SrmRow); | 
 |  |  |                         stackerCraneTaskCommand.EndColumn = Convert.ToInt16(routers.FirstOrDefault().SrmColumn); | 
 |  |  |                         stackerCraneTaskCommand.EndLayer = Convert.ToInt16(routers.FirstOrDefault().SrmLayer); | 
 |  |  |  | 
 |  |  |                         string[] sourceCodes = task.CurrentAddress.Split("-"); | 
 |  |  |                         if (sourceCodes.Length == 3) | 
 |  |  |                         { | 
 |  |  |                             stackerCraneTaskCommand.StartRow = Convert.ToInt16(sourceCodes[0]) % 2 != 0 ? (short)1 : (short)2; | 
 |  |  |                             stackerCraneTaskCommand.StartColumn = Convert.ToInt16(sourceCodes[1]); | 
 |  |  |                             stackerCraneTaskCommand.StartLayer = Convert.ToInt16(sourceCodes[2]); | 
 |  |  |                         } | 
 |  |  |                         else | 
 |  |  |                         { | 
 |  |  |                             //数据配置错误 | 
 |  |  |                             _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"出库任务起点错误,起点:【{task.CurrentAddress}】"); | 
 |  |  |                             return null; | 
 |  |  |                         } | 
 |  |  |                         string[] endCodes = task.NextAddress.Split("-"); | 
 |  |  |                         stackerCraneTaskCommand.EndRow = Convert.ToInt16(endCodes[0]); | 
 |  |  |                         stackerCraneTaskCommand.EndColumn = Convert.ToInt16(endCodes[1]); | 
 |  |  |                         stackerCraneTaskCommand.EndLayer = Convert.ToInt16(endCodes[2]); | 
 |  |  |                         string[] sourceCodes = task.SourceAddress.Split("-"); | 
 |  |  |                         stackerCraneTaskCommand.StartRow = Convert.ToInt16(sourceCodes[0]) % 2 != 0 ? (short)1 : (short)2; | 
 |  |  |                         stackerCraneTaskCommand.StartColumn = Convert.ToInt16(sourceCodes[1]); | 
 |  |  |                         stackerCraneTaskCommand.StartLayer = Convert.ToInt16(sourceCodes[2]); | 
 |  |  |                     } | 
 |  |  |                     else | 
 |  |  |                     { | 
 |  |  |                         _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法获取对应的堆垛机放货站台信息"); | 
 |  |  |                         return null; | 
 |  |  |                         List<Dt_Router> routers = _routerService.QueryNextRoutes(task.Roadway, task.TargetAddress); | 
 |  |  |                         if (routers.Count > 0) | 
 |  |  |                         { | 
 |  |  |                             stackerCraneTaskCommand.EndRow = Convert.ToInt16(routers.FirstOrDefault().SrmRow); | 
 |  |  |                             stackerCraneTaskCommand.EndColumn = Convert.ToInt16(routers.FirstOrDefault().SrmColumn); | 
 |  |  |                             stackerCraneTaskCommand.EndLayer = Convert.ToInt16(routers.FirstOrDefault().SrmLayer); | 
 |  |  |  | 
 |  |  |                             string[] sourceCodes = task.CurrentAddress.Split("-"); | 
 |  |  |                             if (sourceCodes.Length == 3) | 
 |  |  |                             { | 
 |  |  |                                 stackerCraneTaskCommand.StartRow = Convert.ToInt16(sourceCodes[0]) % 2 != 0 ? (short)1 : (short)2; | 
 |  |  |                                 stackerCraneTaskCommand.StartColumn = Convert.ToInt16(sourceCodes[1]); | 
 |  |  |                                 stackerCraneTaskCommand.StartLayer = Convert.ToInt16(sourceCodes[2]); | 
 |  |  |                             } | 
 |  |  |                             else | 
 |  |  |                             { | 
 |  |  |                                 //数据配置错误 | 
 |  |  |                                 _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"出库任务起点错误,起点:【{task.CurrentAddress}】"); | 
 |  |  |                                 return null; | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |                         else | 
 |  |  |                         { | 
 |  |  |                             _taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法获取对应的堆垛机放货站台信息"); | 
 |  |  |                             return null; | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  | 
 |  |  |             } | 
 |  |  |             return stackerCraneTaskCommand; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         /// <summary> | 
 |  |  |         /// 设备心跳 | 
 |  |  |         /// </summary> | 
 |  |  |         /// <param name="commonStackerCrane"></param> | 
 |  |  |         //public async void EqptAlive(CommonStackerCrane commonStackerCrane) | 
 |  |  |         //{ | 
 |  |  |         //    if (commonStackerCrane.StackerOnline) | 
 |  |  |         //    { | 
 |  |  |         //        BasicDto dto = new BasicDto | 
 |  |  |         //        { | 
 |  |  |         //            EmployeeNo = "T00001", | 
 |  |  |         //            EquipmentCode = commonStackerCrane.DeviceCode, | 
 |  |  |         //            RequestTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"), | 
 |  |  |         //            SessionId = Guid.NewGuid().ToString(), | 
 |  |  |         //            Software = commonStackerCrane.DeviceName, | 
 |  |  |         //        }; | 
 |  |  |         //        var respone = await HttpHelper.PostAsync("http://ts-momapp01:12020/api/MachineIntegration/EqptAlive", dto.ToJsonString()); | 
 |  |  |         //        if (respone != null) | 
 |  |  |         //        { | 
 |  |  |         //            var result = JsonConvert.DeserializeObject<ResponseEqptAliveDto>(respone); | 
 |  |  |         //            if (result != null && result.Success) | 
 |  |  |         //            { | 
 |  |  |         //                if (result.KeyFlag == "99") | 
 |  |  |         //                    commonStackerCrane.StackerOnline = true; | 
 |  |  |         //                else if (result.KeyFlag == "98") | 
 |  |  |         //                    commonStackerCrane.StackerOnline = false; | 
 |  |  |         //            } | 
 |  |  |         //        } | 
 |  |  |         //    } | 
 |  |  |         //} | 
 |  |  |  | 
 |  |  |     } | 
 |  |  | } |