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

1013 lines
40 KiB

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