using Microsoft.Extensions.Logging; using SlnMesnac.Repository.service; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; using SlnMesnac.Repository; using SlnMesnac.Repository.service.Impl; using TouchSocket.Sockets; using SlnMesnac.Model.domain; using SlnMesnac.TouchSocket; using System.Timers; using SlnMesnac.Model.Enum; using HslCommunication.Enthernet; using System.Threading; using SlnMesnac.TouchSocket.Entity; using SlnMesnac.Model.AirportApiEntity; using System.Linq; using SlnMesnac.Business.util; namespace SlnMesnac.Business.@base { /// /// 航班任务业务类 /// public class BaseTaskInfoBusiness { /// /// AMR最大运载量 /// public const int AMRStackNumber = 10; /// /// Deliver最大运载量 /// public const int DeliverStackNumber = 15; private TcpServer _tcpServer = null; public Action _Taskaction; public Action _RefreshLogMessageAction; private static BaseTaskInfoBusiness instance; private ILogger _logger; private IAirportTaskService _Taskservice; private IAGVMapPointService _AGVMapPointService; private IAGVStateService _AGVStateService; private IAGVJobService _AGVJobService; private IVisionSettingService _AGVVisionSettingService; private AirPorthttpClient _airPorthttpClient; private BaseAGVBusiness _baseAGVBusiness; private VisionBusiness _visionBusiness; System.Timers.Timer RefreshTimer; public BaseTaskInfoBusiness( ILogger logger, IAirportTaskService Taskservice, IAGVStateService agvService, IAGVMapPointService aGVMapPointService, IAGVJobService agvJobService, IVisionSettingService aVisionSettingService, TcpServer tcpServer, AirPorthttpClient airPorthttpClient, BaseAGVBusiness baseAGVBusiness, VisionBusiness visionBusiness) { _logger = logger; _tcpServer = tcpServer; _Taskservice = Taskservice; _AGVStateService = agvService; _airPorthttpClient = airPorthttpClient; //doWhileGetAGVTaskInfo(); _baseAGVBusiness = baseAGVBusiness; _AGVMapPointService = aGVMapPointService; _AGVJobService = agvJobService; _AGVVisionSettingService = aVisionSettingService; //新建Timer RefreshTimer = new System.Timers.Timer(1000); RefreshTimer.Elapsed += (sender, e) => { //不清理满载AGV 刷新状态 //ClearFullAGV(); RefreshTaskState(); }; _visionBusiness = visionBusiness; } public static BaseTaskInfoBusiness GetInstance( ILogger logger, IAirportTaskService Taskservice, IAGVStateService agvService, IAGVMapPointService aGVMapPointService, IAGVJobService aAGVJobService, IVisionSettingService aVisionSettingService, TcpServer tcpServer, AirPorthttpClient airPorthttpClient, BaseAGVBusiness baseAGVBusiness, VisionBusiness visionBusiness) { if (instance == null) { instance = new BaseTaskInfoBusiness(logger, Taskservice, agvService, aGVMapPointService, aAGVJobService, aVisionSettingService, tcpServer, airPorthttpClient, baseAGVBusiness, visionBusiness); } return instance; } /// /// 获取新任务插入数据库 /// /// public async Task NewTaskInfo(string taskNo, string conveyNo, string flightNo, int totalCount) { var task = new AirportTask() { taskno = taskNo, conveyorno = conveyNo, //判断条件 flightno = flightNo, amragvno = string.Empty, //需要判断,更新 是否有AMR分配 amragvisarrive = string.Empty, //需要判断,更新 AMR是否到达 deliveragvno = string.Empty, //需要判断,更新 是否有Deliver分配 deliveragvisarrive = string.Empty, //需要判断,更新 Deliver是否到达 totalcount = totalCount, //判断条件 总数量是多少 loadcount = 0, //需要判断,更新 现抓取数量 taskstate = "等待", //需要判断,更新 任务状态 starttime = DateTime.Now, finishtime = null, }; try { return await _Taskservice.AddTaskAsync(task); } catch (Exception ex) { _logger.LogError("航班任务新建失败"); return false; } } /// /// 任务刷新Timer控制 /// /// public void TaskStateUpdateTimerOperation(TimerControl state) { try { switch (state) { case TimerControl.Start: RefreshTimer.Start(); break; case TimerControl.Stop: RefreshTimer.Stop(); break; case TimerControl.Dispose: RefreshTimer.Dispose(); break; default: _logger.LogError("未知状态"); break; } } catch (Exception ex) { _logger.LogError("AGV状态操作失败!" + ex.Message); } } #region 任务初次派车调度 /// /// AGV调度 /// Timer刷新任务状态, 有新任务初次下发AGV, Timer执行 /// public void RefreshTaskState() { try { //获取任务列表 List Task = _Taskservice.GetAGVTaskInfos(); if (Task != null && Task.Count > 0) { //更新前端 _RefreshLogMessageAction?.Invoke("任务数量:" + Task.Count); foreach (AirportTask taskItem in Task) { ///////////////////////////////////////////////////// 查询待执行任务,如果是新任务就下发车辆 ///////////////////////////////////////////////////// if (taskItem.taskstate == "等待") { /////////////////////////////////////////////////////// 如果AMR还没分配是空的 ///////////////////////////////////////////////////// if (string.IsNullOrEmpty(taskItem.amragvno)) { // 首先调一辆最优AMR AGVState firstAMR = _baseAGVBusiness.GetBestAGV(AgvType.AMR); // 有空闲车辆 赋值 准备看看是否需要deliver if (firstAMR != null && !string.IsNullOrEmpty(firstAMR.agvno)) { string amrTaskId = _baseAGVBusiness.EndTaskAndClearErrorAndDownloadTask( firstAMR.agvno, _AGVJobService.GetAGVJobListByTypeAndConveyorNo("1000入位", taskItem.conveyorno).JobGuid); _logger.LogInformation($"为AMR[ {firstAMR.agvno}]分配任务,目标:[ {taskItem.conveyorno} ]号传送带"); taskItem.amragvno = firstAMR.agvno; taskItem.amragvisarrive = "未到达"; _Taskservice.UpdateTaskAsync(taskItem); } // 如果没调到AMR直接 goto结束 else { _logger.LogInformation($"任务 [{taskItem.taskno}] 暂时匹配不到空闲AMR!"); goto OUT_POINT; } // 需要Deliver和AMR才能装下 if (taskItem.totalcount > (AMRStackNumber - firstAMR.stackcount)) { // 调一辆最优Deliver AGVState firstDeliver = _baseAGVBusiness.GetBestAGV(AgvType.Deliver); // 如果有Deliver 赋值 调整状态为派车中 if (firstDeliver != null && !string.IsNullOrEmpty(firstDeliver.agvno)) { string deliverTaskID = _baseAGVBusiness.EndTaskAndClearErrorAndDownloadTask( firstDeliver.agvno, _AGVJobService.GetAGVJobListByTypeAndConveyorNo("800入位", taskItem.conveyorno).JobGuid); _logger.LogInformation($"为Deliver[ {firstDeliver.agvno} ]分配任务,目标:[ {taskItem.conveyorno} ]号传送带"); taskItem.deliveragvno = firstDeliver.agvno; taskItem.deliveragvisarrive = "未到达"; taskItem.taskstate = "派车中"; _Taskservice.UpdateTaskAsync(taskItem); goto OUT_POINT; } // 如果没调到Deliver直接 goto结束 else { _logger.LogInformation($"任务 [{taskItem.taskno}] 暂时匹配不到空闲Deliver!"); goto OUT_POINT; } } // 如果不需要直接调整状态为派车 goto结束 else { taskItem.taskstate = "派车中"; _Taskservice.UpdateTaskAsync(taskItem); goto OUT_POINT; } } /////////////////////////////////////////////////////// 如果AMR已分配不是空的 ///////////////////////////////////////////////////// if (!string.IsNullOrEmpty(taskItem.amragvno)) { AGVState TaskAMR = _AGVStateService.GetSingleAGVState(taskItem.amragvno); // 看看是否需要AGV和AMR才能装下 if (taskItem.totalcount > (AMRStackNumber - TaskAMR.stackcount)) { // 调一辆最优Deliver AGVState firstDeliver = _baseAGVBusiness.GetBestAGV(AgvType.Deliver); // 如果有Deliver 赋值 调整状态为派车中 if (firstDeliver != null && !string.IsNullOrEmpty(firstDeliver.agvno)) { string deliverTaskID = _baseAGVBusiness.EndTaskAndClearErrorAndDownloadTask( firstDeliver.agvno, _AGVJobService.GetAGVJobListByTypeAndConveyorNo("800入位", taskItem.conveyorno).JobGuid); _logger.LogInformation($"为Deliver[ {firstDeliver.agvno} ]分配任务,目标:[ {taskItem.conveyorno} ]号传送带"); taskItem.deliveragvno = firstDeliver.agvno; taskItem.deliveragvisarrive = "未到达"; taskItem.taskstate = "派车中"; _Taskservice.UpdateTaskAsync(taskItem); goto OUT_POINT; } // 匹配不到直接goto else { _logger.LogInformation($"任务 [{taskItem.taskno}] 暂时匹配不到空闲Deliver!"); goto OUT_POINT; } } // 不需要Delievr直接改任务状态 else { taskItem.taskstate = "派车中"; _Taskservice.UpdateTaskAsync(taskItem); goto OUT_POINT; } } OUT_POINT:; //未分配成功的退出点 } //根据小车状态更新任务表中AMR是否到达状态,如果到达就改变任务表的状态 if (!string.IsNullOrEmpty(taskItem.amragvno) && taskItem.amragvisarrive == "未到达") { AGVState agvstate = _AGVStateService.GetSingleAGVState(taskItem.amragvno); if (agvstate.taskstate == "已暂停") { taskItem.amragvisarrive = "已到达"; _logger.LogInformation($"[ {taskItem.conveyorno} ]号传送带AMR[ {agvstate.agvno} ]已到达"); } _Taskservice.UpdateTaskAsync(taskItem); } //根据小车状态更新任务表中Deliver是否到达状态,如果到达就改变任务表的状态 if (!string.IsNullOrEmpty(taskItem.deliveragvno) && taskItem.deliveragvisarrive == "未到达") { AGVState agvstate = _AGVStateService.GetSingleAGVState(taskItem.deliveragvno); if (agvstate.taskstate == "已暂停") { taskItem.deliveragvisarrive = "已到达"; _logger.LogInformation($"[ {taskItem.conveyorno} ]号传送带Deliver[ {agvstate.agvno} ]已到达"); } _Taskservice.UpdateTaskAsync(taskItem); } //查询执行中的任务车辆是否到达,如果指派的车都到达就开始抓取 if (taskItem.taskstate == "派车中") { //只有amr的情况 if (taskItem.amragvisarrive == "已到达" && string.IsNullOrEmpty(taskItem.deliveragvno)) { int amrStackNo = _AGVStateService.GetSingleAGVState(taskItem.amragvno).stackcount; //调用机械臂向AMR小车抓取 _visionBusiness.RequestVisionStartWork(StackState.NXAMRNeedPositioning, amrStackNo, _tcpServer.VID); taskItem.taskstate = "抓取中"; _Taskservice.UpdateTaskAsync(taskItem); _logger.LogInformation($"[ {taskItem.conveyorno} ]号传送带开始工作"); } //amr和deliver都用的情况 if (taskItem.amragvisarrive == "已到达" && taskItem.deliveragvisarrive == "已到达") { int agvStackNo = _AGVStateService.GetSingleAGVState(taskItem.deliveragvno).stackcount; //调用机械臂向Deliver小车抓取 _visionBusiness.RequestVisionStartWork(StackState.NXAGVNeedPositioning, agvStackNo, _tcpServer.VID); taskItem.taskstate = "抓取中"; _Taskservice.UpdateTaskAsync(taskItem); _logger.LogInformation($"[ {taskItem.conveyorno} ]号传送带开始工作"); } } } } } catch (Exception ex) { _logger.LogError($"查询任务列表初次下发任务发生错误Message:{ex.Message}"); } } #endregion /// /// 停止所有任务 /// public void StopAllTask() { List taskList = _Taskservice.GetTaskInfos(x => x.taskstate == "抓取中" || x.taskstate == "派车中").ToList(); //任务状态设置为已终止并且机械臂复位 foreach (var taskInfo in taskList) { _visionBusiness.RequestVisionReplace(_AGVVisionSettingService.GetVisionSettingByAMRGUID(taskInfo.amragvno).VisionID); taskInfo.finishtime = DateTime.Now; taskInfo.taskstate = "已终止"; _Taskservice.UpdateTaskAsync(taskInfo); _logger.LogInformation($"任务 [{taskInfo.taskno}] 已终止"); } //agv全部停止 var responseList = _airPorthttpClient.AGVAllStateRequest(); if (responseList == null || responseList.count == 0) { _logger.LogInformation($"连接失败或无小车连接"); return; } foreach (var response in responseList.Data) { if (!string.IsNullOrEmpty(response.TaskID) && response.AgvMoveStatus != 1 && response.AgvMoveStatus != 3) { _baseAGVBusiness.EndTaskAndClearError(response.Guid); _logger.LogInformation($"小车 [{response.Name}] 任务已终止"); } } _logger.LogInformation($"全部复位完毕"); } } }