AgvSystems.cs 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. using Newtonsoft.Json;
  2. using PlcSiemens.Core.Extension;
  3. using ServiceCenter.Extensions;
  4. using ServiceCenter.Logs;
  5. using ServiceCenter.SqlSugars;
  6. using System.ComponentModel;
  7. using WCS.Core;
  8. using WCS.Entity;
  9. using WCS.Entity.Protocol.Station;
  10. using WCS.WorkEngineering.Extensions;
  11. using WCS.WorkEngineering.Model.WMS;
  12. using WCS.WorkEngineering.WebApi.Controllers;
  13. using WCS.WorkEngineering.WebApi.Models.WMS.Request;
  14. using WCS.WorkEngineering.WebApi.Models.WMS.Response;
  15. using WCS.WorkEngineering.Worlds;
  16. using TaskStatus = WCS.Entity.TaskStatus;
  17. namespace WCS.WorkEngineering.Systems
  18. {
  19. /// <summary>
  20. /// Agv交互系统
  21. /// </summary>
  22. [BelongTo(typeof(MainWorld))]
  23. [Description("Agv交互系统")]
  24. public class AgvSystems : DeviceSystem<Device<IStation520>>
  25. {
  26. protected override bool ParallelDo => true;
  27. public AgvSystems()
  28. {
  29. }
  30. public override void Do(Device<IStation520> obj)
  31. {
  32. if (obj.Entity.Code == "AGVOut")
  33. {
  34. var agvTaskInfos = new List<WCS_AgvTaskInfo>();
  35. //获取所有未结束的叫料及背负式补空AGV任务
  36. SqlSugarHelper.Do(db =>
  37. {
  38. agvTaskInfos = db.Queryable<WCS_AgvTaskInfo>().ReadPast().Where(v => v.TaskType == AGVTaskType.CallMaterial)
  39. .Where(v => v.Status < AGVTaskStatus.MissionCompleted)
  40. .SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.AddTime).ToList();
  41. });
  42. //有需要处理的AGV任务
  43. if (agvTaskInfos.Any())
  44. {
  45. this.ExRecord(obj.Entity.Code, "可用出库AGV任务列表", agvTaskInfos.Select(v => v.ID).ToList());
  46. var taskInfos = new List<WCS_TaskInfo>();
  47. foreach (var agv in agvTaskInfos)
  48. {
  49. try
  50. {
  51. SqlSugarHelper.Do(db =>
  52. {
  53. switch (agv.AgvStatus)
  54. {
  55. //取货点安全交互
  56. case AGVTaskStatus.RequestOrPermission2 when agv.Status != AGVTaskStatus.RequestOrPermission2:
  57. {
  58. var taskInfoPick = db.Queryable<WCS_TaskInfo>().NoLock().First(v => v.ID == agv.TaskId);
  59. if (taskInfoPick == null) throw new Exception($"未找到对应的WCS任务{agv.TaskId}");
  60. agv.Status = AGVTaskStatus.RequestOrPermission2;
  61. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  62. taskInfoPick.AddWCS_TASK_DTL(db, "agv", $"允许AGV任务{agv.ID}在站台{agv.Station}取货");
  63. AgvApi.ContinueTask(agv.AgvID, agv.Station);
  64. break;
  65. }
  66. case AGVTaskStatus.PutRequestOrPermission when agv.Status != AGVTaskStatus.PutRequestOrPermission:
  67. {
  68. agv.Status = AGVTaskStatus.PutRequestOrPermission;
  69. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  70. AgvApi.ContinueTask(agv.AgvID, agv.Station);
  71. break;
  72. }
  73. case AGVTaskStatus.LeaveGet when agv.Status != AGVTaskStatus.LeaveGet:
  74. var taskInfo = db.Queryable<WCS_TaskInfo>().NoLock().First(v => v.ID == agv.TaskId);
  75. if (taskInfo == null) throw new Exception($"未找到对应的WCS任务{agv.TaskId}");
  76. World.Log($"AGV取货结束:开始{agv.ID}--{agv.Station}");
  77. var devinfo = new Device<IStation520>(Device.All.First(x => x.Code == agv.Station), World);
  78. if (!taskInfo.AddrFrom.StartsWith("92"))
  79. {
  80. devinfo.Data.CmdType = StationCmd.Res5;
  81. }
  82. if (taskInfo.AddrFrom.StartsWith("92") && taskInfo.Device == "CR")
  83. {
  84. var res = WmsApi.SrmPickOutCompleted(taskInfo.ID);
  85. if (res.ResCode != ResponseStatusCodeEnum.Sucess)
  86. {
  87. throw new Exception(res.ResMsg);
  88. }
  89. }
  90. agv.Status = AGVTaskStatus.LeaveGet;
  91. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  92. World.Log($"AGV取货结束:结束{agv.ID}--{agv.Station}");
  93. break;
  94. //完成任务
  95. case AGVTaskStatus.MissionCompleted when agv.Status != AGVTaskStatus.MissionCompleted:
  96. {
  97. if (agv.TaskType is AGVTaskType.CallForMaterial or AGVTaskType.ForkliftFilling or AGVTaskType.CallMaterial)
  98. {
  99. var taskInfoFinish = db.Queryable<WCS_TaskInfo>().RowLock().First(v => v.AgvTaskID == agv.ID);
  100. //if (taskInfo == null) throw new Exception($"未找到AGV任务{agv.ID}对应WCS任务");
  101. //更新AGV任务状态
  102. agv.Status = AGVTaskStatus.MissionCompleted;
  103. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  104. //更新WCS任务状态
  105. if (taskInfoFinish != null)
  106. {
  107. taskInfoFinish.Status = Entity.TaskStatus.Finish;
  108. taskInfoFinish.EndTime = DateTime.Now;
  109. db.UpdateableRowLock(taskInfoFinish).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
  110. taskInfoFinish.AddWCS_TASK_DTL(db, "agv", "任务完成");
  111. taskInfos.Add(taskInfoFinish);
  112. }
  113. }
  114. else
  115. {
  116. agv.Status = AGVTaskStatus.MissionCompleted;
  117. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  118. }
  119. break;
  120. }
  121. }
  122. });
  123. }
  124. catch (Exception ex)
  125. {
  126. World.Log(ex.Message, LogLevelEnum.Mid);
  127. this.ExRecord(obj.Entity.Code, ex.Message);
  128. }
  129. }
  130. }
  131. }
  132. else if (obj.Entity.Code == "AGVIn")
  133. {
  134. List<WCS_AgvTaskInfo> agvTaskInfos = new List<WCS_AgvTaskInfo>();
  135. //获取所有未结束的入库AGV任务
  136. SqlSugarHelper.Do(db =>
  137. {
  138. agvTaskInfos = db.Queryable<WCS_AgvTaskInfo>()
  139. .Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot)
  140. .SplitTable(tabs => tabs.Take(2)).OrderBy(v => v.EditTime).ToList();
  141. });
  142. if (agvTaskInfos.Any())
  143. {
  144. foreach (var agv in agvTaskInfos)
  145. {
  146. try
  147. {
  148. SqlSugarHelper.Do(db =>
  149. {
  150. #region 开始跟据AGV状态做出处理
  151. switch (agv.AgvStatus)
  152. {
  153. case AGVTaskStatus.NewBuild when agv.Status == AGVTaskStatus.NewBuild:
  154. if (agv.WorkShop != 111)
  155. {
  156. agv.AgvID = agv.ID.ToString();
  157. agv.Status = AGVTaskStatus.Confirm;
  158. agv.AgvStatus = AGVTaskStatus.Confirm;
  159. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  160. }
  161. //人工满托入库
  162. if (agv.TaskType == AGVTaskType.EnterDepot && (agv.Station == "2535" || agv.Station == "2935" || agv.Station == "2735" || agv.Station == "3135"))
  163. {
  164. //fjSysConfig config1 = new fjSysConfig();
  165. var config1 = db.Queryable<fjSysConfig>().NoLock().First(x => x.Code == "FullPalletInMax");
  166. if (config1 != null)
  167. {
  168. if (!(db.Queryable<WCS_TaskInfo>().NoLock().Where(x => x.Status == TaskStatus.AGVExecution && x.BusType == "人工满托入库").Count() < config1.SContent.ToShort()))
  169. {
  170. throw new Exception($"人工组盘任务数已达{config1.SContent.ToShort()},暂停下发任务");
  171. }
  172. }
  173. AgvApi.满托入库(agv.Position, agv.ID.ToString(), agv.Station);
  174. var tasknew = db.Queryable<WCS_TaskInfo>().NoLock().Where(x => x.ID == agv.TaskId).First();
  175. if (tasknew != null)
  176. {
  177. tasknew.Status = TaskStatus.AGVExecution;
  178. tasknew.EditTime = DateTime.Now;
  179. db.UpdateableRowLock(tasknew).UpdateColumns(x => new { x.Status, x.EditTime }).ExecuteCommand();
  180. tasknew.AddWCS_TASK_DTL(db, "agv", "任务下发agv执行");
  181. }
  182. else
  183. {
  184. throw new Exception($"未找到WCS任务{agv.TaskId},请确认任务状态");
  185. }
  186. }
  187. //退料重绕
  188. else if (agv.WorkShop == 222)
  189. {
  190. AgvApi.退料重绕(agv.Position, agv.ID.ToString(), agv.Station);
  191. var tasknew = db.Queryable<WCS_TaskInfo>().NoLock().Where(x => x.ID == agv.TaskId).First();
  192. if (tasknew != null)
  193. {
  194. tasknew.Status = TaskStatus.AGVExecution;
  195. tasknew.EditTime = DateTime.Now;
  196. db.UpdateableRowLock(tasknew).UpdateColumns(x => new { x.Status, x.EditTime }).ExecuteCommand();
  197. tasknew.AddWCS_TASK_DTL(db, "agv", "任务下发agv执行");
  198. }
  199. else
  200. {
  201. throw new Exception($"未找到WCS任务{agv.TaskId},请确认任务状态");
  202. }
  203. }
  204. //重绕退料区搬运
  205. else if (agv.WorkShop == 333)
  206. {
  207. AgvApi.退料搬运(agv.Position, agv.ID.ToString(), agv.Station);
  208. }
  209. else if (agv.WorkShop != 111)
  210. {
  211. AgvApi.托盘回库(agv.Position, agv.ID.ToString(), agv.Station);
  212. }
  213. break;
  214. //巷道分配
  215. case AGVTaskStatus.RequestOrPermission1 when agv.Status != AGVTaskStatus.Complete1:
  216. {
  217. var task = db.Queryable<WCS_TaskOld>().NoLock().Where(x => x.Id == agv.TaskId).SplitTable(x => x.Take(2)).First();
  218. if (task == null) throw new Exception($"未找到对应的WCS任务{agv.TaskId}");
  219. if (task.BusType != TaskBusType.帘线退料重绕.GetDescription())
  220. {
  221. //获取当前任务可以去的目标地址
  222. var positionList = new List<string>(); //当前分配点对应的放货点
  223. //var allPositionList = new List<string>(); //同库区另一侧的放货点
  224. //var nearPositionList = new List<string>(); //所有的放货点
  225. //GetPositionList(positionList, nearPositionList, allPositionList, task.WarehouseCode);
  226. switch (agv.Station)
  227. {
  228. case "2501":
  229. positionList.AddRange(new List<string>() { "2501", "2505", "2509", "2513" });
  230. break;
  231. case "2701":
  232. positionList.AddRange(new List<string>() { "2701", "2705", "2709", "2713" });
  233. break;
  234. case "2901":
  235. positionList.AddRange(new List<string>() { "2901", "2905", "2909", "2913" });
  236. break;
  237. case "3101":
  238. positionList.AddRange(new List<string>() { "3101", "3105", "3109", "3113" });
  239. break;
  240. case "3301":
  241. positionList.AddRange(new List<string>() { "3301", "3305", "3309", "3313" });
  242. break;
  243. case "3501":
  244. positionList.AddRange(new List<string>() { "3501", "3505", "3509", "3513" });
  245. break;
  246. }
  247. List<WCS_AgvTaskInfo> agvs = new List<WCS_AgvTaskInfo>(); //当前分配点对应的放货点已用点
  248. //List<WCS_AgvTaskInfo> agvsNear = new List<WCS_AgvTaskInfo>(); //同库区另一侧的放货点已用点
  249. //List<WCS_AgvTaskInfo> agvsAll = new List<WCS_AgvTaskInfo>(); //所有的放货点已用点
  250. agvs = db.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status > AGVTaskStatus.Confirm && v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot && positionList.Contains(v.Station))
  251. .SplitTable(v => v.Take(2)).ToList();
  252. //agvsAll = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status > AGVTaskStatus.Confirm && v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot && allPositionList.Contains(v.Station))
  253. // .SplitTable(v => v.Take(2)).ToList();
  254. //agvsNear = db.Default.Queryable<WCS_AgvTaskInfo>().Where(v => v.Status > AGVTaskStatus.Confirm && v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot && nearPositionList.Contains(v.Station))
  255. // .SplitTable(v => v.Take(2)).ToList();
  256. //获取放货点
  257. var agvPositionLists = agvs.Select(x => x.Station).Distinct();
  258. //var agvPositionListsNear = agvsNear.Select(x => x.Station).Distinct();
  259. //var agvPositionListsAll = agvsAll.Select(x => x.Station).Distinct();
  260. //获取各区域可用点
  261. var endDev = positionList.Where(x => !agvPositionLists.Contains(x)).ToList();
  262. //var endNearDev = nearPositionList.Where(x => !agvPositionListsNear.Contains(x)).ToList();
  263. //var endAllDev = allPositionList.Where(x => !agvPositionListsAll.Contains(x)).ToList();
  264. World.Log($"agv可用巷道信息:{JsonConvert.SerializeObject(endDev)}");
  265. //World.Log($"agv可用巷道信息(所有):{JsonConvert.SerializeObject(endAllDev)}");
  266. if (!endDev.Any() /*&& !endAllDev.Any() && !endNearDev.Any()*/)//没有可用放货站台
  267. {
  268. var msg = $"任务{agv.ID}已无可用放货站台";
  269. foreach (var ag in agvs)
  270. {
  271. msg += $"[任务号:{ag.ID},目标地址:{ag.Station}]";
  272. }
  273. throw new Exception(msg);
  274. }
  275. //获取没有光电信息的设备集合
  276. try
  277. {
  278. // 获取可用站台
  279. var devs = Device.All.Where(x => endDev.Contains(x.Code)).Select(x =>
  280. new Device<IStation520, IStation521, IStation523>(x, World));
  281. devs = devs.Where(x =>
  282. !x.Data3.Status.HasFlag(StationStatus.Run) &&
  283. !x.Data3.Status.HasFlag(StationStatus.PH_Status) &&
  284. x.Data3.Status.HasFlag(StationStatus.Auto)).ToList();
  285. //var devsNear = Device.All.Where(x => endNearDev.Contains(x.Code)).Select(x =>
  286. // new Device<IStation520, IStation521, IStation523>(x, World));
  287. //devsNear = devsNear.Where(x =>
  288. // !x.Data3.Status.HasFlag(StationStatus.Run) &&
  289. // !x.Data3.Status.HasFlag(StationStatus.PH_Status) &&
  290. // x.Data3.Status.HasFlag(StationStatus.Auto)).ToList();
  291. //var devsAll = Device.All.Where(x => endAllDev.Contains(x.Code)).Select(x =>
  292. // new Device<IStation520, IStation521, IStation523>(x, World));
  293. //devsAll = devsAll.Where(x =>
  294. // !x.Data3.Status.HasFlag(StationStatus.Run) &&
  295. // !x.Data3.Status.HasFlag(StationStatus.PH_Status) &&
  296. // x.Data3.Status.HasFlag(StationStatus.Auto)).OrderBy(v => allPositionList.Contains(v.Entity.Code)).ToList();
  297. if (!devs.Any()) //自身所属位置无可用放货点
  298. {
  299. throw new Exception($"当前任务{agv.ID}无可用站台");
  300. #region 弃用
  301. //if (devsNear.Any())//先判断同库一侧
  302. //{
  303. // foreach (var dev in devsNear)
  304. // {
  305. // if (!dev.Data3.Status.HasFlag(StationStatus.Run) && !dev.Data3.Status.HasFlag(StationStatus.PH_Status) && dev.Data3.Status.HasFlag(StationStatus.Auto))
  306. // {
  307. // World.Log($"任务执行过程:开始{agv.ID}-{JsonConvert.SerializeObject(devsAll.Select(x => x.Entity.Code).ToList())}");
  308. // agv.Status = AGVTaskStatus.Complete1;
  309. // agv.Station = dev.Entity.Code;
  310. // db.Default.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  311. // World.Log($"任务执行过程:完成agv任务更新{agv.ID}--{agv.Station}");
  312. // task.AddWCS_TASK_DTL(db.Default, "皮盘返库任务分配巷道", agv.Station, $"任务分配至:{agv.Station}");
  313. // World.Log($"任务执行过程:完成任务明细添加{agv.Station}");
  314. // AgvApi.ContinueTask(agv.AgvID, agv.Station);
  315. // World.Log($"任务执行过程:任务成功下发AGV{agv.AgvID}--{agv.Station}");
  316. // return;
  317. // }
  318. // }
  319. //}
  320. //else if (devsAll.Any())
  321. //{
  322. // foreach (var dev in devsAll)
  323. // {
  324. // if (!dev.Data3.Status.HasFlag(StationStatus.Run) && !dev.Data3.Status.HasFlag(StationStatus.PH_Status) && dev.Data3.Status.HasFlag(StationStatus.Auto))
  325. // {
  326. // World.Log($"任务执行过程:开始{agv.ID}-{JsonConvert.SerializeObject(devsAll.Select(x => x.Entity.Code).ToList())}");
  327. // agv.Status = AGVTaskStatus.Complete1;
  328. // agv.Station = dev.Entity.Code;
  329. // db.Default.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  330. // World.Log($"任务执行过程:完成agv任务更新{agv.ID}--{agv.Station}");
  331. // task.AddWCS_TASK_DTL(db.Default, "皮盘返库任务分配巷道", agv.Station, $"任务分配至:{agv.Station}");
  332. // World.Log($"任务执行过程:完成任务明细添加{agv.Station}");
  333. // AgvApi.ContinueTask(agv.AgvID, agv.Station);
  334. // World.Log($"任务执行过程:任务成功下发AGV{agv.AgvID}--{agv.Station}");
  335. // return;
  336. // }
  337. // }
  338. //}
  339. World.Log("可用站台均有货或有执行中任务");
  340. return;
  341. #endregion 弃用
  342. }
  343. World.Log($"任务执行过程:开始{agv.ID}-{JsonConvert.SerializeObject(devs.Select(x => x.Entity.Code).ToList())}");
  344. agv.Status = AGVTaskStatus.Complete1;
  345. agv.Station = devs.MinBy(x => x.Entity.Code).Entity.Code;
  346. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  347. World.Log($"任务执行过程:完成agv任务更新{agv.ID}--{agv.Station}");
  348. task.AddWCS_TASK_DTL(db, "皮盘返库任务分配巷道", agv.Station, $"任务分配至:{agv.Station}");
  349. World.Log($"任务执行过程:完成任务明细添加{agv.Station}");
  350. AgvApi.ContinueTask(agv.AgvID, agv.Station);
  351. World.Log($"任务执行过程:任务成功下发AGV{agv.AgvID}--{agv.Station}");
  352. }
  353. catch (Exception e)
  354. {
  355. throw new Exception($"{e.Message}");
  356. }
  357. }
  358. else if (task.BusType == TaskBusType.帘线退料重绕.GetDescription())
  359. {
  360. var con = db.Queryable<fjSysConfig>().NoLock().First(x => x.Code == "CRTLZone").SContent;
  361. var isUse = false || con != null && con == "1";
  362. //首先判断退料输送线是否可放货
  363. var ph_9001 = new Device<IStation523>(Device.All.First(x => x.Code == "9001"), World);
  364. var ph_9101 = new Device<IStation523>(Device.All.First(x => x.Code == "9101"), World);
  365. var flag1 = !db.Queryable<WCS_AgvTaskInfo>().NoLock().Where(v => v.Status > AGVTaskStatus.Confirm && v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot && v.Station == "9001")
  366. .SplitTable(v => v.Take(2)).Any() && !ph_9001.Data.Status.HasFlag(StationStatus.PH_Status);
  367. var flag2 = !db.Queryable<WCS_AgvTaskInfo>().NoLock().Where(v => v.Status > AGVTaskStatus.Confirm && v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot && v.Station == "9101")
  368. .SplitTable(v => v.Take(2)).Any() && !ph_9101.Data.Status.HasFlag(StationStatus.PH_Status);
  369. var taskApply = db.Queryable<WCS_TaskInfo>().NoLock().Where(x => x.ID == agv.TaskId).First();
  370. if (flag2)
  371. {
  372. if (taskApply != null)
  373. {
  374. agv.Status = AGVTaskStatus.Complete1;
  375. agv.Station = "9101";
  376. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  377. AgvApi.ContinueTask(agv.AgvID, agv.Station);
  378. taskApply.AddrTo = agv.Station;
  379. db.UpdateableRowLock(taskApply).UpdateColumns(x => new { x.AddrTo }).ExecuteCommand();
  380. World.Log($"帘线退料重绕分配目标放货点,任务{agv.ID}分配至:{agv.Station}");
  381. taskApply.AddWCS_TASK_DTL(db, "agv", $"帘线退料重绕分配目标放货点,任务分配至:{agv.Station}");
  382. }
  383. else
  384. {
  385. throw new Exception($"未找到WCS任务{agv.TaskId},请确认任务状态");
  386. }
  387. return;
  388. }
  389. else if (flag1)
  390. {
  391. if (taskApply != null)
  392. {
  393. agv.Status = AGVTaskStatus.Complete1;
  394. agv.Station = "9001";
  395. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  396. AgvApi.ContinueTask(agv.AgvID, agv.Station);
  397. taskApply.AddrTo = agv.Station;
  398. db.UpdateableRowLock(taskApply).UpdateColumns(x => new { x.AddrTo }).ExecuteCommand();
  399. World.Log($"帘线退料重绕分配目标放货点,任务{agv.ID}分配至:{agv.Station}");
  400. taskApply.AddWCS_TASK_DTL(db, "agv", $"帘线退料重绕分配目标放货点,任务分配至:{agv.Station}");
  401. }
  402. else
  403. {
  404. throw new Exception($"未找到WCS任务{agv.TaskId},请确认任务状态");
  405. }
  406. return;
  407. }
  408. else if (isUse)//请求WMS分配可用放货点
  409. {
  410. List<string> allDevs = new List<string> { "9210", "9211", "9212", "9213", "9214",/* "9215", "9216", "9217", "9218" */};
  411. var agvStas = db.Queryable<WCS_AgvTaskInfo>().NoLock().Where(v => v.Status > AGVTaskStatus.Confirm && v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot && (allDevs.Contains(v.Station) || allDevs.Contains(v.Position)))
  412. .SplitTable(v => v.Take(2)).ToList();
  413. var agvStaLists = agvStas.Select(x => x.Station).Distinct();
  414. var devs = allDevs.Where(x => !agvStaLists.Contains(x)).ToList();
  415. var devsPut = Device.All.Where(x => devs.Contains(x.Code)).Select(x =>
  416. new Device<IStation520, IStation521, IStation523>(x, World));
  417. devsPut = devsPut.Where(x =>
  418. !x.Data3.Status.HasFlag(StationStatus.Run) &&
  419. !x.Data3.Status.HasFlag(StationStatus.PH_Status) &&
  420. x.Data3.Status.HasFlag(StationStatus.Auto)).ToList();
  421. if (taskApply == null)
  422. {
  423. throw new Exception($"找不到对应wcs任务{agv.TaskId}");
  424. }
  425. if (devsPut.Any())
  426. {
  427. foreach (var dev in devsPut)
  428. {
  429. if (!dev.Data3.Status.HasFlag(StationStatus.PH_Status) &&
  430. !db.Queryable<WCS_AgvTaskInfo>().NoLock().Where(v => v.Status > AGVTaskStatus.Confirm && v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot && (v.Station == dev.Entity.Code || v.Position == dev.Entity.Code))
  431. .SplitTable(v => v.Take(2)).Any())
  432. {
  433. var sta = dev.Entity.Code;
  434. var res = WmsApi.GetFlatLocalIn(agv.TaskId, "T2", dev.Entity.Code, 1);
  435. if (res.ResCode == ResponseStatusCodeEnum.Sucess && res.ResData.CellNo == dev.Entity.Code)
  436. {
  437. sta = dev.Entity.Code;
  438. }
  439. else if (res.ResCode == ResponseStatusCodeEnum.Sucess)
  440. {
  441. sta = res.ResData.CellNo;
  442. World.Log($"{dev.Entity.Code}分配货位{res.ResData.CellNo}");
  443. }
  444. else
  445. {
  446. continue;
  447. }
  448. agv.Status = AGVTaskStatus.Complete1;
  449. agv.Station = dev.Entity.Code;
  450. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  451. AgvApi.ContinueTask(agv.AgvID, agv.Station);
  452. taskApply.AddrTo = agv.Station;
  453. db.UpdateableRowLock(taskApply).UpdateColumns(x => new { x.AddrTo }).ExecuteCommand();
  454. taskApply.AddWCS_TASK_DTL(db, "agv", $"帘线退料重绕分配目标放货点,任务分配至:{agv.Station}");
  455. World.Log($"帘线退料重绕分配目标放货点,任务{agv.ID}分配至:{agv.Station}");
  456. return;
  457. }
  458. }
  459. }
  460. else
  461. {
  462. throw new Exception("已无可用放货站台,请等待");
  463. }
  464. }
  465. else
  466. {
  467. throw new Exception("已无可用放货站台,请等待");
  468. }
  469. }
  470. break;
  471. }
  472. //放货站点安全交互
  473. case AGVTaskStatus.RequestOrPermission2 when agv.Status != AGVTaskStatus.RequestOrPermission2:
  474. {
  475. if (agv.Station.IsNullOrEmpty()) throw new Exception($"无有效放货地址");
  476. //var dev = Device.All.First(x => x.Code == agv.Station);
  477. var devPut = new Device<IStation520, IStation521, IStation523>(Device.All.First(x => x.Code == agv.Station), World);
  478. var taskPut = db.Queryable<WCS_TaskOld>().NoLock().Where(x => x.Id == agv.TaskId).SplitTable(x => x.Take(2)).First();
  479. var flag = false;
  480. if (taskPut == null)
  481. {
  482. throw new Exception($"未找到WCS任务{agv.TaskId},请确认任务状态");
  483. }
  484. else if (taskPut.BusType == "人工满托入库")
  485. {
  486. flag = true;
  487. }
  488. if (devPut.Data3.Status.HasFlag(StationStatus.PH_Status))
  489. {
  490. throw new Exception($"{agv.Station}站台有光电小车无法放货,请检查实际情况并处理");
  491. }
  492. if (flag)
  493. {
  494. if (!devPut.Data3.Status.HasFlag(StationStatus.Low_Station_2))
  495. {
  496. throw new Exception($"{agv.Station}站台不在低位小车无法放货,请检查并处理");
  497. }
  498. var tasking = db.Queryable<WCS_AgvTaskInfo>().NoLock().Where(v => v.Status < AGVTaskStatus.MissionCompleted && v.TaskType == AGVTaskType.EnterDepot
  499. && v.Station == agv.Station && v.GoodsSum == 1).SplitTable(tabs => tabs.Take(2)).First();
  500. if (tasking != null)
  501. {
  502. throw new Exception($"{agv.Station}站台有执行中任务{tasking.ID},请确认该任务实际位置");
  503. }
  504. agv.GoodsSum = 1;
  505. }
  506. agv.Status = AGVTaskStatus.RequestOrPermission2;
  507. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  508. //taskPut.AddWCS_TASK_DTL(db.Default, "agv", $"允许agv任务{agv.ID}放货");
  509. if (taskPut.BusType != TaskBusType.帘线退料重绕.GetDescription() && taskPut.BusType != TaskBusType.重绕满托入库.GetDescription())
  510. {
  511. devPut.Data.CmdType = StationCmd.Res1;
  512. }
  513. //调继续执行任务接口
  514. AgvApi.ContinueTask(agv.AgvID, agv.Station);
  515. break;
  516. }
  517. case AGVTaskStatus.LeavePut when agv.Status != AGVTaskStatus.LeavePut:
  518. break;
  519. //完成任务
  520. case AGVTaskStatus.MissionCompleted when agv.Status != AGVTaskStatus.MissionCompleted:
  521. var taskold = db.Queryable<WCS_TaskOld>().NoLock().Where(x => x.Id == agv.TaskId).SplitTable(x => x.Take(2)).First();
  522. if (agv.TaskType == AGVTaskType.EnterDepot)
  523. {
  524. agv.Status = AGVTaskStatus.MissionCompleted;
  525. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  526. var devinfo = new Device<IStation520, IStation521>(Device.All.First(x => x.Code == agv.Station), World);
  527. if (taskold.BusType != TaskBusType.帘线退料重绕.GetDescription() && taskold.BusType != TaskBusType.重绕满托入库.GetDescription())
  528. {
  529. devinfo.Data.CmdType = StationCmd.Res2;
  530. }
  531. if (taskold.LastInteractionPoint == "2" || taskold.BusType == TaskBusType.重绕满托入库.GetDescription() || taskold.BusType == TaskBusType.帘线退料重绕.GetDescription()) //如果是单独取空任务直接完成
  532. {
  533. var task = db.Queryable<WCS_TaskInfo>().NoLock().Where(x => x.ID == agv.TaskId).First();
  534. if (task != null)
  535. {
  536. task.Status = TaskStatus.Finish;
  537. task.EndTime = DateTime.Now;
  538. db.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
  539. task.AddWCS_TASK_DTL(db, "agv", "任务完成");
  540. }
  541. }
  542. else if (taskold.BusType == "人工满托入库")
  543. {
  544. var task = db.Queryable<WCS_TaskInfo>().NoLock().Where(x => x.ID == agv.TaskId).First();
  545. if (task != null)
  546. {
  547. task.Status = TaskStatus.ConveyorExecution;
  548. devinfo.Data.TaskNumber = task.ID;
  549. task.EndTime = DateTime.Now;
  550. db.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
  551. task.AddWCS_TASK_DTL(db, "agv", "任务放货完成");
  552. }
  553. }
  554. }
  555. break;
  556. case AGVTaskStatus.Cancel when agv.Status != AGVTaskStatus.Cancel:
  557. var taskold1 = db.Queryable<WCS_TaskOld>().NoLock().Where(x => x.Id == agv.TaskId).SplitTable(x => x.Take(2)).First();
  558. agv.Status = AGVTaskStatus.Cancel;
  559. db.UpdateableRowLock(agv).SplitTable(x => x.Take(2)).ExecuteCommand();
  560. if (taskold1.LastInteractionPoint == "2") //如果是单独取空任务直接取消
  561. {
  562. var task = db.Queryable<WCS_TaskInfo>().NoLock().Where(x => x.ID == agv.TaskId).First();
  563. if (task != null)
  564. {
  565. task.Status = TaskStatus.Cancel;
  566. task.EndTime = DateTime.Now;
  567. db.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
  568. task.AddWCS_TASK_DTL(db, "agv", "任务取消");
  569. }
  570. }
  571. break;
  572. }
  573. #endregion 开始跟据AGV状态做出处理
  574. });
  575. }
  576. catch (Exception ex)
  577. {
  578. if (ex.Message.Contains("SqlTransaction")) World.Log($"{ex.Message}:{ex.StackTrace}");
  579. else World.Log(ex.Message, LogLevelEnum.Mid);
  580. }
  581. }
  582. }
  583. }
  584. }
  585. public override bool Select(Device dev)
  586. {
  587. return dev.Code is "AGVIn" or "AGVOut";
  588. }
  589. /// <summary>
  590. /// 获取可用放货点
  591. /// </summary>
  592. /// <param name="positionList"></param>
  593. /// <param name="nearPositionList"></param>
  594. /// <param name="allPositionList"></param>
  595. /// <param name="warehouseCode"></param>
  596. private void GetPositionList(List<string> positionList, List<string> nearPositionList, List<string> allPositionList, string warehouseCode)
  597. {
  598. switch (warehouseCode)
  599. {
  600. case "1N":
  601. positionList.AddRange(new List<string>() { "2501", "2505", "2509", "2513" });
  602. nearPositionList.AddRange(new List<string>() {
  603. "2701", "2705", "2709", "2713" });
  604. allPositionList.AddRange(new List<string>() {
  605. "2901", "2905", "2909", "2913","3101", "3105", "3109", "3113", "3301", "3305", "3309", "3313","3501", "3505", "3509", "3513"});
  606. break;
  607. case "1S":
  608. positionList.AddRange(new List<string>() { "2701", "2705", "2709", "2713" });
  609. nearPositionList.AddRange(new List<string>() {
  610. "2501", "2505", "2509", "2513" });
  611. allPositionList.AddRange(new List<string>() {
  612. "3101", "3105", "3109", "3113", "2901", "2905", "2909", "2913", "3501", "3505", "3509", "3513", "3301", "3305", "3309", "3313"});
  613. break;
  614. case "2N":
  615. positionList.AddRange(new List<string>() { "2901", "2905", "2909", "2913" });
  616. nearPositionList.AddRange(new List<string>() {
  617. "3101", "3105", "3109", "3113" });
  618. allPositionList.AddRange(new List<string>() {
  619. "2501" , "2505" , "2509" , "2513" , "2701", "2705", "2709", "2713","3301", "3305", "3309", "3313", "3501", "3505", "3509", "3513"});
  620. break;
  621. case "2S":
  622. positionList.AddRange(new List<string>() { "3101", "3105", "3109", "3113" });
  623. nearPositionList.AddRange(new List<string>() {
  624. "2901", "2905", "2909", "2913" });
  625. allPositionList.AddRange(new List<string>() {
  626. "2701" , "2705" , "2709" , "2713" ,"2501" , "2505" , "2509" , "2513" , "3501" , "3505" , "3509" , "3513","3301", "3305", "3309", "3313"});
  627. break;
  628. case "3N":
  629. positionList.AddRange(new List<string>() { "3301", "3305", "3309", "3313" });
  630. nearPositionList.AddRange(new List<string>() {
  631. "3501", "3505", "3509", "3513" });
  632. allPositionList.AddRange(new List<string>() {
  633. "2901", "2905", "2909", "2913", "3101", "3105", "3109", "3113","2501" , "2505" , "2509" , "2513" , "2701", "2705", "2709", "2713" });
  634. break;
  635. case "3S":
  636. positionList.AddRange(new List<string>() { "3501", "3505", "3509", "3513" });
  637. nearPositionList.AddRange(new List<string>() {
  638. "3301", "3305", "3309", "3313" });
  639. allPositionList.AddRange(new List<string>() {
  640. "3101", "3105", "3109", "3113", "2901", "2905", "2909", "2913", "2701" , "2705" , "2709" , "2713" ,"2501" , "2505" , "2509" , "2513" });
  641. break;
  642. }
  643. }
  644. }
  645. }