终端一体化运控平台
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Control_Morks.cs 36 KiB

2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  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. using BPASmartClient.Model.小炒机;
  22. using BPA.Models;
  23. using System.Speech.Synthesis;
  24. using System.Windows.Forms;
  25. using System.Media;
  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. 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. }
  283. /// <summary>
  284. /// 数据解析
  285. /// </summary>
  286. private void DataParse()
  287. {
  288. EventBus.EventBus.GetInstance().Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  289. {
  290. if (@event == null) return;
  291. if (@event is DoOrderEvent order)
  292. {
  293. mORKS.doOrderEvents.Add(order);
  294. if (order.MorkOrder.GoodBatchings == null) return;
  295. if (mORKS.HistorySuborderId.Contains(order.MorkOrder.SuborderId)) return;
  296. OrderCount++;
  297. if (DateTime.Now.Subtract(Json<OrderStatistics>.Data.StatisticsTime).Days != 0)
  298. Json<OrderStatistics>.Data.Count = 0;
  299. Json<OrderStatistics>.Data.StatisticsTime = DateTime.Now;
  300. Json<OrderStatistics>.Data.Count++;
  301. Json<OrderStatistics>.Save();
  302. OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT);
  303. if (order.MorkOrder.GoodBatchings.Count <= 1)
  304. {
  305. DeviceProcessLogShow($"数据解析失败,商品物料信息为空,请检查后台配置!");
  306. return;
  307. }
  308. DeviceProcessLogShow($"接收到{OrderCount}次订单,订单ID:{order.MorkOrder.SuborderId}");
  309. mORKS.HistorySuborderId.Add(order.MorkOrder.SuborderId);
  310. foreach (var item in order.MorkOrder.GoodBatchings)
  311. {
  312. var res = orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId);
  313. if (res != null)
  314. {
  315. if (ushort.TryParse(res.BatchingLoc, out ushort loc))
  316. {
  317. if (loc >= 1 && loc <= 5)
  318. {
  319. if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  320. mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { GoodName = order.MorkOrder.GoodsName, Loc = ushort.Parse(res.BatchingLoc), SuborderId = order.MorkOrder.SuborderId, BatchingId = res.BatchingId });
  321. }
  322. else if (loc >= 10 && loc <= 11)
  323. {
  324. int index = 0;
  325. if (recipeBoms != null)
  326. {
  327. index = Array.FindIndex(recipeBoms.RecipeIds?.ToArray(), p => p.RecipeId == order.MorkOrder.RecipeId);
  328. index++;
  329. }
  330. if (mORKS.TakeBowlTask.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  331. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo()
  332. {
  333. BatchingId = res.BatchingId,
  334. GoodName = order.MorkOrder.GoodsName,
  335. Loc = ushort.Parse(res.BatchingLoc),
  336. SuborderId = order.MorkOrder.SuborderId,
  337. RecipeNumber = (index >= 1 && index <= 10) ? (ushort)index : (ushort)0
  338. });
  339. }
  340. }
  341. }
  342. else
  343. {
  344. DeviceProcessLogShow($"数据解析失败,未找到商品信息,请检查后台配置!");
  345. }
  346. }
  347. }
  348. });
  349. }
  350. public override void MainTask()
  351. {
  352. mORKS.AllowRun = mORKS.InitComplete;
  353. if (Json<KeepDataBase>.Data.IsVerify)
  354. IsHealth = mORKS.Error && mORKS.InitComplete;
  355. else
  356. IsHealth = true;
  357. TakeBowlTask();
  358. TakeNoodleTask();
  359. OutNoodleTask();
  360. SingleDetect();
  361. TurntableControl();
  362. var data = new List<bool>();
  363. for (int i = 0; i < Json<MorksPar>.Data.parSets.Count; i++)
  364. {
  365. data.Add(Json<MorksPar>.Data.parSets.ElementAt(i).IsShield);
  366. }
  367. WriteControl("M260.0", data.ToArray());
  368. OrderChange(mORKS.OutMealId, ORDER_STATUS.COOKING);
  369. OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_COOK);
  370. }
  371. private void BowlControl(OrderLocInfo orderLocInfo)
  372. {
  373. if (orderLocInfo.Loc >= 10 && orderLocInfo.Loc <= 11)
  374. {
  375. mORKS.TakeBowlId = orderLocInfo.SuborderId;
  376. mORKS.TakeBowName = orderLocInfo.GoodName;
  377. TakeBowlControl(orderLocInfo.Loc);
  378. SetRecipeNumber(orderLocInfo.RecipeNumber);
  379. OrderChange(mORKS.TakeBowlId, ORDER_STATUS.COOKING);
  380. DeviceProcessLogShow($"订单【{mORKS.TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]");
  381. mORKS.TakeBowlInterlock = true;
  382. }
  383. }
  384. /// <summary>
  385. /// 取碗控制
  386. /// </summary>
  387. private void TakeBowlTask()
  388. {
  389. if (mORKS.AllowRun && mORKS.TakeBowlTask.Count > 0 && !mORKS.TakeBowlIdle && !mORKS.TakeBowlInterlock)
  390. {
  391. DeviceProcessLogShow("开始取碗流程");
  392. ushort BowLoc = 0;
  393. var res = orderMaterialDelivery?.BatchingInfo?.Where(p => p.BatchingId == mORKS.TakeBowlTask.ElementAt(0).BatchingId).ToList();
  394. if (res == null || res?.Count == 0)
  395. {
  396. if (mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo)) BowlControl(orderLocInfo);
  397. }
  398. else
  399. {
  400. foreach (var item in res)
  401. {
  402. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  403. {
  404. //DeviceProcessLogShow($"位置:={loc},检测开关1:{alarm.Supply1_LossBowl},检测开关1:{alarm.Supply2_LossBowl}");
  405. if (loc == 10 && !alarm.Supply1_LossBowl)
  406. {
  407. BowLoc = loc;
  408. break;
  409. }
  410. else if (loc == 11 && !alarm.Supply2_LossBowl)
  411. {
  412. BowLoc = loc;
  413. break;
  414. }
  415. }
  416. }
  417. if (BowLoc >= 10 && BowLoc <= 11)
  418. {
  419. if (mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
  420. {
  421. orderLocInfo.Loc = BowLoc;
  422. BowlControl(orderLocInfo);
  423. }
  424. }
  425. }
  426. }
  427. }
  428. /// <summary>
  429. /// 转台控制
  430. /// </summary>
  431. private void TurntableControl()
  432. {
  433. if (Global.EnableLocalSimOrder)
  434. {
  435. //不做轮询,直接取面,模拟订单使用
  436. if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  437. {
  438. if (mORKS.TurntableLowerLimit)
  439. {
  440. TurntableStart(mORKS.RBTakeNoodleTask.ElementAt(0).Loc);
  441. mORKS.TurntableLocLists.Clear();
  442. mORKS.AllowTakeNoodle = true;
  443. DeviceProcessLogShow($"控制机器人去转台【{mORKS.RBTakeNoodleTask.ElementAt(0).Loc}】号位置取面");
  444. }
  445. }
  446. }
  447. else
  448. {
  449. //正常轮询
  450. if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  451. {
  452. var result = orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKS.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
  453. if (result != null)
  454. {
  455. var res = result.FirstOrDefault(P => P.BatchingLoc == mORKS.TurntableFeedbackloc.ToString());
  456. if (mORKS.TurntableLowerLimit && res != null)
  457. {
  458. TurntableStart(mORKS.TurntableFeedbackloc);
  459. mORKS.TurntableLocLists.Clear();
  460. mORKS.AllowTakeNoodle = true;
  461. DeviceProcessLogShow($"控制机器人去转台【{mORKS.TurntableFeedbackloc}】号位置取面");
  462. }
  463. else
  464. {
  465. if (!mORKS.TurntableInterlock)
  466. {
  467. foreach (var item in result)
  468. {
  469. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  470. {
  471. if (mORKS.TurntableFeedbackloc != loc && !mORKS.TurntableLocLists.Contains(loc))
  472. {
  473. if (!mORKS.TurntableLowerLimit)
  474. {
  475. WriteData("M32.7", false);
  476. DeviceProcessLogShow($"执行了转台启动互锁信号复位");
  477. }
  478. TurntableStart(loc);
  479. DeviceProcessLogShow($"没有物料检测的启动转台控制,转台位置:[{loc}]");
  480. break;
  481. }
  482. else if (mORKS.TurntableFeedbackloc == loc && !mORKS.TurntableLocLists.Contains(loc)) mORKS.TurntableLocLists.Add(loc);
  483. }
  484. }
  485. }
  486. }
  487. }
  488. else DeviceProcessLogShow("未找到可用的物料信息");
  489. }
  490. }
  491. //if (DelayRTrig.GetInstance("互锁信号复位").Start(!mORKS.TurntableLowerLimit && mORKS.TurntableMoveInPlace, 2))
  492. //{
  493. // if (!mORKS.TurntableLowerLimit)
  494. // {
  495. // WriteData("M32.7", false);
  496. // DeviceProcessLogShow($"执行了转台启动互锁信号复位");
  497. // }
  498. //}
  499. //补料中检测
  500. if (RTrig.GetInstance("mORKS.Feeding").Start(mORKS.Feeding))
  501. {
  502. mORKS.AllowTakeNoodle = false;
  503. mORKS.TakeNoodleInterlock = false;
  504. }
  505. //转台到位检测
  506. if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace && mORKS.CurrentLoc == mORKS.TurntableFeedbackloc))
  507. {
  508. mORKS.CurrentLoc = 0;
  509. mORKS.TurntableInterlock = false;
  510. DeviceProcessLogShow("转台到位检测");
  511. }
  512. //补料完成检测
  513. if (RTrig.GetInstance("FeedComplete").Start(mORKS.FeedComplete))
  514. {
  515. if (!mORKS.AllowTakeNoodle && mORKS.TurntableLocLists.Count > 0)
  516. {
  517. mORKS.TurntableLocLists.Clear();
  518. mORKS.TurntableInterlock = false;
  519. DeviceProcessLogShow("补料完成检测");
  520. }
  521. }
  522. }
  523. /// <summary>
  524. /// 取面任务
  525. /// </summary>
  526. private void TakeNoodleTask()
  527. {
  528. //取面控制
  529. if (mORKS.AllowRun && mORKS.RobotIdle && !mORKS.Feeding && !mORKS.RobotTaskInterlock && mORKS.AllowTakeNoodle && mORKS.TurntableMoveInPlace && !mORKS.TakeNoodleInterlock && !mORKS.OutNoodleing && mORKS.RBTakeNoodleTask.Count > 0)
  530. {
  531. int loc = Array.FindIndex(mORKS.NoodleCookerStatus, p => p == false);//查找煮面炉空闲位置
  532. if (loc >= 0 && loc <= 5)
  533. {
  534. if (mORKS.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
  535. {
  536. mORKS.CookNodelId[loc] = orderLocInfo.SuborderId;
  537. SetFallNoodleLoc((ushort)(loc + 1));
  538. //机器人开始取面
  539. RobotTakeNoodle();
  540. OrderChange(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
  541. DeviceProcessLogShow($"订单【{orderLocInfo.SuborderId}】,机器人倒面至【{loc + 1}】号煮面栏");
  542. //写入煮面时间
  543. List<ushort> values = new List<ushort>();
  544. values.Add(Json<MorksPar>.Data.parSets.ElementAt(loc).Minute);
  545. values.Add(Json<MorksPar>.Data.parSets.ElementAt(loc).Second);
  546. WriteData($"VW{116 + (loc * 6)}", values.ToArray());
  547. mORKS.TakeNoodleInterlock = true;
  548. }
  549. }
  550. }
  551. }
  552. /// <summary>
  553. /// 出餐控制
  554. /// </summary>
  555. private void OutNoodleTask()
  556. {
  557. if (mORKS.AllowFallNoodle && mORKS.RobotTaskInterlock && !mORKS.TakeNoodleInterlock && mORKS.RobotIdle && !mORKS.TakeMealDetect)
  558. {
  559. int loc = Array.FindIndex(mORKS.CookNodelId, p => p == mORKS.IngredientsCompleteId && p.Length > 0);
  560. if (loc >= 0 && loc <= 5)
  561. {
  562. if (mORKS.CookNoodlesComplete[loc])
  563. {
  564. SetTakeNoodleLoc((ushort)(loc + 1));
  565. RobotOutMeal();
  566. CookNoodleStatusReset((ushort)(loc + 1));
  567. ResetAllowFallNoodle();
  568. //新增,待测试
  569. if (mORKS.RbOutMealComplete)
  570. {
  571. ResetCookComplete();
  572. mORKS.CookCompleteFlatBit = false;
  573. DeviceProcessLogShow("取餐过程中复位出餐完成信号");
  574. }
  575. if (!string.IsNullOrEmpty(mORKS.OutMealId)) OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_TAKE);
  576. mORKS.OutMealId = mORKS.IngredientsCompleteId;
  577. mORKS.OutMealName = mORKS.IngredientsCompleteName;
  578. mORKS.IngredientsCompleteId = string.Empty;
  579. mORKS.CookNodelId[loc] = string.Empty;
  580. DeviceProcessLogShow($"{loc + 1} 号位置出餐控制,订单ID:{mORKS.OutMealId}");
  581. mORKS.OutNoodleing = true;
  582. }
  583. }
  584. }
  585. }
  586. /// <summary>
  587. /// 信号检测
  588. /// </summary>
  589. private void SingleDetect()
  590. {
  591. //允许倒面信号检测
  592. if (RTrig.GetInstance("AllowFallNoodle").Start(mORKS.AllowFallNoodle))
  593. {
  594. mORKS.IngredientsCompleteId = mORKS.TakeBowlId;
  595. mORKS.IngredientsCompleteName = mORKS.TakeBowName;
  596. mORKS.TakeBowlId = string.Empty;
  597. mORKS.TakeBowName = string.Empty;
  598. DeviceProcessLogShow($"碗到位,允许到面,{mORKS.IngredientsCompleteId}");
  599. mORKS.TakeBowlInterlock = false;
  600. }
  601. //出餐完成信号检测
  602. if (RTrig.GetInstance("CompleteChange").Start(mORKS.RbOutMealComplete))
  603. {
  604. OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_COOK);
  605. DeviceProcessLogShow($"订单【{mORKS.OutMealId}】制作完成");
  606. mORKS.CookCompleteFlatBit = true;
  607. mORKS.OutNoodleing = false;
  608. WaitMeaLSpeak(mORKS.OutMealName);
  609. }
  610. //加汤
  611. /*if (Delay.GetInstance("加汤延时判断").Start(mORKS.TakeMealDetect && mORKS.CookCompleteFlatBit, 1))
  612. {
  613. AddSoup();
  614. }*/
  615. //取餐完成逻辑处理
  616. if (Delay.GetInstance("CompleteChange1").Start(!mORKS.TakeMealDetect, 1) && mORKS.CookCompleteFlatBit == true)
  617. {
  618. OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_TAKE);
  619. DeviceProcessLogShow($"订单【{mORKS.OutMealId}】取餐完成");
  620. ResetCookComplete();
  621. mORKS.CookCompleteFlatBit = false;
  622. mORKS.OutMealId = string.Empty;
  623. mORKS.OutMealName = string.Empty;
  624. }
  625. //机器人取面完成信号检测
  626. if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKS.RbTakeNoodleComplete))
  627. {
  628. mORKS.TakeNoodleInterlock = false;
  629. mORKS.AllowTakeNoodle = false;
  630. mORKS.TurntableInterlock = false;
  631. DeviceProcessLogShow("机器人取面完成信号检测");
  632. TakeNoodleCompleteReset();
  633. }
  634. int OutMealRequstCount = mORKS.CookNoodlesComplete.Where(p => p == true).ToList().Count;
  635. int mlCount = mORKS.NoodleCookerStatus.Where(p => p == true).ToList().Count;
  636. int index = Array.FindIndex(mORKS.CookNodelId, p => p == mORKS.IngredientsCompleteId);
  637. bool isok = index >= 0 && index < mORKS.CookNoodlesComplete.Length && mORKS.CookNoodlesComplete[index];
  638. mORKS.PriorityJudgment = Delay.GetInstance("取餐优先级判断").Start(mORKS.TurntableLocLists.Count > 0 && !mORKS.TurntableLowerLimit, 4);
  639. //mORKS.RobotTaskInterlock = OutMealRequstCount > 0 && mORKS.AllowFallNoodle && (mlCount >= 2 || mORKS.RBTakeNoodleTask.Count == 0 || mORKS.PriorityJudgment);
  640. mORKS.InvertedNoodlesOpenBusy = Json<MorksPar>.Data.InvertedNoodles_OpenBusyNum;
  641. mORKS.RobotTaskInterlock = isok && mORKS.AllowFallNoodle && (mlCount >= mORKS.InvertedNoodlesOpenBusy || mORKS.RBTakeNoodleTask.Count == 0 || mORKS.PriorityJudgment) && !mORKS.TakeMealDetect;//加个取餐口检测判断是否去面
  642. }
  643. /// <summary>
  644. /// 语音提醒取餐
  645. /// </summary>
  646. /// <param name="meal"></param>
  647. private void WaitMeaLSpeak(string meal)
  648. {
  649. VoiceAPI.m_SystemPlayWav(@"Vioce\电子提示音.wav");
  650. Thread.Sleep(1000);
  651. if (meal != null) mORKS.speech.Speak(meal);
  652. VoiceAPI.m_SystemPlayWav(@"Vioce\取餐通知.wav");
  653. }
  654. #region PLC 控制函数
  655. private void WriteData(string address, object value)
  656. {
  657. EventBus.EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = address, Value = value });
  658. }
  659. /// <summary>
  660. /// 写入配方数据到 PLC
  661. /// </summary>
  662. private void WriteRecipeBoms()
  663. {
  664. List<ushort> recipeBoms = new List<ushort>();
  665. if (this.recipeBoms == null) return;
  666. foreach (var item in this.recipeBoms.RecipeIds)
  667. {
  668. foreach (var rec in item.Recipes)
  669. {
  670. recipeBoms.Add((ushort)rec);
  671. }
  672. }
  673. if (recipeBoms.Count > 0)
  674. {
  675. //配方数据地址范围:VW2000 - VW2278
  676. WriteData("VW2000", recipeBoms.ToArray());
  677. DeviceProcessLogShow("写配方成功");
  678. }
  679. else { DeviceProcessLogShow("配方数据为空"); }
  680. }
  681. /// <summary>
  682. /// 取面完成复位
  683. /// </summary>
  684. private void TakeNoodleCompleteReset()
  685. {
  686. WriteData("M100.4", false);
  687. }
  688. /// <summary>
  689. /// 指定煮面口状态复位
  690. /// </summary>
  691. /// <param name="num"></param>
  692. private void CookNoodleStatusReset(int num)
  693. {
  694. if (num >= 1 && num <= 6)
  695. {
  696. WriteData($"102.{num - 1}", false);
  697. DeviceProcessLogShow($"{num}号煮面口占用复位");
  698. }
  699. }
  700. /// <summary>
  701. /// 写配方编号
  702. /// </summary>
  703. /// <param name="num"></param>
  704. private void SetRecipeNumber(ushort num)
  705. {
  706. WriteData("VW0", num);
  707. }
  708. /// <summary>
  709. /// 启动转台
  710. /// </summary>
  711. /// <param name="loc"></param>
  712. private void TurntableStart(ushort loc)
  713. {
  714. mORKS.CurrentLoc = loc;
  715. mORKS.TurntableInterlock = true;
  716. mORKS.TurntableLocLists.Add(loc);
  717. WriteData("VW2", loc);
  718. WriteData("M0.5", true);
  719. }
  720. /// <summary>
  721. /// 设置倒面位置
  722. /// </summary>
  723. /// <param name="loc"></param>
  724. private void SetFallNoodleLoc(ushort loc)
  725. {
  726. WriteData("VW4", loc);
  727. }
  728. /// <summary>
  729. /// 设置取面位置
  730. /// </summary>
  731. /// <param name="loc"></param>
  732. private void SetTakeNoodleLoc(ushort loc)
  733. {
  734. WriteData("VW6", loc);
  735. }
  736. /// <summary>
  737. /// 加汤控制
  738. /// </summary>
  739. private async void AddSoup()
  740. {
  741. //M0.6
  742. WriteData("M0.6", true);
  743. await Task.Delay(Convert.ToInt32(Json<MorksPar>.Data.AddSoupTime * 1000));
  744. WriteData("M0.6", false);
  745. }
  746. /// <summary>
  747. /// 取碗控制
  748. /// </summary>
  749. /// <param name="loc"></param>
  750. private void TakeBowlControl(ushort loc)
  751. {
  752. if (loc == 10)//小碗
  753. {
  754. WriteData("M0.1", true);
  755. }
  756. else if (loc == 11)//大碗
  757. {
  758. WriteData("M0.2", true);
  759. }
  760. }
  761. /// <summary>
  762. /// 机器人取面
  763. /// </summary>
  764. private void RobotTakeNoodle()
  765. {
  766. WriteData("M0.3", true);
  767. }
  768. /// <summary>
  769. /// 机器人取餐
  770. /// </summary>
  771. private void RobotOutMeal()
  772. {
  773. WriteData("M0.4", true);
  774. }
  775. /// <summary>
  776. /// 制作完成信号复位
  777. /// </summary>
  778. private void ResetCookComplete()
  779. {
  780. WriteData("M100.6", false);
  781. }
  782. /// <summary>
  783. /// 复位允许取面信号
  784. /// </summary>
  785. private void ResetAllowFallNoodle()
  786. {
  787. WriteData("M100.3", false);
  788. }
  789. /// <summary>
  790. /// 设备初始化
  791. /// </summary>
  792. public async void DeviceInit()
  793. {
  794. WriteData("M0.0", true);
  795. await Task.Delay(1000);
  796. WriteData("M0.0", false);
  797. }
  798. public override void SimOrder()
  799. {
  800. EventBus.EventBus.GetInstance().Subscribe<MorksSimorderModel>(0, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  801. {
  802. if (@event != null && @event is MorksSimorderModel msm)
  803. {
  804. string guid = Guid.NewGuid().ToString();
  805. if (msm.NoodleLoc >= 1 && msm.NoodleLoc <= 5)
  806. {
  807. mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = (ushort)msm.NoodleLoc, SuborderId = guid });
  808. MessageLog.GetInstance.Show($"添加订单:面条位置【{(ushort)msm.NoodleLoc}】");
  809. }
  810. if (msm.Bowloc >= 10 && msm.Bowloc <= 11)
  811. {
  812. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)msm.Bowloc, SuborderId = guid });
  813. MessageLog.GetInstance.Show($"添加订单:碗位置【{(ushort)msm.Bowloc}】");
  814. }
  815. }
  816. });
  817. }
  818. #endregion
  819. }
  820. }