终端一体化运控平台
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

943 行
40 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using BPA.Message.Enum;
  4. using BPASmartClient.Device;
  5. using BPASmartClient.Model;
  6. using BPASmartClient.Peripheral;
  7. using BPA.Helper;
  8. using System.Threading;
  9. using BPA.Message;
  10. using System.Linq;
  11. using BPASmartClient.Model.PLC;
  12. using System.Threading.Tasks;
  13. using System.Reflection;
  14. using BPASmartClient.MorkMV1.Model;
  15. using System.Collections.ObjectModel;
  16. using BPASmartClient.MorkMV1.ViewModel;
  17. using BPASmartClient.Business;
  18. using BPASmartClient.Model.小炒机;
  19. using BPA.Models;
  20. using System.Windows.Forms;
  21. using System.Media;
  22. using BPASmartClient.CustomResource;
  23. using Microsoft.EntityFrameworkCore.Metadata.Internal;
  24. using static BPA.Helper.EventBus;
  25. //using BPA.Helper;
  26. namespace BPASmartClient.MorkMV1
  27. {
  28. public class Control_MorkMV1 : BaseDevice
  29. {
  30. public override DeviceClientType DeviceType => DeviceClientType.MORKM;
  31. GVL_MorkMV1 mORKM = new GVL_MorkMV1();
  32. Alarm alarm = new Alarm();
  33. public override void DoMain()
  34. {
  35. MonitorViewModel.DeviceId = DeviceId;
  36. ServerInit();
  37. DataParse();
  38. Json<MorksPar>.Read();
  39. Json<OrderStatistics>.Read();
  40. if (Json<MorksPar>.Data.parSets == null) Json<MorksPar>.Data.parSets = new ObservableCollection<ParSet>();
  41. if (Json<MorksPar>.Data.parSets.Count < 6)
  42. {
  43. Json<MorksPar>.Data.parSets.Clear();
  44. for (int i = 0; i < 6; i++)
  45. {
  46. Json<MorksPar>.Data.parSets.Add(new ParSet()
  47. {
  48. CheckBoxContext = $"煮面口{i + 1}屏蔽",
  49. Minute = 1,
  50. Second = 0,
  51. IsShield = false,
  52. TextBlockContext = $"煮面口{i + 1}时间设定"
  53. });
  54. }
  55. }
  56. ActionManage.GetInstance.Register(new Action<object[]>((o) =>
  57. {
  58. if (o.Length > 0)
  59. {
  60. Random rd = new Random();
  61. TaskManage.GetInstance.StartLong(new Action(() =>
  62. {
  63. int NoodleLoc = (int)o[0] == 0 ? rd.Next(1, 6) : (int)o[0];
  64. int BowlLoc = (int)o[1] == 0 ? rd.Next(10, 12) : (int)o[1];
  65. string guid = new Guid().ToString();
  66. mORKM.RBTakeNoodleTask.Enqueue(new MOrderLocInfo() { Loc = (ushort)NoodleLoc, SuborderId = guid });
  67. MessageLog.GetInstance.Show($"添加订单:面条位置【{NoodleLoc}】");
  68. mORKM.TakeBowlTask.Enqueue(new MOrderLocInfo() { Loc = (ushort)BowlLoc, SuborderId = guid });
  69. MessageLog.GetInstance.Show($"添加订单:碗位置【{BowlLoc}】");
  70. Thread.Sleep(60000);
  71. }), "ForOrder");
  72. }
  73. }), "EnableForOrder");
  74. ActionManage.GetInstance.Register(new Action<object>((o) =>
  75. {
  76. if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value);
  77. }), "WriteVW");
  78. ActionManage.GetInstance.Register(new Action<object>((o) =>
  79. {
  80. if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value);
  81. }), "WriteBools");
  82. ActionManage.GetInstance.Register(new Action(() => { DeviceInit(); }), "InitDevice");
  83. }
  84. public override void ResetProgram()
  85. {
  86. mORKM = null;
  87. mORKM = new GVL_MorkMV1();
  88. }
  89. public override void Stop()
  90. {
  91. }
  92. private void ServerInit()
  93. {
  94. //物料信息
  95. EventBus.GetInstance().Subscribe<MaterialDeliveryEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  96. {
  97. if (@event == null) return;
  98. if (@event is MaterialDeliveryEvent material)
  99. {
  100. orderMaterialDelivery = material.orderMaterialDelivery;
  101. }
  102. });
  103. //配方数据信息
  104. EventBus.GetInstance().Subscribe<RecipeBomEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  105. {
  106. if (@event == null) return;
  107. if (@event is RecipeBomEvent recipe)
  108. {
  109. recipeBoms = recipe.recipeBoms;
  110. }
  111. });
  112. }
  113. private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS)
  114. {
  115. var res = mORKM.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid);
  116. string goodName = string.Empty;
  117. string SortNum = string.Empty;
  118. if (res != null)
  119. {
  120. goodName = res.MorkOrder.GoodsName;
  121. SortNum = res.MorkOrder.SortNum.ToString();
  122. }
  123. if (!string.IsNullOrEmpty(goodName) && !string.IsNullOrEmpty(SortNum))
  124. {
  125. EventBus.GetInstance().Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType });
  126. var index = DataServer.GetInstance.morkS.MakeOrder.FindIndex(p => p.SortNum == SortNum);
  127. if (index >= 0 && index < DataServer.GetInstance.morkS.MakeOrder.Count)
  128. {
  129. if (oRDER_STATUS == ORDER_STATUS.COMPLETED_COOK)
  130. {
  131. DataServer.GetInstance.morkS.MakeOrder.RemoveAt(index);
  132. DataServer.GetInstance.morkS.MakeOrderOver.Add(new OrderMakeModel()
  133. {
  134. Status = oRDER_STATUS,
  135. GoodName = goodName,
  136. SortNum = SortNum,
  137. StopTime = DateTime.Now.ToString("HH:mm:ss")
  138. });
  139. }
  140. else if (oRDER_STATUS == ORDER_STATUS.COMPLETED_TAKE)
  141. {
  142. var temp = DataServer.GetInstance.morkS.MakeOrderOver.FirstOrDefault(p => p.SortNum == SortNum);
  143. if (temp != null) DataServer.GetInstance.morkS.MakeOrderOver.Remove(temp);
  144. }
  145. else
  146. {
  147. DataServer.GetInstance.morkS.MakeOrder.ElementAt(index).Status = oRDER_STATUS;
  148. }
  149. }
  150. else
  151. {
  152. DataServer.GetInstance.morkS.MakeOrder.Add(new OrderMakeModel()
  153. {
  154. Status = oRDER_STATUS,
  155. GoodName = goodName,
  156. SortNum = SortNum,
  157. StartTime = DateTime.Now.ToString("HH:mm:ss")
  158. });
  159. }
  160. }
  161. }
  162. private void GetStatus(string key, Action<object> action)
  163. {
  164. if (peripheralStatus.ContainsKey(key))
  165. {
  166. if (peripheralStatus[key] != null)
  167. {
  168. action?.Invoke(peripheralStatus[key]);
  169. }
  170. }
  171. }
  172. public override void ReadData()
  173. {
  174. DataServer.GetInstance.morkS.Alarm.Clear();
  175. alarms.ForEach(item =>
  176. {
  177. DataServer.GetInstance.morkS.Alarm.Add(new AlarmModel()
  178. {
  179. AlarmTime = $"{item.Date} {item.Time}",
  180. AlarmMs = item.Info
  181. });
  182. });
  183. GetStatus("M0.1", new Action<object>((obj) =>
  184. {
  185. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 7)
  186. {
  187. Initing = !bools[0];
  188. mORKM.InitComplete = bools[0];
  189. mORKM.MoveScrewRodInitCom = bools[1];
  190. mORKM.SacrificialVesselInitCom = bools[2];
  191. mORKM.CylinderInitCom = bools[3];
  192. mORKM.NoodleCookerInitCom = bools[4];
  193. mORKM.RobotInitCom = bools[5];
  194. mORKM.SiloInitCom = bools[6];
  195. alarm.DeviceNoInit = !mORKM.InitComplete;
  196. alarm.MoveScrewRodNoInit = !mORKM.MoveScrewRodInitCom;
  197. alarm.SacrificialVesselNoInit = !mORKM.SacrificialVesselInitCom;
  198. alarm.CylinderNoInit = !mORKM.CylinderInitCom;
  199. alarm.NoodleCookerNoInit = !mORKM.NoodleCookerInitCom;
  200. alarm.RobotNoInit = !mORKM.RobotInitCom;
  201. alarm.SiloNoInit = !mORKM.SiloInitCom;
  202. }
  203. }));
  204. GetStatus("M10.0", new Action<object>((obj) =>
  205. {
  206. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 2)
  207. {
  208. mORKM.AllowInvertedFace = bools[0];
  209. mORKM.DiningComplete = bools[1];
  210. }
  211. }));
  212. GetStatus("M10.4", new Action<object>((obj) =>
  213. {
  214. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1)
  215. {
  216. mORKM.DropBowlMechanismStatus = bools[0];
  217. }
  218. }));
  219. GetStatus("M12.2", new Action<object>((obj) =>
  220. {
  221. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1)
  222. {
  223. mORKM.FixedFlag = bools[0];
  224. }
  225. }));
  226. GetStatus("M13.5", new Action<object>((obj) =>
  227. {
  228. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1)
  229. {
  230. mORKM.SiloInPlace = bools[0];
  231. }
  232. }));
  233. GetStatus("M16.6", new Action<object>((obj) =>
  234. {
  235. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 2)
  236. {
  237. mORKM.RobotInvertedSurfaceCom = bools[0];
  238. mORKM.RobotTakeNoodleCom = bools[1];
  239. }
  240. }));
  241. GetStatus("M17.4", new Action<object>((obj) =>
  242. {
  243. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1)
  244. {
  245. mORKM.RobotStatus = bools[0];
  246. }
  247. }));
  248. GetStatus("M18.0", new Action<object>((obj) =>
  249. {
  250. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 5)
  251. {
  252. mORKM.SmallBowlYesOrNoCheck = bools[0];
  253. mORKM.LargeBowYesOrNoCheck = bools[1];
  254. mORKM.TurntableLowPosition = bools[2];
  255. mORKM.TurntableHighPosition = bools[3];
  256. alarm.Supply2_LossBowl = !mORKM.SmallBowlYesOrNoCheck;
  257. alarm.Supply1_LossBowl = !mORKM.LargeBowYesOrNoCheck;
  258. }
  259. }));
  260. GetStatus("VW17", new Action<object>((obj) =>
  261. {
  262. if (obj is ushort[] ushorts && ushorts.Length > 0 && ushorts.Length <= 1)
  263. {
  264. var tt = ushorts.ToBytes(true).ToUshorts();
  265. for (byte i = 0; i < 6; i++)
  266. {
  267. if (RTrig.GetInstance($"CookNoodleCom{i + 1}").Start(tt[0].GetBitValue((byte)(i + 1))))
  268. {
  269. if (!string.IsNullOrEmpty(mORKM.CookNodelId[i]))
  270. mORKM.CookNoodleCom[i] = true;
  271. }
  272. }
  273. mORKM.Heating = ushorts[0].GetBitValue(15);
  274. mORKM.TemperatureReaches = ushorts[0].GetBitValue(16);
  275. alarm.MachineLowTemperature = !mORKM.TemperatureReaches;
  276. }
  277. }));
  278. GetStatus("VW770", new Action<object>((obj) =>
  279. {
  280. if (obj is ushort[] ushorts && ushorts.Length > 0 && ushorts.Length <= 1)
  281. {
  282. mORKM.CurrentFeedbackLoc = ushorts[0];
  283. }
  284. }));
  285. mORKM.TakeBowlTaskCount = mORKM.TakeBowlTask.Count;
  286. mORKM.RBTakeNoodleTaskCount = mORKM.RBTakeNoodleTask.Count;
  287. for (int i = 0; i < Json<MorksPar>.Data.parSets.Count; i++)
  288. {
  289. mORKM.nsm.ElementAt(i).IsShield = Json<MorksPar>.Data.parSets.ElementAt(i).IsShield;
  290. mORKM.nsm.ElementAt(i).NoodleCookerStatus = mORKM.NoodleCookerStatus[i];
  291. }
  292. }
  293. /// <summary>
  294. /// 数据解析
  295. /// </summary>
  296. private void DataParse()
  297. {
  298. EventBus.GetInstance().Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  299. {
  300. if (@event == null) return;
  301. if (@event is DoOrderEvent order)
  302. {
  303. mORKM.doOrderEvents.Add(order);
  304. if (order.MorkOrder.GoodBatchings == null) return;
  305. if (mORKM.HistorySuborderId.Contains(order.MorkOrder.SuborderId)) return;
  306. OrderCount++;
  307. if (DateTime.Now.Subtract(Json<OrderStatistics>.Data.StatisticsTime).Days != 0)
  308. Json<OrderStatistics>.Data.Count = 0;
  309. Json<OrderStatistics>.Data.StatisticsTime = DateTime.Now;
  310. Json<OrderStatistics>.Data.Count++;
  311. Json<OrderStatistics>.Save();
  312. OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT);
  313. DeviceProcessLogShow($"接收到{OrderCount}次订单,订单ID:{order.MorkOrder.SuborderId}");
  314. mORKM.HistorySuborderId.Add(order.MorkOrder.SuborderId);
  315. List<MOrderLocInfo> oli = new List<MOrderLocInfo>();
  316. foreach (var item in order.MorkOrder.GoodBatchings)
  317. {
  318. var res = orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId);
  319. if (res != null)
  320. {
  321. if (ushort.TryParse(res.BatchingLoc, out ushort loc))
  322. {
  323. if (loc >= 1 && loc <= 5)
  324. {
  325. var x = Json<MorksPar>.Data.DishLibraryParSets.FirstOrDefault(p => p.TextBlockContext == loc.ToString());
  326. if (x != null)
  327. {
  328. for (int i = 0; i < item.BatchingCount; i++)
  329. {
  330. oli.Add(new MOrderLocInfo()
  331. {
  332. GoodName = order.MorkOrder.GoodsName,
  333. Loc = ushort.Parse(res.BatchingLoc),
  334. SuborderId = order.MorkOrder.SuborderId,
  335. SortNum = order.MorkOrder.SortNum,
  336. BatchingId = res.BatchingId,
  337. Minute = x.Minute,
  338. Second = x.Second,
  339. LocDishType = x.LocDishType
  340. });
  341. }
  342. }
  343. }
  344. }
  345. }
  346. }
  347. for (int i = 0; i <= 1; i++)
  348. {
  349. oli.Where(p => p.LocDishType == i).ToList()?.ForEach(y =>
  350. {
  351. mORKM.RBTakeNoodleTask.Enqueue(new MOrderLocInfo()
  352. {
  353. GoodName = y.GoodName,
  354. Loc = y.Loc,
  355. SuborderId = y.SuborderId,
  356. SortNum = y.SortNum,
  357. BatchingId = y.BatchingId,
  358. LocDishType = y.LocDishType,
  359. Minute = y.Minute,
  360. RecipeId = y.RecipeId,
  361. RecipeNumber = y.RecipeNumber,
  362. Recipes = y.Recipes,
  363. Second = y.Second
  364. });
  365. });
  366. }
  367. if (mORKM.TakeBowlTask.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  368. mORKM.TakeBowlTask.Enqueue(new OrderLocInfo()
  369. {
  370. GoodName = order.MorkOrder.GoodsName,
  371. Loc = 11,
  372. SuborderId = order.MorkOrder.SuborderId,
  373. SortNum = order.MorkOrder.SortNum,
  374. });
  375. if (!mORKM.SuborderCount.ContainsKey(order.MorkOrder.SuborderId))
  376. {
  377. mORKM.SuborderCount.TryAdd(order.MorkOrder.SuborderId, new SuborderInfo()
  378. {
  379. ActualCount = oli.Count,
  380. AcMeatDishesCount = oli.Where(p => p.LocDishType == 0).ToList().Count,
  381. AcVegetableCount = oli.Where(p => p.LocDishType == 1).ToList().Count,
  382. });
  383. }
  384. }
  385. });
  386. }
  387. public override void MainTask()
  388. {
  389. mORKM.AllowRun = mORKM.InitComplete;
  390. if (Json<KeepDataBase>.Data.IsVerify)
  391. IsHealth = mORKM.InitComplete;
  392. else
  393. IsHealth = true;
  394. TakeBowlTask();
  395. TakeNoodleTask();
  396. OutNoodleTask();
  397. SingleDetect();
  398. TurntableControl();
  399. }
  400. private void BowlControl(OrderLocInfo orderLocInfo)
  401. {
  402. if (orderLocInfo.Loc >= 10 && orderLocInfo.Loc <= 11)
  403. {
  404. mORKM.TakeBowlId = orderLocInfo.SuborderId;
  405. mORKM.TakeBowName = orderLocInfo.GoodName;
  406. mORKM.TakeBowSortNum = orderLocInfo.SortNum;
  407. TakeBowlControl(orderLocInfo.Loc);
  408. OrderChange(mORKM.TakeBowlId, ORDER_STATUS.COOKING);
  409. DeviceProcessLogShow($"订单【{mORKM.TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]");
  410. mORKM.TakeBowlInterlock = true;
  411. }
  412. }
  413. /// <summary>
  414. /// 取碗控制
  415. /// </summary>
  416. private void TakeBowlTask()
  417. {
  418. if (mORKM.AllowRun && mORKM.TakeBowlTask.Count > 0 && !mORKM.DropBowlMechanismStatus && !mORKM.TakeBowlInterlock)
  419. {
  420. ushort BowLoc = 0;
  421. var res = orderMaterialDelivery?.BatchingInfo?.Where(p => p.BatchingId == mORKM.TakeBowlTask.ElementAt(0).BatchingId).ToList();
  422. if (res == null || res?.Count == 0)
  423. {
  424. if (mORKM.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo)) BowlControl(orderLocInfo);
  425. }
  426. else
  427. {
  428. foreach (var item in res)
  429. {
  430. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  431. {
  432. if (loc == 10 && mORKM.SmallBowlYesOrNoCheck)
  433. {
  434. BowLoc = loc;
  435. break;
  436. }
  437. else if (loc == 11 && mORKM.LargeBowYesOrNoCheck)
  438. {
  439. BowLoc = loc;
  440. break;
  441. }
  442. }
  443. }
  444. if (BowLoc >= 10 && BowLoc <= 11)
  445. {
  446. if (mORKM.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
  447. {
  448. orderLocInfo.Loc = BowLoc;
  449. BowlControl(orderLocInfo);
  450. }
  451. }
  452. }
  453. }
  454. }
  455. /// <summary>
  456. /// 转台控制
  457. /// </summary>
  458. private void TurntableControl()
  459. {
  460. if (Global.EnableLocalSimOrder)
  461. {
  462. //不做轮询,直接取面,模拟订单使用
  463. if (mORKM.SiloInPlace && !mORKM.Feeding && mORKM.InitComplete && !mORKM.AllowTakeNoodle && mORKM.RBTakeNoodleTask.Count > 0)
  464. {
  465. if (mORKM.TurntableLowPosition)
  466. {
  467. TurntableStart(mORKM.RBTakeNoodleTask.ElementAt(0).Loc);
  468. mORKM.TurntableLocLists.Clear();
  469. mORKM.AllowTakeNoodle = true;
  470. DeviceProcessLogShow($"控制机器人去转台【{mORKM.RBTakeNoodleTask.ElementAt(0).Loc}】号位置取面");
  471. }
  472. }
  473. }
  474. else
  475. {
  476. //正常轮询
  477. if (Delay.GetInstance("到位检测延时").Start(mORKM.SiloInPlace, 2))
  478. {
  479. if (mORKM.SiloInPlace && !mORKM.Feeding && mORKM.InitComplete && !mORKM.AllowTakeNoodle && mORKM.RBTakeNoodleTask.Count > 0)
  480. {
  481. var result = orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKM.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
  482. if (result != null)
  483. {
  484. var res = result.FirstOrDefault(P => P.BatchingLoc == mORKM.CurrentFeedbackLoc.ToString());
  485. if (mORKM.TurntableLowPosition && res != null)
  486. {
  487. TurntableStart(mORKM.CurrentFeedbackLoc);
  488. mORKM.TurntableLocLists.Clear();
  489. mORKM.AllowTakeNoodle = true;
  490. DeviceProcessLogShow($"控制机器人去转台【{mORKM.CurrentFeedbackLoc}】号位置取面");
  491. }
  492. else
  493. {
  494. if (!mORKM.TurntableInterlock)
  495. {
  496. foreach (var item in result)
  497. {
  498. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  499. {
  500. if (mORKM.CurrentFeedbackLoc != loc && !mORKM.TurntableLocLists.Contains(loc))
  501. {
  502. if (!mORKM.TurntableLowPosition)
  503. {
  504. DeviceProcessLogShow($"执行了转台启动互锁信号复位");
  505. }
  506. TurntableStart(loc);
  507. DeviceProcessLogShow($"没有物料检测的启动转台控制,转台位置:[{loc}]");
  508. break;
  509. }
  510. else if (mORKM.CurrentFeedbackLoc == loc && !mORKM.TurntableLocLists.Contains(loc)) mORKM.TurntableLocLists.Add(loc);
  511. }
  512. }
  513. }
  514. }
  515. }
  516. else DeviceProcessLogShow("未找到可用的物料信息");
  517. }
  518. }
  519. }
  520. //补料中检测
  521. if (RTrig.GetInstance("mORKS.Feeding").Start(mORKM.Feeding))
  522. {
  523. mORKM.AllowTakeNoodle = false;
  524. mORKM.TakeNoodleInterlock = false;
  525. }
  526. //转台到位检测
  527. if (RTrig.GetInstance("TurntableInPlace").Start(mORKM.SiloInPlace && mORKM.CurrentLoc == mORKM.CurrentFeedbackLoc))
  528. {
  529. mORKM.TurntableInterlock = false;
  530. DeviceProcessLogShow("转台到位检测");
  531. }
  532. //补料完成检测
  533. if (RTrig.GetInstance("FeedComplete").Start(mORKM.FeedComplete))
  534. {
  535. if (!mORKM.AllowTakeNoodle && mORKM.TurntableLocLists.Count > 0)
  536. {
  537. mORKM.TurntableLocLists.Clear();
  538. mORKM.TurntableInterlock = false;
  539. DeviceProcessLogShow("补料完成检测");
  540. }
  541. }
  542. }
  543. /// <summary>
  544. /// 取面任务
  545. /// </summary>
  546. private void TakeNoodleTask()
  547. {
  548. //取面控制
  549. if (mORKM.AllowRun && mORKM.RobotStatus && !mORKM.RobotOutDinnigLock && !mORKM.Feeding && !mORKM.RobotTaskInterlock && mORKM.AllowTakeNoodle && mORKM.SiloInPlace && !mORKM.TakeNoodleInterlock && mORKM.RBTakeNoodleTask.Count > 0)
  550. {
  551. if (mORKM.CurrentLoc == mORKM.CurrentFeedbackLoc)
  552. {
  553. int loc = mORKM.nsm.ToList().FindIndex(p => p.NoodleCookerStatus == false && p.IsShield == false);//查找煮面炉空闲位置
  554. if (loc >= 0 && loc <= 5)
  555. {
  556. if (mORKM.RBTakeNoodleTask.TryDequeue(out MOrderLocInfo orderLocInfo))
  557. {
  558. //写入煮面时间
  559. List<ushort> values = new List<ushort>();
  560. values.Add(orderLocInfo.Minute);
  561. values.Add(orderLocInfo.Second);
  562. WriteData($"VW{324 + (loc * 4)}", values.ToArray());
  563. mORKM.CurrentLoc = 0;
  564. mORKM.CookNodelId[loc] = orderLocInfo.SuborderId;
  565. mORKM.NoodleCookerStatus[loc] = true;
  566. SetFallNoodleLoc((ushort)(loc + 1));
  567. //机器人开始取面
  568. OrderChange(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
  569. DeviceProcessLogShow($"订单【{orderLocInfo.SuborderId}】,机器人倒面至【{loc + 1}】号煮面栏");
  570. if (mORKM.SuborderCount.ContainsKey(orderLocInfo.SuborderId))
  571. {
  572. if (orderLocInfo.LocDishType == 0)
  573. mORKM.SuborderCount[orderLocInfo.SuborderId].MeatDishesLoc.Add(loc + 1);
  574. else if (orderLocInfo.LocDishType == 1)
  575. mORKM.SuborderCount[orderLocInfo.SuborderId].VegetableLoc.Add(loc + 1);
  576. }
  577. mORKM.TakeNoodleInterlock = true;
  578. }
  579. }
  580. }
  581. }
  582. }
  583. /// <summary>
  584. /// 出餐控制
  585. /// </summary>
  586. private void OutNoodleTask()
  587. {
  588. if (mORKM.AllowInvertedFace && !mORKM.RobotOutDinnigLock && mORKM.RobotTaskInterlock && !mORKM.TakeNoodleInterlock && mORKM.RobotStatus)
  589. {
  590. for (int i = 0; i < mORKM.CookNodelId.Length; i++)
  591. {
  592. if (mORKM.CookNodelId[i] == mORKM.IngredientsCompleteId && !string.IsNullOrEmpty(mORKM.CookNodelId[i]))
  593. {
  594. if (mORKM.CookNoodleCom[i] && mORKM.SuborderCount.ContainsKey(mORKM.CookNodelId[i]))
  595. {
  596. var x = mORKM.SuborderCount[mORKM.CookNodelId[i]];
  597. //执行取素菜操作
  598. if (!mORKM.RobotOutDinnigLock && x.AcVegetableCount != x.CuVegetableCount)
  599. {
  600. int index = x.VegetableLoc.FindIndex(p => p == i + 1);
  601. if (index >= 0)
  602. {
  603. SetTakeNoodleLoc((ushort)(x.VegetableLoc.ElementAt(index)));
  604. mORKM.NoodleCookerStatus[i] = false;
  605. WriteData($"VW260", (ushort)0);//设置出汤时间
  606. DeviceProcessLogShow($"{x.VegetableLoc.ElementAt(index)} 号位置-[素菜]-出餐控制,订单ID:{mORKM.CookNodelId[i]}");
  607. mORKM.CookNodelId[i] = string.Empty;
  608. mORKM.CookNoodleCom[i] = false;
  609. x.VegetableLoc.RemoveAt(index);
  610. x.CuVegetableCount++;
  611. mORKM.RobotOutDinnigLock = true;
  612. }
  613. }
  614. //执行取荤菜
  615. if (!mORKM.RobotOutDinnigLock && x.AcVegetableCount == x.CuVegetableCount && x.AcMeatDishesCount != x.CuMeatDishesCount)
  616. {
  617. int index = x.MeatDishesLoc.FindIndex(p => p == i + 1);
  618. if (index >= 0)
  619. {
  620. SetTakeNoodleLoc((ushort)(x.MeatDishesLoc.ElementAt(index)));
  621. mORKM.NoodleCookerStatus[i] = false;
  622. WriteData($"VW260", (ushort)0);//设置出汤时间
  623. DeviceProcessLogShow($"{x.MeatDishesLoc.ElementAt(index)} 号位置-[荤菜]-出餐控制,订单ID:{mORKM.CookNodelId[i]}");
  624. mORKM.CookNodelId[i] = string.Empty;
  625. mORKM.CookNoodleCom[i] = false;
  626. x.MeatDishesLoc.RemoveAt(index);
  627. x.CuMeatDishesCount++;
  628. mORKM.RobotOutDinnigLock = true;
  629. }
  630. }
  631. }
  632. }
  633. }
  634. }
  635. }
  636. /// <summary>
  637. /// 验证是否可以出餐
  638. /// </summary>
  639. /// <returns></returns>
  640. private bool IsCanDiningOut(bool condition)
  641. {
  642. if (mORKM.AllowInvertedFace && condition && !mORKM.RobotOutDinnigLock && !mORKM.TakeNoodleInterlock && mORKM.RobotStatus)
  643. {
  644. for (int i = 0; i < mORKM.CookNodelId.Length; i++)
  645. {
  646. if (mORKM.CookNodelId[i] == mORKM.IngredientsCompleteId && !string.IsNullOrEmpty(mORKM.CookNodelId[i]))
  647. {
  648. if (mORKM.CookNoodleCom[i] && mORKM.SuborderCount.ContainsKey(mORKM.CookNodelId[i]))
  649. {
  650. var x = mORKM.SuborderCount[mORKM.CookNodelId[i]];
  651. //执行取素菜操作
  652. if (x.AcVegetableCount != x.CuVegetableCount)
  653. {
  654. int index = x.VegetableLoc.FindIndex(p => p == i + 1);
  655. if (index >= 0)
  656. {
  657. return true;
  658. }
  659. }
  660. //执行取荤菜
  661. if (!mORKM.RobotOutDinnigLock && x.AcVegetableCount == x.CuVegetableCount && x.AcMeatDishesCount != x.CuMeatDishesCount)
  662. {
  663. int index = x.MeatDishesLoc.FindIndex(p => p == i + 1);
  664. if (index >= 0)
  665. {
  666. return true;
  667. }
  668. }
  669. }
  670. }
  671. }
  672. }
  673. return false;
  674. }
  675. /// <summary>
  676. /// 信号检测
  677. /// </summary>
  678. private void SingleDetect()
  679. {
  680. //允许倒面信号检测
  681. if (RTrig.GetInstance("AllowFallNoodle").Start(mORKM.AllowInvertedFace))
  682. {
  683. mORKM.IngredientsCompleteId = mORKM.TakeBowlId;
  684. mORKM.IngredientsCompleteName = mORKM.TakeBowName;
  685. mORKM.IngredientsCompleteSortNum = mORKM.TakeBowSortNum;
  686. mORKM.TakeBowSortNum = 0;
  687. mORKM.TakeBowlId = string.Empty;
  688. mORKM.TakeBowName = string.Empty;
  689. DeviceProcessLogShow($"碗到位,允许到面,{mORKM.IngredientsCompleteId}");
  690. mORKM.TakeBowlInterlock = false;
  691. }
  692. //取餐完成逻辑处理
  693. if (RTrig.GetInstance("CompleteChange1").Start(mORKM.DiningComplete) && mORKM.CookCompleteFlatBit == true)
  694. {
  695. OrderChange(mORKM.OutMealId, ORDER_STATUS.COMPLETED_TAKE);
  696. DeviceProcessLogShow($"订单【{mORKM.OutMealId}】取餐完成");
  697. WriteData("M10.1", false);
  698. DeviceProcessLogShow($"出餐订单序号【{mORKM.OutMealSortNum}】");
  699. VoiceAPI.Speak(mORKM.OutMealSortNum.ToString());
  700. mORKM.CookCompleteFlatBit = false;
  701. mORKM.OutMealId = string.Empty;
  702. mORKM.OutMealName = string.Empty;
  703. mORKM.OutMealSortNum = 0;
  704. }
  705. //机器人取面完成信号检测
  706. if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKM.RobotTakeNoodleCom))
  707. {
  708. mORKM.TakeNoodleInterlock = false;
  709. mORKM.AllowTakeNoodle = false;
  710. mORKM.TurntableInterlock = false;
  711. DeviceProcessLogShow("机器人取面完成信号检测");
  712. }
  713. //机器人倒面完成信号检测
  714. if (RTrig.GetInstance("RobotInvertedSurfaceCom").Start(mORKM.RobotInvertedSurfaceCom))
  715. {
  716. if (mORKM.SuborderCount.ContainsKey(mORKM.IngredientsCompleteId))
  717. {
  718. var x = mORKM.SuborderCount[mORKM.IngredientsCompleteId];
  719. if (x.CuMeatDishesCount + x.CuVegetableCount == x.ActualCount)
  720. {
  721. OrderChange(mORKM.IngredientsCompleteId, ORDER_STATUS.COMPLETED_COOK);
  722. DeviceProcessLogShow($"订单【{mORKM.IngredientsCompleteId}】制作完成");
  723. mORKM.SuborderCount.Remove(mORKM.IngredientsCompleteId, out _);
  724. mORKM.CookCompleteFlatBit = true;
  725. mORKM.OutMealId = mORKM.IngredientsCompleteId;
  726. mORKM.OutMealName = mORKM.IngredientsCompleteName;
  727. mORKM.OutMealSortNum = mORKM.IngredientsCompleteSortNum;
  728. mORKM.IngredientsCompleteId = string.Empty;
  729. CookComplete();
  730. DeviceProcessLogShow($"倒面完成");
  731. }
  732. }
  733. mORKM.RobotOutDinnigLock = false;
  734. }
  735. int OutMealRequstCount = mORKM.CookNoodleCom.Where(p => p == true).ToList().Count;
  736. int BusyCount = mORKM.nsm.Where(p => p.NoodleCookerStatus == true && p.IsShield == false).ToList().Count;//忙碌数量
  737. int IdleCount = mORKM.nsm.Where(p => p.NoodleCookerStatus == false && p.IsShield == false).ToList().Count;//空闲数量
  738. bool isok = false;
  739. for (int i = 0; i < mORKM.CookNodelId.Length; i++)
  740. {
  741. if (mORKM.CookNodelId[i] == mORKM.IngredientsCompleteId && mORKM.CookNoodleCom[i])
  742. {
  743. isok = true;
  744. break;
  745. }
  746. }
  747. mORKM.PriorityJudgment = Delay.GetInstance("取餐优先级判断").Start(mORKM.TurntableLocLists.Count > 0 && !mORKM.TurntableLowPosition, 4);
  748. mORKM.RobotTaskInterlock = IsCanDiningOut(isok && IdleCount >= 0) && (BusyCount >= 2 || mORKM.RBTakeNoodleTask.Count == 0 || mORKM.PriorityJudgment);
  749. }
  750. /// <summary>
  751. /// 语音提醒取餐
  752. /// </summary>
  753. /// <param name="meal"></param>
  754. private void WaitMeaLSpeak(string meal)
  755. {
  756. //VoiceAPI.m_SystemPlayWav(@"Vioce\电子提示音.wav");
  757. //Thread.Sleep(1000);
  758. //if (meal != null) mORKS.speech.Speak(meal);
  759. //VoiceAPI.m_SystemPlayWav(@"Vioce\取餐通知.wav");
  760. }
  761. #region PLC 控制函数
  762. private void WriteData(string address, object value)
  763. {
  764. EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = address, Value = value });
  765. }
  766. /// <summary>
  767. /// 设备初始化
  768. /// </summary>
  769. public async void DeviceInit()
  770. {
  771. WriteData("M0.0", true);
  772. await Task.Delay(1000);
  773. WriteData("M0.0", false);
  774. }
  775. /// <summary>
  776. /// 取碗控制
  777. /// </summary>
  778. /// <param name="loc"></param>
  779. private void TakeBowlControl(ushort loc)
  780. {
  781. if (loc == 10)//一次性碗
  782. {
  783. WriteData("M9.1", true);
  784. }
  785. else if (loc == 11)//大碗
  786. {
  787. WriteData("M9.0", true);
  788. }
  789. }
  790. /// <summary>
  791. /// 启动转台
  792. /// </summary>
  793. /// <param name="loc"></param>
  794. private void TurntableStart(ushort loc)
  795. {
  796. if (loc >= 1 && loc <= 5)
  797. {
  798. mORKM.CurrentLoc = loc;
  799. mORKM.TurntableInterlock = true;
  800. mORKM.TurntableLocLists.Add(loc);
  801. WriteData($"M13.{loc - 1}", true);
  802. }
  803. }
  804. /// <summary>
  805. /// 设置倒面位置
  806. /// </summary>
  807. /// <param name="loc"></param>
  808. private void SetFallNoodleLoc(ushort loc)
  809. {
  810. if (loc >= 1 && loc <= 6)
  811. WriteData($"M14.{loc - 1}", true);
  812. }
  813. /// <summary>
  814. /// 设置取面位置
  815. /// </summary>
  816. /// <param name="loc"></param>
  817. private void SetTakeNoodleLoc(ushort loc)
  818. {
  819. if (loc >= 1 && loc <= 6)
  820. WriteData($"M15.{loc - 1}", true);
  821. }
  822. /// <summary>
  823. /// 上位机单订单执行完成
  824. /// </summary>
  825. private void CookComplete()
  826. {
  827. WriteData("M11.0", true);
  828. }
  829. public override void SimOrder()
  830. {
  831. EventBus.GetInstance().Subscribe<MorksSimorderModel>(0, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  832. {
  833. if (@event != null && @event is MorksSimorderModel msm)
  834. {
  835. string guid = Guid.NewGuid().ToString();
  836. if (msm.NoodleLoc >= 1 && msm.NoodleLoc <= 5)
  837. {
  838. mORKM.RBTakeNoodleTask.Enqueue(new MOrderLocInfo() { Loc = (ushort)msm.NoodleLoc, SuborderId = guid });
  839. MessageLog.GetInstance.Show($"添加订单:面条位置【{(ushort)msm.NoodleLoc}】");
  840. }
  841. if (msm.Bowloc >= 10 && msm.Bowloc <= 11)
  842. {
  843. mORKM.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)msm.Bowloc, SuborderId = guid });
  844. MessageLog.GetInstance.Show($"添加订单:碗位置【{(ushort)msm.Bowloc}】");
  845. }
  846. }
  847. });
  848. }
  849. #endregion
  850. }
  851. }