AgvController.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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. static object lockerApplyEmptySpool = new object();
  27. static object lockerAgvCallback = new object();
  28. /// <summary>
  29. /// AGV任务下发测试
  30. /// </summary>
  31. /// <param name="type">任务类型</param>
  32. /// <param name="code">RFID</param>
  33. /// <param name="pos">目标位置</param>
  34. /// <returns></returns>
  35. [HttpPost]
  36. public string AgvDebug(int type, string code, string pos)
  37. {
  38. try
  39. {
  40. switch (type)
  41. {
  42. case 1:
  43. AgvApi.机台补空(pos, code, "1");
  44. break;
  45. case 2:
  46. //AgvApi.机台补满();
  47. break;
  48. case 3:
  49. AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1");
  50. break;
  51. default:
  52. break;
  53. }
  54. return "成功";
  55. }
  56. catch (Exception ex)
  57. {
  58. return $"Error-----" +
  59. $"{ex.Message}------" +
  60. $"{ex.StackTrace}";
  61. }
  62. }
  63. /// <summary>
  64. /// 背负式AGV请求出库任务
  65. /// </summary>
  66. /// <param name="reqDto">请求参数</param>
  67. /// <returns></returns>
  68. [HttpPost]
  69. public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto)
  70. {
  71. return new ApplyEmptySpoolResponse()
  72. {
  73. ResCode = Models.WMS.Response.ResponseStatusCodeEnum.AccountError,
  74. ResMsg = "接口已禁用,已经改为主动下发方式"
  75. };
  76. var key = $"WCS:Lock:AGV:{nameof(ApplyEmptySpool)}";
  77. ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();
  78. lock (lockerApplyEmptySpool)
  79. {
  80. LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"传入参数--{JsonConvert.SerializeObject(reqDto)}");
  81. if (RedisHub.Default.Get(key) != null)
  82. {
  83. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  84. agvFill.ResMsg = $"[{nameof(ApplyEmptySpool)}]--触发并发管控";
  85. return agvFill;
  86. }
  87. RedisHub.Default.Set(key, nameof(ApplyEmptySpool), 60);
  88. }
  89. try
  90. {
  91. try
  92. {
  93. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  94. if (!World.IsStart)
  95. {
  96. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  97. agvFill.ResMsg = "WCS初始化中";
  98. return agvFill;
  99. }
  100. var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
  101. // 检测三个站台是否有货
  102. obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList();
  103. if (!obj.Any())
  104. {
  105. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  106. agvFill.ResMsg = "无空轮";
  107. return agvFill;
  108. }
  109. SqlSugarHelper.Do(db =>
  110. {
  111. //查询此请求是否已经有过任务
  112. var existtask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2)).Where(v => v.EditWho == reqDto.Reqid ).Select(v => v).ToList();
  113. if (existtask != null && existtask.Any())
  114. {
  115. var temp = existtask.ToList().First();
  116. agvFill.LocCode = temp.Station;
  117. agvFill.SpoolType = "4";
  118. agvFill.ResMsg = "";
  119. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
  120. agvFill.TaskCode = temp.AgvID;
  121. }
  122. else
  123. {
  124. var res = WmsApi.GetTunnelEmptyConCount();
  125. var agvStations = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
  126. .Where(v => v.Status < AGVTaskStatus.Complete3 && (v.TaskType == AGVTaskType.CallForMaterial || (v.TaskType == AGVTaskType.CallMaterial && v.WorkShop == 111 && v.Status >= AGVTaskStatus.Confirm))).Select(v => v.Station).ToList();
  127. obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList();
  128. if (!obj.Any())
  129. {
  130. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  131. agvFill.ResMsg = "无可用取货站点";
  132. return;
  133. }
  134. foreach (var item in res.ResDataList)
  135. {
  136. var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
  137. .Select(v => v.Targets).SelectMany(v => v)
  138. .Where(v => v.HasProtocol(typeof(IStation520)))
  139. .Where(v => v.Code is "1012" or "1014" or "1016")
  140. .FirstOrDefault();
  141. item.Tunnel = station.ToInt();
  142. }
  143. var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
  144. var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code));
  145. var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务");
  146. if (task.BusType != "一楼立库出空轮" && task.TaskGroupKey != "1")
  147. {
  148. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  149. agvFill.ResMsg = $"{dev.Entity.Code}不可用";
  150. return;
  151. }
  152. var id = db.GetAGVTaskId();
  153. var agv = new WCS_AgvTaskInfo()
  154. {
  155. ID = id,
  156. AgvID = $"HJBK{id}{task.ID}",
  157. TaskType = AGVTaskType.CallForMaterial,
  158. Status = AGVTaskStatus.NewBuild,
  159. Station = dev.Entity.Code,
  160. AddWho = "WCS",
  161. EditWho = reqDto.Reqid//请求id暂存
  162. };
  163. //创建对应的AGV任务
  164. db.Default.Insertable(agv).SplitTable().ExecuteCommand();
  165. task.AgvTaskID = agv.ID;
  166. task.Status = Entity.TaskStatus.AGVExecution;
  167. db.Default.Updateable(task).ExecuteCommand();
  168. task.AddWCS_TASK_DTL(db, dev.Entity.Code, "AGV", "agv执行中");
  169. agvFill.LocCode = dev.Entity.Code;
  170. agvFill.SpoolType = "4";
  171. agvFill.ResMsg = "";
  172. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
  173. agvFill.TaskCode = agv.AgvID;
  174. }
  175. });
  176. }
  177. catch (Exception ex)
  178. {
  179. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  180. agvFill.ResMsg = ex.Message;
  181. }
  182. LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"返回参数{JsonConvert.SerializeObject(agvFill)}");
  183. }
  184. finally
  185. {
  186. RedisHub.Default.Del(key);
  187. }
  188. return agvFill;
  189. }
  190. /// <summary>
  191. /// AGV执行回调
  192. /// </summary>
  193. /// <param name="reqDto"></param>
  194. /// <returns></returns>
  195. [HttpPost]
  196. public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto)
  197. {
  198. return new AgvCallbackResponse()
  199. {
  200. code = AgvResponseCode.Error,
  201. message = "接口已禁用"
  202. };
  203. var key = $"WCS:Lock:AGV:{nameof(AgvCallback)+ reqDto.taskCode}";
  204. var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" };
  205. lock (lockerAgvCallback)
  206. {
  207. if (RedisHub.Default.Get(key) != null)
  208. {
  209. res.code = AgvResponseCode.Error;
  210. res.message = $"[{nameof(AgvCallback) + reqDto.taskCode}]--触发并发管控";
  211. return res;
  212. }
  213. RedisHub.Default.Set(key, nameof(AgvCallback), 60);
  214. }
  215. try
  216. {
  217. //if (RedisHub.Default.Get(key) != null)
  218. //{
  219. // res.code = AgvResponseCode.Error;
  220. // res.message = $"[{nameof(AgvCallback)}]--触发并发管控";
  221. //}
  222. //else
  223. //{
  224. //RedisHub.Default.Set(key, nameof(AgvCallback));
  225. WCS_TaskInfo taskInfo = null;
  226. try
  227. {
  228. SqlSugarHelper.Do(db =>
  229. {
  230. //跟据AGVid找到对应的AGV任务
  231. var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted).SplitTable(tabs => tabs.Take(2)).First();
  232. if (agvTask == null)
  233. {
  234. res.code = AgvResponseCode.Fail;
  235. res.message = "未找到对应的AGV任务";
  236. }
  237. else
  238. {
  239. switch (reqDto.method)
  240. {
  241. //case "start": //表示请求巷道
  242. // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  243. // break;
  244. //case "end": //表示请求巷道
  245. // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  246. // break;
  247. case "applyContinue": //表示手动调用请求巷道
  248. agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1;
  249. break;
  250. case "applyContinueManaual": //表示请求巷道
  251. agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1;
  252. agvTask.Status = AGVTaskStatus.Confirm;
  253. break;
  254. case "applySecurity": //表示请求放货或取货
  255. agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission2;
  256. break;
  257. case "end_1": //一楼出满任务完成
  258. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  259. break;
  260. case "hjend_2": //补空任务完成
  261. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  262. break;
  263. case "endhjBM": //取满任务完成
  264. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  265. break;
  266. case "end": //二楼出满任务完成
  267. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  268. break;
  269. case "tcEnd": //机台补空任务完成
  270. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  271. break;
  272. case "exc_end": //异常信息上抛-值不匹配
  273. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  274. break;
  275. case "outbin": //小车退出取货位
  276. agvTask.AgvStatus = AGVTaskStatus.Complete3;
  277. break;
  278. case "cancel": //取消任务
  279. //agvTask.AgvStatus = AGVTaskStatus.Cancel;
  280. break;
  281. default:
  282. break;
  283. }
  284. db.Default.Updateable(agvTask).SplitTable(x => x.Take(2)).ExecuteCommand();
  285. res.code = AgvResponseCode.Success;
  286. res.message = "成功";
  287. }
  288. });
  289. }
  290. catch (Exception ex)
  291. {
  292. res.code = AgvResponseCode.Error;
  293. res.message = ex.Message;
  294. }
  295. //}
  296. }
  297. finally
  298. {
  299. RedisHub.Default.Del(key);
  300. }
  301. return res;
  302. }
  303. }
  304. }