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.
 
 

500 lines
21 KiB

  1. using System;
  2. using HBLConsole.Interface;
  3. using HBLConsole.Service;
  4. using HBLConsole.Communication;
  5. using BPA.Message;
  6. using HBLConsole.Model;
  7. using System.Linq;
  8. using System.Threading;
  9. using HBLConsole.Factory;
  10. using BPA.Message.Enum;
  11. using BPA.Message.IOT;
  12. using System.Collections.Generic;
  13. namespace HBLConsole.MORKD
  14. {
  15. public class Control_MORKD : IControl
  16. {
  17. GVL_MORKD mORKD = new GVL_MORKD();
  18. Alarm_MORKD alarm = new Alarm_MORKD();
  19. public void ConnectOk()
  20. {
  21. Main();
  22. ReadData();
  23. ResetProgram();
  24. }
  25. public void DataParse<T>(T order)
  26. {
  27. if (order is MorkOrderPush morkOrderPush)
  28. {
  29. foreach (var item in morkOrderPush.GoodBatchings)
  30. {
  31. var res = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingId == item.BatchingId);
  32. if (res != null)
  33. {
  34. if (ushort.TryParse(res.BatchingLoc, out ushort loc))
  35. {
  36. if (loc >= 1 && loc <= 5)
  37. {
  38. mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId, BatchingId = res.BatchingId });
  39. }
  40. else if (loc >= 6 && loc <= 10)
  41. {
  42. mORKD.TakeSoupTask.Enqueue(new OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId });
  43. }
  44. else if (loc >= 11 && loc <= 12)
  45. {
  46. mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(loc - 10), SuborderId = morkOrderPush.SuborderId });
  47. }
  48. }
  49. }
  50. }
  51. }
  52. }
  53. public void Init()
  54. {
  55. ActionManage.GetInstance.Register(new Action(() => { mORKD.InitControl(); }), "InitCommand");
  56. }
  57. bool Initing = false;
  58. /// <summary>
  59. /// 复位程序
  60. /// </summary>
  61. private void ResetProgram()
  62. {
  63. ThreadManage.GetInstance.StartLong(new Action(() =>
  64. {
  65. if (RTrig.GetInstance("ResetProgram").Start(Initing))
  66. {
  67. ThreadManage.GetInstance.StopTask("MainTask", new Action(() =>
  68. {
  69. ThreadManage.GetInstance.StopTask("ReadPLCData", new Action(() =>
  70. {
  71. mORKD = null;
  72. mORKD = new GVL_MORKD();
  73. ActionManage.GetInstance.Send("ResetProgram");
  74. ReadData();
  75. Main();
  76. }));
  77. }));
  78. }
  79. Thread.Sleep(10);
  80. }), "ResetProgram");
  81. }
  82. public void Main()
  83. {
  84. ThreadManage.GetInstance.StartLong(new Action(() =>
  85. {
  86. mORKD.AllowRun = mORKD.InitComplete && !mORKD.TemperatureReached;
  87. TakeBowlTask();
  88. TakeNoodleTask();
  89. OutNoodleTask();
  90. SingleDetect();
  91. TurntableControl();
  92. OutSoupTask();
  93. TakeSoupTask();
  94. Thread.Sleep(10);
  95. }), "MainTask");
  96. }
  97. public void ReadData()
  98. {
  99. ThreadManage.GetInstance.StartLong(new Action(() =>
  100. {
  101. ModbusTcpHelper.GetInstance.Readbool(1120, 30, new Action<bool[]>((bools) =>
  102. {
  103. mORKD.InitComplete = bools[0];
  104. mORKD.TurntableInPlace = bools[1];
  105. mORKD.RBTakeNoodleComplete = bools[2];
  106. for (int i = 0; i < 2; i++)
  107. {
  108. mORKD.AxisIdle[i] = bools[3 + i];
  109. mORKD.AxisAllowInvertedNoodle[i] = bools[5 + i];
  110. mORKD.AxisAllowInvertedSoup[i] = bools[7 + i];
  111. mORKD.SoupHeatComplete[i] = bools[9 + i];
  112. mORKD.BreakMechanismIdle[i] = bools[25 + i];
  113. }
  114. for (int i = 0; i < 6; i++)
  115. {
  116. mORKD.CookNoodleBasketIdle[i] = bools[11 + i];
  117. mORKD.CookNoodleComplete[i] = bools[17 + i];
  118. }
  119. mORKD.TakeNoodleRobotIdle = bools[23];
  120. mORKD.TakeSoupRobotIdle = bools[24];
  121. mORKD.TakeSoupComplete = bools[27];
  122. mORKD.PutNoodleTakeMealComplete = bools[28];
  123. Initing = bools[29];
  124. }));
  125. ModbusTcpHelper.GetInstance.Readbool(1280, 11, new Action<bool[]>((bools) =>
  126. {
  127. mORKD.TurntableLowerLimit = bools[0];
  128. mORKD.TurntableUpLimit = bools[1];
  129. for (int i = 0; i < 5; i++)
  130. {
  131. mORKD.SoupMaterialShortage[i] = bools[2 + i];
  132. }
  133. for (int i = 0; i < 3; i++)
  134. {
  135. mORKD.OutMealDetect[i] = bools[7 + i];
  136. }
  137. mORKD.TemperatureReached = bools[10];
  138. }));
  139. var ResLoc = ModbusTcpHelper.GetInstance.Read(720, ReadType.HoldingRegisters);
  140. if (ResLoc != null)
  141. {
  142. if (ResLoc is ushort loc)
  143. {
  144. mORKD.TurntableFeedbackloc = loc;
  145. }
  146. }
  147. Thread.Sleep(100);
  148. }), "ReadPLCData");
  149. }
  150. public void SimOrder<T>(T simOrder)
  151. {
  152. if (simOrder != null)
  153. {
  154. if (simOrder is List<ushort> locs)
  155. {
  156. string subId = Guid.NewGuid().ToString();
  157. foreach (var item in locs)
  158. {
  159. if (item >= 1 && item <= 5)
  160. {
  161. var res = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingLoc == item.ToString());
  162. if (res != null)
  163. {
  164. mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, BatchingId = res.BatchingId, SuborderId = subId });
  165. MessageLog.GetInstance.Show($"添加订单:面条位置【{item}】");
  166. }
  167. }
  168. if (item >= 6 && item <= 10)
  169. {
  170. mORKD.TakeSoupTask.Enqueue(new OrderLocInfo() { Loc = item, SuborderId = subId });
  171. MessageLog.GetInstance.Show($"添加订单:浇头位置【{item}】");
  172. }
  173. if (item >= 11 && item <= 12)
  174. {
  175. mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(item - 10), SuborderId = subId });
  176. MessageLog.GetInstance.Show($"添加订单:碗位置【{item - 10}】");
  177. }
  178. }
  179. }
  180. }
  181. }
  182. /// <summary>
  183. /// IOT 广播消息命令
  184. /// </summary>
  185. public void IotBroadcast<T>(T broadcast)
  186. {
  187. if (broadcast != null && broadcast is IOTCommandModel iOTCommand)
  188. {
  189. switch (iOTCommand.CommandName)
  190. {
  191. case 0://控制类
  192. if (iOTCommand.CommandValue != null)
  193. {
  194. if (iOTCommand.CommandValue.ContainsKey("SimOrder"))
  195. {
  196. SimOrder(new SimOrderData { NoodleLoc = 1, BowlLoc = 10 });
  197. }
  198. }
  199. break;
  200. case 1://设置属性
  201. break;
  202. case 2://通知消息
  203. break;
  204. default:
  205. break;
  206. }
  207. }
  208. }
  209. /// <summary>
  210. /// 取碗控制
  211. /// </summary>
  212. private void TakeBowlTask()
  213. {
  214. mORKD.AxisIdleIndex = mORKD.AxisIdle.GetIndex(true);
  215. mORKD.AxisIdleLockIndex = mORKD.AxisIdleLock.GetIndex(false);
  216. if (mORKD.AxisIdleLockIndex == mORKD.AxisIdleIndex)
  217. {
  218. if (mORKD.AxisIdleIndex >= 0 && mORKD.AxisIdleIndex <= 1)
  219. {
  220. if (mORKD.AllowRun && mORKD.TakeBowlTask.Count > 0)
  221. {
  222. if (mORKD.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
  223. {
  224. mORKD.AxisAllowInvertedNoodleID[mORKD.AxisIdleIndex] = orderLocInfo.SuborderId;
  225. mORKD.DropBowlStart((ushort)(mORKD.AxisIdleIndex + 1), orderLocInfo.Loc);
  226. mORKD.AxisIdleLock[mORKD.AxisIdleLockIndex] = true;
  227. MessageLog.GetInstance.Show($"执行取碗控制,碗位置:[{orderLocInfo.Loc}],轴位置:[{mORKD.AxisIdleIndex + 1}]");
  228. MessageLog.GetInstance.Show($"{mORKD.AxisIdleIndex + 1}号轴订单ID:[{orderLocInfo.SuborderId}]");
  229. }
  230. }
  231. }
  232. }
  233. }
  234. /// <summary>
  235. /// 转台控制
  236. /// </summary>
  237. private void TurntableControl()
  238. {
  239. if (mORKD.TurntableInPlace && mORKD.InitComplete && !mORKD.AllowTakeNoodle && mORKD.RBTakeNoodleTask.Count > 0)
  240. {
  241. var result = Json<BatchingInfoPar>.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKD.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
  242. if (mORKD.TurntableLowerLimit)
  243. {
  244. if (mORKD.TurntableFeedbackloc == mORKD.RBTakeNoodleTask.ElementAt(0).Loc || (result?.Count > 0 && result?.Count == mORKD.TurntableLocLists.Count))
  245. {
  246. mORKD.TurntableLocLists.Clear();
  247. mORKD.AllowTakeNoodle = true;
  248. MessageLog.GetInstance.Show("转台位置OK,执行机器人取面");
  249. }
  250. else
  251. {
  252. if (!mORKD.TurntableInterlock)
  253. {
  254. mORKD.TurntableStart(mORKD.RBTakeNoodleTask.ElementAt(0).Loc);
  255. MessageLog.GetInstance.Show($"有物料检测,反馈位置不同的转台启动控制,转台位置:[{mORKD.RBTakeNoodleTask.ElementAt(0).Loc}]");
  256. }
  257. }
  258. }
  259. else
  260. {
  261. if (!mORKD.TurntableInterlock)
  262. {
  263. if (result!= null)
  264. {
  265. foreach (var item in result)
  266. {
  267. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  268. {
  269. if (mORKD.TurntableFeedbackloc != loc && !mORKD.TurntableLocLists.Contains(loc))
  270. {
  271. mORKD.TurntableStart(loc);
  272. MessageLog.GetInstance.Show($"没有物料检测的启动转台控制,转台位置:[{loc}]");
  273. break;
  274. }
  275. else if (mORKD.TurntableFeedbackloc == loc && !mORKD.TurntableLocLists.Contains(loc)) mORKD.TurntableLocLists.Add(loc);
  276. }
  277. }
  278. }
  279. //result?.ForEach(item =>
  280. //{
  281. // if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  282. // {
  283. // if (mORKD.TurntableFeedbackloc != loc && !mORKD.TurntableLocLists.Contains(loc))
  284. // {
  285. // mORKD.TurntableStart(loc);
  286. // MessageLog.GetInstance.Show($"没有物料检测的启动转台控制,转台位置:[{loc}]");
  287. // return;
  288. // }
  289. // else if (mORKD.TurntableFeedbackloc == loc) mORKD.TurntableLocLists.Add(loc);
  290. // }
  291. //});
  292. }
  293. }
  294. }
  295. //转台到位检测
  296. if (RTrig.GetInstance("TurntableInPlace").Start(mORKD.TurntableInPlace))
  297. {
  298. mORKD.TurntableInterlock = false;
  299. }
  300. }
  301. /// <summary>
  302. /// 取面任务
  303. /// </summary>
  304. private void TakeNoodleTask()
  305. {
  306. //取面控制
  307. if (mORKD.AllowRun && mORKD.TakeNoodleRobotIdle && !mORKD.RobotTaskInterlock && mORKD.AllowTakeNoodle)
  308. {
  309. if (mORKD.TurntableInPlace && !mORKD.OutNoodleing && mORKD.RBTakeNoodleTask.Count > 0)
  310. {
  311. int loc = mORKD.CookNoodleBasketIdle.GetIndex(false);//查找煮面炉空闲位置
  312. if (loc >= 0 && loc <= 5)
  313. {
  314. if (mORKD.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
  315. {
  316. mORKD.RBTakeNoodleStart((ushort)(loc + 1), orderLocInfo.Loc);
  317. mORKD.CookNodelId[loc] = orderLocInfo.SuborderId;
  318. SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
  319. //MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,煮面栏:[{loc + 1}]");
  320. mORKD.TakeNoodleInterlock = true;
  321. MessageLog.GetInstance.Show($"{loc + 1}号煮面篮订单ID:[{orderLocInfo.SuborderId}]");
  322. }
  323. }
  324. }
  325. }
  326. //机器人取面完成信号检测
  327. if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKD.RBTakeNoodleComplete))
  328. {
  329. mORKD.TakeNoodleInterlock = false;
  330. mORKD.AllowTakeNoodle = false;
  331. MessageLog.GetInstance.Show("转台取面完成");
  332. mORKD.TakeNoodleCompleteReset();
  333. }
  334. }
  335. /// <summary>
  336. /// 出餐控制
  337. /// </summary>
  338. private void OutNoodleTask()
  339. {
  340. for (ushort i = 0; i < 6; i++)
  341. {
  342. if (RTrig.GetInstance($"CookNoodleCompleteTask{i}").Start(mORKD.CookNoodleComplete[i]))
  343. {
  344. mORKD.CookNoodleCompleteTask.Enqueue(i);
  345. }
  346. }
  347. if (mORKD.RobotTaskInterlock && !mORKD.TakeNoodleInterlock && mORKD.TakeNoodleRobotIdle)
  348. {
  349. if (mORKD.CookNoodleCompleteTask.Count > 0)
  350. {
  351. string id = mORKD.CookNodelId[mORKD.CookNoodleCompleteTask.ElementAt(0)];
  352. int index = mORKD.AxisAllowInvertedNoodleID.GetIndex(id);
  353. if (index >= 0 && index <= 1)
  354. {
  355. if (mORKD.AxisAllowInvertedNoodle[index])
  356. {
  357. if (mORKD.CookNoodleCompleteTask.TryDequeue(out ushort loc))
  358. {
  359. mORKD.OutNoodleing = true;
  360. mORKD.RBOutNoodleStart((ushort)(loc + 1), (ushort)(index + 1));
  361. mORKD.AxisIdleLock[index] = false;
  362. mORKD.AxisAllowInvertedSoupID[index] = mORKD.AxisAllowInvertedNoodleID[index];
  363. mORKD.AxisAllowInvertedNoodleID[index] = string.Empty;
  364. MessageLog.GetInstance.Show($"从{loc + 1}号位置取面");
  365. MessageLog.GetInstance.Show($"倒入{index + 1}号碗位置");
  366. MessageLog.GetInstance.Show($"{index + 1}号轴允许倒浇头ID:[{ mORKD.AxisAllowInvertedSoupID[index]}]");
  367. }
  368. }
  369. }
  370. }
  371. }
  372. int mlCount = mORKD.CookNoodleBasketIdle.Where(p => p == true).ToList().Count;
  373. mORKD.RobotTaskInterlock = mORKD.CookNoodleCompleteTask.Count > 0 && (mlCount >= 2 || mORKD.RBTakeNoodleTask.Count == 0);
  374. }
  375. /// <summary>
  376. /// 取浇头控制
  377. /// </summary>
  378. private void TakeSoupTask()
  379. {
  380. int index = mORKD.BreakMechanismIdle.GetIndex(true);
  381. if (index >= 0 && index <= 1)
  382. {
  383. if (mORKD.TakeSoupTask.Count > 0 && !mORKD.AllowTakeSoup && mORKD.TakeSoupRobotIdle && mORKD.AllowRun)
  384. {
  385. if (mORKD.TakeSoupTask.TryDequeue(out OrderLocInfo orderLocInfo))
  386. {
  387. mORKD.SoupHeatLocID[index] = orderLocInfo.SuborderId;
  388. mORKD.RBTakeSoupStart(orderLocInfo.Loc, (ushort)(index + 1));
  389. SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
  390. MessageLog.GetInstance.Show($"{index + 1}号浇头加热位ID:[{ mORKD.SoupHeatLocID[index]}]");
  391. }
  392. }
  393. }
  394. if (RTrig.GetInstance("TakeSoupComplete").Start(mORKD.TakeSoupComplete))
  395. {
  396. mORKD.AllowTakeSoup = false;
  397. MessageLog.GetInstance.Show("取浇头完成");
  398. mORKD.TakeSoupCompleteReset();
  399. }
  400. }
  401. /// <summary>
  402. /// 浇头加热完成出浇头控制
  403. /// </summary>
  404. private void OutSoupTask()
  405. {
  406. if (!mORKD.AllowTakeSoup && !mORKD.AllowPutSoup && mORKD.TakeSoupRobotIdle)
  407. {
  408. mORKD.PutNoodleLoc = mORKD.OutMealDetect.GetIndex(false);
  409. if (mORKD.PutNoodleLoc >= 0 && mORKD.PutNoodleLoc <= 2)
  410. {
  411. for (int i = 0; i < 2; i++)
  412. {
  413. if (mORKD.SoupHeatComplete[i] && mORKD.SoupHeatLocID[i].Length > 0)
  414. {
  415. for (int m = 0; m < 2; m++)
  416. {
  417. if (mORKD.AxisAllowInvertedSoup[m] && mORKD.AxisAllowInvertedSoupID[m].Length > 0)
  418. {
  419. if (mORKD.SoupHeatLocID[i] == mORKD.AxisAllowInvertedSoupID[m])
  420. {
  421. mORKD.HeatCompleteTakeSoupStart((ushort)(i + 1), (ushort)(m + 1), (ushort)(mORKD.PutNoodleLoc + 1));
  422. mORKD.OutMealId[mORKD.PutNoodleLoc] = mORKD.AxisAllowInvertedSoupID[m];
  423. mORKD.AxisAllowInvertedSoupID[m] = string.Empty;
  424. mORKD.SoupHeatLocID[i] = string.Empty;
  425. MessageLog.GetInstance.Show($"{mORKD.PutNoodleLoc + 1}号出餐口订单ID:[{ mORKD.OutMealId[mORKD.PutNoodleLoc]}]");
  426. }
  427. }
  428. }
  429. }
  430. }
  431. }
  432. }
  433. if (RTrig.GetInstance("PutNoodleTakeMealComplete").Start(mORKD.PutNoodleTakeMealComplete))
  434. {
  435. mORKD.AllowPutSoup = false;
  436. SimpleFactory.GetInstance.OrderChanged(mORKD.OutMealId[mORKD.PutNoodleLoc], ORDER_STATUS.COMPLETED_COOK);
  437. mORKD.PutNoodleTakeMealCompleteReset();
  438. }
  439. }
  440. /// <summary>
  441. /// 信号检测
  442. /// </summary>
  443. private void SingleDetect()
  444. {
  445. //取餐完成
  446. //var RemoveItem = Json<MorkOrderPushPar>.Data.morkOrderPushes.FirstOrDefault(p => p.OrderPush.SuborderId == "取餐口订单ID");
  447. //if (RemoveItem != null)
  448. // Json<MorkOrderPushPar>.Data.morkOrderPushes.Remove(RemoveItem);
  449. }
  450. }
  451. }