diff --git a/SlnMesnac.Business/base/AirPortAGVMapPointBusiness.cs b/SlnMesnac.Business/base/AirPortAGVMapPointBusiness.cs index 16e0fe0..940d80e 100644 --- a/SlnMesnac.Business/base/AirPortAGVMapPointBusiness.cs +++ b/SlnMesnac.Business/base/AirPortAGVMapPointBusiness.cs @@ -1,8 +1,10 @@ using Microsoft.Extensions.Logging; +using SlnMesnac.Model.domain; using SlnMesnac.Repository.service; using SlnMesnac.TouchSocket; using System; using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; using System.Text; namespace SlnMesnac.Business.@base @@ -13,22 +15,79 @@ namespace SlnMesnac.Business.@base { private ILogger _logger; private static BaseStateRefreshBusiness instance; + private AirPorthttpClient _airPorthttpClient; + private IAGVMapPointService _agvMapPointService; - public BaseStateRefreshBusiness(ILogger logger) + public BaseStateRefreshBusiness(ILogger logger, AirPorthttpClient airPorthttpClient, IAGVMapPointService aGVMapPointService) { _logger = logger; - + _agvMapPointService = aGVMapPointService; + _airPorthttpClient = airPorthttpClient; } - public static BaseStateRefreshBusiness GetInstance(ILogger logger) + public static BaseStateRefreshBusiness GetInstance(ILogger logger, AirPorthttpClient airPorthttpClient, IAGVMapPointService aGVMapPointService) { if (instance == null) { - instance = new BaseStateRefreshBusiness(logger); + instance = new BaseStateRefreshBusiness(logger, airPorthttpClient, aGVMapPointService); } return instance; } + /// + /// 获取活跃地图的点位更新到数据库 + /// + /// + 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 list = new List(); + 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); + } } } diff --git a/SlnMesnac.Business/base/BaseAGVBusiness.cs b/SlnMesnac.Business/base/BaseAGVBusiness.cs index 937debc..8ead836 100644 --- a/SlnMesnac.Business/base/BaseAGVBusiness.cs +++ b/SlnMesnac.Business/base/BaseAGVBusiness.cs @@ -1,4 +1,5 @@ -using System; +using SlnMesnac.Model.AirportApiEntity; +using System; using System.Collections.Generic; using System.Text; @@ -6,6 +7,44 @@ namespace SlnMesnac.Business.@base { public class BaseAGVBusiness { + /// + /// 向AGV小车下发任务 + /// + /// + public bool DownloadTask(string taskID, string jobID) + { + AGVRequestAddTaskEntity aGVRequestAddTaskEntity = new AGVRequestAddTaskEntity() + { + businessOrderId = taskID, + priority = 0, + RobotType = "S800", + robotId = "", + group = "", + taskSource = "Mesnac", + taskType = 3, + verifyStatus = 0, + enableSplitCar = 0, + load = new List() + { + new LoadsEntity() + { + jobid = jobID, + location = "", + param = new List() + { + new ParamEntity() + { + paramname = "", + paramvalue = "", + } + }, + robotPort = "" + } + }, + }; + return true; + + } } } diff --git a/SlnMesnac.Business/base/BaseStateRefreshBusiness.cs b/SlnMesnac.Business/base/BaseStateRefreshBusiness.cs index 2937d39..097dc1e 100644 --- a/SlnMesnac.Business/base/BaseStateRefreshBusiness.cs +++ b/SlnMesnac.Business/base/BaseStateRefreshBusiness.cs @@ -25,6 +25,7 @@ namespace SlnMesnac.Business.@base _airPorthttpClient = airPorthttpClient; _aGVSettingService = aGVSettingService; } + public static BaseStateRefreshBusiness GetInstance(ILogger logger, IAGVStateService agvService, AirPorthttpClient airPorthttpClient, IAGVSettingService aGVSettingService) { if (instance == null) diff --git a/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs b/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs index 95d0f5b..3c00af0 100644 --- a/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs +++ b/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs @@ -158,7 +158,6 @@ namespace SlnMesnac.Business.@base Task.Delay(1000); } - })); } @@ -377,6 +376,5 @@ namespace SlnMesnac.Business.@base } } - } } \ No newline at end of file diff --git a/SlnMesnac.Business/base/VisionBusiness.cs b/SlnMesnac.Business/base/VisionBusiness.cs new file mode 100644 index 0000000..6fd5390 --- /dev/null +++ b/SlnMesnac.Business/base/VisionBusiness.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.Logging; +using SlnMesnac.Repository.service; +using SlnMesnac.TouchSocket; +using System; +using System.Collections.Generic; +using System.Text; + +namespace SlnMesnac.Business.@base +{ + public class VisionBusiness + { + private ILogger _logger; + private static VisionBusiness instance; + + private TcpServer _tcpServer; + + public VisionBusiness(ILogger logger, TcpServer tcpServer) + { + _logger = logger; + _tcpServer = tcpServer; + } + + public static VisionBusiness GetInstance(ILogger logger, TcpServer tcpServer) + { + if (instance == null) + { + instance = new VisionBusiness(logger, tcpServer); + } + return instance; + } + + + } +} diff --git a/SlnMesnac.Model/AirportApiEntity/AGVAddTaskEntity.cs b/SlnMesnac.Model/AirportApiEntity/AGVAddTaskEntity.cs index 42d4d99..212d0c6 100644 --- a/SlnMesnac.Model/AirportApiEntity/AGVAddTaskEntity.cs +++ b/SlnMesnac.Model/AirportApiEntity/AGVAddTaskEntity.cs @@ -12,12 +12,12 @@ namespace SlnMesnac.Model.AirportApiEntity /// /// 任务单ID-AGVC的任务ID /// - public string businessOrderId { get; set; } + public string businessOrderId { get; set; } = string.Empty; /// /// 设备类型 /// - public string RobotType { get; set; } + public string RobotType { get; set; } = string.Empty; /// /// 优先级 默认值0 @@ -27,7 +27,7 @@ namespace SlnMesnac.Model.AirportApiEntity /// /// 机器人ID /// - public string roborId { get; set; } + public string robotId { get; set; } = string.Empty; /// /// 分组ID 默认空 @@ -47,17 +47,17 @@ namespace SlnMesnac.Model.AirportApiEntity /// /// 验证任务 0:不验证 1:需要验证 传0 /// - public int verifyStatus { get; set; } + public int verifyStatus { get; set; } = 0; /// /// 是否允许分⻋执⾏(默认FALSE) /// - public int? enableSplitCar { get; set; } + public int enableSplitCar { get; set; } = 0; /// /// 任务描述 /// - public string? desc { get; set; } + public string desc { get; set; } = string.Empty ; /// /// 装货点 @@ -83,7 +83,7 @@ namespace SlnMesnac.Model.AirportApiEntity /// /// 地图中的点位 默认空字符串 /// - public string loaction { get; set; } = string.Empty; + public string location { get; set; } = string.Empty; /// /// 参数 数据跟location一样 diff --git a/SlnMesnac.TouchSocket/AirPorthttpClient.cs b/SlnMesnac.TouchSocket/AirPorthttpClient.cs index fb8513d..41588a0 100644 --- a/SlnMesnac.TouchSocket/AirPorthttpClient.cs +++ b/SlnMesnac.TouchSocket/AirPorthttpClient.cs @@ -18,6 +18,8 @@ using JsonSerializer = System.Text.Json.JsonSerializer; using Serilog; using Serilog.Events; using Microsoft.Extensions.Logging; +using System.Net.Http; +using static System.Net.WebRequestMethods; namespace SlnMesnac.TouchSocket { @@ -69,35 +71,46 @@ namespace SlnMesnac.TouchSocket /// /// /// - public T JTokenToEntity(JToken value) where T : class + public AGVResponseEntity JTokenToEntity(JToken value) where T : class { if (value == null) { + _logger.LogError("返回空数据!"); return null; } string json = value.ToString(); if (string.IsNullOrEmpty(json)) { + _logger.LogError("解析数据为空!"); + return null; + } + AGVResponseEntity ResponseEntity; + try + { + ResponseEntity = JsonSerializer.Deserialize>(json); + return ResponseEntity; + } + catch (Exception ex) + { + _logger.LogError($"Json反序列化发生错误:{ex.Message}"); return null; } - T ResponseEntity; - ResponseEntity = JsonSerializer.Deserialize(json); - return ResponseEntity; } - /// /// AGV下发任务请求 /// /// /// + /// public AGVResponseEntity AGVAddTaskRequest(AGVRequestAddTaskEntity requestValue) { if (AirportAGVClient == null) { return null; } + JToken responseValue = AirportAGVClient.InvokeT("POST:/api/task/addTask", null, requestValue); - return JTokenToEntity>(responseValue); + return JTokenToEntity(responseValue); } /// @@ -112,7 +125,7 @@ namespace SlnMesnac.TouchSocket return null; } JToken responseValue = AirportAGVClient.InvokeT("POST:/api/task/operationalTask", null, requestValue); - return JTokenToEntity>(responseValue); + return JTokenToEntity(responseValue); } /// @@ -127,7 +140,7 @@ namespace SlnMesnac.TouchSocket return null; } JToken responseValue = AirportAGVClient.InvokeT("PUT:/api/task/getTaskStateDetail", null, requestValue); - return JTokenToEntity>(responseValue); + return JTokenToEntity(responseValue); } /// @@ -141,7 +154,7 @@ namespace SlnMesnac.TouchSocket return null; } JToken responseValue = AirportAGVClient.InvokeT("GET:/api/task/robot/getRobot", null); - return JTokenToEntity>>(responseValue); + return JTokenToEntity>(responseValue); } /// @@ -155,7 +168,7 @@ namespace SlnMesnac.TouchSocket return null; } JToken responseValue = AirportAGVClient.InvokeT("GET:/api/v1.0.0/Maps/mapActive", null); - return JTokenToEntity>(responseValue); + return JTokenToEntity(responseValue); } /// @@ -170,9 +183,35 @@ namespace SlnMesnac.TouchSocket return null; } JToken responseValue = AirportAGVClient.InvokeT("GET:/api/v1.0.0/Positions?mapId={0}", null, requestValue); - return JTokenToEntity>>(responseValue); + return JTokenToEntity>(responseValue); + } + + /// + /// 获取当前所有任务模板信息(目前不可用) + /// + /// + public AGVResponseEntity AGVJobRequest() + { + if (AirportAGVClient == null) + { + return null; + } + JToken responseValue = AirportAGVClient.InvokeT("GET:/api/v1.0.0/Positions?mapId={0}", null); + return JTokenToEntity(responseValue); } } + //HttpClient client1 = new HttpClient(); + + + + //string url = "http://192.168.10.199:5102/api/task/addTask"; + + //string json =Newtonsoft.Json.JsonConvert.SerializeObject(requestValue); + //var context=new StringContent(json,Encoding.UTF8, "application/json"); + //var httpContent = client1.PostAsync(url, context).ConfigureAwait(false).GetAwaiter().GetResult().Content; + //var result = httpContent.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult(); + //_logger.LogInformation(result); + } diff --git a/SlnMesnac.TouchSocket/TcpServer.cs b/SlnMesnac.TouchSocket/TcpServer.cs index 2f9ad4b..05c64a7 100644 --- a/SlnMesnac.TouchSocket/TcpServer.cs +++ b/SlnMesnac.TouchSocket/TcpServer.cs @@ -4,6 +4,7 @@ using Serilog; using Serilog.Core; using SlnMesnac.Config; using SlnMesnac.TouchSocket.Entity; +using SqlSugar; using System; using System.Collections.Generic; using System.Diagnostics; @@ -54,7 +55,7 @@ namespace SlnMesnac.TouchSocket public delegate void RefreshClientInfo(TcpService tcpService); public event RefreshClientInfo? RefreshClientInfoEvent; - public Action RefreshStateAction; + public Action RefreshStateAction; public delegate void GetVisionData(TcpVisionEntity entity, string id); @@ -91,7 +92,13 @@ namespace SlnMesnac.TouchSocket _service = tcpService; _appConfig = appConfig; + //视觉系统回复状态 + ReceiveVisionSysStateEvent += VisionStateRequest; + //视觉系统回复开始码垛 + ReceiveVisionStartWorkEvent += GetVisionWorkState; + //视觉系统回复一次码垛完成结果 ReceiveStackWorkDoneEvent += StackResultSend; + //视觉系统回复人工异常处理完成 ReceiveManualExceptionDealDoneEvent += ManualExceptionDealDone; } @@ -175,7 +182,7 @@ namespace SlnMesnac.TouchSocket // { // Thread.Sleep(4000); // _service.Send(client.Id, new byte[0x01]); - + // } // // 检查是否超过两秒 // if (stopwatch.ElapsedMilliseconds > 2000) @@ -353,9 +360,9 @@ namespace SlnMesnac.TouchSocket /// /// 上位机调度系统每隔固定时间,请求视觉系统状态 /// - public void VisionStateRequest(int port) + public void VisionStateRequest(TcpVisionEntity entity, string id) { - SendRequestVisionSysState(port.ToString()); + SendRequestVisionSysState(id); } /// @@ -367,11 +374,89 @@ namespace SlnMesnac.TouchSocket } /// - /// 一次码垛完成,发送码垛结果 + /// 接受开始工作状态 + /// + /// + /// + private void GetVisionWorkState(TcpVisionEntity entity, string id) + { + string result; + if (entity.DataLength == 1) + { + if (entity.DataBytes[0] == 0x00) + { + result = "正常开始工作"; + + } + else if (entity.DataBytes[0] == 0x01) + { + result = "异常不能开始工作"; + } + else + { + result = "返回未知代码"; + } + } + else + { + result = "数据返回格式错误"; + } + _logger.LogInformation($"视觉系统收到开始工作状态:{result}"); + } + + /// + /// 接受码垛结果 /// public void StackResultSend(TcpVisionEntity entity, string id) { - SendReplayStackResult(id); + string result; + if (entity.DataLength == 1) + { + if (entity.DataBytes[0] == 0x00) + { + result = "码垛完成"; + //上位机回复收到码垛结果 + SendReplayStackResult(id); + if (true) //这里写是否继续下一次码垛的判断条件 + { + //如果码垛没结束继续发下一次的码垛信号 + if (true) //这里写向哪个机器人码垛的判断条件 + { + //发送向搬运机器人(AGVDeliver)码垛的信号 + SendAMRRequestVisionStartWork(new byte[] { 0x10 }, id); + _logger.LogInformation("下一次码垛开始,方向:搬运机器人"); + } + else + { + //发送向复合机器人(AMR)码垛的信号 + SendAMRRequestVisionStartWork(new byte[] { 0x01 }, id); + _logger.LogInformation("下一次码垛开始,方向:复合机器人"); + } + } + else + { + //如果码垛结束就请求复位 + SendStackOverRequestVisionSysReplace(id); + } + } + else if (entity.DataBytes[0] == 0x01) + { + result = "码垛过程失败"; + } + else if (entity.DataBytes[0] == 0x02) + { + result = "码垛检查失败"; + } + else + { + result = "未知返回代码"; + } + } + else + { + result = "返回数据格式错误"; + } + _logger.LogInformation($"视觉系统一次码垛结束:{result}"); } /// diff --git a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs index d9bd170..870e6f5 100644 --- a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs @@ -21,6 +21,7 @@ using SlnMesnac.TouchSocket; using HslCommunication.Enthernet; using SlnMesnac.Config; using System.Threading; +using SlnMesnac.Model.AirportApiEntity; #region << 版 本 注 释 >> /*-------------------------------------------------------------------- @@ -46,7 +47,7 @@ using System.Threading; #endregion << 版 本 注 释 >> namespace SlnMesnac.WPF.ViewModel.IndexPage { - public partial class IndexContentViewModel: ObservableObject + public partial class IndexContentViewModel : ObservableObject { private ILogger _logger; private ILogger _taskBusinessLogger; @@ -64,6 +65,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage { LogMessages = new ObservableCollection(); _taskBusinessLogger = App.ServiceProvider.GetService>(); + _logger = App.ServiceProvider.GetService>(); _taskservice = App.ServiceProvider.GetService(); _agvstateService = App.ServiceProvider.GetService(); _tcpServer = App.ServiceProvider.GetService(); @@ -86,7 +88,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage x.deliveragvno = task.deliveragvno; x.taskstate = task.taskstate; TaskItems = new ObservableCollection(TaskItems); - + } } }; @@ -111,6 +113,50 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage #region 测试数据 LoadTaskInfo(); + + + + ////下发数据测试 + //AGVRequestAddTaskEntity aGVRequestAddTaskEntity = new AGVRequestAddTaskEntity() + //{ + // businessOrderId = "testtask1009", + // priority = 0, + // RobotType = "S800", + // robotId = "53773a420771497b8b699e949e9eaacb", + // group = "", + // taskSource = "agvctest", + // taskType = 0, + // verifyStatus = 0, + // enableSplitCar = 0, + // load = new List() + // { + // new LoadsEntity() + // { + // jobid = "36e065b08a5245df898ba6ff135768a6", + // location = "8491f5771c824bab80a497cc9af63772", + // param = new List() + // { + // new ParamEntity() + // { + // paramname = "p3", + // paramvalue = "8491f5771c824bab80a497cc9af63772", + // } + // }, + // robotPort = "" + // } + // }, + + //}; + + //try + //{ + // _airPorthttpClient.AGVAddTaskRequest(aGVRequestAddTaskEntity); + //} + //catch (Exception ex) + //{ + // _logger.LogError($"接口发生错误:{ex.Message}"); + //} + //Thread.Sleep(5000); //_tcpServer.SendReplyGetManualException( @@ -171,7 +217,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage _timer.Start(); #endregion - + } public async void RefreshTaskItems(AirportTask airportTask) @@ -266,7 +312,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage { } - + } /// /// 系统运行日志输出 @@ -336,7 +382,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage RefreshLogMessage("任务添加成功!"); } - + } /// diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json index a7d7b96..eee07a9 100644 --- a/SlnMesnac.WPF/appsettings.json +++ b/SlnMesnac.WPF/appsettings.json @@ -82,7 +82,7 @@ "redisConfig": "175.27.215.92:6379,password=redis@2023", - "AGVIpConfig": "http://192.168.40.81:5102", + "AGVIpConfig": "http://192.168.10.199:5102", "TCPVisionConfig": "127.0.0.1:6000" }