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($"全部复位完毕");
}
}
}