终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

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