终端一体化运控平台
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

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