WcsController.cs 32 KB

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