终端一体化运控平台
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

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