AgvController.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using Microsoft.AspNetCore.Mvc;
  2. using NetTaste;
  3. using Newtonsoft.Json;
  4. using PlcSiemens.Core.Extension;
  5. using ServiceCenter.Attributes;
  6. using ServiceCenter.Logs;
  7. using ServiceCenter.Redis;
  8. using ServiceCenter.SqlSugars;
  9. using WCS.Core;
  10. using WCS.Entity;
  11. using WCS.Entity.Protocol.Station;
  12. using WCS.WorkEngineering.Extensions;
  13. using WCS.WorkEngineering.Systems;
  14. using WCS.WorkEngineering.WebApi.Models.AGV;
  15. using WCS.WorkEngineering.WebApi.Models.AGV.Request;
  16. using WCS.WorkEngineering.WebApi.Models.AGV.Response;
  17. namespace WCS.WorkEngineering.WebApi.Controllers
  18. {
  19. /// <summary>
  20. /// AGV相关接口控制器
  21. /// </summary>
  22. [ApiController]
  23. [Route("api/[controller]/[action]")]
  24. public class AgvController : ControllerBase
  25. {
  26. /// <summary>
  27. /// AGV任务下发测试
  28. /// </summary>
  29. /// <param name="type">任务类型</param>
  30. /// <param name="code">RFID</param>
  31. /// <param name="pos">目标位置</param>
  32. /// <returns></returns>
  33. [HttpPost]
  34. public string AgvDebug(int type, string code, string pos)
  35. {
  36. try
  37. {
  38. switch (type)
  39. {
  40. case 1:
  41. AgvApi.机台补空(pos, code, "1");
  42. break;
  43. case 2:
  44. //AgvApi.机台补满();
  45. break;
  46. case 3:
  47. AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1");
  48. break;
  49. default:
  50. break;
  51. }
  52. return "成功";
  53. }
  54. catch (Exception ex)
  55. {
  56. return $"Error-----" +
  57. $"{ex.Message}------" +
  58. $"{ex.StackTrace}";
  59. }
  60. }
  61. /// <summary>
  62. /// 背负式AGV请求出库任务
  63. /// </summary>
  64. /// <param name="reqDto">请求参数</param>
  65. /// <returns></returns>
  66. [HttpPost, Log("背负式AGV请求出库任务")]
  67. public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto)
  68. {
  69. var key = $"WCS:Lock:AGV:{nameof(ApplyEmptySpool)}";
  70. ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();
  71. try
  72. {
  73. if (RedisHub.Default.Get(key) != null)
  74. {
  75. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  76. agvFill.ResMsg = $"[{nameof(ApplyEmptySpool)}]--触发并发管控";
  77. }
  78. else
  79. {
  80. RedisHub.Default.Set(key, nameof(ApplyEmptySpool));
  81. LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"传入参数--{JsonConvert.SerializeObject(reqDto)}");
  82. try
  83. {
  84. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  85. if (!World.IsStart)
  86. {
  87. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  88. agvFill.ResMsg = "WCS初始化中";
  89. return agvFill;
  90. }
  91. var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
  92. // 检测三个站台是否有货
  93. obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList();
  94. if (!obj.Any())
  95. {
  96. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  97. agvFill.ResMsg = "无空轮";
  98. return agvFill;
  99. }
  100. SqlSugarHelper.Do(db =>
  101. {
  102. var res = WmsApi.GetTunnelEmptyConCount();
  103. var agvStations = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
  104. .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList();
  105. obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList();
  106. if (!obj.Any())
  107. {
  108. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  109. agvFill.ResMsg = "无可用取货站点";
  110. return;
  111. }
  112. foreach (var item in res.ResDataList)
  113. {
  114. var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
  115. .Select(v => v.Targets).SelectMany(v => v)
  116. .Where(v => v.HasProtocol(typeof(IStation520)))
  117. .Where(v => v.Code is "1012" or "1014" or "1016")
  118. .FirstOrDefault();
  119. item.Tunnel = station.ToInt();
  120. }
  121. var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
  122. var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code));
  123. var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务");
  124. var id = db.GetAGVTaskId();
  125. var agv = new WCS_AgvTaskInfo()
  126. {
  127. ID = id,
  128. AgvID = $"HJBK{id}{task.ID}",
  129. TaskType = AGVTaskType.CallForMaterial,
  130. Status = AGVTaskStatus.NewBuild,
  131. Station = dev.Entity.Code,
  132. AddWho = "WCS"
  133. };
  134. //创建对应的AGV任务
  135. db.Default.Insertable(agv).SplitTable().ExecuteCommand();
  136. task.AgvTaskID = agv.ID;
  137. task.Status = Entity.TaskStatus.AGVExecution;
  138. db.Default.Updateable(task).ExecuteCommand();
  139. task.AddWCS_TASK_DTL(db, dev.Entity.Code, "AGV", "agv执行中");
  140. agvFill.LocCode = dev.Entity.Code;
  141. agvFill.SpoolType = "4";
  142. agvFill.ResMsg = "";
  143. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
  144. agvFill.TaskCode = agv.AgvID;
  145. });
  146. }
  147. catch (Exception ex)
  148. {
  149. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  150. agvFill.ResMsg = ex.Message;
  151. }
  152. LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"返回参数{JsonConvert.SerializeObject(agvFill)}");
  153. }
  154. }
  155. finally
  156. {
  157. RedisHub.Default.Del(key);
  158. }
  159. return agvFill;
  160. }
  161. /// <summary>
  162. /// AGV执行回调
  163. /// </summary>
  164. /// <param name="reqDto"></param>
  165. /// <returns></returns>
  166. [HttpPost, Log("AGV执行回调")]
  167. public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto)
  168. {
  169. var key = $"WCS:Lock:AGV:{nameof(AgvCallback)}";
  170. var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" };
  171. try
  172. {
  173. if (RedisHub.Default.Get(key) != null)
  174. {
  175. res.code = AgvResponseCode.Error;
  176. res.message = $"[{nameof(AgvCallback)}]--触发并发管控";
  177. }
  178. else
  179. {
  180. RedisHub.Default.Set(key, nameof(AgvCallback));
  181. WCS_TaskInfo taskInfo = null;
  182. try
  183. {
  184. SqlSugarHelper.Do(db =>
  185. {
  186. //跟据AGVid找到对应的AGV任务
  187. var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted);
  188. if (agvTask == null)
  189. {
  190. res.code = AgvResponseCode.Fail;
  191. res.message = "未找到对应的AGV任务";
  192. }
  193. else
  194. {
  195. switch (reqDto.method)
  196. {
  197. //case "start": //表示请求巷道
  198. // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  199. // break;
  200. //case "end": //表示请求巷道
  201. // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  202. // break;
  203. case "applyContinue": //表示请求巷道
  204. agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1;
  205. break;
  206. case "applySecurity": //表示请求放货或取货
  207. agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission2;
  208. break;
  209. case "hjend_2": //补空任务完成
  210. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  211. break;
  212. case "endhjBM": //取满任务完成
  213. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  214. break;
  215. case "end": //二楼出满任务完成
  216. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  217. break;
  218. case "tcEnd": //机台补空任务完成
  219. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  220. break;
  221. case "exc_end": //异常信息上抛-值不匹配
  222. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  223. break;
  224. case "outbin": //小车退出取货位
  225. agvTask.AgvStatus = AGVTaskStatus.Complete3;
  226. break;
  227. case "cancel": //取消任务
  228. //agvTask.AgvStatus = AGVTaskStatus.Cancel;
  229. break;
  230. default:
  231. break;
  232. }
  233. db.Default.Updateable(agvTask).SplitTable().ExecuteCommand();
  234. res.code = AgvResponseCode.Success;
  235. res.message = "成功";
  236. }
  237. });
  238. }
  239. catch (Exception ex)
  240. {
  241. res.code = AgvResponseCode.Error;
  242. res.message = ex.Message;
  243. }
  244. }
  245. }
  246. finally
  247. {
  248. RedisHub.Default.Del(key);
  249. }
  250. return res;
  251. }
  252. }
  253. }