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.

363 lines
12 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.Config;
using SlnMesnac.Model.AirportApiEntity;
using SlnMesnac.Model.domain;
using SlnMesnac.Model.Enum;
using SlnMesnac.Repository;
using SlnMesnac.Repository.service;
using SlnMesnac.TouchSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SlnMesnac.Business.@base
{
/// <summary>
/// AGV业务类
/// </summary>
public class BaseAGVBusiness
{
private ILogger<BaseAGVBusiness> _logger;
private static BaseAGVBusiness instance;
private AppConfig _appConfig;
private AirPorthttpClient _airPorthttpClient;
private IAGVStateService _AGVStateService;
private IAGVMapPointService _AGVMapPointService;
public BaseAGVBusiness(ILogger<BaseAGVBusiness> logger,
AirPorthttpClient airPorthttpClient,
IAGVStateService AGVStateService,
IAGVMapPointService aGVMapPointService,
AppConfig appConfig)
{
_logger = logger;
_airPorthttpClient = airPorthttpClient;
_AGVStateService = AGVStateService;
_AGVMapPointService = aGVMapPointService;
_appConfig = appConfig;
}
public static BaseAGVBusiness GetInstance(ILogger<BaseAGVBusiness> logger,
AirPorthttpClient airPorthttpClient,
IAGVStateService AGVStateService,
IAGVMapPointService aGVMapPointService,
AppConfig appConfig)
{
if (instance == null)
{
instance = new BaseAGVBusiness(logger, airPorthttpClient, AGVStateService, aGVMapPointService, appConfig);
}
return instance;
}
/// <summary>
/// 封装任务类
/// </summary>
/// <param name="AGVGUID"></param>
/// <param name="JobGUID"></param>
/// <param name="PointGUID"></param>
/// <param name="ParamName"></param>
/// <param name="TaskName"></param>
/// <param name="RobotType"></param>
/// <returns></returns>
public AGVRequestAddTaskEntity NewTaskEntity(string AGVGUID, string JobGUID, string PointGUID, string ParamName, string TaskName = "AGVCTask", string RobotType = "S800")
{
AGVRequestAddTaskEntity aGVRequestAddTaskEntity = new AGVRequestAddTaskEntity()
{
businessOrderId = TaskName,
priority = 0,
RobotType = RobotType,
robotId = AGVGUID,
group = "",
taskSource = "agvc",
taskType = 0,
verifyStatus = 0,
enableSplitCar = 0,
load = new List<LoadsEntity>()
{
new LoadsEntity()
{
jobid = JobGUID,
location = PointGUID,
param = new List<ParamEntity>()
{
new ParamEntity()
{
paramname = ParamName,
paramvalue = PointGUID,
}
},
robotPort = ""
}
},
};
return aGVRequestAddTaskEntity;
}
/// <summary>
/// 发送封装的任务类
/// </summary>
/// <returns>任务ID</returns>
public string DownloadTask(string AGVGUID, string JobGUID, string PointGUID, string ParamName, string TaskName = "AGVCTask", string RobotType = "S800")
{
try
{
var result = _airPorthttpClient.AGVAddTaskRequest(NewTaskEntity(AGVGUID, JobGUID, PointGUID, ParamName, TaskName, RobotType));
if (result.code == 0)
{
return result.Data.guid;
}
else
{
_logger.LogError("错误响应:" + result.message);
return string.Empty;
}
}
catch (Exception ex)
{
_logger.LogError($"接口发生错误:{ex.Message}");
return string.Empty;
}
}
/// <summary>
/// 结束指定AGV的任务
/// </summary>
/// <param name="AGVGUID">AGV小车编号</param>
/// <returns></returns>
public bool EndAGVTask(string AGVGUID)
{
try
{
AGVState agvState = _AGVStateService.GetSingleAGVState(AGVGUID);
if (agvState == null)
{
return false;
}
if (agvState.agvworkstate != "待机")
{
var response = _airPorthttpClient.AGVOperationalTaskRequest(new AGVRequestOperationalTaskEntity()
{
taskid = agvState.taskno,
state = 0,
operatingSource = "agvc",
operatingUser = "agvc",
remark = "agvcEnd"
});
if (response.code == 0)
{
_logger.LogInformation($"AGV {agvState.agvno} 任务 {agvState.taskno} 结束成功");
return true;
}
else
{
_logger.LogError($"AGV {agvState.agvno} 任务 {agvState.taskno} 结束失败 ERROR:{response.message}");
return false;
}
}
else if (agvState.agvworkstate == "待机")
{
_logger.LogError($"AGV {agvState.agvno} 现在无任务");
return false;
}
else
{
_logger.LogError($"AGV {agvState.agvno} 终止任务失败!");
return false;
}
}
catch (Exception ex)
{
_logger.LogError($"AGV任务结束失败 ERROR{ex.Message}");
return false;
}
}
/// <summary>
/// 获取活跃地图的点位更新到数据库
/// </summary>
/// <returns></returns>
public bool GetActiveMapPoint()
{
var result = _airPorthttpClient.AGVMapActiveRequest();
if (result == null)
{
_logger.LogError("AGV活跃地图获取返回Null");
return false;
}
if (result.code != 0)
{
_logger.LogError("AGV活跃地图获取错误内容" + result.message);
return false;
}
if (result.Data == null)
{
_logger.LogError("活跃地图获取无数据");
return false;
}
string mapID = result.Data.guid;
var res = _airPorthttpClient.AGVMapPositionRequest(mapID);
if (res == null)
{
_logger.LogError("地图点位获取返回Null");
return false;
}
if (res.code != 0)
{
_logger.LogError($"地图点位获取错误,内容:{res.message}");
}
if (res.Data == null)
{
_logger.LogError("地图点位获取无数据");
return false;
}
List<AGVMapPoint> list = new List<AGVMapPoint>();
foreach (var a in res.Data)
{
list.Add(new AGVMapPoint()
{
MapID = a.mapId,
PointGuid = a.guid,
PointName = a.name,
PointType = a.type.ToString(),
MapName = a.name,
});
}
return _AGVMapPointService.DeleteAndAddAgvMapPoint(list);
}
/// <summary>
/// 结束当前任务 清除报警 下发任务
/// </summary>
/// <param name="agvName"></param>
/// <param name="jobName"></param>
/// <returns>新任务GUID</returns>
public string EndTaskAndClearErrorAndDownloadTask(string agvguid, string jobName)
{
bool result = false;
try
{
//终止小车当前任务
result = EndTaskAndClearError(agvguid);
var param = _appConfig.JobConfig.Where(x => x.JobName == jobName).First();
//调用小车到抓取位置
return DownloadTask(agvguid, param.JobGUID, param.PointGUID, param.PointParamName);
}
catch (Exception ex)
{
return string.Empty;
}
}
/// <summary>
/// 结束任务并清除报警 延迟1s
/// </summary>
public bool EndTaskAndClearError(string agvguid)
{
bool result1 = false, result2 = false;
try
{
Task.Run(() =>
{
result1 = EndAGVTask(agvguid);
Task.Delay(500);
result2 = ClaerError(agvguid);
});
return result1 && result2;
}
catch (Exception ex)
{
_logger.LogError("结束任务并清除报警发生异常 " + ex);
return false;
}
}
/// <summary>
/// 清除报警 延迟500ms
/// </summary>
public bool ClaerError(string agvguid)
{
bool result = false;
try
{
Task.Run(() =>
{
var response = _airPorthttpClient.AGVErrorClear(_appConfig.AGVConfig.Where(x => x.AGVGUID == agvguid).First().AGVIp);
Task.Delay(500);
if (response == null)
{
_logger.LogError("清除报警返回空数据");
result = false;
return false;
}
if(response.code == 0)
{
_logger.LogError("清除报警成功");
result = true;
return true;
}
else
{
_logger.LogError("清除报警失败 message:" + response.message);
result = false;
return false;
}
});
return result;
}
catch (Exception ex)
{
_logger.LogError("清除报警发生异常 " + ex);
return false;
}
}
/// <summary>
/// 筛选一辆空闲且指定类型剩余可用空间最大的AGV, 返回GUID
/// </summary>
/// <returns></returns>
public AGVState GetBestAGV(AgvType agvType)
{
try
{
List<AGVState> lists = _AGVStateService.GetAgvState(agvType).Where(x => x.agvworkstate == "待机").ToList();
AGVState agv = lists.Where(x => x.stackcount == lists.Min(x => x.stackcount)).FirstOrDefault();
//var list = _AGVStateService
return agv;
}
catch(Exception ex)
{
_logger.LogError($"AGV筛选发生错误{ex.Message}");
return null;
}
}
/// <summary>
/// AGV任务状态代码匹配
/// </summary>
/// <param name="no"></param>
/// <returns></returns>
public static string AGVTaskStatusSelect(int no)
{
switch (no)
{
case 0: return "已终止";
case 1: return "待执行";
case 2: return "正在执行";
case 3: return "已完成";
case 4: return "已取消";
case 5: return "已暂停";
case 6: return "匹配中";
case 7: return "核验中";
default: return "未知代码";
}
}
}
}