diff --git a/SlnMesnac.Business/base/BaseAGVBusiness.cs b/SlnMesnac.Business/base/BaseAGVBusiness.cs
index 0bcb6b1..764c0fc 100644
--- a/SlnMesnac.Business/base/BaseAGVBusiness.cs
+++ b/SlnMesnac.Business/base/BaseAGVBusiness.cs
@@ -2,6 +2,7 @@
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;
@@ -132,7 +133,7 @@ namespace SlnMesnac.Business.@base
{
try
{
- AGVState agvState = _AGVStateService.GetAGVState(AGVGUID);
+ AGVState agvState = _AGVStateService.GetSingleAGVState(AGVGUID);
if (agvState == null)
{
return false;
@@ -237,16 +238,16 @@ namespace SlnMesnac.Business.@base
///
///
/// 新任务GUID
- public string EndTaskAndClearErrorAndDownloadTask(string agvName, string jobName)
+ public string EndTaskAndClearErrorAndDownloadTask(string agvguid, string jobName)
{
bool result = false;
try
{
//终止小车当前任务
- result = EndTaskAndClearError(agvName);
+ result = EndTaskAndClearError(agvguid);
var param = _appConfig.JobConfig.Where(x => x.JobName == jobName).First();
//调用小车到抓取位置
- return DownloadTask(_appConfig.AGVConfig.Where(x => x.AGVName == agvName).First().AGVGUID, param.JobGUID, param.PointGUID, param.PointParamName);
+ return DownloadTask(agvguid, param.JobGUID, param.PointGUID, param.PointParamName);
}
catch (Exception ex)
{
@@ -257,16 +258,16 @@ namespace SlnMesnac.Business.@base
///
/// 结束任务并清除报警 延迟1s
///
- public bool EndTaskAndClearError(string agvName)
+ public bool EndTaskAndClearError(string agvguid)
{
bool result1 = false, result2 = false;
try
{
Task.Run(() =>
{
- result1 = EndAGVTask(_appConfig.AGVConfig.Where(x => x.AGVName == agvName).First().AGVGUID);
- Thread.Sleep(500);
- result2 = ClaerError(_appConfig.AGVConfig.Where(x => x.AGVName == agvName).First().AGVIp);
+ result1 = EndAGVTask(agvguid);
+ Task.Delay(500);
+ result2 = ClaerError(agvguid);
});
return result1 && result2;
}
@@ -280,15 +281,15 @@ namespace SlnMesnac.Business.@base
///
/// 清除报警 延迟500ms
///
- public bool ClaerError(string agvName)
+ public bool ClaerError(string agvguid)
{
bool result = false;
try
{
Task.Run(() =>
{
- var response = _airPorthttpClient.AGVErrorClear(_appConfig.AGVConfig.Where(x => x.AGVName == agvName).First().AGVIp);
- Thread.Sleep(500);
+ var response = _airPorthttpClient.AGVErrorClear(_appConfig.AGVConfig.Where(x => x.AGVGUID == agvguid).First().AGVIp);
+ Task.Delay(500);
if (response == null)
{
_logger.LogError("清除报警返回空数据");
@@ -317,6 +318,26 @@ namespace SlnMesnac.Business.@base
}
}
+ ///
+ /// 筛选一辆空闲且指定类型剩余可用空间最大的AGV, 返回GUID
+ ///
+ ///
+ public AGVState GetBestAGV(AgvType agvType)
+ {
+ try
+ {
+ List 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;
+ }
+ }
+
///
/// AGV任务状态代码匹配
///
diff --git a/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs b/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs
index 08335f1..959982c 100644
--- a/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs
+++ b/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs
@@ -19,22 +19,34 @@ using System.Linq;
namespace SlnMesnac.Business.@base
{
+ ///
+ /// 航班任务业务类
+ ///
public class BaseTaskInfoBusiness
{
+ public const int AMRStackNumber = 10;
+ 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 AirPorthttpClient _airpttpClient;
+ private BaseAGVBusiness _baseAGVBusiness;
+ System.Timers.Timer RefreshTimer;
public BaseTaskInfoBusiness(
ILogger logger,
IAirportTaskService Taskservice,
IAGVStateService agvService,
+ IAGVMapPointService aGVMapPointService,
+ IAGVJobService agvJobService,
TcpServer tcpServer,
- AirPorthttpClient airPorthttpClient)
+ AirPorthttpClient airPorthttpClient,
+ BaseAGVBusiness baseAGVBusiness)
{
_logger = logger;
_tcpServer = tcpServer;
@@ -43,18 +55,26 @@ namespace SlnMesnac.Business.@base
_airpttpClient = airPorthttpClient;
InitClearTimer();
//doWhileGetAGVTaskInfo();
+ RefreshTimer = new System.Timers.Timer(1000);
+ RefreshTimer.Elapsed += (sender, e) => RefreshTaskState();
+ _baseAGVBusiness = baseAGVBusiness;
+ _AGVMapPointService = aGVMapPointService;
+ _AGVJobService = agvJobService;
}
public static BaseTaskInfoBusiness GetInstance(
ILogger logger,
IAirportTaskService Taskservice,
IAGVStateService agvService,
+ IAGVMapPointService aGVMapPointService,
+ IAGVJobService aAGVJobService,
TcpServer tcpServer,
- AirPorthttpClient airPorthttpClient)
+ AirPorthttpClient airPorthttpClient,
+ BaseAGVBusiness baseAGVBusiness)
{
if (instance == null)
{
- instance = new BaseTaskInfoBusiness(logger, Taskservice, agvService, tcpServer, airPorthttpClient);
+ instance = new BaseTaskInfoBusiness(logger, Taskservice, agvService, aGVMapPointService, aAGVJobService, tcpServer, airPorthttpClient, baseAGVBusiness);
}
return instance;
}
@@ -76,8 +96,8 @@ namespace SlnMesnac.Business.@base
deliveragvisarrive = string.Empty, //需要判断,更新 Deliver是否到达
totalcount = totalCount, //判断条件 总数量是多少
loadcount = 0, //需要判断,更新 现抓取数量
- taskstate = "新任务待分配", //需要判断,更新 任务状态
- starttime = DateTime.Now,
+ taskstate = "等待", //需要判断,更新 任务状态
+ starttime = DateTime.Now,
finishtime = null,
deliveragvTaskNo = string.Empty, //需要判断,更新
amragvTaskNo = string.Empty, //需要判断,更新
@@ -94,7 +114,87 @@ namespace SlnMesnac.Business.@base
}
}
+ ///
+ /// AGV状态查询控制
+ ///
+ ///
+ public void AGVStateUpdateTimerOperation(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);
+ }
+
+ }
+
+ ///
+ /// Timer刷新任务状态, 有新任务初次下发AGV
+ ///
+ 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 == "等待" || string.IsNullOrEmpty(taskItem.amragvno))
+ {
+ //首先调一辆最优AMR
+ AGVState firstAMR = _baseAGVBusiness.GetBestAGV(AgvType.AMR);
+ string amrTaskId = _baseAGVBusiness.EndTaskAndClearErrorAndDownloadTask(
+ firstAMR.agvno,
+ _AGVJobService.GetAGVJobListByTypeAndConveyorNo("1000入位", taskItem.conveyorno).JobName);
+ taskItem.amragvTaskNo = amrTaskId;
+ taskItem.amragvno = firstAMR.agvno;
+ taskItem.amragvisarrive = "未到达";
+ taskItem.taskstate = "执行中";
+ //需要AGV和AMR才能装下
+ if (taskItem.totalcount > (AMRStackNumber - firstAMR.stackcount))
+ {
+ //调一辆最优Deliver
+ AGVState firstDeliver = _baseAGVBusiness.GetBestAGV(AgvType.Deliver);
+ string deliverTaskID = _baseAGVBusiness.EndTaskAndClearErrorAndDownloadTask(
+ firstDeliver.agvno,
+ _AGVJobService.GetAGVJobListByTypeAndConveyorNo("800入位", taskItem.conveyorno).JobName);
+ taskItem.deliveragvTaskNo = amrTaskId;
+ taskItem.deliveragvno = firstDeliver.agvno;
+ taskItem.deliveragvisarrive = "未到达";
+ }
+ _Taskservice.UpdateTaskAsync(taskItem);
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"查询任务列表初次下发任务发生错误Message:{ex.Message}");
+ }
+ }
///
/// 获取任务列表,向待执行任务派发AGV (定期执行)
@@ -128,6 +228,7 @@ namespace SlnMesnac.Business.@base
_logger.LogInformation($"正在为AGV,AMR分配任务");
//查询AGV设备状态及AMR设备状态
+
//这里要看AGV是否会立刻更新状态
CreateAGVTask(taskItem);
//查询机械臂状态
@@ -147,7 +248,7 @@ namespace SlnMesnac.Business.@base
_logger.LogInformation($"正在为AGV分配任务");
}
}
-
+
_Taskaction?.Invoke(taskItem);
}
}
@@ -196,7 +297,7 @@ namespace SlnMesnac.Business.@base
{
try
{
- Task.Run((() =>
+ Task.Run(() =>
{
while (true)
{
@@ -204,7 +305,7 @@ namespace SlnMesnac.Business.@base
Task.Delay(1000);
}
- }));
+ });
}
catch (Exception ex)
@@ -228,7 +329,7 @@ namespace SlnMesnac.Business.@base
timer.Start();
}
-
+
///
/// 向AMR派发任务
diff --git a/SlnMesnac.Model/domain/AGVJob.cs b/SlnMesnac.Model/domain/AGVJob.cs
new file mode 100644
index 0000000..a85be0e
--- /dev/null
+++ b/SlnMesnac.Model/domain/AGVJob.cs
@@ -0,0 +1,57 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SlnMesnac.Model.domain
+{
+ public class AGVJob
+ {
+ [SqlSugar.SugarColumn(ColumnName = "id", IsPrimaryKey = true, IsIdentity = true)]
+ public int ID { get; set; }
+
+ ///
+ /// 模板名字
+ ///
+ [SugarColumn(ColumnName = "jobname")]
+ public string JobName { get; set; }
+
+ ///
+ /// 模板GUID
+ ///
+ [SugarColumn(ColumnName = "jobguid")]
+ public string JobGuid { get; set; }
+
+ ///
+ /// 模板对应的传送带编号
+ ///
+ [SugarColumn(ColumnName = "conveyorno")]
+ public string ConveyorNo { get; set; }
+
+ ///
+ /// 模板类型
+ ///
+ [SugarColumn(ColumnName = "jobtype")]
+ public string JobType { get; set; }
+
+ ///
+ /// 模板参数点位GUID
+ ///
+ [SugarColumn(ColumnName = "pointguid")]
+ public string PointGuid { get; set; }
+
+ ///
+ /// 模板参数点位名称
+ ///
+ [SugarColumn(ColumnName = "pointname")]
+ public string PointName { get; set; }
+
+ ///
+ /// 模板参数点位参数名
+ ///
+ [SugarColumn(ColumnName = "pointparamname")]
+ public string PointParamName { get; set; }
+
+
+ }
+}
diff --git a/SlnMesnac.Model/domain/AGVSetting.cs b/SlnMesnac.Model/domain/AGVSetting.cs
index 1f48505..56f987e 100644
--- a/SlnMesnac.Model/domain/AGVSetting.cs
+++ b/SlnMesnac.Model/domain/AGVSetting.cs
@@ -21,5 +21,15 @@ namespace SlnMesnac.Model.domain
/// AGV类型 1:DeliverAGV 2: AMRAGV
///
public string AGVType { get; set; }
+
+ ///
+ /// AGV名称
+ ///
+ public string AGVName { get; set; }
+
+ ///
+ /// AGVIp
+ ///
+ public string AGVIp { get; set; }
}
}
diff --git a/SlnMesnac.Model/domain/AGVState.cs b/SlnMesnac.Model/domain/AGVState.cs
index 90a98ff..31cb48e 100644
--- a/SlnMesnac.Model/domain/AGVState.cs
+++ b/SlnMesnac.Model/domain/AGVState.cs
@@ -11,61 +11,69 @@ namespace SlnMesnac.Repository
[SugarTable("AGVState")]
public partial class AGVState
{
- ///
- /// Desc:
- /// Default:
- /// Nullable:False
- ///
- [SugarColumn(IsPrimaryKey=true,IsIdentity=true,ColumnName="ID")]
- public int id {get;set;}
+ ///
+ /// Desc:
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "ID")]
+ public int id { get; set; }
- ///
- /// Desc:AGV编号
- /// Default:
- /// Nullable:False
- ///
- [SugarColumn(ColumnName="AGVNo")]
- public string agvno {get;set;}
+ ///
+ /// Desc:AGV编号
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "AGVNo")]
+ public string agvno { get; set; }
- ///
- /// Desc:AGV类型 1:DeliverAGV 2: AMRAGV
- /// Default:
- /// Nullable:False
- ///
- [SugarColumn(ColumnName="AGVType")]
- public string agvtype {get;set;}
+ ///
+ /// Desc:AGV类型 1:DeliverAGV 2: AMRAGV
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "AGVType")]
+ public string agvtype { get; set; }
- ///
- /// Desc:任务编号
- /// Default:
- /// Nullable:False
- ///
- [SugarColumn(ColumnName="TaskNo")]
- public string taskno {get;set;}
+ ///
+ /// Desc:任务编号
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "TaskNo")]
+ public string taskno { get; set; }
- ///
- /// Desc:AGV报警状态
- /// Default:
- /// Nullable:False
- ///
- [SugarColumn(ColumnName="AGVAlarmState")]
- public string agvalarmstate {get;set;}
+ ///
+ /// Desc:AGV报警状态
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "AGVAlarmState")]
+ public string agvalarmstate { get; set; }
- ///
- /// Desc:AGV工作状态
- /// Default:
- /// Nullable:False
- ///
- [SugarColumn(ColumnName="AGVWorkState")]
- public string agvworkstate {get;set;}
+ ///
+ /// Desc:AGV工作状态
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "AGVWorkState")]
+ public string agvworkstate { get; set; }
- ///
- /// Desc:刷新时间
- /// Default:
- /// Nullable:False
- ///
- [SugarColumn(ColumnName="RefreshTime")]
- public DateTime refreshtime {get;set;}
+ ///
+ /// Desc:刷新时间
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "RefreshTime")]
+ public DateTime refreshtime { get; set; }
+
+ ///
+ /// Desc:码筐计数
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "StackCount")]
+ public int stackcount { get; set; }
}
}
diff --git a/SlnMesnac.Repository/service/IAGVJobService.cs b/SlnMesnac.Repository/service/IAGVJobService.cs
new file mode 100644
index 0000000..ea7b682
--- /dev/null
+++ b/SlnMesnac.Repository/service/IAGVJobService.cs
@@ -0,0 +1,32 @@
+using SlnMesnac.Model.domain;
+using SlnMesnac.Repository.service.@base;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SlnMesnac.Repository.service
+{
+ public interface IAGVJobService : IBaseService
+ {
+ ///
+ /// 获取AGV模板列表
+ ///
+ ///
+ List GetAGVJobList();
+
+ ///
+ /// 根据模板类型获取对应的AGV模板列表
+ ///
+ ///
+ ///
+ List GetAGVJobListByJobType(string jobType);
+
+ ///
+ /// 根据模板类型和传送带编号获取对应的AGV模板
+ ///
+ ///
+ ///
+ ///
+ AGVJob GetAGVJobListByTypeAndConveyorNo(string jobType, string conveyorno);
+ }
+}
diff --git a/SlnMesnac.Repository/service/IAGVStateService.cs b/SlnMesnac.Repository/service/IAGVStateService.cs
index 736a18e..1821791 100644
--- a/SlnMesnac.Repository/service/IAGVStateService.cs
+++ b/SlnMesnac.Repository/service/IAGVStateService.cs
@@ -49,7 +49,7 @@ namespace SlnMesnac.Repository.service
///
///
///
- AGVState GetAGVState(string AGVguid);
+ AGVState GetSingleAGVState(string AGVguid);
}
}
\ No newline at end of file
diff --git a/SlnMesnac.Repository/service/Impl/AGVJobServiceImpl.cs b/SlnMesnac.Repository/service/Impl/AGVJobServiceImpl.cs
new file mode 100644
index 0000000..c9a7c25
--- /dev/null
+++ b/SlnMesnac.Repository/service/Impl/AGVJobServiceImpl.cs
@@ -0,0 +1,61 @@
+using Microsoft.Extensions.Logging;
+using SlnMesnac.Model.domain;
+using SlnMesnac.Repository.service.@base;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SlnMesnac.Repository.service.Impl
+{
+ public class AGVJobServiceImpl : BaseServiceImpl, IAGVJobService
+ {
+ private ILogger _logger;
+ public AGVJobServiceImpl(Repository repository, ILogger logger) : base(repository)
+ {
+ _logger = logger;
+ }
+
+ public List GetAGVJobList()
+ {
+ try
+ {
+ var list = _rep.GetList();
+ return list;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"获取列表发生错误: {ex.Message}");
+ return null;
+ }
+ }
+
+ public List GetAGVJobListByJobType(string jobType)
+ {
+ try
+ {
+ var list = _rep.GetList().Where(x => x.JobType == jobType).ToList();
+ return list;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"获取列表发生错误: {ex.Message}");
+ return null;
+ }
+ }
+
+ public AGVJob GetAGVJobListByTypeAndConveyorNo(string jobType, string conveyorno)
+ {
+ try
+ {
+ AGVJob record = GetAGVJobListByJobType(jobType).Where(x => x.ConveyorNo == conveyorno).First();
+ return record;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError($"获取列表发生错误: {ex.Message}");
+ return null;
+ }
+ }
+ }
+}
diff --git a/SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs b/SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs
index 6735b5f..f3332e3 100644
--- a/SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs
+++ b/SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs
@@ -134,7 +134,7 @@ namespace SlnMesnac.Repository.service.Impl
///
///
///
- public AGVState GetAGVState(string AGVguid)
+ public AGVState GetSingleAGVState(string AGVguid)
{
try
{
diff --git a/SlnMesnac.TouchSocket/AirPorthttpClient.cs b/SlnMesnac.TouchSocket/AirPorthttpClient.cs
index 10cedf9..022c396 100644
--- a/SlnMesnac.TouchSocket/AirPorthttpClient.cs
+++ b/SlnMesnac.TouchSocket/AirPorthttpClient.cs
@@ -93,7 +93,7 @@ namespace SlnMesnac.TouchSocket
// }
//}
- public AGVResponseEntity JsonStringToEntity(string json) where T : class
+ public AGVResponseEntity JsonStringToEntity(string json) where T : class
{
if (json == null)
{
@@ -127,7 +127,7 @@ namespace SlnMesnac.TouchSocket
///
public AGVResponseEntity AGVAddTaskRequest(AGVRequestAddTaskEntity requestValue)
{
- if(_httpClient == null)
+ if (_httpClient == null)
{
_logger.LogError("http服务为空");
return null;
@@ -276,13 +276,13 @@ namespace SlnMesnac.TouchSocket
// {
// _logger.LogError("http服务为空");
// }
- // //序列化输入数据
+ // 序列化输入数据
// string json = Newtonsoft.Json.JsonConvert.SerializeObject(requestValue);
// var context = new StringContent(json, Encoding.UTF8, "application/json");
- // var httpContent = _httpClient.PostAsync($"{Url}/api/task/addTask", context).ConfigureAwait(false).GetAwaiter().GetResult().Content;
+ // var httpContent = _httpClient.PostAsync($"http://192.168.10.199/api/v1.0.0/Jobs", context).ConfigureAwait(false).GetAwaiter().GetResult().Content;
// string result = httpContent.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
// AGVResponseEntity responseEntity = JsonConvert.DeserializeObject>(result);
- // //JToken responseValue = AirportAGVClient.InvokeT("GET:/api/v1.0.0/Positions?mapId={0}", null);
+ // JToken responseValue = AirportAGVClient.InvokeT("GET:/api/v1.0.0/Positions?mapId={0}", null);
// return JTokenToEntity