机械臂cs.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. using Newtonsoft.Json;
  2. using ServiceCenter.Extensions;
  3. using ServiceCenter.Logs;
  4. using ServiceCenter.SqlSugars;
  5. using System.ComponentModel;
  6. using WCS.Core;
  7. using WCS.Entity;
  8. using WCS.Entity.Protocol.Protocol.Robot;
  9. using WCS.Entity.Protocol.Robot;
  10. using WCS.Entity.Protocol.Station;
  11. using WCS.WorkEngineering.Extensions;
  12. using WCS.WorkEngineering.Worlds.环形库.环形库;
  13. using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
  14. using TaskStatus = WCS.Entity.TaskStatus;
  15. namespace WCS.WorkEngineering.Systems
  16. {
  17. /// <summary>
  18. /// 机械臂
  19. /// </summary>
  20. [BelongTo(typeof(RingWorld1))]
  21. [Description("机械臂")]
  22. public class 机械臂 : DeviceSystem<Device<IRobot520, IRobot521, IRobot522>>
  23. {
  24. protected override bool ParallelDo => 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, IRobot530>>> PutDevices = new();
  33. public 机械臂()
  34. {
  35. //获取所有的机械臂 集合
  36. var devices = Device.All.Where(v => v.HasFlag(DeviceFlags.Robot));
  37. //开始分配
  38. foreach (var robot in devices)
  39. {
  40. //取货设备
  41. PickUpDevices.Add(robot.Code, robot.Sources.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => v).ToList());
  42. PutDevices.Add(robot.Code, robot.Targets.Where(v => v.HasFlag(DeviceFlags.输送机)).Select(v => new Device<IStation520, IStation521, IStation523, IRobot530>(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 is { TaskFinishId1: 0, TaskFinishId2: 0 }) obj.Data.OkAck = 0;
  50. if (obj.Data2.TaskFinishId1 > 0 || obj.Data2.TaskFinishId2 > 0)
  51. {
  52. //处理完成的任务信息
  53. var tasks = new List<WCS_TaskInfo>();
  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.Where(task => task.Status == Entity.TaskStatus.StackerExecution))
  61. {
  62. //根据任务类型做不同的处理
  63. switch (task.Type)
  64. {
  65. case TaskType.SetPlate: //工字轮入库
  66. //完成任务
  67. task.Status = Entity.TaskStatus.Finish;
  68. task.EndTime = DateTime.Now;
  69. db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
  70. task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "入库任务结束");
  71. break;
  72. case TaskType.OutDepot:
  73. //var pall = db.Default.Queryable<WCS_TaskInfo>().Where(x => x.AddrTo == task.AddrTo && x.Type == TaskType.Delivery && x.Status < TaskStatus.Finish).First() ?? throw new Exception($"未找到对应的托盘搬运任务,无法进行绑盘");
  74. task.Status = Entity.TaskStatus.StackerCompleted;
  75. task.EditTime = DateTime.Now;
  76. db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EditTime }).ExecuteCommand();
  77. task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "出库任务结束");
  78. break;
  79. case TaskType.TransferDepot:
  80. task.Status = Entity.TaskStatus.Finish;
  81. task.EndTime = DateTime.Now;
  82. db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.EndTime }).ExecuteCommand();
  83. task.AddWCS_TASK_DTL(db.Default, task.AddrTo, "移库任务结束");
  84. break;
  85. }
  86. tasks.Add(task);
  87. }
  88. });
  89. if (!tasks.Any()) throw new KnownException("数据库提交事务错误", LogLevelEnum.High);
  90. // 写入信号
  91. obj.Data.OkAck = 1;
  92. World.Log($"机械臂任务处理:结束--完成任务{obj.Data2.TaskFinishId1}--{obj.Data2.TaskFinishId2}", LogLevelEnum.Mid);
  93. }
  94. #endregion 处理完成任务
  95. //robot是否可以下发任务
  96. if (obj.Data2.VoucherNo != obj.Data.VoucherNo)
  97. {
  98. World.Log($"凭证号不一致,DB520:{obj.Data.VoucherNo},DB521:{obj.Data2.VoucherNo}", LogLevelEnum.Mid);
  99. return;
  100. }
  101. if (obj.Data2.RobotMode != RobotMode.Automatic)
  102. {
  103. World.Log($"robot处于{obj.Data2.RobotMode.GetDescription()}模式", LogLevelEnum.Mid);
  104. return;
  105. }
  106. if (obj.Data2.RunStatus != RobotRunStatus.Idle)
  107. {
  108. World.Log($"robot处于{obj.Data2.RunStatus.GetDescription()}状态", LogLevelEnum.Mid);
  109. return;
  110. }
  111. //判断是否有任务是机器人执行中
  112. //再检查是否有等待执行的货物
  113. SqlSugarHelper.Do(db =>
  114. {
  115. //获取当前堆垛机的所有未完成任务 ,就算查到了未提交的事务也无所谓,无非下一个周期再执行一次
  116. var tasks = db.Default.Queryable<WCS_TaskInfo>().NoLock().Where(v => v.Status < Entity.TaskStatus.Finish && v.Device == obj.Entity.Code);
  117. //任务集合是否有处于堆垛机执行状态的任务
  118. if (tasks.Any(v => v.Status == Entity.TaskStatus.StackerExecution)) throw new KnownException($"有任务处于堆垛机执行状态", LogLevelEnum.High);
  119. });
  120. //获取入库次数
  121. var inQuantity = obj.Entity.GetFlag<int>("InQuantity");
  122. var inMaxQuantity = 2; //出入库的周期检查比为1:3
  123. //入库任务优先 或 上一个周期是出库任务并且出库任务无优先
  124. if (inQuantity <= inMaxQuantity) //入库任务
  125. {
  126. //判断本次优先执行楼层,并设置下次执行时优先楼层
  127. var floor = obj.Entity.GetFlag<int>("FloorIn");
  128. floor = floor % 2 + 1;
  129. obj.Entity.SetFlag("FloorIn", floor);
  130. obj.Entity.SetFlag("InQuantity", inQuantity + 1);
  131. //获取当前机械臂所有的取货站台
  132. var pickUpDevices = obj.Entity.Sources.Where(x => x.HasFlag(DeviceFlags.输送机)).Where(x => x.DeviceGroup.Any()).Select(
  133. x =>
  134. {
  135. var group = x.DeviceGroup.Select(s => new Device<IStation523, IStation524>(s, World)).ToList();
  136. return new Tuple<Device<IStation523, IStation524>, List<Device<IStation523, IStation524>>>(new Device<IStation523, IStation524>(x, World), group);
  137. }).ToList();
  138. if (!pickUpDevices.Any()) throw new KnownException($"机械臂{obj.Entity.Code}无取货路径点", LogLevelEnum.High);
  139. //获取取货设备的设备组中都是停止运行的
  140. var arrIn = pickUpDevices.Where(x => x.Item2.All(a => !a.Data.Status.HasFlag(StationStatus.Run)))
  141. .Where(x =>
  142. {
  143. var inStock = x.Item2.Any(a => a.Data2.TaskNumber > 0 && a.Data.Status.HasFlag(StationStatus.PH_Status));
  144. var minDevice = x.Item2.OrderBy(o => o.Entity.Code.ToShort()).First();
  145. return minDevice.Data2.TaskNumber > 0 && minDevice.Data.Status.HasFlag(StationStatus.PH_Status) && minDevice.Data2.CmdType.HasFlag(StationCmd.Res7) && inStock;
  146. }).ToList();
  147. //.OrderBy(x => x.Item1.Data2.TaskNumber)
  148. if (!arrIn.Any())
  149. {
  150. World.Log($"[{obj.Entity.Code}]等待入库任务输送到位");
  151. obj.Entity.SetFlag("InQuantity", 4); //在无货物的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
  152. return;
  153. }
  154. //等待下发的任务信息
  155. var taskList = new List<Tuple<WCS_TaskInfo, Device<IStation523, IStation524>>>();
  156. SqlSugarHelper.Do(db =>
  157. {
  158. //跟据设备组中第一个设备任务号最小的一个先执行
  159. var devGroup = arrIn.MinBy(x => x.Item1.Data2.TaskNumber).Item2
  160. .Where(x => x.Data2.TaskNumber > 0 && x.Data.Status.HasFlag(StationStatus.PH_Status));
  161. if (!devGroup.Any())
  162. {
  163. obj.Entity.SetFlag("InQuantity", 4); //在无有效取货位的情况下,只检查一次,下次直接查询是否有出库任务,避免无效检查周期的产生
  164. throw new KnownException($"无有效入库取货位", LogLevelEnum.High);
  165. }
  166. foreach (var dev in devGroup)
  167. {
  168. var task = db.Default.Queryable<WCS_TaskInfo>().First(v => v.Type == TaskType.SetPlate && v.Status == Entity.TaskStatus.FinishOfShunt && dev.Data2.TaskNumber == v.ID);
  169. if (task == null) continue;
  170. task.Status = Entity.TaskStatus.StackerExecution;
  171. task.LastInteractionPoint = dev.Entity.Code;
  172. task.SrmStation = dev.Entity.Code;
  173. task.Device = obj.Entity.Code;
  174. task.EditWho = "WCS";
  175. db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.AddrTo, x.Line, x.Col, x.Layer, x.Depth, x.LastInteractionPoint, x.SrmStation, x.Device, x.EditWho }).ExecuteCommand();
  176. task.AddWCS_TASK_DTL(db.Default, dev.Entity.Code, task.AddrTo, "任务下发机械臂执行");
  177. taskList.Add(new(task, dev));
  178. }
  179. });
  180. if (!taskList.Any()) return;
  181. switch (taskList.Count)
  182. {
  183. case 1:
  184. var task = taskList.FirstOrDefault().Item1;
  185. var dev = taskList.FirstOrDefault().Item2;
  186. //下发任务
  187. obj.Data.TaskNumber1 = task.ID;
  188. obj.Data.SLine1 = dev.Entity.Code.ToShort();
  189. obj.Data.SCol1 = 0;
  190. obj.Data.SLayer1 = 0;
  191. obj.Data.SDepth1 = 0;
  192. obj.Data.ELine1 = task.Line.ToShort();
  193. obj.Data.ECol1 = task.Col.ToShort();
  194. obj.Data.ELayer1 = task.Layer.ToShort();
  195. obj.Data.EDepth1 = task.Depth.ToShort();
  196. obj.Data.TaskNumber2 = 0;
  197. obj.Data.SLine2 = 0;
  198. obj.Data.SCol2 = 0;
  199. obj.Data.SLayer2 = 0;
  200. obj.Data.SDepth2 = 0;
  201. obj.Data.ELine2 = 0;
  202. obj.Data.ECol2 = 0;
  203. obj.Data.ELayer2 = 0;
  204. obj.Data.EDepth2 = 0;
  205. obj.Data.TaskSum = taskList.Count.ToShort();
  206. obj.Data.GoodsType = task.GoodsType switch
  207. {
  208. 18 => 1,
  209. 34 => 2,
  210. 50 => 3,
  211. _ => 0
  212. };
  213. obj.Data.TaskType = 3;
  214. obj.Data.VoucherNo++;
  215. break;
  216. case 2:
  217. taskList = taskList.OrderBy(x => x.Item1.Depth).ToList();
  218. //一工位取深度较大的任务
  219. var taskInfo = taskList[1];
  220. task = taskInfo.Item1;
  221. dev = taskInfo.Item2;
  222. obj.Data.TaskNumber1 = task.ID;
  223. obj.Data.SLine1 = dev.Entity.Code.ToShort();
  224. obj.Data.SCol1 = 0;
  225. obj.Data.SLayer1 = 0;
  226. obj.Data.SDepth1 = 0;
  227. obj.Data.ELine1 = task.Line.ToShort();
  228. obj.Data.ECol1 = task.Col.ToShort();
  229. obj.Data.ELayer1 = task.Layer.ToShort();
  230. obj.Data.EDepth1 = task.Depth.ToShort();
  231. //二工位取深度较少的值
  232. taskInfo = taskList[0];
  233. task = taskInfo.Item1;
  234. dev = taskInfo.Item2;
  235. obj.Data.TaskNumber2 = task.ID;
  236. obj.Data.SLine2 = dev.Entity.Code.ToShort();
  237. obj.Data.SCol2 = 0;
  238. obj.Data.SLayer2 = 0;
  239. obj.Data.SDepth2 = 0;
  240. obj.Data.ELine2 = task.Line.ToShort();
  241. obj.Data.ECol2 = task.Col.ToShort();
  242. obj.Data.ELayer2 = task.Layer.ToShort();
  243. obj.Data.EDepth2 = task.Depth.ToShort();
  244. obj.Data.TaskSum = taskList.Count.ToShort();
  245. obj.Data.GoodsType = task.GoodsType switch
  246. {
  247. 18 => 1,
  248. 34 => 2,
  249. 50 => 3,
  250. _ => 0
  251. };
  252. obj.Data.TaskType = 3;
  253. obj.Data.VoucherNo++;
  254. break;
  255. default:
  256. throw new KnownException($"无法执行多个任务", LogLevelEnum.Mid);
  257. }
  258. World.Log($"机械臂任务处理:下发入库任务{obj.Data.TaskNumber1}--{obj.Data.TaskNumber2}--{obj.Data.VoucherNo}", LogLevelEnum.Mid);
  259. }
  260. else //出库任务
  261. {
  262. //判断本次优先执行楼层,并设置下次执行时优先楼层
  263. var floor = obj.Entity.GetFlag<int>("FloorOut");
  264. floor = floor % 2 + 1;
  265. obj.Entity.SetFlag("FloorOut", floor);
  266. obj.Entity.SetFlag("InQuantity", 0);
  267. //获取当前堆垛机所有的取货站台
  268. var arrOut = PutDevices.First(v => v.Key == obj.Entity.Code).Value;
  269. if (!arrOut.Any()) throw new KnownException($"机械臂{obj.Entity.Code}无放货路径点", LogLevelEnum.High);
  270. //获取可以放货的设备集合
  271. arrOut = arrOut.Where(v => v.Data3.Status.HasFlag(StationStatus.PH_Status) && v.Data.TaskNumber == 0 && v.Data.GoodsEnd == 0).ToList();//有光电
  272. if (!arrOut.Any())
  273. {
  274. World.Log($"[{obj.Entity.Code}]等待出库任务输送到位");
  275. return;
  276. }
  277. var taskInfoList = new List<WCS_TaskInfo>();
  278. var nextAdd = "";
  279. SqlSugarHelper.Do(db =>
  280. {
  281. //所有出库点设备号,即
  282. var allOutCode = arrOut.Select(v => new
  283. {
  284. v.Entity.Code,
  285. v.Data4.Type
  286. }).ToList();
  287. //两个工位同时码垛,并不会一个执行一次,只有一个托盘任务全部执行完毕,才会继续执行下一个,先生成任务的码垛工位会优先执行
  288. var taskInfos = db.Default.Queryable<WCS_TaskInfo>().Where(v => (v.Status == Entity.TaskStatus.WaitingToExecute || v.Status == TaskStatus.ConveyorExecution) && v.Type == TaskType.OutDepot)
  289. .ToList().Where(v => allOutCode.Any(x => v.SrmStation == x.Code && v.PalletType == x.Type)).ToList();
  290. var deliveryTask = db.Default.Queryable<WCS_TaskInfo>().Where(x => x.Status > 0 && x.Type == TaskType.Delivery).ToList().Select(x => x.AddrTo);
  291. taskInfos = taskInfos.Where(x => deliveryTask.Contains(x.SrmStation)).ToList();
  292. if (!taskInfos.Any())
  293. {
  294. World.Log("等待空托盘到位");
  295. return;
  296. }
  297. if (!taskInfos.Any()) throw new KnownException($"未找到站台{JsonConvert.SerializeObject(allOutCode)}可用的出库任务", LogLevelEnum.Mid);
  298. var srmStation = taskInfos.GroupBy(x => x.SrmStation).Where(x => x.Any(s => s.Status == TaskStatus.WaitingToExecute)).Select(x => new
  299. {
  300. x.Key,
  301. x.OrderByDescending(t => t.AddTime).First().AddTime
  302. }).OrderBy(x => x.AddTime).First().Key;
  303. taskInfos = taskInfos.Where(x => x.SrmStation == srmStation).ToList(); //找到一个可以放货的待执行站台
  304. //如果全部是待执行状态,需要验证待执行的任务的数量是否与任务总数相等
  305. if (taskInfos.All(x => x.Status == TaskStatus.WaitingToExecute))
  306. {
  307. var task = taskInfos.First();
  308. if (task.FullQty != taskInfos.Count) throw new KnownException($"等待站台{srmStation}所有码垛出库任务完成初始化", LogLevelEnum.Mid);
  309. }
  310. taskInfos = taskInfos.Where(x => x.Status == TaskStatus.WaitingToExecute).OrderBy(x => x.ProdLine).ToList();
  311. if (taskInfos.FirstOrDefault().WarehouseCode.Contains("S")) //如果是南侧,翻转排序
  312. {
  313. taskInfos = taskInfos.OrderByDescending(x => x.ProdLine).ToList();
  314. }
  315. taskInfos = taskInfos.Take(2).ToList();
  316. var warehouseCode = taskInfos.FirstOrDefault().WarehouseCode;
  317. if (taskInfos.Count == 2) //有两个任务
  318. {
  319. var minDepth = taskInfos!.MinBy(x => x.Depth);
  320. var maxDepth = taskInfos.MaxBy(x => x.Depth);
  321. //产品类型不同时,只能取一个
  322. if (minDepth.GoodsType != maxDepth.GoodsType)
  323. {
  324. //南边取位号较大的,北边取位号较小的
  325. taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
  326. }
  327. //深度之和等于6(机械臂当前无法同时执行两个三深度的取货任务)
  328. else if (taskInfos.Sum(x => x.Depth) == 6)
  329. {
  330. taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
  331. }
  332. else if (taskInfos[0].SrmStation != taskInfos[1].SrmStation)
  333. {
  334. taskInfos = warehouseCode.Contains("S") ? taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList() : taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
  335. }
  336. else if (warehouseCode.Contains("S"))
  337. {
  338. //从大到小 一抓偶数
  339. var max = taskInfos.MaxBy(x => x.ProdLine).ProdLine;
  340. if ((max & 1) == 1) //抓一不是偶数
  341. {
  342. taskInfos = taskInfos.OrderByDescending(x => x.ProdLine).Take(1).ToList();
  343. }
  344. }
  345. else if (warehouseCode.Contains("N"))
  346. {
  347. //从小到达 一抓奇数
  348. var mix = taskInfos.MinBy(x => x.ProdLine).ProdLine;
  349. if ((mix & 1) == 0) //抓一不是奇数
  350. {
  351. taskInfos = taskInfos.OrderBy(x => x.ProdLine).Take(1).ToList();
  352. }
  353. }
  354. }
  355. foreach (var task in taskInfos)
  356. {
  357. task.Status = Entity.TaskStatus.StackerExecution;
  358. task.LastInteractionPoint = task.Device;
  359. task.StartTime = DateTime.Now;
  360. task.EditWho = "WCS";
  361. nextAdd = task.SrmStation;
  362. db.Default.UpdateableRowLock(task).UpdateColumns(x => new { x.Status, x.LastInteractionPoint, x.StartTime, x.EditWho }).ExecuteCommand();
  363. task.AddWCS_TASK_DTL(db.Default, task.Device, task.SrmStation, "任务下发机械臂执行");
  364. taskInfoList.Add(task);
  365. }
  366. });
  367. if (!taskInfoList.Any()) return;
  368. switch (taskInfoList.Count)
  369. {
  370. case 1:
  371. var task = taskInfoList.FirstOrDefault();
  372. //下发任务
  373. obj.Data.TaskNumber1 = task.ID;
  374. obj.Data.SLine1 = task.Line.ToShort();
  375. obj.Data.SCol1 = task.Col.ToShort();
  376. obj.Data.SLayer1 = task.Layer.ToShort();
  377. obj.Data.SDepth1 = task.Depth.ToShort();
  378. obj.Data.ELine1 = nextAdd.ToShort();
  379. obj.Data.ECol1 = task.ProdLine;
  380. obj.Data.ELayer1 = 0;
  381. obj.Data.EDepth1 = 0;
  382. obj.Data.TaskNumber2 = 0;
  383. obj.Data.SLine2 = 0;
  384. obj.Data.SCol2 = 0;
  385. obj.Data.SLayer2 = 0;
  386. obj.Data.SDepth2 = 0;
  387. obj.Data.ELine2 = 0;
  388. obj.Data.ECol2 = 0;
  389. obj.Data.ELayer2 = 0;
  390. obj.Data.EDepth2 = 0;
  391. obj.Data.TaskSum = taskInfoList.Count.ToShort();
  392. obj.Data.GoodsType = task.GoodsType switch
  393. {
  394. 18 => 1,
  395. 34 => 2,
  396. 50 => 3,
  397. _ => 0
  398. };
  399. obj.Data.TaskType = 4;
  400. obj.Data.VoucherNo++;
  401. break;
  402. case 2:
  403. taskInfoList = taskInfoList.OrderBy(x => x.Depth).ToList();
  404. //一工位取深度较大的任务
  405. var taskInfo = taskInfoList[1];
  406. obj.Data.TaskNumber1 = taskInfo.ID;
  407. obj.Data.SLine1 = taskInfo.Line.ToShort();
  408. obj.Data.SCol1 = taskInfo.Col.ToShort();
  409. obj.Data.SLayer1 = taskInfo.Layer.ToShort();
  410. obj.Data.SDepth1 = taskInfo.Depth.ToShort();
  411. obj.Data.ELine1 = nextAdd.ToShort();
  412. obj.Data.ECol1 = taskInfo.WarehouseCode.Contains("S") ? taskInfoList.Max(x => x.ProdLine) : taskInfoList.Min(x => x.ProdLine);
  413. obj.Data.ELayer1 = 0;
  414. obj.Data.EDepth1 = 0;
  415. //二工位取深度较少的值
  416. taskInfo = taskInfoList[0];
  417. obj.Data.TaskNumber2 = taskInfo.ID;
  418. obj.Data.SLine2 = taskInfo.Line.ToShort();
  419. obj.Data.SCol2 = taskInfo.Col.ToShort();
  420. obj.Data.SLayer2 = taskInfo.Layer.ToShort();
  421. obj.Data.SDepth2 = taskInfo.Depth.ToShort();
  422. obj.Data.ELine2 = nextAdd.ToShort();
  423. obj.Data.ECol2 = taskInfo.WarehouseCode.Contains("S") ? taskInfoList.Min(x => x.ProdLine) : taskInfoList.Max(x => x.ProdLine);
  424. obj.Data.ELayer2 = 0;
  425. obj.Data.EDepth2 = 0;
  426. obj.Data.TaskSum = taskInfoList.Count.ToShort();
  427. obj.Data.GoodsType = taskInfo.GoodsType switch
  428. {
  429. 18 => 1,
  430. 34 => 2,
  431. 50 => 3,
  432. _ => 0
  433. };
  434. obj.Data.TaskType = 4;
  435. obj.Data.VoucherNo++;
  436. break;
  437. default:
  438. throw new KnownException($"无法执行多个任务", LogLevelEnum.Mid);
  439. }
  440. World.Log($"机械臂任务处理:下发出库任务{obj.Data.TaskNumber1}--{obj.Data.TaskNumber2}--{obj.Data.VoucherNo}", LogLevelEnum.Mid);
  441. }
  442. }
  443. public override bool Select(Device dev)
  444. {
  445. return dev.Code is "Robot1" or "Robot2" or "Robot3" or "Robot4" or "Robot5" or "Robot6";
  446. }
  447. }
  448. }