You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

383 lines
19 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
{
/// <summary>
/// 航班任务业务类
/// </summary>
public class BaseTaskInfoBusiness
{
/// <summary>
/// AMR最大运载量
/// </summary>
public const int AMRStackNumber = 10;
/// <summary>
/// Deliver最大运载量
/// </summary>
public const int DeliverStackNumber = 15;
private TcpServer _tcpServer = null;
public Action<AirportTask> _Taskaction;
public Action<string> _RefreshLogMessageAction;
private static BaseTaskInfoBusiness instance;
private ILogger<BaseTaskInfoBusiness> _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<BaseTaskInfoBusiness> 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<BaseTaskInfoBusiness> 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;
}
/// <summary>
/// 获取新任务插入数据库
/// </summary>
/// <returns></returns>
public async Task<bool> 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;
}
}
/// <summary>
/// 任务刷新Timer控制
/// </summary>
/// <param name="state"></param>
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 任务初次派车调度
/// <summary>
/// AGV调度
/// Timer刷新任务状态, 有新任务初次下发AGV, Timer执行
/// </summary>
public void RefreshTaskState()
{
try
{
//获取任务列表
List<AirportTask> 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
/// <summary>
/// 停止所有任务
/// </summary>
public void StopAllTask()
{
List<AirportTask> 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($"全部复位完毕");
}
}
}