终端一体化运控平台
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

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