终端一体化运控平台
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

1039 行
43 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.MorkS.Model;
  15. using System.Collections.ObjectModel;
  16. using BPASmartClient.MorkS.ViewModel;
  17. using BPASmartClient.Business;
  18. using BPASmartClient.Model.小炒机;
  19. using BPA.Models;
  20. using System.Speech.Synthesis;
  21. using System.Windows.Forms;
  22. using System.Media;
  23. using BPASmartClient.CustomResource;
  24. using static BPA.Helper.EventBus;
  25. using System.Collections.Concurrent;
  26. namespace BPASmartClient.MorkS
  27. {
  28. public class Control_Morks : BaseDevice
  29. {
  30. public override DeviceClientType DeviceType => DeviceClientType.MORKS;
  31. GVL_MORKS mORKS = new GVL_MORKS();
  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. mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = (ushort)NoodleLoc, SuborderId = guid });
  67. MessageLog.GetInstance.Show($"添加订单:面条位置【{NoodleLoc}】");
  68. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { 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. mORKS = null;
  87. mORKS = new GVL_MORKS();
  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. WriteRecipeBoms();
  111. }
  112. });
  113. OrderNotifyInit();
  114. }
  115. #region 接口状态更新
  116. ConcurrentQueue<OrderStatusModel> osm = new ConcurrentQueue<OrderStatusModel>();
  117. private void OrderNotifyInit()
  118. {
  119. TaskManage.GetInstance.StartLong(() =>
  120. {
  121. while (osm.Count > 0)
  122. {
  123. TempOrderChange(osm.ElementAt(0).SubOrderId, osm.ElementAt(0).Status, () =>
  124. {
  125. osm.TryDequeue(out OrderStatusModel tempOSM);
  126. DeviceProcessLogShow($"订单:【{tempOSM.SubOrderId}】, 状态:【{tempOSM.Status}】, API状态修改成功");
  127. });
  128. }
  129. Thread.Sleep(100);
  130. }, $"订单状态更新接口{DeviceId}", true);
  131. }
  132. private void TempOrderChange(string subid, ORDER_STATUS oRDER_STATUS, Action complete)
  133. {
  134. var res = mORKS.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid);
  135. string goodName = string.Empty;
  136. string SortNum = string.Empty;
  137. if (res != null)
  138. {
  139. goodName = res.MorkOrder.GoodsName;
  140. SortNum = res.MorkOrder.SortNum.ToString();
  141. }
  142. //if (mORKS.doe.ContainsKey(subid))
  143. //{
  144. //goodName = mORKS.doe[subid].MorkOrder.GoodsName;
  145. //SortNum = mORKS.doe[subid].MorkOrder.SortNum.ToString();
  146. if (!string.IsNullOrEmpty(goodName) && !string.IsNullOrEmpty(SortNum))
  147. {
  148. EventBus.GetInstance.Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType }, e => { complete?.Invoke(); });
  149. var index = DataServer.GetInstance.morkS.MakeOrder.FindIndex(p => p.SortNum == SortNum);
  150. if (index >= 0 && index < DataServer.GetInstance.morkS.MakeOrder.Count)
  151. {
  152. if (oRDER_STATUS == ORDER_STATUS.COMPLETED_COOK)
  153. {
  154. DataServer.GetInstance.morkS.MakeOrder.RemoveAt(index);
  155. DataServer.GetInstance.morkS.MakeOrderOver.Add(new OrderMakeModel()
  156. {
  157. Status = oRDER_STATUS,
  158. GoodName = goodName,
  159. SortNum = SortNum,
  160. StopTime = DateTime.Now.ToString("HH:mm:ss")
  161. });
  162. }
  163. else if (oRDER_STATUS == ORDER_STATUS.COMPLETED_TAKE)
  164. {
  165. var temp = DataServer.GetInstance.morkS.MakeOrderOver.FirstOrDefault(p => p.SortNum == SortNum);
  166. if (temp != null) DataServer.GetInstance.morkS.MakeOrderOver.Remove(temp);
  167. }
  168. else
  169. {
  170. DataServer.GetInstance.morkS.MakeOrder.ElementAt(index).Status = oRDER_STATUS;
  171. }
  172. }
  173. else
  174. {
  175. DataServer.GetInstance.morkS.MakeOrder.Add(new OrderMakeModel()
  176. {
  177. Status = oRDER_STATUS,
  178. GoodName = goodName,
  179. SortNum = SortNum,
  180. StartTime = DateTime.Now.ToString("HH:mm:ss")
  181. });
  182. }
  183. //mORKS.doe.Remove(subid, out _);
  184. }
  185. //}
  186. }
  187. #endregion
  188. private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS)
  189. {
  190. osm.Enqueue(new OrderStatusModel() { SubOrderId = subid, Status = oRDER_STATUS });
  191. //var res = mORKS.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid);
  192. //string goodName = string.Empty;
  193. //string SortNum = string.Empty;
  194. //if (res != null)
  195. //{
  196. // goodName = res.MorkOrder.GoodsName;
  197. // SortNum = res.MorkOrder.SortNum.ToString();
  198. //}
  199. ////if (mORKS.doe.ContainsKey(subid))
  200. ////{
  201. ////goodName = mORKS.doe[subid].MorkOrder.GoodsName;
  202. ////SortNum = mORKS.doe[subid].MorkOrder.SortNum.ToString();
  203. //if (!string.IsNullOrEmpty(goodName) && !string.IsNullOrEmpty(SortNum))
  204. //{
  205. // EventBus.GetInstance.Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType });
  206. // var index = DataServer.GetInstance.morkS.MakeOrder.FindIndex(p => p.SortNum == SortNum);
  207. // if (index >= 0 && index < DataServer.GetInstance.morkS.MakeOrder.Count)
  208. // {
  209. // if (oRDER_STATUS == ORDER_STATUS.COMPLETED_COOK)
  210. // {
  211. // DataServer.GetInstance.morkS.MakeOrder.RemoveAt(index);
  212. // DataServer.GetInstance.morkS.MakeOrderOver.Add(new OrderMakeModel()
  213. // {
  214. // Status = oRDER_STATUS,
  215. // GoodName = goodName,
  216. // SortNum = SortNum,
  217. // StopTime = DateTime.Now.ToString("HH:mm:ss")
  218. // });
  219. // }
  220. // else if (oRDER_STATUS == ORDER_STATUS.COMPLETED_TAKE)
  221. // {
  222. // var temp = DataServer.GetInstance.morkS.MakeOrderOver.FirstOrDefault(p => p.SortNum == SortNum);
  223. // if (temp != null) DataServer.GetInstance.morkS.MakeOrderOver.Remove(temp);
  224. // }
  225. // else
  226. // {
  227. // DataServer.GetInstance.morkS.MakeOrder.ElementAt(index).Status = oRDER_STATUS;
  228. // }
  229. // }
  230. // else
  231. // {
  232. // DataServer.GetInstance.morkS.MakeOrder.Add(new OrderMakeModel()
  233. // {
  234. // Status = oRDER_STATUS,
  235. // GoodName = goodName,
  236. // SortNum = SortNum,
  237. // StartTime = DateTime.Now.ToString("HH:mm:ss")
  238. // });
  239. // }
  240. // //mORKS.doe.Remove(subid, out _);
  241. //}
  242. ////}
  243. }
  244. private void GetStatus(string key, Action<object> action)
  245. {
  246. if (peripheralStatus.ContainsKey(key))
  247. {
  248. if (peripheralStatus[key] != null)
  249. {
  250. action?.Invoke(peripheralStatus[key]);
  251. }
  252. }
  253. }
  254. public override void ReadData()
  255. {
  256. //DataServer.GetInstance.morkS.Alarm.Clear();
  257. //alarms.ForEach(item =>
  258. //{
  259. // DataServer.GetInstance.morkS.Alarm.Add(new AlarmModel()
  260. // {
  261. // AlarmTime = $"{item.Date} {item.Time}",
  262. // AlarmMs = item.Info
  263. // });
  264. //});
  265. GetStatus("M230.0", new Action<object>((obj) =>
  266. {
  267. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 24)
  268. {
  269. alarm.MachineLeftLowTemperature = bools[0];
  270. alarm.MachineRightLowTemperature = bools[1];
  271. alarm.Supply1_LossBowl = bools[2];
  272. alarm.Supply2_LossBowl = bools[3];
  273. alarm.Supply1_ErrorOutBowl = bools[4];
  274. alarm.Supply2_ErrorOutBowl = bools[5];
  275. alarm.PushBowlCylinderError = bools[6];
  276. alarm.NoodleMacCommunicateError = bools[7];
  277. alarm.DosingMacCommunicateError = bools[8];
  278. alarm.RobotMacCommunicateError = bools[9];
  279. alarm.DeviceEstop = bools[10];
  280. alarm.RobotInitError = bools[11];
  281. alarm.RobotUrgentStop = bools[12];
  282. alarm.RobotNotInRemoteMode = bools[13];
  283. alarm.RobotNotInReady = bools[14];
  284. alarm.RobotSelfInException = bools[15];
  285. alarm.LeftLackWater = bools[16];
  286. alarm.RightLackWater = bools[17];
  287. alarm.SvrewInitFail = bools[18];
  288. alarm.TurntableInitFail = bools[19];
  289. alarm.RobotInitFail = bools[20];
  290. alarm.NoodleCookerInitFail = bools[21];
  291. alarm.PushBowlInitFail1 = bools[22];
  292. alarm.PushBowlInitFail2 = bools[23];
  293. }
  294. }));
  295. GetStatus("M0.3", new Action<object>((obj) =>
  296. {
  297. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 3)
  298. {
  299. mORKS.RobotTakeNoodle = bools[0];
  300. mORKS.RobotOutMeal = bools[1];
  301. mORKS.MoveTurntable = bools[2];
  302. }
  303. }));
  304. GetStatus("M100.0", new Action<object>((obj) =>
  305. {
  306. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 16)
  307. {
  308. mORKS.InitComplete = bools[0];
  309. mORKS.TakeBowlIdle = bools[1];
  310. mORKS.TemperatureReached = bools[2];
  311. mORKS.AllowFallNoodle = bools[3];
  312. mORKS.RbTakeNoodleComplete = bools[4];
  313. mORKS.RbFallNoodleComplete = bools[5];
  314. mORKS.RbOutMealComplete = bools[6];
  315. mORKS.RobotIdle = bools[7];
  316. mORKS.TakeMealDetect = bools[8];
  317. mORKS.MissingBowl = bools[9];
  318. Initing = bools[10];
  319. mORKS.TurntableLowerLimit = bools[11];
  320. mORKS.MissingBowlSignal2 = bools[12];
  321. mORKS.TurntableUpLimit = bools[13];
  322. mORKS.FeedComplete = bools[14];
  323. mORKS.TurntableMoveInPlace = bools[15];
  324. DataServer.GetInstance.morkS.MorkS_Temp = mORKS.TemperatureReached;
  325. DataServer.GetInstance.morkS.Morks_SiloMeasUp = mORKS.TurntableUpLimit;
  326. DataServer.GetInstance.morkS.Morks_SiloMeasDown = mORKS.TurntableLowerLimit;
  327. DataServer.GetInstance.morkS.MorkS_NoBowMeas1 = mORKS.MissingBowl;
  328. DataServer.GetInstance.morkS.MorkS_NoBowMeas2 = mORKS.MissingBowlSignal2;
  329. }
  330. }));
  331. GetStatus("M235.0", new Action<object>((obj) =>
  332. {
  333. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1)
  334. {
  335. mORKS.Error = bools[0];
  336. }
  337. }));
  338. GetStatus("M102.0", new Action<object>((obj) =>
  339. {
  340. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 7)
  341. {
  342. for (int i = 0; i < 6; i++)
  343. {
  344. mORKS.NoodleCookerStatus[i] = bools[i];
  345. }
  346. mORKS.Feeding = bools[6];
  347. }
  348. }));
  349. GetStatus("M103.0", new Action<object>((obj) =>
  350. {
  351. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 6)
  352. {
  353. for (int i = 0; i < 6; i++)
  354. {
  355. mORKS.CookNoodlesComplete[i] = bools[i];
  356. DataServer.GetInstance.morkS.Morks_NoodleUpOrDown[i] = bools[i];
  357. }
  358. }
  359. }));
  360. GetStatus("VW372", new Action<object>((obj) =>
  361. {
  362. if (obj is ushort[] UshortValue && UshortValue.Length > 0 && UshortValue.Length <= 1)
  363. mORKS.TurntableFeedbackloc = UshortValue[0];
  364. DataServer.GetInstance.morkS.MorkS_BinLocation = mORKS.TurntableFeedbackloc;
  365. }));
  366. }
  367. /// <summary>
  368. /// 数据解析
  369. /// </summary>
  370. private void DataParse()
  371. {
  372. if (!Global.LocalOrderModel)//小程序下单
  373. {
  374. EventBus.GetInstance.Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  375. {
  376. if (@event == null) return;
  377. if (@event is DoOrderEvent order)
  378. {
  379. mORKS.doOrderEvents.Add(order);
  380. //mORKS.doe.TryAdd(order.MorkOrder.SuborderId, order);
  381. DeviceProcessLogShow($"接收到{order.MorkOrder.SortNum}号订单");
  382. if (order.MorkOrder.GoodBatchings == null) return;
  383. if (mORKS.HistorySuborderId.Contains(order.MorkOrder.SuborderId)) return;
  384. OrderCount++;
  385. if (DateTime.Now.Subtract(Json<OrderStatistics>.Data.StatisticsTime).Days != 0)
  386. Json<OrderStatistics>.Data.Count = 0;
  387. Json<OrderStatistics>.Data.StatisticsTime = DateTime.Now;
  388. Json<OrderStatistics>.Data.Count++;
  389. Json<OrderStatistics>.Save();
  390. OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT);
  391. if (order.MorkOrder.GoodBatchings.Count <= 1)
  392. {
  393. DeviceProcessLogShow($"数据解析失败,商品物料信息为空,请检查后台配置!");
  394. return;
  395. }
  396. DeviceProcessLogShow($"接收到{OrderCount}次订单,订单ID:{order.MorkOrder.SuborderId}");
  397. mORKS.HistorySuborderId.Add(order.MorkOrder.SuborderId);
  398. foreach (var item in order.MorkOrder.GoodBatchings)
  399. {
  400. var res = orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId);
  401. if (res != null)
  402. {
  403. if (ushort.TryParse(res.BatchingLoc, out ushort loc))
  404. {
  405. if (loc >= 1 && loc <= 5)
  406. {
  407. if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  408. mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo()
  409. {
  410. GoodName = order.MorkOrder.GoodsName,
  411. Loc = ushort.Parse(res.BatchingLoc),
  412. SuborderId = order.MorkOrder.SuborderId,
  413. SortNum = order.MorkOrder.SortNum,
  414. BatchingId = res.BatchingId
  415. });
  416. }
  417. else if (loc >= 10 && loc <= 11)
  418. {
  419. int index = 0;
  420. if (recipeBoms != null)
  421. {
  422. index = Array.FindIndex(recipeBoms.RecipeIds?.ToArray(), p => p.RecipeId == order.MorkOrder.RecipeId);
  423. index++;
  424. }
  425. if (mORKS.TakeBowlTask.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  426. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo()
  427. {
  428. BatchingId = res.BatchingId,
  429. GoodName = order.MorkOrder.GoodsName,
  430. Loc = ushort.Parse(res.BatchingLoc),
  431. SuborderId = order.MorkOrder.SuborderId,
  432. SortNum = order.MorkOrder.SortNum,
  433. RecipeNumber = (index >= 1 && index <= 10) ? (ushort)index : (ushort)0
  434. });
  435. }
  436. }
  437. }
  438. else
  439. {
  440. DeviceProcessLogShow($"数据解析失败,未找到商品信息,请检查后台配置!");
  441. }
  442. }
  443. }
  444. });
  445. }
  446. }
  447. public override void MainTask()
  448. {
  449. mORKS.AllowRun = mORKS.InitComplete;
  450. if (Json<KeepDataBase>.Data.IsVerify)
  451. IsHealth = mORKS.Error && mORKS.InitComplete;
  452. else
  453. IsHealth = true;
  454. TakeBowlTask();
  455. TakeNoodleTask();
  456. OutNoodleTask();
  457. SingleDetect();
  458. TurntableControl();
  459. var data = new List<bool>();
  460. for (int i = 0; i < Json<MorksPar>.Data.parSets.Count; i++)
  461. {
  462. data.Add(Json<MorksPar>.Data.parSets.ElementAt(i).IsShield);
  463. }
  464. WriteControl("M260.0", data.ToArray());
  465. }
  466. private void BowlControl(OrderLocInfo orderLocInfo)
  467. {
  468. if (orderLocInfo.Loc >= 10 && orderLocInfo.Loc <= 11)
  469. {
  470. mORKS.TakeBowlId = orderLocInfo.SuborderId;
  471. mORKS.TakeBowName = orderLocInfo.GoodName;
  472. mORKS.TakeBowSortNum = orderLocInfo.SortNum;
  473. TakeBowlControl(orderLocInfo.Loc);
  474. SetRecipeNumber(orderLocInfo.RecipeNumber);
  475. OrderChange(mORKS.TakeBowlId, ORDER_STATUS.COOKING);
  476. DeviceProcessLogShow($"订单【{mORKS.TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]");
  477. mORKS.TakeBowlInterlock = true;
  478. }
  479. }
  480. /// <summary>
  481. /// 取碗控制
  482. /// </summary>
  483. private void TakeBowlTask()
  484. {
  485. if (mORKS.AllowRun && mORKS.TakeBowlTask.Count > 0 && !mORKS.TakeBowlIdle && !mORKS.TakeBowlInterlock)
  486. {
  487. DeviceProcessLogShow("开始取碗流程");
  488. ushort BowLoc = 0;
  489. var res = orderMaterialDelivery?.BatchingInfo?.Where(p => p.BatchingId == mORKS.TakeBowlTask.ElementAt(0).BatchingId).ToList();
  490. if (res == null || res?.Count == 0)//本地或者模拟订单
  491. {
  492. var bowlLoc = mORKS.TakeBowlTask.ElementAt(0).Loc;
  493. if (bowlLoc == 10 && !alarm.Supply1_LossBowl)
  494. {
  495. BowLoc = bowlLoc;
  496. }
  497. else if (bowlLoc == 11 && !alarm.Supply2_LossBowl)
  498. {
  499. BowLoc = bowlLoc;
  500. }
  501. if (BowLoc >= 10 && BowLoc <= 11 && mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
  502. {
  503. BowlControl(orderLocInfo);
  504. }
  505. }
  506. else
  507. {
  508. foreach (var item in res)
  509. {
  510. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  511. {
  512. //DeviceProcessLogShow($"位置:={loc},检测开关1:{alarm.Supply1_LossBowl},检测开关1:{alarm.Supply2_LossBowl}");
  513. if (loc == 10 && !alarm.Supply1_LossBowl)
  514. {
  515. BowLoc = loc;
  516. break;
  517. }
  518. else if (loc == 11 && !alarm.Supply2_LossBowl)
  519. {
  520. BowLoc = loc;
  521. break;
  522. }
  523. }
  524. }
  525. if (BowLoc >= 10 && BowLoc <= 11)
  526. {
  527. if (mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
  528. {
  529. orderLocInfo.Loc = BowLoc;
  530. BowlControl(orderLocInfo);
  531. }
  532. }
  533. }
  534. }
  535. }
  536. /// <summary>
  537. /// 转台控制
  538. /// </summary>
  539. private void TurntableControl()
  540. {
  541. if (Global.EnableLocalSimOrder || Global.LocalOrderModel)
  542. {
  543. //不做轮询,直接取面,模拟订单使用
  544. if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  545. {
  546. if (mORKS.TurntableLowerLimit)
  547. {
  548. TurntableStart(mORKS.RBTakeNoodleTask.ElementAt(0).Loc);
  549. mORKS.TurntableLocLists.Clear();
  550. mORKS.AllowTakeNoodle = true;
  551. DeviceProcessLogShow($"控制机器人去转台【{mORKS.RBTakeNoodleTask.ElementAt(0).Loc}】号位置取面");
  552. }
  553. }
  554. }
  555. else
  556. {
  557. //正常轮询
  558. if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  559. {
  560. var result = orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKS.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
  561. if (result != null)
  562. {
  563. var res = result.FirstOrDefault(P => P.BatchingLoc == mORKS.TurntableFeedbackloc.ToString());
  564. if (mORKS.TurntableLowerLimit && res != null)
  565. {
  566. TurntableStart(mORKS.TurntableFeedbackloc);
  567. mORKS.TurntableLocLists.Clear();
  568. mORKS.AllowTakeNoodle = true;
  569. DeviceProcessLogShow($"控制机器人去转台【{mORKS.TurntableFeedbackloc}】号位置取面");
  570. }
  571. else
  572. {
  573. if (!mORKS.TurntableInterlock)
  574. {
  575. foreach (var item in result)
  576. {
  577. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  578. {
  579. if (mORKS.TurntableFeedbackloc != loc && !mORKS.TurntableLocLists.Contains(loc))
  580. {
  581. if (!mORKS.TurntableLowerLimit)
  582. {
  583. WriteData("M32.7", false);
  584. DeviceProcessLogShow($"执行了转台启动互锁信号复位");
  585. }
  586. TurntableStart(loc);
  587. DeviceProcessLogShow($"没有物料检测的启动转台控制,转台位置:[{loc}]");
  588. break;
  589. }
  590. else if (mORKS.TurntableFeedbackloc == loc && !mORKS.TurntableLocLists.Contains(loc)) mORKS.TurntableLocLists.Add(loc);
  591. }
  592. }
  593. }
  594. }
  595. }
  596. else DeviceProcessLogShow("未找到可用的物料信息");
  597. }
  598. }
  599. //if (DelayRTrig.GetInstance("互锁信号复位").Start(!mORKS.TurntableLowerLimit && mORKS.TurntableMoveInPlace, 2))
  600. //{
  601. // if (!mORKS.TurntableLowerLimit)
  602. // {
  603. // WriteData("M32.7", false);
  604. // DeviceProcessLogShow($"执行了转台启动互锁信号复位");
  605. // }
  606. //}
  607. //补料中检测
  608. if (RTrig.GetInstance("mORKS.Feeding").Start(mORKS.Feeding))
  609. {
  610. mORKS.AllowTakeNoodle = false;
  611. mORKS.TakeNoodleInterlock = false;
  612. }
  613. //转台到位检测
  614. if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace && mORKS.CurrentLoc == mORKS.TurntableFeedbackloc))
  615. {
  616. mORKS.CurrentLoc = 0;
  617. mORKS.TurntableInterlock = false;
  618. DeviceProcessLogShow("转台到位检测");
  619. }
  620. //补料完成检测
  621. if (RTrig.GetInstance("FeedComplete").Start(mORKS.FeedComplete))
  622. {
  623. if (!mORKS.AllowTakeNoodle && mORKS.TurntableLocLists.Count > 0)
  624. {
  625. mORKS.TurntableLocLists.Clear();
  626. mORKS.TurntableInterlock = false;
  627. DeviceProcessLogShow("补料完成检测");
  628. }
  629. }
  630. }
  631. /// <summary>
  632. /// 取面任务
  633. /// </summary>
  634. private void TakeNoodleTask()
  635. {
  636. //取面控制
  637. if (mORKS.AllowRun && mORKS.RobotIdle && !mORKS.Feeding && !mORKS.RobotTaskInterlock && mORKS.AllowTakeNoodle && mORKS.TurntableMoveInPlace && !mORKS.TakeNoodleInterlock && !mORKS.OutNoodleing && mORKS.RBTakeNoodleTask.Count > 0)
  638. {
  639. int loc = Array.FindIndex(mORKS.NoodleCookerStatus, p => p == false);//查找煮面炉空闲位置
  640. if (loc >= 0 && loc <= 5)
  641. {
  642. if (mORKS.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
  643. {
  644. mORKS.CookNodelId[loc] = orderLocInfo.SuborderId;
  645. SetFallNoodleLoc((ushort)(loc + 1));
  646. //机器人开始取面
  647. RobotTakeNoodle();
  648. OrderChange(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
  649. DeviceProcessLogShow($"订单【{orderLocInfo.SuborderId}】,机器人倒面至【{loc + 1}】号煮面栏");
  650. //写入煮面时间
  651. List<ushort> values = new List<ushort>();
  652. values.Add(Json<MorksPar>.Data.parSets.ElementAt(loc).Minute);
  653. values.Add(Json<MorksPar>.Data.parSets.ElementAt(loc).Second);
  654. WriteData($"VW{116 + (loc * 6)}", values.ToArray());
  655. mORKS.TakeNoodleInterlock = true;
  656. }
  657. }
  658. }
  659. }
  660. /// <summary>
  661. /// 出餐控制
  662. /// </summary>
  663. private void OutNoodleTask()
  664. {
  665. if (mORKS.AllowFallNoodle && mORKS.RobotTaskInterlock && !mORKS.TakeNoodleInterlock && mORKS.RobotIdle && !mORKS.TakeMealDetect)
  666. {
  667. int loc = Array.FindIndex(mORKS.CookNodelId, p => p == mORKS.IngredientsCompleteId && p.Length > 0);
  668. if (loc >= 0 && loc <= 5)
  669. {
  670. if (mORKS.CookNoodlesComplete[loc])
  671. {
  672. SetTakeNoodleLoc((ushort)(loc + 1));
  673. RobotOutMeal();
  674. CookNoodleStatusReset((ushort)(loc + 1));
  675. ResetAllowFallNoodle();
  676. //新增,待测试
  677. if (mORKS.RbOutMealComplete)
  678. {
  679. ResetCookComplete();
  680. mORKS.CookCompleteFlatBit = false;
  681. DeviceProcessLogShow("取餐过程中复位出餐完成信号");
  682. }
  683. if (!string.IsNullOrEmpty(mORKS.OutMealId)) OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_TAKE);
  684. mORKS.OutMealId = mORKS.IngredientsCompleteId;
  685. mORKS.OutMealName = mORKS.IngredientsCompleteName;
  686. mORKS.OutMealSortNum = mORKS.IngredientsCompleteSortNum;
  687. mORKS.IngredientsCompleteId = string.Empty;
  688. mORKS.CookNodelId[loc] = string.Empty;
  689. DeviceProcessLogShow($"{loc + 1} 号位置出餐控制,订单ID:{mORKS.OutMealId}");
  690. mORKS.OutNoodleing = true;
  691. }
  692. }
  693. }
  694. }
  695. /// <summary>
  696. /// 信号检测
  697. /// </summary>
  698. private void SingleDetect()
  699. {
  700. //允许倒面信号检测
  701. if (RTrig.GetInstance("AllowFallNoodle").Start(mORKS.AllowFallNoodle))
  702. {
  703. mORKS.IngredientsCompleteId = mORKS.TakeBowlId;
  704. mORKS.IngredientsCompleteName = mORKS.TakeBowName;
  705. mORKS.IngredientsCompleteSortNum = mORKS.TakeBowSortNum;
  706. mORKS.TakeBowlId = string.Empty;
  707. mORKS.TakeBowName = string.Empty;
  708. mORKS.TakeBowSortNum = 0;
  709. DeviceProcessLogShow($"碗到位,允许到面,{mORKS.IngredientsCompleteId}");
  710. mORKS.TakeBowlInterlock = false;
  711. }
  712. //出餐完成信号检测
  713. if (RTrig.GetInstance("CompleteChange").Start(mORKS.RbOutMealComplete))
  714. {
  715. OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_COOK);
  716. DeviceProcessLogShow($"订单【{mORKS.OutMealId}】制作完成");
  717. mORKS.CookCompleteFlatBit = true;
  718. mORKS.OutNoodleing = false;
  719. }
  720. //加汤
  721. /*if (Delay.GetInstance("加汤延时判断").Start(mORKS.TakeMealDetect && mORKS.CookCompleteFlatBit, 1))
  722. {
  723. AddSoup();
  724. }*/
  725. //取餐完成逻辑处理
  726. if (Delay.GetInstance("CompleteChange1").Start(!mORKS.TakeMealDetect, 1) && mORKS.CookCompleteFlatBit == true)
  727. {
  728. OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_TAKE);
  729. DeviceProcessLogShow($"订单【{mORKS.OutMealId}】取餐完成");
  730. ResetCookComplete();
  731. DeviceProcessLogShow($"出餐订单【{mORKS.OutMealSortNum.ToString()}】");
  732. DeviceProcessLogShow($"出餐订单序号【{mORKS.OutMealSortNum}】");
  733. VoiceAPI.Speak(mORKS.OutMealSortNum.ToString());
  734. //DeviceProcessLogShow($"叫号系统通知主题【MORKS/VoiceCall/{DeviceId}】");
  735. //Plugin.GetInstance.GetPlugin<MQTTMgr>().Publish($"MORKS/VoiceCall/{DeviceId}", mORKS.OutMealSortNum.ToString());
  736. mORKS.CookCompleteFlatBit = false;
  737. mORKS.OutMealId = string.Empty;
  738. mORKS.OutMealName = string.Empty;
  739. mORKS.OutMealSortNum = 0;
  740. }
  741. //机器人取面完成信号检测
  742. if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKS.RbTakeNoodleComplete))
  743. {
  744. mORKS.TakeNoodleInterlock = false;
  745. mORKS.AllowTakeNoodle = false;
  746. mORKS.TurntableInterlock = false;
  747. DeviceProcessLogShow("机器人取面完成信号检测");
  748. TakeNoodleCompleteReset();
  749. }
  750. int OutMealRequstCount = mORKS.CookNoodlesComplete.Where(p => p == true).ToList().Count;
  751. int mlCount = mORKS.NoodleCookerStatus.Where(p => p == true).ToList().Count;
  752. int index = Array.FindIndex(mORKS.CookNodelId, p => p == mORKS.IngredientsCompleteId);
  753. bool isok = index >= 0 && index < mORKS.CookNoodlesComplete.Length && mORKS.CookNoodlesComplete[index];
  754. mORKS.PriorityJudgment = Delay.GetInstance("取餐优先级判断").Start(mORKS.TurntableLocLists.Count > 0 && !mORKS.TurntableLowerLimit, 4);
  755. //mORKS.RobotTaskInterlock = OutMealRequstCount > 0 && mORKS.AllowFallNoodle && (mlCount >= 2 || mORKS.RBTakeNoodleTask.Count == 0 || mORKS.PriorityJudgment);
  756. mORKS.InvertedNoodlesOpenBusy = Json<MorksPar>.Data.InvertedNoodles_OpenBusyNum;
  757. mORKS.RobotTaskInterlock = isok && mORKS.AllowFallNoodle && (mlCount >= mORKS.InvertedNoodlesOpenBusy || mORKS.RBTakeNoodleTask.Count == 0 || mORKS.PriorityJudgment) && !mORKS.TakeMealDetect;//加个取餐口检测判断是否去面
  758. }
  759. ///// <summary>
  760. ///// 语音提醒取餐
  761. ///// </summary>
  762. ///// <param name="meal"></param>
  763. //private void WaitMeaLSpeak(string meal)
  764. //{
  765. // VoiceAPI.m_SystemPlayWav(@"Vioce\电子提示音.wav");
  766. // Thread.Sleep(1000);
  767. // if (meal != null) mORKS.speech.Speak(meal);
  768. // VoiceAPI.m_SystemPlayWav(@"Vioce\取餐通知.wav");
  769. //}
  770. #region PLC 控制函数
  771. private void WriteData(string address, object value)
  772. {
  773. EventBus.GetInstance.Publish(new WriteModel() { DeviceId = DeviceId, Address = address, Value = value });
  774. }
  775. /// <summary>
  776. /// 写入配方数据到 PLC
  777. /// </summary>
  778. private void WriteRecipeBoms()
  779. {
  780. List<ushort> recipeBoms = new List<ushort>();
  781. if (this.recipeBoms == null) return;
  782. foreach (var item in this.recipeBoms.RecipeIds)
  783. {
  784. foreach (var rec in item.Recipes)
  785. {
  786. recipeBoms.Add((ushort)rec);
  787. }
  788. }
  789. if (recipeBoms.Count > 0)
  790. {
  791. //配方数据地址范围:VW2000 - VW2278
  792. WriteData("VW2000", recipeBoms.ToArray());
  793. DeviceProcessLogShow("写配方成功");
  794. }
  795. else { DeviceProcessLogShow("配方数据为空"); }
  796. }
  797. /// <summary>
  798. /// 取面完成复位
  799. /// </summary>
  800. private void TakeNoodleCompleteReset()
  801. {
  802. WriteData("M100.4", false);
  803. }
  804. /// <summary>
  805. /// 指定煮面口状态复位
  806. /// </summary>
  807. /// <param name="num"></param>
  808. private void CookNoodleStatusReset(int num)
  809. {
  810. if (num >= 1 && num <= 6)
  811. {
  812. WriteData($"102.{num - 1}", false);
  813. DeviceProcessLogShow($"{num}号煮面口占用复位");
  814. }
  815. }
  816. /// <summary>
  817. /// 写配方编号
  818. /// </summary>
  819. /// <param name="num"></param>
  820. private void SetRecipeNumber(ushort num)
  821. {
  822. WriteData("VW0", num);
  823. }
  824. /// <summary>
  825. /// 启动转台
  826. /// </summary>
  827. /// <param name="loc"></param>
  828. private void TurntableStart(ushort loc)
  829. {
  830. mORKS.CurrentLoc = loc;
  831. mORKS.TurntableInterlock = true;
  832. mORKS.TurntableLocLists.Add(loc);
  833. WriteData("VW2", loc);
  834. WriteData("M0.5", true);
  835. }
  836. /// <summary>
  837. /// 设置倒面位置
  838. /// </summary>
  839. /// <param name="loc"></param>
  840. private void SetFallNoodleLoc(ushort loc)
  841. {
  842. WriteData("VW4", loc);
  843. }
  844. /// <summary>
  845. /// 设置取面位置
  846. /// </summary>
  847. /// <param name="loc"></param>
  848. private void SetTakeNoodleLoc(ushort loc)
  849. {
  850. WriteData("VW6", loc);
  851. }
  852. /// <summary>
  853. /// 加汤控制
  854. /// </summary>
  855. private async void AddSoup()
  856. {
  857. //M0.6
  858. WriteData("M0.6", true);
  859. await Task.Delay(Convert.ToInt32(Json<MorksPar>.Data.AddSoupTime * 1000));
  860. WriteData("M0.6", false);
  861. }
  862. /// <summary>
  863. /// 取碗控制
  864. /// </summary>
  865. /// <param name="loc"></param>
  866. private void TakeBowlControl(ushort loc)
  867. {
  868. if (loc == 10)//小碗
  869. {
  870. WriteData("M0.1", true);
  871. }
  872. else if (loc == 11)//大碗
  873. {
  874. WriteData("M0.2", true);
  875. }
  876. }
  877. /// <summary>
  878. /// 机器人取面
  879. /// </summary>
  880. private void RobotTakeNoodle()
  881. {
  882. WriteData("M0.3", true);
  883. }
  884. /// <summary>
  885. /// 机器人取餐
  886. /// </summary>
  887. private void RobotOutMeal()
  888. {
  889. WriteData("M0.4", true);
  890. }
  891. /// <summary>
  892. /// 制作完成信号复位
  893. /// </summary>
  894. private void ResetCookComplete()
  895. {
  896. WriteData("M100.6", false);
  897. }
  898. /// <summary>
  899. /// 复位允许取面信号
  900. /// </summary>
  901. private void ResetAllowFallNoodle()
  902. {
  903. WriteData("M100.3", false);
  904. }
  905. /// <summary>
  906. /// 设备初始化
  907. /// </summary>
  908. public async void DeviceInit()
  909. {
  910. WriteData("M0.0", true);
  911. await Task.Delay(1000);
  912. WriteData("M0.0", false);
  913. }
  914. public override void SimOrder()
  915. {
  916. EventBus.GetInstance.Subscribe<MorksSimorderModel>(0, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  917. {
  918. if (@event != null && @event is MorksSimorderModel msm)
  919. {
  920. string guid = Guid.NewGuid().ToString();
  921. if (msm.NoodleLoc >= 1 && msm.NoodleLoc <= 5)
  922. {
  923. mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = (ushort)msm.NoodleLoc, SuborderId = guid });
  924. MessageLog.GetInstance.Show($"添加订单:面条位置【{(ushort)msm.NoodleLoc}】");
  925. }
  926. if (msm.Bowloc >= 10 && msm.Bowloc <= 11)
  927. {
  928. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)msm.Bowloc, SuborderId = guid });
  929. MessageLog.GetInstance.Show($"添加订单:碗位置【{(ushort)msm.Bowloc}】");
  930. }
  931. }
  932. });
  933. }
  934. #endregion
  935. }
  936. }