终端一体化运控平台
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.

Control_MORKM.cs 40 KiB

2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
2 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using System.Diagnostics;
  8. using BPASmartClient.Device;
  9. using BPASmartClient.Helper;
  10. using BPA.Message.Enum;
  11. using BPASmartClient.Model;
  12. using BPASmartClient.EventBus;
  13. using static BPASmartClient.EventBus.EventBus;
  14. using BPASmartClient.MorkM.Model;
  15. using System.Collections.ObjectModel;
  16. using BPASmartClient.Model.PLC;
  17. using BPASmartClient.MorkM.ViewModel;
  18. using BPA.Message;
  19. namespace BPASmartClient.MorkM
  20. {
  21. public class Control_MORKM : BaseDevice
  22. {
  23. public override DeviceClientType DeviceType => DeviceClientType.MORKM;
  24. GVL_MORKM mORKS = new GVL_MORKM();
  25. Alarm alarm = new Alarm();
  26. HardwareStatus hardwareStatus = new HardwareStatus();
  27. public void SimOrder<T>(T simOrder)
  28. {
  29. if (simOrder != null)
  30. {
  31. if (simOrder is List<ushort> locs)
  32. {
  33. OrderInformation newOrder = new OrderInformation();//新加
  34. List<OrderLocInfo> orders = new List<OrderLocInfo>();
  35. string subId = Guid.NewGuid().ToString();
  36. foreach (var item in locs)
  37. {
  38. if (item >= 1 && item <= 5)
  39. {
  40. orders.Add(new OrderLocInfo() { Loc = item, SuborderId = subId, MakeType = false });
  41. //mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, SuborderId = subId });
  42. //DeviceProcessLogShow($"添加订单:面条位置【{item}】");
  43. }
  44. if (item >= 10 && item <= 11)
  45. {
  46. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = item, SuborderId = subId, MakeType = false });
  47. DeviceProcessLogShow($"添加订单:碗位置【{item}】");
  48. }
  49. }
  50. //手动供碗 调试用
  51. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo()
  52. {
  53. Loc = 11,
  54. SuborderId = subId,
  55. MakeType = false
  56. }) ;
  57. mORKS.DishNumber = orders.Count;//订单中配菜的数量
  58. while (orders.Count > 0)
  59. {
  60. for (int i = 0; i < orders.Count; i++)
  61. {
  62. var res = orders.FirstOrDefault(p => p.Loc % 2 != 0);
  63. if (res != null)
  64. {
  65. //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == res.SuborderId) == null)
  66. mORKS.RBTakeNoodleTask.Enqueue(res);
  67. orders.Remove(res);
  68. }
  69. else
  70. {
  71. //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == orders[i].SuborderId) == null)
  72. mORKS.RBTakeNoodleTask.Enqueue(orders[i]);
  73. mORKS.VegtabNum++;
  74. orders.RemoveAt(i);
  75. }
  76. }
  77. }
  78. Dictionary<string, OrderInformation> dic = new Dictionary<string, OrderInformation>();
  79. newOrder.DishNum = mORKS.DishNumber;
  80. newOrder.VegatableNumber = mORKS.VegtabNum;
  81. dic.Add(subId, newOrder);
  82. mORKS.Conqueue.Enqueue(dic);
  83. mORKS.VegtabNum = 0;
  84. mORKS.DishNumber = 0;
  85. }
  86. }
  87. }
  88. ///// <summary>
  89. ///// IOT 广播消息命令
  90. ///// </summary>
  91. //public void IotBroadcast<T>(T broadcast)
  92. //{
  93. // if (broadcast != null && broadcast is IOTCommandModel iOTCommand)
  94. // {
  95. // DeviceProcessLogShow($"IOT 广播消息命令 {iOTCommand.deviceName} 设备命令 {iOTCommand.CommandName} 控制变量{iOTCommand.CommandValue.Keys.First()}{iOTCommand.CommandValue[iOTCommand.CommandValue.Keys.First()]}");
  96. // switch (iOTCommand.CommandName)
  97. // {
  98. // case 0://控制类
  99. // if (iOTCommand.CommandValue != null)
  100. // {
  101. // if (iOTCommand.CommandValue.ContainsKey("order"))
  102. // {
  103. // List<ushort> vs = new List<ushort>();
  104. // vs.Add((ushort)(new Random().Next(1, 5)));
  105. // vs.Add(ushort.Parse(iOTCommand.CommandValue["order"]));
  106. // SimOrder(vs);
  107. // }
  108. // else if (iOTCommand.CommandValue.ContainsKey("init"))
  109. // {
  110. // DeviceInit();
  111. // }
  112. // else if (iOTCommand.CommandValue.ContainsKey("stop"))
  113. // {
  114. // }
  115. // else if (iOTCommand.CommandValue.ContainsKey("start"))
  116. // {
  117. // }
  118. // }
  119. // break;
  120. // case 1://设置属性
  121. // break;
  122. // case 2://通知消息
  123. // break;
  124. // default:
  125. // break;
  126. // }
  127. // }
  128. //}
  129. int OrderCount = 0;
  130. ///// <summary>
  131. ///// 数据解析
  132. ///// </summary>
  133. public void DataParse()
  134. {
  135. EventBus.EventBus.GetInstance().Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  136. {
  137. if (@event == null) return;
  138. if (@event is DoOrderEvent order)
  139. {
  140. mORKS.doOrderEvents.Add(order);
  141. if (order.MorkOrder.GoodBatchings == null) return;
  142. OrderCount++;
  143. OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT);
  144. DeviceProcessLogShow($"接收到{OrderCount}次订单");
  145. //if (order is MorkOrderPush morkOrderPush)
  146. //{
  147. OrderInformation newOrder = new OrderInformation();//2022.4.30 修改
  148. List<OrderLocInfo> locs = new List<OrderLocInfo>();
  149. foreach (var item in order.MorkOrder.GoodBatchings)
  150. {
  151. var res =orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId);
  152. if (res != null)
  153. {
  154. if (ushort.TryParse(res.BatchingLoc, out ushort loc))
  155. {
  156. if (loc >= 1 && loc <= 5)
  157. {
  158. locs.Add(new OrderLocInfo() { Loc = ushort.Parse(res.BatchingLoc), SuborderId = order.MorkOrder.SuborderId, BatchingId = res.BatchingId, MakeType = order.MorkOrder.MakeID == "2" }); //新增冒菜干拌or加汤
  159. }
  160. else if (loc >= 10 && loc <= 11)
  161. {
  162. int index = 0;
  163. if (Json<BatchingInfoPar>.Data.recipeBoms != null)
  164. {
  165. index = Array.FindIndex(Json<BatchingInfoPar>.Data.recipeBoms?.RecipeIds.ToArray(), p => p.RecipeId == order.MorkOrder.RecipeId);
  166. index++;
  167. }
  168. if (mORKS.TakeBowlTask.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  169. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo()
  170. {
  171. Loc = 11,
  172. SuborderId = order.MorkOrder.SuborderId,
  173. RecipeNumber = (index >= 1 && index <= 10) ? (ushort)index : (ushort)0,
  174. MakeType = order.MorkOrder.MakeID == "2"
  175. });
  176. }
  177. }
  178. }
  179. }
  180. //手动供碗 调试用
  181. mORKS.TakeBowlTask.Enqueue(new OrderLocInfo()
  182. {
  183. Loc = 11,
  184. SuborderId = order.MorkOrder.SuborderId,
  185. MakeType = order.MorkOrder.MakeID == "2"
  186. });
  187. mORKS.DishNumber = locs.Count;//订单中配菜的数量 2022.4.30 修改
  188. while (locs.Count > 0)
  189. {
  190. for (int i = 0; i < locs.Count; i++)
  191. {
  192. var res = locs.FirstOrDefault(p => p.Loc % 2 != 0);
  193. if (res != null)
  194. {
  195. //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == res.SuborderId) == null)
  196. mORKS.RBTakeNoodleTask.Enqueue(res);
  197. locs.Remove(res);
  198. }
  199. else
  200. {
  201. //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == locs[i].SuborderId) == null)
  202. mORKS.RBTakeNoodleTask.Enqueue(locs[i]);
  203. mORKS.VegtabNum++;
  204. locs.RemoveAt(i);
  205. }
  206. }
  207. }
  208. Dictionary<string, OrderInformation> dic = new Dictionary<string, OrderInformation>();
  209. newOrder.DishNum = mORKS.DishNumber;
  210. newOrder.VegatableNumber = mORKS.VegtabNum;
  211. //newOrder.MakeType = morkOrderPush.MakeType;
  212. dic.Add(order.MorkOrder.SuborderId, newOrder);
  213. mORKS.Conqueue.Enqueue(dic);
  214. mORKS.VegtabNum = 0;
  215. mORKS.DishNumber = 0;
  216. //}
  217. }
  218. });
  219. }
  220. public override void MainTask()
  221. {
  222. mORKS.AllowRun = mORKS.InitComplete;
  223. if (Json<KeepDataBase>.Data.IsVerify)
  224. IsHealth = mORKS.Error && mORKS.InitComplete;
  225. else
  226. IsHealth = true;
  227. //if (mORKS.AllowRun)
  228. //{
  229. TakeBowlTask();
  230. TakeNoodleTask();
  231. OutNoodleTask();
  232. SingleDetect();
  233. TurntableControl();
  234. }
  235. /// <summary>
  236. /// 取碗控制
  237. /// </summary>
  238. private void TakeBowlTask()
  239. {
  240. if (mORKS.AllowRun && mORKS.TakeBowlTask.Count > 0 && !mORKS.TakeBowlIdle && !mORKS.TakeBowlInterlock)
  241. {
  242. if (mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo))
  243. {
  244. mORKS.TakeBowlId = orderLocInfo.SuborderId;
  245. mORKS.OutMealType = orderLocInfo.MakeType;//新增冒菜干拌or加汤
  246. TakeBowlControl(orderLocInfo.Loc);
  247. SetRecipeNumber(orderLocInfo.RecipeNumber);
  248. OrderChange(mORKS.TakeBowlId, ORDER_STATUS.COOKING);
  249. DeviceProcessLogShow($"订单【{ mORKS.TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]");
  250. }
  251. mORKS.TakeBowlInterlock = true;
  252. }
  253. }
  254. /// <summary>
  255. /// 转台控制
  256. /// </summary>
  257. private void TurntableControl()
  258. {
  259. if (GeneralConfig.EnableLocalSimOrder)
  260. {
  261. //不做轮询,直接取面,模拟订单使用
  262. if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  263. {
  264. if (mORKS.TurntableLowerLimit)
  265. {
  266. TurntableStart(mORKS.RBTakeNoodleTask.ElementAt(0).Loc);
  267. if (mORKS.RBTakeNoodleTask.ElementAt(0).Loc == mORKS.TurntableFeedbackloc)
  268. {
  269. mORKS.TurntableLocLists.Clear();
  270. mORKS.AllowTakeNoodle = true;
  271. DeviceProcessLogShow($"控制机器人去转台【{mORKS.RBTakeNoodleTask.ElementAt(0).Loc}】号位置取面");
  272. }
  273. }
  274. }
  275. }
  276. else
  277. {
  278. //正常轮询
  279. if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0)
  280. {
  281. var result = orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKS.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList();
  282. if (result != null)
  283. {
  284. var res = result.FirstOrDefault(P => P.BatchingLoc == mORKS.TurntableFeedbackloc.ToString());
  285. if (mORKS.TurntableLowerLimit && res != null)
  286. {
  287. TurntableStart(mORKS.TurntableFeedbackloc);
  288. mORKS.TurntableLocLists.Clear();
  289. mORKS.AllowTakeNoodle = true;
  290. DeviceProcessLogShow($"控制机器人去转台【{mORKS.TurntableFeedbackloc}】号位置取面");
  291. }
  292. else
  293. {
  294. if (!mORKS.TurntableInterlock)
  295. {
  296. foreach (var item in result)
  297. {
  298. if (ushort.TryParse(item.BatchingLoc, out ushort loc))
  299. {
  300. if (mORKS.TurntableFeedbackloc != loc && !mORKS.TurntableLocLists.Contains(loc))
  301. {
  302. TurntableStart(loc);
  303. DeviceProcessLogShow($"没有物料检测的启动转台控制,转台位置:[{loc}]");
  304. break;
  305. }
  306. else if (mORKS.TurntableFeedbackloc == loc && !mORKS.TurntableLocLists.Contains(loc)) mORKS.TurntableLocLists.Add(loc);
  307. }
  308. }
  309. }
  310. }
  311. }
  312. else DeviceProcessLogShow("未找到可用的物料信息");
  313. }
  314. }
  315. //转台到位检测
  316. if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace && mORKS.CurrentLoc == mORKS.TurntableFeedbackloc))
  317. {
  318. mORKS.CurrentLoc = 0;
  319. mORKS.TurntableInterlock = false;
  320. DeviceProcessLogShow("转台到位检测");
  321. }
  322. //补料完成检测
  323. if (RTrig.GetInstance("FeedComplete").Start(mORKS.FeedComplete))
  324. {
  325. if (!mORKS.AllowTakeNoodle && mORKS.TurntableLocLists.Count > 0)
  326. {
  327. mORKS.TurntableLocLists.Clear();
  328. mORKS.TurntableInterlock = false;
  329. DeviceProcessLogShow("补料完成检测");
  330. }
  331. }
  332. }
  333. /// <summary>
  334. /// 取面任务
  335. /// </summary>
  336. private void TakeNoodleTask()
  337. {
  338. //取面控制
  339. if (mORKS.AllowRun && mORKS.RobotIdle && !mORKS.Feeding && (!mORKS.RobotTaskInterlock || !mORKS.VegNoodlesLock && mORKS.relock) && mORKS.AllowTakeNoodle && mORKS.TurntableMoveInPlace && !mORKS.TakeNoodleInterlock && !mORKS.OutNoodleing && mORKS.RBTakeNoodleTask.Count > 0)
  340. {
  341. int loc = Array.FindIndex(mORKS.NoodleCookerStatus, p => p == false);//查找煮面炉空闲位置
  342. if (loc >= 0 && loc <= 5)
  343. {
  344. if (mORKS.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo))
  345. {
  346. // mORKS.CookNodelId[loc] = orderLocInfo.SuborderId;
  347. mORKS.orderLocInfos[loc] = orderLocInfo;
  348. SetFallNoodleLoc((ushort)(loc + 1));
  349. //机器人开始取面
  350. RobotTakeNoodle();
  351. // SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING);
  352. DeviceProcessLogShow($"订单【{orderLocInfo.SuborderId}】,机器人倒面至【{loc + 1}】号煮面栏");
  353. //写入煮菜时间
  354. List<ushort> values = new List<ushort>();
  355. if (mORKS.orderLocInfos[loc].Loc % 2 == 0)//素菜
  356. {
  357. values.Add(2);//分
  358. values.Add(0);//秒
  359. EventBus.EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = $"VW{ 116 + (loc * 6) }", Value = values.ToArray() });
  360. }
  361. else //荤菜
  362. {
  363. values.Add(4);//分
  364. values.Add(0);//秒
  365. EventBus.EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = $"VW{ 116 + (loc * 6) }", Value = values.ToArray() });
  366. }
  367. mORKS.TakeNoodleInterlock = true;
  368. }
  369. }
  370. }
  371. }
  372. /// <summary>
  373. /// 出餐控制
  374. /// </summary>
  375. private void OutNoodleTask()
  376. {
  377. if (mORKS.AllowFallNoodle && mORKS.RobotTaskInterlock && !mORKS.TakeNoodleInterlock && mORKS.RobotIdle && !mORKS.TakeMealDetect)
  378. {
  379. // var list= mORKS.CookNoodlesComplete.Where(p => p == true).ToList();
  380. mORKS.HasVeg = false;
  381. for (int i = 0; i < mORKS.CookNoodlesComplete.Length; i++)
  382. {
  383. if (mORKS.CookNoodlesComplete[i] && mORKS.orderLocInfos[i] != null && mORKS.orderLocInfos[i].SuborderId == mORKS.IngredientsCompleteId)
  384. {
  385. if (!mORKS.relock)
  386. {
  387. if (mORKS.Conqueue.TryDequeue(out Dictionary<string, OrderInformation> dic))
  388. {
  389. mORKS.Vnum = dic[mORKS.orderLocInfos[i].SuborderId].VegatableNumber;
  390. mORKS.TotalNum = dic[mORKS.orderLocInfos[i].SuborderId].DishNum;
  391. mORKS.relock = true;
  392. }
  393. }
  394. if (mORKS.orderLocInfos[i].Loc % 2 == 0)
  395. {
  396. mORKS.HasVeg = true;
  397. mORKS.ListOrder.Add(i, mORKS.orderLocInfos[i]);//找出当前订单煮熟的素菜
  398. }
  399. else if (!mORKS.HasVeg)
  400. {
  401. mORKS.ListOrderMeat.Add(i, mORKS.orderLocInfos[i]);//找出当前订单煮熟的荤菜
  402. }
  403. }
  404. }
  405. if (mORKS.ListOrder.Count > 0)
  406. {
  407. foreach (KeyValuePair<int, OrderLocInfo> item in mORKS.ListOrder)
  408. {
  409. while (!mORKS.RobotIdle)
  410. {
  411. }
  412. int location = item.Key; //煮面炉位置
  413. ushort number = item.Value.Loc;//荤素编号
  414. SetTakeNoodleLoc((ushort)(location + 1));
  415. RobotOutMeal();
  416. CookNoodleStatusReset((ushort)(location + 1));
  417. // ResetAllowFallNoodle();
  418. mORKS.OutMealId = mORKS.IngredientsCompleteId;
  419. // mORKS.CookNodelId[loc] = string.Empty;
  420. mORKS.orderLocInfos[location] = null;
  421. DeviceProcessLogShow($"{location + 1}号位置出餐控制");
  422. mORKS.OutNoodleing = true;
  423. mORKS.Count++;
  424. CheckLastDish();
  425. }
  426. }
  427. if (mORKS.ListOrderMeat.Count > 0 && mORKS.Count == mORKS.Vnum && mORKS.ListOrder.Count == 0)
  428. {
  429. foreach (KeyValuePair<int, OrderLocInfo> item in mORKS.ListOrderMeat)
  430. {
  431. while (!mORKS.RobotIdle)
  432. {
  433. }
  434. int location = item.Key; //煮面炉位置
  435. ushort number = item.Value.Loc;//荤素编号
  436. SetTakeNoodleLoc((ushort)(location + 1));
  437. RobotOutMeal();
  438. CookNoodleStatusReset((ushort)(location + 1));
  439. // ResetAllowFallNoodle();
  440. mORKS.OutMealId = mORKS.IngredientsCompleteId;
  441. // mORKS.CookNodelId[loc] = string.Empty;
  442. mORKS.orderLocInfos[location] = null;
  443. // mORKS.Count++;
  444. DeviceProcessLogShow($"{location + 1}号位置出餐控制");
  445. mORKS.OutNoodleing = true;
  446. mORKS.CountMeat++;
  447. CheckLastDish();
  448. }
  449. }
  450. mORKS.ListOrder.Clear();
  451. mORKS.ListOrderMeat.Clear();
  452. }
  453. }
  454. /// <summary>
  455. /// 检查是否是当前订单最后一个配菜
  456. /// </summary>
  457. public void CheckLastDish()
  458. {
  459. mORKS.Num = 0;
  460. foreach (var item1 in mORKS.orderLocInfos)
  461. {
  462. if (item1 != null)
  463. {
  464. if (item1.SuborderId == mORKS.OutMealId)
  465. {
  466. mORKS.Num++;
  467. //mORKS.Count++;
  468. //mORKS.CountMeat++;
  469. }
  470. }
  471. }
  472. if (mORKS.Num == 0 && mORKS.Count + mORKS.CountMeat == mORKS.TotalNum)
  473. {
  474. if (mORKS.OutMealType)
  475. {
  476. AddSoup();//加汤
  477. DeviceProcessLogShow("正在加汤");
  478. }
  479. else
  480. {
  481. //不加汤
  482. }
  483. CookComplete(); //告诉机器人冒菜已经煮完
  484. ResetAllowFallNoodle();
  485. //mORKS.VegNoodlesLock = false;
  486. mORKS.VegN = 0;
  487. mORKS.relock = false;
  488. mORKS.Count = 0;
  489. mORKS.CountMeat = 0;
  490. mORKS.IngredientsCompleteId = string.Empty;
  491. mORKS.TakeBowlId = string.Empty;
  492. mORKS.TakeBowlInterlock = false;
  493. }
  494. else
  495. {
  496. while (mORKS.RobotIdle)
  497. {
  498. }
  499. // Thread.Sleep(3000);
  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("碗到位,允许到面");
  513. DeviceProcessLogShow($"碗到位,允许到面,{mORKS.IngredientsCompleteId}");
  514. // mORKS.TakeBowlInterlock = false;
  515. }
  516. //出餐完成信号检测
  517. if (RTrig.GetInstance("CompleteChange").Start(mORKS.RbOutMealComplete))
  518. {
  519. OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_COOK);
  520. DeviceProcessLogShow($"订单【{mORKS.OutMealId}】制作完成");
  521. mORKS.OutNoodleing = false;
  522. }
  523. //取餐完成逻辑处理
  524. if (DelayRTrig.GetInstance("CompleteChange1").Start(mORKS.RbOutMealComplete && !mORKS.TakeMealDetect, 2))
  525. {
  526. OrderChange(mORKS.OutMealId, ORDER_STATUS.COMPLETED_TAKE);
  527. DeviceProcessLogShow($"订单【{mORKS.OutMealId}】取餐完成");
  528. ResetCookComplete();
  529. mORKS.OutMealId = string.Empty;
  530. }
  531. //机器人取面完成信号检测
  532. if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKS.RbTakeNoodleComplete))
  533. {
  534. mORKS.TakeNoodleInterlock = false;
  535. mORKS.AllowTakeNoodle = false;
  536. mORKS.TurntableInterlock = false;
  537. DeviceProcessLogShow("机器人取面完成信号检测");
  538. TakeNoodleCompleteReset();
  539. }
  540. //转台到位检测
  541. //if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace))
  542. //{
  543. // mORKS.TurntableInterlock = false;
  544. //}
  545. mORKS.VegNoodlesLock = false;
  546. for (int i = 0; i < mORKS.CookNoodlesComplete.Length; i++)
  547. {
  548. if (mORKS.CookNoodlesComplete[i] && mORKS.orderLocInfos[i] != null && mORKS.orderLocInfos[i].SuborderId == mORKS.IngredientsCompleteId)
  549. {
  550. if ((mORKS.orderLocInfos[i].Loc % 2 == 0 || mORKS.Vnum == 0) && mORKS.relock)
  551. {
  552. mORKS.VegNoodlesLock = true;
  553. mORKS.VegN++;
  554. break;
  555. }
  556. }
  557. }
  558. if (mORKS.VegN == mORKS.Vnum && mORKS.VegN < mORKS.TotalNum && mORKS.relock)
  559. {
  560. mORKS.VegNoodlesLock = true;
  561. }
  562. int OutMealRequstCount = mORKS.CookNoodlesComplete.Where(p => p == true).ToList().Count;
  563. int mlCount = mORKS.NoodleCookerStatus.Where(p => p == true).ToList().Count;
  564. mORKS.RobotTaskInterlock = OutMealRequstCount > 0 && mORKS.AllowFallNoodle && (mlCount >= 1 || mORKS.RBTakeNoodleTask.Count == 0);
  565. if (mORKS.RobotIdle && mORKS.RobotTaskInterlock == false)
  566. {
  567. mORKS.OutNoodleing = false;
  568. }
  569. }
  570. #region PLC 控制函数
  571. /// <summary>
  572. /// 写入配方数据到 PLC
  573. /// </summary>
  574. private void WriteRecipeBoms()
  575. {
  576. List<ushort> recipeBoms = new List<ushort>();
  577. if (this.recipeBoms == null) return;
  578. foreach (var item in this.recipeBoms.RecipeIds)
  579. {
  580. foreach (var rec in item.Recipes)
  581. {
  582. recipeBoms.Add((ushort)rec);
  583. }
  584. }
  585. if (recipeBoms.Count > 0)
  586. {
  587. //配方数据地址范围:VW2000 - VW2278
  588. WriteData("VW2000", recipeBoms.ToArray());
  589. DeviceProcessLogShow("写配方成功");
  590. }
  591. else { DeviceProcessLogShow("配方数据为空"); }
  592. }
  593. /// <summary>
  594. /// 取面完成复位
  595. /// </summary>
  596. private void TakeNoodleCompleteReset()
  597. {
  598. WriteData("M100.4", false);
  599. }
  600. /// <summary>
  601. /// 指定煮面口状态复位
  602. /// </summary>
  603. /// <param name="num"></param>
  604. private void CookNoodleStatusReset(int num)
  605. {
  606. if (num >= 1 && num <= 6)
  607. {
  608. WriteData($"102.{num - 1}", false);
  609. DeviceProcessLogShow($"{num}号煮面口占用复位");
  610. }
  611. }
  612. /// <summary>
  613. /// 写配方编号
  614. /// </summary>
  615. /// <param name="num"></param>
  616. private void SetRecipeNumber(ushort num)
  617. {
  618. WriteData("VW0", num);
  619. }
  620. /// <summary>
  621. /// 启动转台
  622. /// </summary>
  623. /// <param name="loc"></param>
  624. private void TurntableStart(ushort loc)
  625. {
  626. mORKS.CurrentLoc = loc;
  627. mORKS.TurntableInterlock = true;
  628. mORKS.TurntableLocLists.Add(loc);
  629. WriteData("VW2", loc);
  630. WriteData("M0.5", true);
  631. }
  632. /// <summary>
  633. /// 设置倒面位置
  634. /// </summary>
  635. /// <param name="loc"></param>
  636. private void SetFallNoodleLoc(ushort loc)
  637. {
  638. WriteData("VW4", loc);
  639. }
  640. /// <summary>
  641. /// 设置取面位置
  642. /// </summary>
  643. /// <param name="loc"></param>
  644. private void SetTakeNoodleLoc(ushort loc)
  645. {
  646. WriteData("VW6", loc);
  647. }
  648. /// <summary>
  649. /// 取碗控制
  650. /// </summary>
  651. /// <param name="loc"></param>
  652. private void TakeBowlControl(ushort loc)
  653. {
  654. if (loc == 10)//小碗
  655. {
  656. WriteData("M0.1", true);
  657. }
  658. else if (loc == 11)//大碗
  659. {
  660. WriteData("M0.2", true);
  661. }
  662. }
  663. /// <summary>
  664. /// 机器人取面
  665. /// </summary>
  666. private void RobotTakeNoodle()
  667. {
  668. WriteData("M0.3", true);
  669. }
  670. /// <summary>
  671. /// 机器人取餐
  672. /// </summary>
  673. private void RobotOutMeal()
  674. {
  675. WriteData("M0.4", true);
  676. }
  677. /// <summary>
  678. /// 制作完成信号复位
  679. /// </summary>
  680. private void ResetCookComplete()
  681. {
  682. WriteData("M100.6", false);
  683. }
  684. /// <summary>
  685. /// 复位允许取面信号
  686. /// </summary>
  687. private void ResetAllowFallNoodle()
  688. {
  689. WriteData("M100.3", false);
  690. }
  691. /// <summary>
  692. /// 设备初始化
  693. /// </summary>
  694. public async void DeviceInit()
  695. {
  696. WriteData("M0.0", true);
  697. await Task.Delay(1000);
  698. WriteData("M0.0", false);
  699. }
  700. /// <summary>
  701. /// 制作完成,允许机器人往外推碗
  702. /// </summary>
  703. public void CookComplete()
  704. {
  705. ////ModbusTcpHelper.GetInstance.Write((ushort)ModbusTcpHelper.GetInstance.GetBoolAddress("M0.6"), WriteType.Coils, true);
  706. EventBus.EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = "M0.6", Value = true });
  707. }
  708. /// <summary>
  709. /// 是否加汤
  710. /// </summary>
  711. public void AddSoup()
  712. {
  713. ////ModbusTcpHelper.GetInstance.Write((ushort)ModbusTcpHelper.GetInstance.GetBoolAddress("M0.7"), WriteType.Coils, true);
  714. EventBus.EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = "M0.7", Value = true });
  715. }
  716. private void ServerInit()
  717. {
  718. //物料信息
  719. EventBus.EventBus.GetInstance().Subscribe<MaterialDeliveryEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  720. {
  721. if (@event == null) return;
  722. if (@event is MaterialDeliveryEvent material)
  723. {
  724. orderMaterialDelivery = material.orderMaterialDelivery;
  725. }
  726. });
  727. //配方数据信息
  728. EventBus.EventBus.GetInstance().Subscribe<RecipeBomEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  729. {
  730. if (@event == null) return;
  731. if (@event is RecipeBomEvent recipe)
  732. {
  733. recipeBoms = recipe.recipeBoms;
  734. WriteRecipeBoms();
  735. }
  736. });
  737. }
  738. public override void DoMain()
  739. {
  740. MonitorViewModel.DeviceId = DeviceId;
  741. ServerInit();
  742. DataParse();
  743. Json<MorksPar>.Read();
  744. if (Json<MorksPar>.Data.parSets == null) Json<MorksPar>.Data.parSets = new ObservableCollection<ParSet>();
  745. if (Json<MorksPar>.Data.parSets.Count < 6)
  746. {
  747. Json<MorksPar>.Data.parSets.Clear();
  748. for (int i = 0; i < 6; i++)
  749. {
  750. Json<MorksPar>.Data.parSets.Add(new ParSet()
  751. {
  752. CheckBoxContext = $"煮面口{i + 1}屏蔽",
  753. Minute = 1,
  754. Second = 0,
  755. IsShield = false,
  756. TextBlockContext = $"煮面口{i + 1}时间设定"
  757. });
  758. }
  759. }
  760. ActionManage.GetInstance.Register(new Action<object>((o) =>
  761. {
  762. if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value);
  763. }), "WriteVW");
  764. ActionManage.GetInstance.Register(new Action<object>((o) =>
  765. {
  766. if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value);
  767. }), "WriteBools");
  768. ActionManage.GetInstance.Register(new Action(() => { DeviceInit(); }), "InitDevice");//设备初始化注册
  769. ActionManage.GetInstance.Register(new Action<object>((o) => { SimOrder(o); }), "SimOrder");//模拟订单委托注册
  770. }
  771. private void WriteData(string address, object value)
  772. {
  773. EventBus.EventBus.GetInstance().Publish(new WriteModel() { DeviceId = DeviceId, Address = address, Value = value });
  774. }
  775. public override void ResetProgram()
  776. {
  777. mORKS = null;
  778. mORKS = new GVL_MORKM();
  779. }
  780. private void GetStatus(string key, Action<object> action)
  781. {
  782. if (peripheralStatus.ContainsKey(key))
  783. {
  784. if (peripheralStatus[key] != null)
  785. {
  786. action?.Invoke(peripheralStatus[key]);
  787. }
  788. }
  789. }
  790. private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS)
  791. {
  792. var res = mORKS.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid);
  793. string goodName = string.Empty;
  794. string SortNum = string.Empty;
  795. if (res != null)
  796. {
  797. goodName = res.MorkOrder.GoodsName;
  798. SortNum = res.MorkOrder.SortNum.ToString();
  799. }
  800. EventBus.EventBus.GetInstance().Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType });
  801. }
  802. public override void Stop()
  803. {
  804. }
  805. public override void ReadData()
  806. {
  807. GetStatus("M230.0", new Action<object>((obj) =>
  808. {
  809. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 24)
  810. {
  811. alarm.MachineLeftLowTemperature = bools[0];
  812. alarm.MachineRightLowTemperature = bools[1];
  813. alarm.Supply1_LossBowl = bools[2];
  814. alarm.Supply2_LossBowl = bools[3];
  815. alarm.Supply1_ErrorOutBowl = bools[4];
  816. alarm.Supply2_ErrorOutBowl = bools[5];
  817. alarm.PushBowlCylinderError = bools[6];
  818. alarm.NoodleMacCommunicateError = bools[7];
  819. alarm.DosingMacCommunicateError = bools[8];
  820. alarm.RobotMacCommunicateError = bools[9];
  821. alarm.DeviceEstop = bools[10];
  822. alarm.RobotInitError = bools[11];
  823. alarm.RobotUrgentStop = bools[12];
  824. alarm.RobotNotInRemoteMode = bools[13];
  825. alarm.RobotNotInReady = bools[14];
  826. alarm.RobotSelfInException = bools[15];
  827. alarm.LeftLackWater = bools[16];
  828. alarm.RightLackWater = bools[17];
  829. alarm.SvrewInitFail = bools[18];
  830. alarm.TurntableInitFail = bools[19];
  831. alarm.RobotInitFail = bools[20];
  832. alarm.NoodleCookerInitFail = bools[21];
  833. alarm.PushBowlInitFail1 = bools[22];
  834. alarm.PushBowlInitFail2 = bools[23];
  835. }
  836. }));
  837. GetStatus("M0.3", new Action<object>((obj) =>
  838. {
  839. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 3)
  840. {
  841. mORKS.RobotTakeNoodle = bools[0];
  842. mORKS.RobotOutMeal = bools[1];
  843. mORKS.MoveTurntable = bools[2];
  844. }
  845. }));
  846. GetStatus("M100.0", new Action<object>((obj) =>
  847. {
  848. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 16)
  849. {
  850. mORKS.InitComplete = bools[0];
  851. mORKS.TakeBowlIdle = bools[1];
  852. mORKS.TemperatureReached = bools[2];
  853. mORKS.AllowFallNoodle = bools[3];
  854. mORKS.RbTakeNoodleComplete = bools[4];
  855. mORKS.RbFallNoodleComplete = bools[5];
  856. mORKS.RbOutMealComplete = bools[6];
  857. mORKS.RobotIdle = bools[7];
  858. mORKS.TakeMealDetect = bools[8];
  859. mORKS.MissingBowl = bools[9];
  860. Initing = bools[10];
  861. mORKS.TurntableLowerLimit = bools[11];
  862. mORKS.MissingBowlSignal2 = bools[12];
  863. mORKS.TurntableUpLimit = bools[13];
  864. mORKS.FeedComplete = bools[14];
  865. mORKS.TurntableMoveInPlace = bools[15];
  866. }
  867. }));
  868. GetStatus("M235.0", new Action<object>((obj) =>
  869. {
  870. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1)
  871. {
  872. mORKS.Error = bools[0];
  873. }
  874. }));
  875. GetStatus("M102.0", new Action<object>((obj) =>
  876. {
  877. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 7)
  878. {
  879. for (int i = 0; i < 6; i++)
  880. {
  881. mORKS.NoodleCookerStatus[i] = bools[i];
  882. }
  883. mORKS.Feeding = bools[6];
  884. }
  885. }));
  886. GetStatus("M103.0", new Action<object>((obj) =>
  887. {
  888. if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 6)
  889. {
  890. for (int i = 0; i < 6; i++)
  891. {
  892. mORKS.CookNoodlesComplete[i] = bools[i];
  893. }
  894. }
  895. }));
  896. GetStatus("VW372", new Action<object>((obj) =>
  897. {
  898. if (obj is ushort[] UshortValue && UshortValue.Length > 0 && UshortValue.Length <= 1)
  899. mORKS.TurntableFeedbackloc = UshortValue[0];
  900. }));
  901. }
  902. public override void SimOrder()
  903. {
  904. }
  905. #endregion
  906. }
  907. }