机械臂cs.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. using ServiceCenter.Extensions;
  2. using ServiceCenter.Logs;
  3. using ServiceCenter.SqlSugars;
  4. using SqlSugar;
  5. using System.ComponentModel;
  6. using WCS.Core;
  7. using WCS.Entity;
  8. using WCS.WorkEngineering.Extensions;
  9. using WCS.WorkEngineering.Protocol.Robot;
  10. using WCS.WorkEngineering.Protocol.Station;
  11. using WCS.WorkEngineering.WebApi.Controllers;
  12. using WCS.WorkEngineering.Worlds;
  13. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  14. namespace WCS.WorkEngineering.Systems
  15. {
  16. /// <summary>
  17. /// 机械臂
  18. /// </summary>
  19. [BelongTo(typeof(RingWorld))]
  20. [Description("机械臂")]
  21. public class 机械臂 : DeviceSystem<Device<IRobot520, IRobot521, IRobot522>>
  22. {
  23. protected override bool ParallelDo => true;
  24. protected override bool SaveLogsToFile => true;
  25. /// <summary>
  26. /// 取货点设备集合
  27. /// </summary>
  28. private Dictionary<string, List<Device>> PickUpDevices = new();
  29. /// <summary>
  30. /// 放货设备
  31. /// </summary>
  32. private Dictionary<string, List<Device<IStation520, IStation521, IStation523>>> PutDevices = new();
  33. public 机械臂()
  34. {
  35. //获取所有的机械臂 集合
  36. var devices = Device.All.Where(v => v.HasFlag(DeviceFlags.Robot));
  37. //开始分配
  38. foreach (var roobot in devices)
  39. {
  40. //取货设备
  41. PickUpDevices.Add(roobot.Code, roobot.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => v).ToList());
  42. PutDevices.Add(roobot.Code, roobot.Targets.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Device<IStation520, IStation521, IStation523>(v, World)).ToList());
  43. }
  44. }
  45. public override void Do(Device<IRobot520, IRobot521, IRobot522> obj)
  46. {
  47. #region 处理完成任务
  48. //判断DB520 完成任务确认清除信号 是否为1
  49. if (obj.Data.OkAck == 1 && obj.Data2.TaskFinishId1 == 0 || obj.Data2.TaskFinishId2 == 0) obj.Data.OkAck = 0;
  50. if (obj.Data2.TaskFinishId1 > 0 || obj.Data2.TaskFinishId2 > 0)
  51. {
  52. //处理完成的任务信息
  53. WCS_TaskInfo taskInfo = null;
  54. //开始处理
  55. SqlSugarHelper.Do(db =>
  56. {
  57. World.Log($"机械臂任务处理:开始--完成任务{obj.Data2.TaskFinishId1}--{obj.Data2.TaskFinishId2}", LogLevelEnum.Low);
  58. //根据DB521任务号获取对应任务
  59. var taskInfoList = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.ID == obj.Data2.TaskFinishId1 || v.ID == obj.Data2.TaskFinishId2).ToList();
  60. foreach (var task in taskInfoList)
  61. {
  62. if (task.Status != Entity.TaskStatus.StackerExecution) continue;
  63. //根据任务类型做不同的处理
  64. switch (task.Type)
  65. {
  66. case TaskType.SetPlate: //工字轮入库
  67. //完成任务
  68. task.Status = Entity.TaskStatus.Finish;
  69. task.EedTime = DateTime.Now;
  70. db.Default.Updateable(task).ExecuteCommand();
  71. task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "入库任务结束");
  72. break;
  73. case TaskType.OutDepot:
  74. task.Status = Entity.TaskStatus.Finish;
  75. task.EedTime = DateTime.Now;
  76. db.Default.Updateable(task).ExecuteCommand();
  77. task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "出库任务结束");
  78. break;
  79. case TaskType.TransferDepot:
  80. task.Status = Entity.TaskStatus.Finish;
  81. task.EedTime = DateTime.Now;
  82. db.Default.Updateable(task).ExecuteCommand();
  83. task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "移库任务结束");
  84. break;
  85. }
  86. if (task.Status >= Entity.TaskStatus.Finish) task.CompleteOrCancelTasks(db.Default);
  87. taskInfo = task;
  88. }
  89. });
  90. if (taskInfo == null) throw new KnownException("数据库提交事务错误", LogLevelEnum.High);
  91. // 写入信号
  92. obj.Data.OkAck = 1;
  93. //通知WMS任务完成
  94. if (taskInfo.Status == Entity.TaskStatus.Finish) WmsApi.CompleteTask(taskInfo.ID);
  95. if (taskInfo.Type == TaskType.OutDepot && taskInfo.Status == Entity.TaskStatus.ConveyorExecution) WmsApi.SrmPickOutCompleted(taskInfo.ID);
  96. World.Log($"机械臂任务处理:结束--完成任务{obj.Data2.TaskFinishId1}--{obj.Data2.TaskFinishId2}", LogLevelEnum.Mid);
  97. }
  98. #endregion 处理完成任务
  99. //robot是否可以下发任务
  100. if (obj.Data2.VoucherNo != obj.Data.VoucherNo) throw new KnownException($"凭证号不一致,DB520:{obj.Data.VoucherNo},DB521:{obj.Data2.VoucherNo}", LogLevelEnum.Mid);
  101. if (obj.Data2.RobotMode != RobotMode.Automatic) throw new KnownException($"robot处于{obj.Data2.RobotMode.GetDescription()}模式", LogLevelEnum.Low);
  102. if (obj.Data2.RunStatus != RobotRunStatus.Idle) throw new KnownException($"robot处于{obj.Data2.RunStatus.GetDescription()}状态", LogLevelEnum.High);
  103. //上一个周期是不是出库任务 第一次获取返回结果会是false
  104. var lastIsOut = obj.Entity.GetFlag<bool>("LastIsOut");
  105. obj.Entity.SetFlag("LastIsOut", !lastIsOut);
  106. //入库任务优先 或 上一个周期是出库任务并且出库任务无优先
  107. if (lastIsOut) //入库任务
  108. {
  109. //判断本次优先执行楼层,并设置下次执行时优先楼层
  110. var floor = obj.Entity.GetFlag<int>("FloorIn");
  111. floor = floor % 2 + 1;
  112. obj.Entity.SetFlag("FloorIn", floor);
  113. //获取当前机械臂所有的取货站台
  114. var pickUpDevices = obj.Entity.Sources.Where(x => x.HasFlag(DeviceFlags.输送机)).Where(x => x.DeviceGroup.Any()).Select(
  115. x =>
  116. {
  117. var group = x.DeviceGroup.Select(s => new Device<IStation523, IStation524>(s, World)).ToList();
  118. return new Tuple<Device<IStation523, IStation524>, List<Device<IStation523, IStation524>>>(new Device<IStation523, IStation524>(x, World), group);
  119. }).ToList();
  120. if (!pickUpDevices.Any()) throw new KnownException($"机械臂{obj.Entity.Code}无取货路径点", LogLevelEnum.High);
  121. //获取取货设备的设备组中都是停止运行的
  122. var arrIn = pickUpDevices.Where(x => x.Item2.All(a => !a.Data.Status.HasFlag(StationStatus.Run)))
  123. .Where(x => x.Item2.OrderBy(o => o.Entity.Code.ToShort()) //前两个设备中有取货任务的
  124. .Take(2)
  125. .Any(a => a.Data2.TaskNumber > 0 && a.Data.Status.HasFlag(StationStatus.PH_Status)))
  126. .ToList();
  127. if (!arrIn.Any()) throw new KnownException($"[{obj.Entity.Code}]等待入库任务输送到位", LogLevelEnum.Mid);
  128. //等待下发的任务信息
  129. var taskList = new List<Tuple<WCS_TaskInfo, Device<IStation523, IStation524>>>();
  130. SqlSugarHelper.Do(db =>
  131. {
  132. //跟据设备组中第一个设备任务号最小的一个先执行
  133. var devGroup = arrIn.MinBy(x => x.Item2.OrderBy(o => o.Data2.TaskNumber));
  134. foreach (var dev in devGroup.Item2.OrderBy(x => x.Entity.Code.ToShort()).Take(2)
  135. )
  136. {
  137. var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.Type == TaskType.SetPlate && v.Status == Entity.TaskStatus.FinishOfShunt && dev.Data2.TaskNumber == v.ID);
  138. if (task == null) continue;
  139. var res = WmsApi.RingApplyStockInLoc(task.ID, task.Device, dev.Entity.Code, task.Height);
  140. task.Status = Entity.TaskStatus.StackerExecution;
  141. task.AddrTo = res.ResData.CellNo;
  142. task.Line = res.ResData.Row;
  143. task.Col = res.ResData.Colomn;
  144. task.Layer = res.ResData.Layer;
  145. task.Depth = res.ResData.Row;
  146. task.LastInteractionPoint = dev.Entity.Code;
  147. task.SrmStation = dev.Entity.Code;
  148. task.EditWho = "WCS";
  149. db.Default.Updateable(task).ExecuteCommand();
  150. task.AddWCS_TASK_DTL(db.Default, dev.Entity.Code, task.AddrTo, "任务下发机械臂执行");
  151. taskList.Add(new(task, dev));
  152. }
  153. });
  154. if (!taskList.Any()) return;
  155. switch (taskList.Count)
  156. {
  157. case 1:
  158. var task = taskList.FirstOrDefault().Item1;
  159. var dev = taskList.FirstOrDefault().Item2;
  160. //下发任务
  161. obj.Data.TaskNumber1 = task.ID;
  162. obj.Data.SLine1 = dev.Entity.Code.ToShort();
  163. obj.Data.SCol1 = 0;
  164. obj.Data.SLayer1 = 0;
  165. obj.Data.SDepth1 = 0;
  166. obj.Data.ELine1 = task.Line.ToShort();
  167. obj.Data.ECol1 = task.Col.ToShort();
  168. obj.Data.ELayer1 = task.Layer.ToShort();
  169. obj.Data.EDepth1 = task.Depth.ToShort();
  170. obj.Data.TaskNumber2 = 0;
  171. obj.Data.SLine2 = 0;
  172. obj.Data.SCol2 = 0;
  173. obj.Data.SLayer2 = 0;
  174. obj.Data.SDepth2 = 0;
  175. obj.Data.ELine2 = 0;
  176. obj.Data.ECol2 = 0;
  177. obj.Data.ELayer2 = 0;
  178. obj.Data.EDepth2 = 0;
  179. obj.Data.TaskSum = taskList.Count.ToShort();
  180. obj.Data.GoodsType = 1;
  181. obj.Data.TaskType = 3;
  182. obj.Data.VoucherNo++;
  183. break;
  184. case 2:
  185. //一工位取深度较大的任务
  186. var taskInfo = taskList.MaxBy(x => x.Item1.Depth);
  187. task = taskInfo.Item1;
  188. dev = taskInfo.Item2;
  189. obj.Data.TaskNumber1 = task.ID;
  190. obj.Data.SLine1 = dev.Entity.Code.ToShort();
  191. obj.Data.SCol1 = 0;
  192. obj.Data.SLayer1 = 0;
  193. obj.Data.SDepth1 = 0;
  194. obj.Data.ELine1 = task.Line.ToShort();
  195. obj.Data.ECol1 = task.Col.ToShort();
  196. obj.Data.ELayer1 = task.Layer.ToShort();
  197. obj.Data.EDepth1 = task.Depth.ToShort();
  198. //二工位取深度较少的值
  199. taskInfo = taskList.MinBy(x => x.Item1.Depth);
  200. task = taskInfo.Item1;
  201. dev = taskInfo.Item2;
  202. obj.Data.TaskNumber2 = task.ID;
  203. obj.Data.SLine2 = dev.Entity.Code.ToShort();
  204. obj.Data.SCol2 = 0;
  205. obj.Data.SLayer2 = 0;
  206. obj.Data.SDepth2 = 0;
  207. obj.Data.ELine2 = task.Line.ToShort();
  208. obj.Data.ECol2 = task.Col.ToShort();
  209. obj.Data.ELayer2 = task.Layer.ToShort();
  210. obj.Data.EDepth2 = task.Depth.ToShort();
  211. obj.Data.TaskSum = taskList.Count.ToShort();
  212. obj.Data.GoodsType = 1;
  213. obj.Data.TaskType = 3;
  214. obj.Data.VoucherNo++;
  215. break;
  216. default:
  217. throw new KnownException($"无法执行多个任务", LogLevelEnum.Mid);
  218. }
  219. }
  220. else if (!lastIsOut) //出库任务
  221. {
  222. //判断本次优先执行楼层,并设置下次执行时优先楼层
  223. var floor = obj.Entity.GetFlag<int>("FloorOut");
  224. floor = floor % 2 + 1;
  225. obj.Entity.SetFlag("FloorOut", floor);
  226. //获取当前堆垛机所有的取货站台
  227. var arrOut = PutDevices.First(v => v.Key == obj.Entity.Code).Value;
  228. if (!arrOut.Any()) throw new KnownException($"机械臂{obj.Entity.Code}无放货路径点", LogLevelEnum.High);
  229. //获取可以放货的设备集合
  230. arrOut = arrOut.Where(v => v.Data3.Status.HasFlag(StationStatus.PH_Status)).ToList();//无光电
  231. if (!arrOut.Any()) throw new KnownException($"[{obj.Entity.Code}]等待出库任务输送到位", LogLevelEnum.Mid);
  232. WCS_TaskInfo taskInfo = null;
  233. SqlSugarHelper.Do(db =>
  234. {
  235. var allOutCode = arrOut.Select(v => v.Entity.Code).ToList();
  236. var task = db.Default.Queryable<WCS_TaskInfo>().Where(v => v.Type == TaskType.OutDepot && v.Status == Entity.TaskStatus.WaitingToExecute)
  237. .Where(v => allOutCode.Contains(v.SrmStation))
  238. .OrderByDescending(v => v.Priority)
  239. .OrderBy(v => v.AddTime)
  240. .First() ?? throw new KnownException($"{obj.Entity.Code}未找到出库任务", LogLevelEnum.High);
  241. task.Status = Entity.TaskStatus.StackerExecution;
  242. task.LastInteractionPoint = task.Device;
  243. task.EditWho = "WCS";
  244. db.Default.Updateable(task).ExecuteCommand();
  245. task.AddWCS_TASK_DTL(db.Default, task.Device, task.SrmStation, "任务下发机械臂执行");
  246. taskInfo = task;
  247. });
  248. if (taskInfo == null) throw new KnownException("数据更新错误", LogLevelEnum.High);
  249. var addrFrom = taskInfo.AddrFrom.Split("-");
  250. obj.Data.TaskNumber1 = taskInfo.ID;
  251. obj.Data.SLine1 = addrFrom[0].ToShort();
  252. obj.Data.SCol1 = addrFrom[1].ToShort();
  253. obj.Data.SLayer1 = addrFrom[2].ToShort();
  254. obj.Data.SDepth1 = addrFrom[3].ToShort();
  255. obj.Data.ELine1 = taskInfo.SrmStation.ToShort();
  256. obj.Data.ECol1 = taskInfo.ProdLine;
  257. obj.Data.TaskSum = 1;
  258. obj.Data.GoodsType = 1;
  259. obj.Data.TaskType = 4;
  260. obj.Data.VoucherNo++;
  261. }
  262. }
  263. public override bool Select(Device dev)
  264. {
  265. return dev.HasFlag(DeviceFlags.Robot);
  266. }
  267. }
  268. }