终端一体化运控平台
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

942 rindas
40 KiB

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