using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WCS.BLL.DbModels; using WCS.BLL.Tool; using WCS.DAL.Db; using WCS.DAL.DbModels; using WCS.Model; using WCS.Model.ApiModel.AGV; using WCS.Model.ApiModel.InOutRecord; using WCS.Model.ApiModel.MXBackgroundThread; namespace WCS.BLL.Manager { //AGV动作相关 public static class AGVManager { public static void InitBackgroundThread() { #region 定时任务:定时查询任务状态 Task.Run(() => { while (true) { //每5秒同步一次 Thread.Sleep(3000); try { var url = @"http://192.168.18.150:8181/rcms/services/rest/hikRpcService/queryTaskStatus"; var tasks = DbHelp.db.Queryable() .Where(t => t.CreateTime > DateTime.Now.AddDays(-7)) //只查询7天内agv任务数据 .Where(t => t.TaskStatus != TaskStatusEnum.取消完成 && t.TaskStatus != TaskStatusEnum.已结束) .OrderBy(t => t.Id) .ToList(); if (tasks != null && tasks.Count > 0) { Logs.Write("【定时任务】获取任务状态 开始", LogsType.Tasks); for (int i = 0; i < tasks.Count; i++) { try { //请求RCS获取任务状态 var data = new AGVQueryTaskStatusRequest(); data.taskCodes.Add(tasks[i].TaskCode); var result = ApiHelp.GetDataFromHttp(url, data, "POST", true); if (result != null && result.code == "0" && result.data != null && result.data.Count > 0) { var isUpdate = false; //获取成功 是否与当前任务状态一致 如果不一致 进行更新 var responseData = result.data.First(); if (responseData.agvCode != tasks[i].AgvCode) { isUpdate = true; tasks[i].AgvCode = responseData.agvCode; } if (responseData.taskStatus != tasks[i].TaskStatus.ToString()) { Enum.TryParse(responseData.taskStatus, out TaskStatusEnum status); isUpdate = true; tasks[i].TaskStatus = status; //取消任务时 货架数据需要更新 if (status == TaskStatusEnum.取消完成) { var shelf = DbHelp.db.Queryable() .Where(t => t.ShelfCode == tasks[i].ShelfCode) .Where(t => t.CurrentTaskCode == tasks[i].TaskCode) .Where(t => t.DestinationLocationId == tasks[i].EndLocationId) .First(); if (shelf != null) { shelf.DestinationLocationId = 0; shelf.DestinationLocaiotnCode = string.Empty; shelf.TransStatus = TransStatusEnum.静止; shelf.CurrentTaskCode = string.Empty; DbHelp.db.Updateable(shelf).ExecuteCommand(); } } } if (isUpdate) { tasks[i].ModifyTime = DateTime.Now; if (tasks[i].TaskStatus != TaskStatusEnum.已创建 && tasks[i].TaskStatus != TaskStatusEnum.正在执行) { tasks[i].AgvStatus = "-"; } DbHelp.db.Updateable(tasks[i]).ExecuteCommand(); } } } catch (Exception ex) { Logs.Write("【定时任务】获取任务状态异常:" + ex.Message, LogsType.Tasks); } Thread.Sleep(50); } } else { } } catch (Exception ex) { Logs.Write("【定时任务】获取任务状态异常:" + ex.Message, LogsType.Tasks); } } }); #endregion #region 定时任务:定时同步货架绑定情况 Task.Run(() => { while (true) { Logs.Write("【定时任务】定时同步货架绑定情况,开始", LogsType.Tasks); try { var url = @"http://192.168.18.150:8181/rcms/services/rest/hikRpcService/syncMapDatas"; var data = new AGVSyncMapDatasRequest(); var result = ApiHelp.GetDataFromHttp(url, data, "POST", true); if (result != null && result.data != null && result.data.Count > 0) { //获取RCS地图上所有的货架 var rcsDatas = result.data.Where(t => !string.IsNullOrEmpty(t.podCode)) .Select(t => new { ShelfCode = t.podCode, LocationCode = t.positionCode, }) .Distinct() .ToList(); var shelfCodesInRcs = rcsDatas.Select(t => t.ShelfCode).Distinct().ToList(); var locationCodeInRcs = rcsDatas.Select(t => t.LocationCode).Distinct().ToList(); //获取位置 var Locations = DbHelp.db.Queryable() .Where(t => locationCodeInRcs.Contains(t.LocationCode)) .ToList(); //更新货架的信息 var shelfs = DbHelp.db.Queryable() .Where(t => t.TransStatus == TransStatusEnum.静止) .ToList(); foreach (var shelf in shelfs) { var currentLocationId = shelf.CurrentLocationId; //RCS中有货架储位信息 if (shelfCodesInRcs.Contains(shelf.ShelfCode)) { var rcsData = rcsDatas.Where(t => t.ShelfCode == shelf.ShelfCode).FirstOrDefault(); if (rcsData == null) { //此情况先按兵不动 continue; } var location = Locations.Where(t => t.LocationCode == rcsData.LocationCode).FirstOrDefault(); //货架绑定在我系统中未配置的点位上 if (location == null) { shelf.CurrentLocationId = 0; shelf.CurrentLocaiotnCode = string.Empty; } //货架绑定在系统中已配置的点位上 else { shelf.CurrentLocationId = location.Id; shelf.CurrentLocaiotnCode = location.LocationCode; } } //RCS中没有货架储位的信息 else { shelf.CurrentLocationId = 0; shelf.CurrentLocaiotnCode = string.Empty; } //只更新产生变化的 缩小更新范围 if (currentLocationId != shelf.CurrentLocationId) { shelf.IsSelected = true; } } shelfs = shelfs.Where(t => t.IsSelected).ToList(); if (shelfs != null && shelfs.Count > 0) { Logs.Write($"【定时任务】定时同步货架绑定情况,更新{shelfs.Count}个货架", LogsType.Tasks); DbHelp.db.Updateable(shelfs) .UpdateColumns(t => new { t.CurrentLocationId, t.CurrentLocaiotnCode }) //.Where(t => t.TransStatus == TransStatusEnum.静止) .ExecuteCommand(); } Logs.Write($"【定时任务】定时同步货架绑定情况,更新0个货架", LogsType.Tasks); } } catch (Exception ex) { Logs.Write("【定时任务】定时同步货架绑定情况异常:" + ex.Message,LogsType.Tasks); } Logs.Write("【定时任务】定时同步货架绑定情况,结束", LogsType.Tasks); //每60秒同步一次 Thread.Sleep(20000); } }); #endregion } public static object lockFlag = new object(); /// /// 产生AGV点到点搬运任务 /// public static AGVResponseModel GenAgvSchedulingTask(LocationInfo startLocation, LocationInfo endLocation, string shelfCode, string createUser) { var url = @"http://192.168.18.150:8181/rcms/services/rest/hikRpcService/genAgvSchedulingTask"; var startPositionCodePathItem = new PositionCodePathItem() { positionCode = startLocation.RcsStoreCode, }; var endPositionCodePathItem = new PositionCodePathItem() { positionCode = endLocation.RcsStoreCode, }; List positionCodePathItems = new List(); positionCodePathItems.Add(startPositionCodePathItem); positionCodePathItems.Add((endPositionCodePathItem)); //任务只允许一个一个发送 lock (lockFlag) { //正在执行中的任务 var tasks = DbHelp.db.Queryable() .Where(t => t.TaskStatus == TaskStatusEnum.已创建 || t.TaskStatus == TaskStatusEnum.正在执行) .ToList(); //校验货架 if (tasks.Where(t => t.ShelfCode == shelfCode).Any()) { return new AGVResponseModel() { code = "-999", message = $"货架[{shelfCode}]已有执行中的任务!", }; } //校验起点 if (tasks.Where(t => t.StratLocationId == startLocation.Id).Any()) { return new AGVResponseModel() { code = "-999", message = $"工位[{startLocation.LocationCode}]作为起点已有执行中的任务!", }; } //校验终点 if (tasks.Where(t => t.EndLocationId == endLocation.Id).Any()) { return new AGVResponseModel() { code = "-999", message = $"工位[{endLocation.LocationCode}]作为终点已有执行中的任务!", }; } var body = new GenAgvSchedulingTaskRequest() { positionCodePath = positionCodePathItems, }; var response = ApiHelp.GetDataFromHttp(url, body, "POST", true); if (response.code == "0" && response.message == "成功") { //生成任务数据 var task = new AgvTask() { ShelfCode = shelfCode, RequestCode = body.reqCode, TaskCode = body.taskCode, TaskType = "GenAgvSchedulingTask", StratLocationId = startLocation.Id, StartLocationCode = startLocation.LocationCode, EndLocationId = endLocation.Id, EndLocationCode = endLocation.LocationCode, CreateUser = createUser }; DbHelp.db.Insertable(task).ExecuteCommand(); } return response; } } public static AGVResponseModel GenAgvSchedulingTaskForResend(LocationInfo startLocation, LocationInfo endLocation, AgvTask agvTask, string shelfCode, string createUser) { var url = @"http://192.168.18.150:8181/rcms/services/rest/hikRpcService/genAgvSchedulingTask"; var startPositionCodePathItem = new PositionCodePathItem() { positionCode = startLocation.RcsStoreCode, }; var endPositionCodePathItem = new PositionCodePathItem() { positionCode = endLocation.RcsStoreCode, }; List positionCodePathItems = new List(); positionCodePathItems.Add(startPositionCodePathItem); positionCodePathItems.Add((endPositionCodePathItem)); //任务只允许一个一个发送 lock (lockFlag) { //正在执行中的任务 var tasks = DbHelp.db.Queryable() .Where(t => t.TaskStatus == TaskStatusEnum.已创建 || t.TaskStatus == TaskStatusEnum.正在执行) .ToList(); //校验货架 if (tasks.Where(t => t.ShelfCode == shelfCode).Any()) { return new AGVResponseModel() { code = "-999", message = $"货架[{shelfCode}]已有执行中的任务!", }; } //校验起点 if (tasks.Where(t => t.StratLocationId == startLocation.Id).Any()) { return new AGVResponseModel() { code = "-999", message = $"工位[{startLocation.LocationCode}]作为起点已有执行中的任务!", }; } //校验终点 if (tasks.Where(t => t.EndLocationId == endLocation.Id).Any()) { return new AGVResponseModel() { code = "-999", message = $"工位[{endLocation.LocationCode}]作为终点已有执行中的任务!", }; } agvTask.TaskCode = agvTask.TaskCode + "_resend"; agvTask.CreateTime = DateTime.Now; agvTask.CreateUser = createUser; var body = new GenAgvSchedulingTaskRequest() { taskCode = agvTask.TaskCode, positionCodePath = positionCodePathItems, }; var response = ApiHelp.GetDataFromHttp(url, body, "POST", true); if (response.code == "0" && response.message == "成功") { //DbHelp.db.Updateable(agvTask).ExecuteCommand(); //生成任务数据 var task = new AgvTask() { ShelfCode = shelfCode, RequestCode = body.reqCode, TaskCode = agvTask.TaskCode, TaskType = "GenAgvSchedulingTask", StratLocationId = startLocation.Id, StartLocationCode = startLocation.LocationCode, EndLocationId = endLocation.Id, EndLocationCode = endLocation.LocationCode, CreateUser = createUser }; DbHelp.db.Insertable(task).ExecuteCommand(); } return response; } } /// /// RCS取消任务 /// /// /// public static AGVResponseModel CancelTask(AgvTask agvTask) { try { var url = @"http://192.168.18.150:8181/rcms/services/rest/hikRpcService/cancelTask"; //任务只允许一个一个发送 lock (lockFlag) { var body = new AGVCancelTaskRequest() { taskCode = agvTask.TaskCode, }; var response = ApiHelp.GetDataFromHttp(url, body, "POST", true); if (response.code == "0" && response.message == "成功") { //取消会统一在后台线程更新 //agvTask.TaskStatus = Model.ApiModel.AGV.TaskStatusEnum.取消完成; //DbHelp.db.Updateable(agvTask).ExecuteCommand(); } return response; } } catch (Exception ex) { return new AGVResponseModel() { code = "-1", message = $"发生异常:{ex.Message}" }; } } /// /// RCS货架绑定 解绑 /// /// /// public static AGVResponseModel BindPodAndBerth(string shelfCode, string locationCode, BindPodAndBerthMethod bindPodAndBerthMethod) { try { //货架绑定解绑地址 var url = @"http://192.168.18.150:8181/rcms/services/rest/hikRpcService/bindPodAndBerth"; //任务只允许一个一个发送 lock (lockFlag) { var body = new AGVBindPodAndBerthRequest() { podCode = shelfCode, positionCode = locationCode, pointCode = locationCode, indBind = ((int)bindPodAndBerthMethod).ToString(), }; var response = ApiHelp.GetDataFromHttp(url, body, "POST", true); //if (response.code == "0" && response.message == "成功") //{ //} return response; } } catch (Exception ex) { return new AGVResponseModel() { code = "-1", message = $"发生异常:{ex.Message}" }; } } public static void RefreshAgvStatus() { try { Logs.Write("[刷新AGV状态]开始刷新AGV状态"); var url = @"http://192.168.18.150:8181/rcms-dps/rest/queryAgvStatus"; var body = new AGVQueryAgvStatusRequest(); var response = ApiHelp.GetDataFromHttpShortTime(url, body, "POST", true); if (response == null) { Logs.Write("[刷新AGV状态]Response为空!"); return; } //response不为空 更新task表的状态 var tasks = DbHelp.db.Queryable() .Where(t => t.TaskStatus == TaskStatusEnum.已创建 || t.TaskStatus == TaskStatusEnum.正在执行) .ToList(); if (tasks == null || tasks.Count == 0) { Logs.Write("[刷新AGV状态]状态为执行中或者已创建的任务为空!"); } foreach (var task in tasks) { var agvCode = task.AgvCode; if (string.IsNullOrEmpty(agvCode)) { continue; } var dataItem = response?.data.Where(t => t.robotCode == agvCode).FirstOrDefault(); if (dataItem == null) { continue; } var str = string.Empty; switch (dataItem.status) { case "1": str = "任务完成"; break; case "2": str = "任务执行中"; break; case "3": str = "任务异常"; break; case "4": str = "任务空闲"; break; case "5": str = "机器人暂停"; break; case "6": str = "举升货架状态"; break; case "7": str = "充电状态"; break; case "8": str = "弧线行走中"; break; case "9": str = "充满维护"; break; case "11": str = "背货未识别"; break; case "12": str = "货架偏角过大"; break; case "13": str = "运动库异常"; break; case "14": str = "货码无法识别"; break; case "15": str = "货码不匹配"; break; case "16": str = "举升异常"; break; case "17": str = "充电桩异常"; break; case "18": str = "电量无增加"; break; case "20": str = "充电指令角度错误"; break; case "21": str = "平台下发指令错误"; break; case "23": str = "外力下放"; break; case "24": str = "货架位置偏移"; break; case "25": str = "小车不在锁定区"; break; case "26": str = "下放重试失败"; break; case "27": str = "货架摆歪"; break; case "28": str = "举升电池电量太低"; break; case "29": str = "后退角度偏大"; break; case "30": str = "未背货架举升"; break; case "31": str = "区域锁定失败"; break; case "33": str = "旋转申请暂时失败"; break; case "34": str = "地图切换点地码未识别"; break; default: str = "未知状态"; break; } //更新状态 task.AgvStatus = str; } DbHelp.db.Updateable(tasks).UpdateColumns(t => new { t.AgvStatus }).ExecuteCommand(); Logs.Write("[刷新AGV状态]结束刷新AGV状态"); } catch (Exception ex) { Logs.Write($"[刷新AGV状态]遇到异常{ex.Message}\r\n{ex.StackTrace}"); } } } /// /// 解绑或者绑定 /// public enum BindPodAndBerthMethod { 解绑 = 0, 绑定 = 1, } }