using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using PlcSiemens.Core.Extension; using ServiceCenter.Logs; using ServiceCenter.Redis; using ServiceCenter.SqlSugars; using WCS.Core; using WCS.Entity; using WCS.Entity.Protocol.Station; using WCS.WorkEngineering.Extensions; using WCS.WorkEngineering.Systems; using WCS.WorkEngineering.WebApi.Models.AGV; using WCS.WorkEngineering.WebApi.Models.AGV.Request; using WCS.WorkEngineering.WebApi.Models.AGV.Response; namespace WCS.WorkEngineering.WebApi.Controllers { /// /// AGV相关接口控制器 /// [ApiController] [Route("api/[controller]/[action]")] public class AgvController : ControllerBase { /// /// AGV任务下发测试 /// /// 任务类型 /// RFID /// 目标位置 /// [HttpPost] public string AgvDebug(int type, string code, string pos) { try { switch (type) { case 1: AgvApi.机台补空(pos, code, "1"); break; case 2: //AgvApi.机台补满(); break; case 3: AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1"); break; default: break; } return "成功"; } catch (Exception ex) { return $"Error-----" + $"{ex.Message}------" + $"{ex.StackTrace}"; } } /// /// 背负式agv请求出库任务 /// /// 请求参数 /// [HttpPost] public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto) { lock (LockHub.ApplyEmptySpoolLock) { LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"传入参数--{JsonConvert.SerializeObject(reqDto)}"); ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse(); try { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; if (!World.IsStart) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = "WCS初始化中"; return agvFill; } var obj = World.GetSystemInstance().Invoke("输送机") as List; // 检测三个站台是否有货 obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList(); if (!obj.Any()) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = "无空轮"; return agvFill; } SqlSugarHelper.Do(db => { var res = WmsApi.GetTunnelEmptyConCount(); var agvStations = db.Default.Queryable().SplitTable(tabs => tabs.Take(2)) .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList(); obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList(); if (!obj.Any()) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = "无可用取货站点"; return; } foreach (var item in res.ResDataList) { var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString()) .Select(v => v.Targets).SelectMany(v => v) .Where(v => v.HasProtocol(typeof(IStation520))) .Where(v => v.Code is "1012" or "1014" or "1016") .FirstOrDefault(); item.Tunnel = station.ToInt(); } var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList(); var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code)); var id = db.Default.Queryable().SplitTable(v => v.Take(1)).Max(v => v.ID); var agv = new WCS_AgvTaskInfo() { ID = db.GetAGVTaskId(), TaskType = AGVTaskType.CallForMaterial, Status = AGVTaskStatus.NewBuild, Station = dev.Entity.Code, AddWho = "WCS" }; //创建对应的AGV任务 db.Default.Insertable(agv).SplitTable().ExecuteCommand(); var task = db.Default.Queryable().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务"); task.AgvTaskID = agv.ID; db.Default.Updateable(task).ExecuteCommand(); agvFill.LocCode = dev.Entity.Code; agvFill.SpoolType = "4"; agvFill.ResMsg = ""; agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess; }); } catch (Exception ex) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = ex.Message; } LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"返回参数{JsonConvert.SerializeObject(agvFill)}"); return agvFill; } } /// /// AGV执行回调 /// /// /// [HttpPost] public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto) { lock (LockHub.AgvCallbackLock) { LogHub.InterfacePublish(nameof(AgvCallback), $"传入参数--{JsonConvert.SerializeObject(reqDto)}"); var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" }; WCS_TaskInfo taskInfo = null; try { SqlSugarHelper.Do(db => { //跟据AGVid找到对应的AGV任务 var agvTask = db.Default.Queryable().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted); if (agvTask == null && reqDto.method != "applySecurity") { res.code = AgvResponseCode.Fail; res.message = "未找到对应的AGV任务"; return; } switch (reqDto.method) { //case "start": //表示请求巷道 // agvTask.Status = AGVTaskStatus.RequestOrPermission1; // break; //case "end": //表示请求巷道 // agvTask.Status = AGVTaskStatus.RequestOrPermission1; // break; case "applyContinue": //表示请求巷道 agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1; break; case "applySecurity": //表示请求放货或取货 if (reqDto.callCode is "1012" or "1014" or "1016") { agvTask = db.Default.Queryable().SplitTable(tabs => tabs.Take(2)) .First(v => v.Status == AGVTaskStatus.NewBuild && v.TaskType == AGVTaskType.CallForMaterial && v.Station == reqDto.callCode) ?? throw new Exception("为找找到对应AGV任务"); agvTask.AgvID = reqDto.taskCode; var obj = World.GetSystemInstance().Invoke("输送机") as List; var id = obj.FirstOrDefault(v => v.Entity.Code == agvTask.Station).Data.TaskNumber; taskInfo = db.Default.Queryable().First(v => v.ID == id) ?? throw new Exception("为找找到对应WCS任务"); taskInfo.AgvTaskID = agvTask.ID; taskInfo.Status = Entity.TaskStatus.AGVExecution; db.Default.Updateable(taskInfo).ExecuteCommand(); taskInfo.AddWCS_TASK_DTL(db, agvTask.Station, "agv执行中"); } if (agvTask == null) { res.code = AgvResponseCode.Fail; res.message = "未找到对应的AGV任务"; return; } agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission2; break; case "hjend_2": //补空任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "endhjBM": //取满任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "end": //二楼出满任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "tcEnd": //机台补空任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "exc_end": //异常信息上抛-值不匹配 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "outbin": //小车退出取货位 agvTask.AgvStatus = AGVTaskStatus.Complete3; break; case "cancel": //取消任务 agvTask.AgvStatus = AGVTaskStatus.Cancel; break; default: break; } db.Default.Updateable(agvTask).SplitTable().ExecuteCommand(); res.code = AgvResponseCode.Success; res.message = "成功"; }); } catch (Exception ex) { res.code = AgvResponseCode.Error; res.message = ex.Message; } LogHub.InterfacePublish(nameof(AgvCallback), $"返回结果--{JsonConvert.SerializeObject(res)}"); return res; } } } /// /// AGV相关接口控制器 /// [ApiController] [Route("api/[controller]/[action]")] public class AgvController : ControllerBase { /// /// AGV任务下发测试 /// /// 任务类型 /// RFID /// 目标位置 /// [HttpPost] public string AgvDebug(int type, string code, string pos) { try { switch (type) { case 1: AgvApi.机台补空(pos, code, "1"); break; case 2: //AgvApi.机台补满(); break; case 3: AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1"); break; default: break; } return "成功"; } catch (Exception ex) { return $"Error-----" + $"{ex.Message}------" + $"{ex.StackTrace}"; } } /// /// 背负式AGV请求出库任务 /// /// 请求参数 /// [HttpPost] public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto) { var key = $"WCS:Lock:AGV:{nameof(ApplyEmptySpool)}"; ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse(); try { if (RedisHub.Default.Get(key) != null) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = $"[{nameof(ApplyEmptySpool)}]--触发并发管控"; } else { RedisHub.Default.Set(key, nameof(ApplyEmptySpool)); LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"传入参数--{JsonConvert.SerializeObject(reqDto)}"); try { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; if (!World.IsStart) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = "WCS初始化中"; return agvFill; } var obj = World.GetSystemInstance().Invoke("输送机") as List; // 检测三个站台是否有货 obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList(); if (!obj.Any()) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = "无空轮"; return agvFill; } SqlSugarHelper.Do(db => { var res = WmsApi.GetTunnelEmptyConCount(); var agvStations = db.Default.Queryable().SplitTable(tabs => tabs.Take(2)) .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList(); obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList(); if (!obj.Any()) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = "无可用取货站点"; return; } foreach (var item in res.ResDataList) { var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString()) .Select(v => v.Targets).SelectMany(v => v) .Where(v => v.HasProtocol(typeof(IStation520))) .Where(v => v.Code is "1012" or "1014" or "1016") .FirstOrDefault(); item.Tunnel = station.ToInt(); } var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList(); var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code)); var task = db.Default.Queryable().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务"); var id = db.GetAGVTaskId(); var agv = new WCS_AgvTaskInfo() { ID = id, AgvID = $"HJBK{id}{task.ID}", TaskType = AGVTaskType.CallForMaterial, Status = AGVTaskStatus.NewBuild, Station = dev.Entity.Code, AddWho = "WCS" }; //创建对应的AGV任务 db.Default.Insertable(agv).SplitTable().ExecuteCommand(); task.AgvTaskID = agv.ID; task.Status = Entity.TaskStatus.AGVExecution; db.Default.Updateable(task).ExecuteCommand(); task.AddWCS_TASK_DTL(db, dev.Entity.Code, "AGV", "agv执行中"); agvFill.LocCode = dev.Entity.Code; agvFill.SpoolType = "4"; agvFill.ResMsg = ""; agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess; agvFill.TaskCode = agv.AgvID; }); } catch (Exception ex) { agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr; agvFill.ResMsg = ex.Message; } LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"返回参数{JsonConvert.SerializeObject(agvFill)}"); } } finally { RedisHub.Default.Del(key); } return agvFill; } /// /// AGV执行回调 /// /// /// [HttpPost] public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto) { var key = $"WCS:Lock:AGV:{nameof(AgvCallback)}"; var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" }; try { if (RedisHub.Default.Get(key) != null) { res.code = AgvResponseCode.Error; res.message = $"[{nameof(AgvCallback)}]--触发并发管控"; } else { RedisHub.Default.Set(key, nameof(AgvCallback)); WCS_TaskInfo taskInfo = null; try { SqlSugarHelper.Do(db => { //跟据AGVid找到对应的AGV任务 var agvTask = db.Default.Queryable().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted); if (agvTask == null) { res.code = AgvResponseCode.Fail; res.message = "未找到对应的AGV任务"; } else { switch (reqDto.method) { //case "start": //表示请求巷道 // agvTask.Status = AGVTaskStatus.RequestOrPermission1; // break; //case "end": //表示请求巷道 // agvTask.Status = AGVTaskStatus.RequestOrPermission1; // break; case "applyContinue": //表示请求巷道 agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1; break; case "applySecurity": //表示请求放货或取货 agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission2; break; case "hjend_2": //补空任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "endhjBM": //取满任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "end": //二楼出满任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "tcEnd": //机台补空任务完成 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "exc_end": //异常信息上抛-值不匹配 agvTask.AgvStatus = AGVTaskStatus.MissionCompleted; break; case "outbin": //小车退出取货位 agvTask.AgvStatus = AGVTaskStatus.Complete3; break; case "cancel": //取消任务 //agvTask.AgvStatus = AGVTaskStatus.Cancel; break; default: break; } db.Default.Updateable(agvTask).SplitTable().ExecuteCommand(); res.code = AgvResponseCode.Success; res.message = "成功"; } }); } catch (Exception ex) { res.code = AgvResponseCode.Error; res.message = ex.Message; } } } finally { RedisHub.Default.Del(key); } return res; } } }