AgvController.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. using Microsoft.AspNetCore.Mvc;
  2. using Newtonsoft.Json;
  3. using PlcSiemens.Core.Extension;
  4. using ServiceCenter.Logs;
  5. using ServiceCenter.Redis;
  6. using ServiceCenter.SqlSugars;
  7. using WCS.Core;
  8. using WCS.Entity;
  9. using WCS.Entity.Protocol.Station;
  10. using WCS.WorkEngineering.Extensions;
  11. using WCS.WorkEngineering.Systems;
  12. using WCS.WorkEngineering.WebApi.Models.AGV;
  13. using WCS.WorkEngineering.WebApi.Models.AGV.Request;
  14. using WCS.WorkEngineering.WebApi.Models.AGV.Response;
  15. namespace WCS.WorkEngineering.WebApi.Controllers
  16. {
  17. /// <summary>
  18. /// AGV相关接口控制器
  19. /// </summary>
  20. [ApiController]
  21. [Route("api/[controller]/[action]")]
  22. public class AgvController : ControllerBase
  23. {
  24. /// <summary>
  25. /// AGV任务下发测试
  26. /// </summary>
  27. /// <param name="type">任务类型</param>
  28. /// <param name="code">RFID</param>
  29. /// <param name="pos">目标位置</param>
  30. /// <returns></returns>
  31. [HttpPost]
  32. public string AgvDebug(int type, string code, string pos)
  33. {
  34. try
  35. {
  36. switch (type)
  37. {
  38. case 1:
  39. AgvApi.机台补空(pos, code, "1");
  40. break;
  41. case 2:
  42. //AgvApi.机台补满();
  43. break;
  44. case 3:
  45. //AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1");
  46. break;
  47. default:
  48. break;
  49. }
  50. return "成功";
  51. }
  52. catch (Exception ex)
  53. {
  54. return $"Error-----" +
  55. $"{ex.Message}------" +
  56. $"{ex.StackTrace}";
  57. }
  58. }
  59. /// <summary>
  60. /// 背负式agv请求出库任务
  61. /// </summary>
  62. /// <param name="reqDto">请求参数</param>
  63. /// <returns></returns>
  64. [HttpPost]
  65. public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto)
  66. {
  67. lock (LockHub.ApplyEmptySpoolLock)
  68. {
  69. LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"传入参数--{JsonConvert.SerializeObject(reqDto)}");
  70. ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();
  71. try
  72. {
  73. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  74. if (!World.IsStart)
  75. {
  76. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  77. agvFill.ResMsg = "WCS初始化中";
  78. return agvFill;
  79. }
  80. var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
  81. // 检测三个站台是否有货
  82. obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList();
  83. if (!obj.Any())
  84. {
  85. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  86. agvFill.ResMsg = "无空轮";
  87. return agvFill;
  88. }
  89. SqlSugarHelper.Do(db =>
  90. {
  91. var res = WmsApi.GetTunnelEmptyConCount();
  92. var agvStations = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
  93. .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList();
  94. obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList();
  95. if (!obj.Any())
  96. {
  97. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  98. agvFill.ResMsg = "无可用取货站点";
  99. return;
  100. }
  101. foreach (var item in res.ResDataList)
  102. {
  103. var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
  104. .Select(v => v.Targets).SelectMany(v => v)
  105. .Where(v => v.HasProtocol(typeof(IStation520)))
  106. .Where(v => v.Code is "1012" or "1014" or "1016")
  107. .FirstOrDefault();
  108. item.Tunnel = station.ToInt();
  109. }
  110. var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
  111. var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code));
  112. var id = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(v => v.Take(1)).Max(v => v.ID);
  113. var agv = new WCS_AgvTaskInfo()
  114. {
  115. ID = db.GetAGVTaskId(),
  116. TaskType = AGVTaskType.CallForMaterial,
  117. Status = AGVTaskStatus.NewBuild,
  118. Station = dev.Entity.Code,
  119. AddWho = "WCS"
  120. };
  121. //创建对应的AGV任务
  122. db.Default.Insertable(agv).SplitTable().ExecuteCommand();
  123. var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务");
  124. task.AgvTaskID = agv.ID;
  125. db.Default.Updateable(task).ExecuteCommand();
  126. agvFill.LocCode = dev.Entity.Code;
  127. agvFill.SpoolType = "4";
  128. agvFill.ResMsg = "";
  129. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
  130. });
  131. }
  132. catch (Exception ex)
  133. {
  134. agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  135. agvFill.ResMsg = ex.Message;
  136. }
  137. LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"返回参数{JsonConvert.SerializeObject(agvFill)}");
  138. return agvFill;
  139. }
  140. }
  141. /// <summary>
  142. /// AGV执行回调
  143. /// </summary>
  144. /// <param name="reqDto"></param>
  145. /// <returns></returns>
  146. [HttpPost]
  147. public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto)
  148. {
  149. lock (LockHub.AgvCallbackLock)
  150. {
  151. LogHub.InterfacePublish(nameof(AgvCallback), $"传入参数--{JsonConvert.SerializeObject(reqDto)}");
  152. var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" };
  153. WCS_TaskInfo taskInfo = null;
  154. try
  155. {
  156. SqlSugarHelper.Do(db =>
  157. {
  158. //跟据AGVid找到对应的AGV任务
  159. var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted);
  160. if (agvTask == null && reqDto.method != "applySecurity")
  161. {
  162. res.code = AgvResponseCode.Fail;
  163. res.message = "未找到对应的AGV任务";
  164. return;
  165. }
  166. switch (reqDto.method)
  167. {
  168. //case "start": //表示请求巷道
  169. // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  170. // break;
  171. //case "end": //表示请求巷道
  172. // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  173. // break;
  174. case "applyContinue": //表示请求巷道
  175. agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1;
  176. break;
  177. case "applySecurity": //表示请求放货或取货
  178. if (reqDto.callCode is "1012" or "1014" or "1016")
  179. {
  180. agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
  181. .First(v => v.Status == AGVTaskStatus.NewBuild && v.TaskType == AGVTaskType.CallForMaterial && v.Station == reqDto.callCode)
  182. ?? throw new Exception("为找找到对应AGV任务");
  183. agvTask.AgvID = reqDto.taskCode;
  184. var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
  185. var id = obj.FirstOrDefault(v => v.Entity.Code == agvTask.Station).Data.TaskNumber;
  186. taskInfo = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == id) ?? throw new Exception("为找找到对应WCS任务");
  187. taskInfo.AgvTaskID = agvTask.ID;
  188. taskInfo.Status = Entity.TaskStatus.AGVExecution;
  189. db.Default.Updateable(taskInfo).ExecuteCommand();
  190. taskInfo.AddWCS_TASK_DTL(db, agvTask.Station, "agv执行中");
  191. }
  192. if (agvTask == null)
  193. {
  194. res.code = AgvResponseCode.Fail;
  195. res.message = "未找到对应的AGV任务";
  196. return;
  197. }
  198. agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission2;
  199. break;
  200. case "hjend_2": //补空任务完成
  201. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  202. break;
  203. case "endhjBM": //取满任务完成
  204. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  205. break;
  206. case "end": //二楼出满任务完成
  207. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  208. break;
  209. case "tcEnd": //机台补空任务完成
  210. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  211. break;
  212. case "exc_end": //异常信息上抛-值不匹配
  213. agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  214. break;
  215. case "outbin": //小车退出取货位
  216. agvTask.AgvStatus = AGVTaskStatus.Complete3;
  217. break;
  218. case "cancel": //取消任务
  219. agvTask.AgvStatus = AGVTaskStatus.Cancel;
  220. break;
  221. default:
  222. break;
  223. }
  224. db.Default.Updateable(agvTask).SplitTable().ExecuteCommand();
  225. res.code = AgvResponseCode.Success;
  226. res.message = "成功";
  227. });
  228. }
  229. catch (Exception ex)
  230. {
  231. res.code = AgvResponseCode.Error;
  232. res.message = ex.Message;
  233. }
  234. LogHub.InterfacePublish(nameof(AgvCallback), $"返回结果--{JsonConvert.SerializeObject(res)}");
  235. return res;
  236. }
  237. }
  238. }
  239. /// <summary>
  240. /// AGV相关接口控制器
  241. /// </summary>
  242. //[ApiController]
  243. //[Route("api/[controller]/[action]")]
  244. //public class AgvController : ControllerBase
  245. //{
  246. // /// <summary>
  247. // /// AGV任务下发测试
  248. // /// </summary>
  249. // /// <param name="type">任务类型</param>
  250. // /// <param name="code">RFID</param>
  251. // /// <param name="pos">目标位置</param>
  252. // /// <returns></returns>
  253. // [HttpPost]
  254. // public string AgvDebug(int type, string code, string pos)
  255. // {
  256. // try
  257. // {
  258. // switch (type)
  259. // {
  260. // case 1:
  261. // AgvApi.机台补空(pos, code, "1");
  262. // break;
  263. // case 2:
  264. // //AgvApi.机台补满();
  265. // break;
  266. // case 3:
  267. // AgvApi.满轮入库(code, pos, Guid.NewGuid().ToString().Replace("-", ""), "1");
  268. // break;
  269. // default:
  270. // break;
  271. // }
  272. // return "成功";
  273. // }
  274. // catch (Exception ex)
  275. // {
  276. // return $"Error-----" +
  277. // $"{ex.Message}------" +
  278. // $"{ex.StackTrace}";
  279. // }
  280. // }
  281. // /// <summary>
  282. // /// 背负式AGV请求出库任务
  283. // /// </summary>
  284. // /// <param name="reqDto">请求参数</param>
  285. // /// <returns></returns>
  286. // [HttpPost]
  287. // public ApplyEmptySpoolResponse ApplyEmptySpool([FromBody] AgvFillEmptySpaceRequest reqDto)
  288. // {
  289. // var key = $"WCS:Lock:AGV:{nameof(ApplyEmptySpool)}";
  290. // ApplyEmptySpoolResponse agvFill = new ApplyEmptySpoolResponse();
  291. // try
  292. // {
  293. // if (RedisHub.Default.Get(key) != null)
  294. // {
  295. // agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  296. // agvFill.ResMsg = $"[{nameof(ApplyEmptySpool)}]--触发并发管控";
  297. // }
  298. // else
  299. // {
  300. // RedisHub.Default.Set(key, nameof(ApplyEmptySpool));
  301. // LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"传入参数--{JsonConvert.SerializeObject(reqDto)}");
  302. // try
  303. // {
  304. // agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  305. // if (!World.IsStart)
  306. // {
  307. // agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  308. // agvFill.ResMsg = "WCS初始化中";
  309. // return agvFill;
  310. // }
  311. // var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke("输送机") as List<Station>;
  312. // // 检测三个站台是否有货
  313. // obj = obj.Where(v => v.Entity.Code is "1012" or "1014" or "1016").Where(v => v.Data3.Status.HasFlag(StatusEunm.PH_Status)).ToList();
  314. // if (!obj.Any())
  315. // {
  316. // agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  317. // agvFill.ResMsg = "无空轮";
  318. // return agvFill;
  319. // }
  320. // SqlSugarHelper.Do(db =>
  321. // {
  322. // var res = WmsApi.GetTunnelEmptyConCount();
  323. // var agvStations = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2))
  324. // .Where(v => v.Status < AGVTaskStatus.Complete3 && v.TaskType == AGVTaskType.CallForMaterial).Select(v => v.Station).ToList();
  325. // obj = obj.Where(v => !agvStations.Contains(v.Entity.Code)).ToList();
  326. // if (!obj.Any())
  327. // {
  328. // agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  329. // agvFill.ResMsg = "无可用取货站点";
  330. // return;
  331. // }
  332. // foreach (var item in res.ResDataList)
  333. // {
  334. // var station = Device.All.Where(v => v.Code == "TY" + item.Tunnel.ToString())
  335. // .Select(v => v.Targets).SelectMany(v => v)
  336. // .Where(v => v.HasProtocol(typeof(IStation520)))
  337. // .Where(v => v.Code is "1012" or "1014" or "1016")
  338. // .FirstOrDefault();
  339. // item.Tunnel = station.ToInt();
  340. // }
  341. // var stationNo = res.ResDataList.OrderBy(v => v.Count).Select(v => v.Tunnel.ToString()).ToList();
  342. // var dev = obj.MinBy(v => stationNo.IndexOf(v.Entity.Code));
  343. // var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.ID == dev.Data.TaskNumber) ?? throw new Exception("无有效任务");
  344. // var id = db.GetAGVTaskId();
  345. // var agv = new WCS_AgvTaskInfo()
  346. // {
  347. // ID = id,
  348. // AgvID = $"HJBK{id}{task.ID}",
  349. // TaskType = AGVTaskType.CallForMaterial,
  350. // Status = AGVTaskStatus.NewBuild,
  351. // Station = dev.Entity.Code,
  352. // AddWho = "WCS"
  353. // };
  354. // //创建对应的AGV任务
  355. // db.Default.Insertable(agv).SplitTable().ExecuteCommand();
  356. // task.AgvTaskID = agv.ID;
  357. // task.Status = Entity.TaskStatus.AGVExecution;
  358. // db.Default.Updateable(task).ExecuteCommand();
  359. // task.AddWCS_TASK_DTL(db, dev.Entity.Code, "AGV", "agv执行中");
  360. // agvFill.LocCode = dev.Entity.Code;
  361. // agvFill.SpoolType = "4";
  362. // agvFill.ResMsg = "";
  363. // agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.Sucess;
  364. // agvFill.TaskCode = agv.AgvID;
  365. // });
  366. // }
  367. // catch (Exception ex)
  368. // {
  369. // agvFill.ResCode = Models.WMS.Response.ResponseStatusCodeEnum.DataSaveErr;
  370. // agvFill.ResMsg = ex.Message;
  371. // }
  372. // LogHub.InterfacePublish(nameof(ApplyEmptySpool), $"返回参数{JsonConvert.SerializeObject(agvFill)}");
  373. // }
  374. // }
  375. // finally
  376. // {
  377. // RedisHub.Default.Del(key);
  378. // }
  379. // return agvFill;
  380. // }
  381. // /// <summary>
  382. // /// AGV执行回调
  383. // /// </summary>
  384. // /// <param name="reqDto"></param>
  385. // /// <returns></returns>
  386. // [HttpPost]
  387. // public AgvCallbackResponse AgvCallback([FromBody] AgvCallbackRequest reqDto)
  388. // {
  389. // var key = $"WCS:Lock:AGV:{nameof(AgvCallback)}";
  390. // var res = new AgvCallbackResponse() { code = AgvResponseCode.Fail, message = "失败" };
  391. // try
  392. // {
  393. // if (RedisHub.Default.Get(key) != null)
  394. // {
  395. // res.code = AgvResponseCode.Error;
  396. // res.message = $"[{nameof(AgvCallback)}]--触发并发管控";
  397. // }
  398. // else
  399. // {
  400. // RedisHub.Default.Set(key, nameof(AgvCallback));
  401. // WCS_TaskInfo taskInfo = null;
  402. // try
  403. // {
  404. // SqlSugarHelper.Do(db =>
  405. // {
  406. // //跟据AGVid找到对应的AGV任务
  407. // var agvTask = db.Default.Queryable<WCS_AgvTaskInfo>().SplitTable(tabs => tabs.Take(2)).First(v => v.AgvID == reqDto.taskCode && v.Status < AGVTaskStatus.MissionCompleted);
  408. // if (agvTask == null)
  409. // {
  410. // res.code = AgvResponseCode.Fail;
  411. // res.message = "未找到对应的AGV任务";
  412. // }
  413. // else
  414. // {
  415. // switch (reqDto.method)
  416. // {
  417. // //case "start": //表示请求巷道
  418. // // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  419. // // break;
  420. // //case "end": //表示请求巷道
  421. // // agvTask.Status = AGVTaskStatus.RequestOrPermission1;
  422. // // break;
  423. // case "applyContinue": //表示请求巷道
  424. // agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission1;
  425. // break;
  426. // case "applySecurity": //表示请求放货或取货
  427. // agvTask.AgvStatus = AGVTaskStatus.RequestOrPermission2;
  428. // break;
  429. // case "hjend_2": //补空任务完成
  430. // agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  431. // break;
  432. // case "endhjBM": //取满任务完成
  433. // agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  434. // break;
  435. // case "end": //二楼出满任务完成
  436. // agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  437. // break;
  438. // case "tcEnd": //机台补空任务完成
  439. // agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  440. // break;
  441. // case "exc_end": //异常信息上抛-值不匹配
  442. // agvTask.AgvStatus = AGVTaskStatus.MissionCompleted;
  443. // break;
  444. // case "outbin": //小车退出取货位
  445. // agvTask.AgvStatus = AGVTaskStatus.Complete3;
  446. // break;
  447. // case "cancel": //取消任务
  448. // //agvTask.AgvStatus = AGVTaskStatus.Cancel;
  449. // break;
  450. // default:
  451. // break;
  452. // }
  453. // db.Default.Updateable(agvTask).SplitTable().ExecuteCommand();
  454. // res.code = AgvResponseCode.Success;
  455. // res.message = "成功";
  456. // }
  457. // });
  458. // }
  459. // catch (Exception ex)
  460. // {
  461. // res.code = AgvResponseCode.Error;
  462. // res.message = ex.Message;
  463. // }
  464. // }
  465. // }
  466. // finally
  467. // {
  468. // RedisHub.Default.Del(key);
  469. // }
  470. // return res;
  471. // }
  472. //}
  473. }