WcsController.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. using Microsoft.AspNetCore.Mvc;
  2. using Newtonsoft.Json;
  3. using ServiceCenter;
  4. using ServiceCenter.Attributes;
  5. using ServiceCenter.Extensions;
  6. using ServiceCenter.Logs;
  7. using ServiceCenter.Redis;
  8. using ServiceCenter.SqlSugars;
  9. using System.Net.NetworkInformation;
  10. using System.Text;
  11. using WCS.Core;
  12. using WCS.Entity;
  13. using WCS.Entity.Protocol.DataStructure;
  14. using WCS.Entity.Protocol.SRM;
  15. using WCS.WorkEngineering.Extensions;
  16. using WCS.WorkEngineering.Systems;
  17. using WCS.WorkEngineering.WebApi.Models.AGV.Response;
  18. using WCS.WorkEngineering.WebApi.Models.WCS.Request;
  19. using WCS.WorkEngineering.WebApi.Models.WCS.Response;
  20. using WCS.WorkEngineering.WebApi.Models.WMS.Response;
  21. namespace WCS.WorkEngineering.WebApi.Controllers
  22. {
  23. /// <summary>
  24. /// WCS相关接口控制器
  25. /// </summary>
  26. [ApiController]
  27. [Route("api/[controller]/[action]")]
  28. public class WcsController : ControllerBase, IDeviceWriter
  29. {
  30. /// <summary>
  31. /// 任务处理接口
  32. /// </summary>
  33. /// <param name="req"></param>
  34. /// <returns></returns>
  35. [HttpPost, Log("任务处理接口")]
  36. public SRes<HandleTaskResponse> HandleTask([FromBody] HandleTaskRequest req)
  37. {
  38. SRes<HandleTaskResponse> response = new SRes<HandleTaskResponse>() { ResCode = ResponseStatusCodeEnum.Sucess, ResDataList = new List<HandleTaskResponse>() };
  39. //取消任务
  40. if (req.Type == HandleTaskTypeEnum.取消任务)
  41. {
  42. SqlSugarHelper.Do(db =>
  43. {
  44. foreach (var item in req.TaskIds)
  45. {
  46. var task = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.ID == item).First();
  47. if (task != null)
  48. {
  49. //验证wms是否能取消
  50. SRes res = HandleTaskVerify(response, item, 106);
  51. if (res == null) continue;
  52. switch (task.Type)
  53. {
  54. case TaskType.SetPlate:
  55. if (task.Status != Entity.TaskStatus.WaitingToExecute)
  56. {
  57. response.ResDataList.Add(new HandleTaskResponse()
  58. {
  59. IsSuccess = false,
  60. TaskNo = item,
  61. Message = $"只能取消待执行状态组盘任务",
  62. });
  63. continue;
  64. }
  65. break;
  66. case TaskType.EnterDepot:
  67. if (task.Status > Entity.TaskStatus.WaitingToExecute && task.Status > Entity.TaskStatus.AGVExecution)
  68. {
  69. response.ResDataList.Add(new HandleTaskResponse()
  70. {
  71. IsSuccess = false,
  72. TaskNo = item,
  73. Message = $"只能取消待执行状态入库任务",
  74. });
  75. continue;
  76. }
  77. break;
  78. case TaskType.OutDepot:
  79. if (task.Status > Entity.TaskStatus.WaitingToExecute)
  80. {
  81. response.ResDataList.Add(new HandleTaskResponse()
  82. {
  83. IsSuccess = false,
  84. TaskNo = item,
  85. Message = $"只能取消待执行状态出库任务",
  86. });
  87. continue;
  88. }
  89. break;
  90. case TaskType.TransferDepot:
  91. if (task.Status > Entity.TaskStatus.WaitingToExecute)
  92. {
  93. response.ResDataList.Add(new HandleTaskResponse()
  94. {
  95. IsSuccess = false,
  96. TaskNo = item,
  97. Message = $"无法取消{task.Status.GetDescription()}的移库任务,只能取消新建/待执行的移库任务",
  98. });
  99. continue;
  100. }
  101. break;
  102. case TaskType.Delivery:
  103. break;
  104. case TaskType.EmptyInit:
  105. if (task.Status != Entity.TaskStatus.WaitingToExecute)
  106. {
  107. response.ResDataList.Add(new HandleTaskResponse()
  108. {
  109. IsSuccess = false,
  110. TaskNo = item,
  111. Message = $"只能取消待执行状态空轮初始化任务",
  112. });
  113. continue;
  114. }
  115. break;
  116. }
  117. SRes cancelRes = CarryTaskInfo(response, item, 106);
  118. if (cancelRes == null) continue;
  119. //找到对应的AGV任务
  120. var agv = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.ID == task.AgvTaskID).SplitTable(v => v.Take(2)).First();
  121. if (agv != null)
  122. {
  123. var cancelTaskUpdateRes = CancelAgvTask(response, item, agv.AgvID);
  124. if (cancelTaskUpdateRes != null) continue;
  125. agv.Status = AGVTaskStatus.Cancel;
  126. agv.AgvStatus = AGVTaskStatus.Cancel;
  127. db.Default.Updateable(agv).SplitTable().ExecuteCommand();
  128. }
  129. //更新任务状态
  130. task.Status = Entity.TaskStatus.Cancel;
  131. task.EedTime = DateTime.Now;
  132. task.EditWho = req.User;
  133. task.ManualRemarks = req.ManualRemarks;
  134. task.AddWCS_TASK_DTL(db, "未知", "任务取消");
  135. db.Default.Updateable(task).ExecuteCommand();
  136. task.CompleteOrCancelTasks(db);
  137. }
  138. else
  139. {
  140. response.ResDataList.Add(new HandleTaskResponse()
  141. {
  142. IsSuccess = false,
  143. TaskNo = item,
  144. Message = $"未找到对应任务{item}"
  145. });
  146. }
  147. }
  148. });
  149. }
  150. // 完成任务
  151. else if (req.Type == HandleTaskTypeEnum.完成任务)
  152. {
  153. SqlSugarHelper.Do(db =>
  154. {
  155. foreach (var item in req.TaskIds)
  156. {
  157. var task = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.ID == item).First();
  158. if (task != null)
  159. {
  160. if (task.Type == TaskType.OutDepot)
  161. {
  162. SRes res = HandleTaskVerify(response, item, 99);
  163. if (res == null) continue;
  164. switch (task.Type)
  165. {
  166. case TaskType.OutDepot:
  167. if (task.Status >= Entity.TaskStatus.Finish)
  168. {
  169. response.ResDataList.Add(new HandleTaskResponse()
  170. {
  171. IsSuccess = false,
  172. TaskNo = item,
  173. Message = $"只能完成未完成状态的任务",
  174. });
  175. continue;
  176. }
  177. break;
  178. }
  179. SRes cancelRes = CarryTaskInfo(response, item, 99);
  180. if (cancelRes == null) continue;
  181. //找到对应的AGV任务
  182. var agv = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.ID == task.AgvTaskID).SplitTable(v => v.Take(2)).First();
  183. if (agv != null)
  184. {
  185. var cancelTaskUpdateRes = CancelAgvTask(response, item, agv.AgvID);
  186. if (cancelTaskUpdateRes != null) continue;
  187. agv.Status = AGVTaskStatus.MissionCompleted;
  188. agv.AgvStatus = AGVTaskStatus.MissionCompleted;
  189. db.Default.Updateable(agv).SplitTable().ExecuteCommand();
  190. }
  191. //更新任务状态
  192. task.Status = Entity.TaskStatus.Finish;
  193. task.EedTime = DateTime.Now;
  194. task.EditWho = req.User;
  195. task.ManualRemarks = req.ManualRemarks;
  196. task.AddWCS_TASK_DTL(db, "未知", "任务完成");
  197. db.Default.Updateable(task).ExecuteCommand();
  198. task.CompleteOrCancelTasks(db);
  199. }
  200. else
  201. {
  202. response.ResDataList.Add(new HandleTaskResponse()
  203. {
  204. IsSuccess = false,
  205. TaskNo = item,
  206. Message = $"未找到对应任务{item}"
  207. });
  208. }
  209. }
  210. }
  211. });
  212. }
  213. else if (req.Type == HandleTaskTypeEnum.重新下发AGV任务)
  214. {
  215. SqlSugarHelper.Do(db =>
  216. {
  217. foreach (var item in req.TaskIds)
  218. {
  219. var task = db.Default.Queryable<WCS_TaskInfo>().Where(t => t.ID == item).First();
  220. if (task != null)
  221. {
  222. if (task.Type == TaskType.SetPlate) //组盘任务
  223. {
  224. response.ResDataList.Add(new HandleTaskResponse()
  225. {
  226. IsSuccess = false,
  227. TaskNo = item,
  228. Message = $"组盘任务无AGV执行流程",
  229. });
  230. continue;
  231. }
  232. else if (task.Type == TaskType.EnterDepot) //入库任务
  233. {
  234. if (task.Floor == 1) //一楼入库
  235. {
  236. }
  237. else if (task.Floor == 2) //二楼入库
  238. {
  239. response.ResDataList.Add(new HandleTaskResponse()
  240. {
  241. IsSuccess = false,
  242. TaskNo = item,
  243. Message = $"二楼入库任务重新下发AGV未实现",
  244. });
  245. continue;
  246. }
  247. }
  248. else if (task.Type == TaskType.OutDepot) //出库
  249. {
  250. }
  251. else if (task.Type == TaskType.TransferDepot) //移库
  252. {
  253. response.ResDataList.Add(new HandleTaskResponse()
  254. {
  255. IsSuccess = false,
  256. TaskNo = item,
  257. Message = $"组盘任务无AGV执行流程",
  258. });
  259. continue;
  260. }
  261. else if (task.Type == TaskType.Delivery) //搬运
  262. {
  263. if (task.Floor == 1)
  264. {
  265. }
  266. else if (task.Floor == 2)
  267. {
  268. response.ResDataList.Add(new HandleTaskResponse()
  269. {
  270. IsSuccess = false,
  271. TaskNo = item,
  272. Message = $"二楼搬运任务重新下发AGV未实现",
  273. });
  274. continue;
  275. }
  276. }
  277. else if (task.Type == TaskType.EmptyInit) //空轮初始化
  278. {
  279. response.ResDataList.Add(new HandleTaskResponse()
  280. {
  281. IsSuccess = false,
  282. TaskNo = item,
  283. Message = $"空轮初始化无AGV执行流程",
  284. });
  285. continue;
  286. }
  287. //找到对应的AGV任务
  288. var agv = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.ID == task.AgvTaskID).SplitTable(v => v.Take(2)).First();
  289. if (agv != null)
  290. {
  291. agv.Status = AGVTaskStatus.NewBuild;
  292. agv.AgvStatus = AGVTaskStatus.NewBuild;
  293. db.Default.Updateable(agv).SplitTable().ExecuteCommand();
  294. }
  295. if (task.Floor == 1)
  296. {
  297. task.Status = Entity.TaskStatus.WaitingToExecute;
  298. }
  299. else if (task.Floor == 2)
  300. {
  301. task.Status = Entity.TaskStatus.ConveyorExecution;
  302. }
  303. task.AddWCS_TASK_DTL(db, "AGV", "重新下发AGV任务");
  304. db.Default.Updateable(task).ExecuteCommand();
  305. }
  306. else
  307. {
  308. response.ResDataList.Add(new HandleTaskResponse()
  309. {
  310. IsSuccess = false,
  311. TaskNo = item,
  312. Message = $"未找到对应任务{item}"
  313. });
  314. }
  315. }
  316. });
  317. }
  318. return response;
  319. }
  320. /// <summary>
  321. /// WMS完成或取消任务验证
  322. /// </summary>
  323. /// <param name="sRes"></param>
  324. /// <param name="id"></param>
  325. /// <param name="agvTask">需要取消任务的AGV任务号</param>
  326. /// <returns></returns>
  327. public CancelTaskResponse? CancelAgvTask(SRes<HandleTaskResponse> sRes, int id, string agvTask)
  328. {
  329. try
  330. {
  331. var res = AgvApi.CancelAgvTask(agvTask);
  332. return res;
  333. }
  334. catch (Exception ex)
  335. {
  336. sRes.ResDataList.Add(new HandleTaskResponse()
  337. {
  338. IsSuccess = false,
  339. TaskNo = id,
  340. Message = $"AGV错误:{ex.Message}",
  341. });
  342. return null;
  343. }
  344. }
  345. /// <summary>
  346. /// WMS完成或取消任务验证
  347. /// </summary>
  348. /// <param name="sRes"></param>
  349. /// <param name="id"></param>
  350. /// <param name="type">99完成,106取消</param>
  351. /// <returns></returns>
  352. public SRes? HandleTaskVerify(SRes<HandleTaskResponse> sRes, int id, int type)
  353. {
  354. try
  355. {
  356. var res = WmsApi.HandleTaskVerify(new List<int>() { id }, type);
  357. return res;
  358. }
  359. catch (Exception ex)
  360. {
  361. sRes.ResDataList.Add(new HandleTaskResponse()
  362. {
  363. IsSuccess = false,
  364. TaskNo = id,
  365. Message = $"WMS错误:{ex.Message}",
  366. });
  367. return null;
  368. }
  369. }
  370. /// <summary>
  371. /// WMS完成或取消任务执行
  372. /// </summary>
  373. /// <param name="sRes"></param>
  374. /// <param name="id"></param>
  375. /// <param name="type">99完成,106取消</param>
  376. /// <returns></returns>
  377. public SRes? CarryTaskInfo(SRes<HandleTaskResponse> sRes, int id, int type)
  378. {
  379. try
  380. {
  381. var res = WmsApi.CarryTaskInfo(new List<int>() { id }, type);
  382. return res;
  383. }
  384. catch (Exception ex)
  385. {
  386. sRes.ResDataList.Add(new HandleTaskResponse()
  387. {
  388. IsSuccess = false,
  389. TaskNo = id,
  390. Message = $"WMS错误:{ex.Message}",
  391. });
  392. return null;
  393. }
  394. }
  395. public SRes? CancelAgvTaskUpdate(SRes<HandleTaskResponse> sRes, int id, int type)
  396. {
  397. try
  398. {
  399. var res = WmsApi.CarryTaskInfo(new List<int>() { id }, type);
  400. return res;
  401. }
  402. catch (Exception ex)
  403. {
  404. sRes.ResDataList.Add(new HandleTaskResponse()
  405. {
  406. IsSuccess = false,
  407. TaskNo = id,
  408. Message = ex.Message,
  409. });
  410. return null;
  411. }
  412. }
  413. /// <summary>
  414. /// 设备信息写入接口
  415. /// </summary>
  416. /// <param name="deviceType">需要写入信息的设备类型</param>
  417. /// <param name="devCode">设备编号</param>
  418. /// <param name="protocol">设备协议类名</param>
  419. /// <param name="propName">写入字段名</param>
  420. /// <param name="value">值</param>
  421. [HttpPost]
  422. public void Write(DeviceTypeEnum deviceType, string devCode, string protocol, string propName, string value)
  423. {
  424. World.GetSystemInstance<DeviceWriteSystem>().Invoke(new DeviceWriteInfo
  425. {
  426. DeviceType = deviceType,
  427. Code = devCode,
  428. Protocol = protocol,
  429. Property = propName,
  430. Value = value
  431. });
  432. }
  433. /// <summary>
  434. /// 设备信息写入接口
  435. /// </summary>
  436. /// <param name="deviceType">需要写入信息的设备类型</param>
  437. /// <param name="devCode">设备编号</param>
  438. /// <param name="protocol">设备协议类名</param>
  439. /// <param name="propName">写入字段名</param>
  440. /// <param name="value">值</param>
  441. [HttpPost]
  442. public void GetDevList()
  443. {
  444. var a = RedisHub.Monitor.LRange("Packs", 0, 80000);
  445. List<DeviceDataPack> packs = new List<DeviceDataPack>();
  446. foreach (var item in a)
  447. {
  448. packs.Add(JsonConvert.DeserializeObject<DeviceDataPack>(item));
  449. }
  450. }
  451. /// <summary>
  452. /// 获取设备配置信息接口
  453. /// </summary>
  454. /// <returns></returns>
  455. [HttpGet]
  456. public List<Device> GetDeviceList()
  457. {
  458. return Device.All.ToList();
  459. }
  460. /// <summary>
  461. /// 获取设备信息
  462. /// </summary>
  463. /// <param name="name">设备名称</param>
  464. /// <returns></returns>
  465. [HttpGet]
  466. public object GetDeviceInfo(string name)
  467. {
  468. var remoteIpAddress = HttpContext.Connection.RemoteIpAddress.ToString();
  469. LogHub.InterfacePublish(nameof(GetDeviceInfo), $"IP:{remoteIpAddress}--传入参数--{JsonConvert.SerializeObject(name)}");
  470. var obj = World.GetSystemInstance<GetDeviceSystem>().Invoke(name);
  471. LogHub.InterfacePublish(nameof(GetDeviceInfo), $"IP:{remoteIpAddress}--返回结果--{JsonConvert.SerializeObject(obj)}");
  472. return obj;
  473. }
  474. /// <summary>
  475. /// 堆垛机测试
  476. /// </summary>
  477. /// <param name="srmcod">堆垛机编号</param>
  478. /// <param name="typeEnum">任务类型</param>
  479. /// <param name="value1">起始行</param>
  480. /// <param name="value2">起始列</param>
  481. /// <param name="value3">起始层</param>
  482. /// <param name="value4">目标行</param>
  483. /// <param name="value5">目标列</param>
  484. /// <param name="value6">目标层</param>
  485. [HttpPost]
  486. public void SrmDeBug(string srmcod, SrmTaskTypeEnum typeEnum, short value1, short value2, short value3, short value4, short value5, short value6)
  487. {
  488. World.GetSystemInstance<SrmDebugSystem>().Invoke(new SrmDebugInfo
  489. {
  490. SrmCode = srmcod,
  491. srmTaskType = typeEnum,
  492. SLine = value1,
  493. SCol = value2,
  494. SLayer = value3,
  495. ELine = value4,
  496. ECol = value5,
  497. ELayer = value6
  498. });
  499. }
  500. #region 设备IP相关
  501. /// <summary>
  502. /// 获取设备Ip集合
  503. /// </summary>
  504. /// <returns>设备Ip集合</returns>
  505. [HttpGet]
  506. public List<string> GetDeviceIpList()
  507. {
  508. if (!ServiceHub.DeviceIPList.Any()) throw new Exception("未配置任何Ip");
  509. return ServiceHub.DeviceIPList;
  510. }
  511. /// <summary>
  512. /// 获取设备IP检测结果
  513. /// </summary>
  514. /// <returns>设备IP检测结果</returns>
  515. [HttpGet]
  516. public List<DeviceIpTestResults> DeviceIpTest()
  517. {
  518. if (!ServiceHub.DeviceIPList.Any()) throw new Exception("未配置任何Ip");
  519. List<DeviceIpTestResults> deviceIpTestResults = new List<DeviceIpTestResults>();
  520. ServiceHub.DeviceIPList.ForEach(ip =>
  521. {
  522. deviceIpTestResults.Add(new DeviceIpTestResults
  523. {
  524. Ip = ip,
  525. Result = PingIpOrDomainName(ip)
  526. });
  527. });
  528. return deviceIpTestResults;
  529. }
  530. /// <summary>
  531. /// 检查Ip是否正常联通
  532. /// </summary>
  533. /// <param name="strIpOrDName">输入参数,表示IP地址或域名</param>
  534. /// <returns></returns>
  535. public static bool PingIpOrDomainName(string strIpOrDName)
  536. {
  537. try
  538. {
  539. Ping objPingSender = new Ping();
  540. PingOptions objPinOptions = new PingOptions();
  541. objPinOptions.DontFragment = true;
  542. string data = "";
  543. byte[] buffer = Encoding.UTF8.GetBytes(data);
  544. int intTimeout = 120;
  545. PingReply objPinReply = objPingSender.Send(strIpOrDName, intTimeout, buffer, objPinOptions);
  546. string strInfo = objPinReply.Status.ToString();
  547. if (strInfo == "Success")
  548. {
  549. return true;
  550. }
  551. else
  552. {
  553. return false;
  554. }
  555. }
  556. catch (Exception)
  557. {
  558. return false;
  559. }
  560. }
  561. #endregion 设备IP相关
  562. }
  563. public interface IDeviceWriter
  564. {
  565. [HttpPost]
  566. void Write(DeviceTypeEnum deviceType, string devCode, string protocol, string propName, string value);
  567. }
  568. /// <summary>
  569. /// 设备Ip通讯检测结构
  570. /// </summary>
  571. public class DeviceIpTestResults
  572. {
  573. public string Ip { get; set; }
  574. public bool Result { get; set; }
  575. }
  576. }