终端一体化运控平台
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

3033 rindas
117 KiB

  1. using BPA.Message;
  2. using System;
  3. using BPA.Message.Enum;
  4. using BPASmartClient.Device;
  5. using BPA.Helper;
  6. using BPASmartClient.Model;
  7. using BPASmartClient.Model.PLC;
  8. using BPA.Models;
  9. using BPASmartClient.Model.小炒机;
  10. using BPASmartClient.MorkF.Model;
  11. using System.Text;
  12. using System.Collections.Concurrent;
  13. using System.Windows.Documents;
  14. using BPASmartClient.Business;
  15. using Microsoft.CodeAnalysis;
  16. using BPASmartClient.MorkF.ViewModel;
  17. using BPASmartClient.ViewModel;
  18. using System.Windows;
  19. using static BPA.Helper.EventBus;
  20. namespace BPASmartClient.MorkF
  21. {
  22. public class Control_MorkF : BaseDevice
  23. {
  24. #region 常数定义
  25. /// <summary>
  26. /// while循环最大sleep次数
  27. /// </summary>
  28. private const int sleepCount = 20;
  29. /// <summary>
  30. /// while循环每次sleep时间
  31. /// </summary>
  32. private const int sleepTime = 500;
  33. /// <summary>
  34. /// 菜品库while循环最大sleep次数
  35. /// </summary>
  36. private const int materialSleepCount = 600;
  37. /// <summary>
  38. /// 菜品库while循环每次sleep时间
  39. /// </summary>
  40. private const int materialSleepTime = 100;
  41. /// <summary>
  42. /// 初始化炒锅数量
  43. /// </summary>
  44. private int count = 2;
  45. /// <summary>
  46. /// 菜品盒下移高度,相对于坐标系
  47. /// </summary>
  48. //private const int materialBoxHigh = 4080;
  49. ////菜品库出餐高度
  50. //private const int materialHigh = 33000;
  51. ////传感器到菜品库的高度(坐标系)
  52. //private const int materialLaserHigh = 34500;
  53. /// <summary>
  54. /// 菜品盒坐标系高度
  55. /// </summary>
  56. private const int materialBoxHeight = 9700;
  57. //传感器1到菜品库的高度(厘米)
  58. //private const int materialLaserHighCM_1 = 22;
  59. ////传感器2到菜品库的高度(厘米)
  60. //private const int materialLaserHighCM_2 = 27;
  61. ////传感器3到菜品库的高度(厘米)
  62. //private const int materialLaserHighCM_3 = 31;
  63. /// <summary>
  64. /// 传感器到隔板的距离(坐标系)
  65. /// </summary>
  66. private const int clapboardLaserHigh = 10000;
  67. ////炒锅1倒菜的xy坐标
  68. //private const int materialPutPositionXFry1 = 70000;
  69. //private const int materialPutPositionYFry1 = 40000;
  70. ////炒锅2倒菜的xy坐标
  71. //private const int materialPutPositionXFry2 = 70000;
  72. //private const int materialPutPositionYFry2 = 40000;
  73. //菜品库机械爪放置菜品距离
  74. private const int materialToFryDistance = 10000;
  75. //当前炒锅,默认为1号炒锅
  76. private int fryIndex = 0;
  77. #endregion
  78. public override DeviceClientType DeviceType => DeviceClientType.MORKCS;
  79. public AutoResetEvent minorReset = new AutoResetEvent(false);
  80. public AutoResetEvent mainReset = new AutoResetEvent(false);
  81. /// <summary>
  82. /// 等待炒制数量
  83. /// </summary>
  84. private int StagingFryCount { get; set; }
  85. /// <summary>
  86. /// 正在炒制数量
  87. /// </summary>
  88. private int FryingCount { get; set; }
  89. /// <summary>
  90. /// 炒锅编号与炒锅实例
  91. /// </summary>
  92. Dictionary<int, GVL_MorkF> morkFs = new Dictionary<int, GVL_MorkF>();//全局对象声明
  93. /// <summary>
  94. /// 菜品库对象
  95. /// </summary>
  96. ML_MorkF ml_morkf = new ML_MorkF();
  97. /// <summary>
  98. /// 小炒菜单集合
  99. /// </summary>f
  100. public static List<StirFryGoods> LocalstirFryGoods = new List<StirFryGoods>();
  101. /// <summary>
  102. /// 待炒小炒队列
  103. /// </summary>
  104. private ConcurrentQueue<OrderLocInfo> StirFryGoodsQuenes = new ConcurrentQueue<OrderLocInfo>();
  105. /// <summary>
  106. /// 炒锅炒制线程名称
  107. /// </summary>
  108. private const String striConst = "炒锅{0}炒制{1}线程";
  109. /// <summary>
  110. /// 当前炒制菜品
  111. /// </summary>
  112. private OrderLocInfo[] nowStirFryGood = new OrderLocInfo[2];
  113. /// <summary>
  114. /// 待取菜队列
  115. /// </summary>
  116. private ConcurrentQueue<MaterialOperation> materialOperationQuenes = new ConcurrentQueue<MaterialOperation>();
  117. List<int> resultorder = new List<int>();//调试变量
  118. /// <summary>
  119. /// 告警列表
  120. /// </summary>
  121. private List<BPA.Message.AlarmModel> alarmModel = new List<BPA.Message.AlarmModel>();
  122. /// <summary>
  123. ///
  124. /// </summary>
  125. private List<StatsModel> statsModels = new List<StatsModel>();
  126. /// <summary>
  127. /// 暂存使用菜品量
  128. /// </summary>
  129. private List<GoodBatchings> stagingGoodBatchings = new List<GoodBatchings>();
  130. /// <summary>
  131. /// 是否为本地炒菜模式,默认为联网的
  132. /// </summary>
  133. private bool isLocalFryingMode { get; set; } = true;
  134. /// <summary>
  135. /// 入口
  136. /// </summary>
  137. public override void DoMain()
  138. {
  139. IsHealth = true;
  140. for (int i = 0; i < count; i++)
  141. {
  142. morkFs.Add(i, new GVL_MorkF());
  143. }
  144. DataParse();//数据解析
  145. CommandRegist();//调试
  146. ServerInit();
  147. DeviceProcessLogShow("MORKF 设备初始化完成");
  148. ///初始化菜品库
  149. //FoodLibInit();
  150. Task2ReadMaterialData();
  151. ScreenDataServer();
  152. Json<MaterialAndFryingTime>.Read();
  153. //更新菜品余量
  154. UpdateMaterialSurplus();
  155. //读取坐标系
  156. MaterialCoordinate materialCoordinate = ReadMaterialCoordinate();
  157. if (materialCoordinate != null)
  158. {
  159. MaterialCoordinate.GetInstance.dicNoMaterialCoordinate = materialCoordinate.dicNoMaterialCoordinate;
  160. MaterialCoordinate.GetInstance.MLCoordinateList = materialCoordinate.MLCoordinateList;
  161. MaterialCoordinate.GetInstance.distance_1 = materialCoordinate.distance_1;
  162. MaterialCoordinate.GetInstance.distance_2 = materialCoordinate.distance_2;
  163. MaterialCoordinate.GetInstance.distance_3 = materialCoordinate.distance_3;
  164. MaterialCoordinate.GetInstance.frying1 = materialCoordinate.frying1;
  165. MaterialCoordinate.GetInstance.frying2 = materialCoordinate.frying2;
  166. MaterialCoordinate.GetInstance.materialHeight = materialCoordinate.materialHeight;
  167. MaterialCoordinate.GetInstance.MaterialOneX = materialCoordinate.MaterialOneX;
  168. MaterialCoordinate.GetInstance.MaterialTwoX = materialCoordinate.MaterialTwoX;
  169. MaterialCoordinate.GetInstance.MaterialThreeX = materialCoordinate.MaterialThreeX;
  170. }
  171. ////菜品库编号与坐标系对象存储
  172. //SaveMaterialCoordinate();
  173. }
  174. /// <summary>
  175. /// 主任务
  176. /// </summary>
  177. public override void MainTask()
  178. {
  179. //炒锅炒制线程
  180. MainProcessExcute();
  181. //菜品库操作线程
  182. MainProcessMaterial();
  183. //MinorProcessExcute();
  184. //SingleProcess();
  185. }
  186. private static object saveMaterialLock = new object();
  187. private void SaveMaterialData()
  188. {
  189. lock (saveMaterialLock)
  190. {
  191. Json<MaterialSurplus>.Data = MaterialSurplusOperation.GetInstance.materialSurplus;
  192. Json<MaterialSurplus>.Save();
  193. }
  194. }
  195. private static object saveMaterialCoordinateLock = new object();
  196. /// <summary>
  197. /// 保存当前的坐标系
  198. /// </summary>
  199. public void SaveMaterialCoordinate()
  200. {
  201. lock (saveMaterialLock)
  202. {
  203. Json<MaterialCoordinate>.Data = MaterialCoordinate.GetInstance;
  204. Json<MaterialCoordinate>.Save();
  205. }
  206. }
  207. /// <summary>
  208. /// 读取坐标系
  209. /// </summary>
  210. /// <returns></returns>
  211. private MaterialCoordinate ReadMaterialCoordinate()
  212. {
  213. try
  214. {
  215. lock (saveMaterialLock)
  216. {
  217. Json<MaterialCoordinate>.Read();
  218. MaterialCoordinate materialCoordinate = Json<MaterialCoordinate>.Data;
  219. return materialCoordinate;
  220. }
  221. }
  222. catch (Exception ex)
  223. {
  224. return null;
  225. }
  226. }
  227. private void Task2ReadMaterialData()
  228. {
  229. TaskManage.GetInstance.StartLong(new Action(() =>
  230. {
  231. //获取定位到达状态
  232. GetStatus("M10.0", new Action<object>((objects) =>
  233. {
  234. if (objects is bool[] bools)
  235. {
  236. //ml_morkf.ArriveComplete = bools[i];
  237. //小炒定点到达上升沿信号捕获
  238. if (RTrig.GetInstance("SmartArriveComplete").Start(bools[0]))
  239. {
  240. if (isInitialArrive == false)
  241. {
  242. //MessageLog.GetInstance.Show("到达上升沿为true,isInitialArrive is false");
  243. isInitialArrive = true;
  244. }
  245. else
  246. {
  247. //MessageLog.GetInstance.Show("到达上升沿为true");
  248. ml_morkf.ArriveComplete = true;
  249. isInitialArrive = true;
  250. }
  251. }
  252. }
  253. }), 2);
  254. }), "ReadMaterialSmartArriveCompleteData", true);
  255. TaskManage.GetInstance.StartLong(new Action(() =>
  256. {
  257. ReadMaterialData();
  258. Thread.Sleep(10);
  259. }), "ReadMaterialData", true);
  260. }
  261. private void ReadMaterialData()
  262. {
  263. //获取激光距离
  264. GetStatus("VW270", new Action<object>((objects) =>
  265. {
  266. if (objects is ushort[] bools)
  267. {
  268. for (int i = 0; i < 1; i++)
  269. {
  270. ml_morkf.LaserDistance = bools[i];
  271. }
  272. }
  273. }), 2);
  274. //获取坐标X
  275. GetStatus("VD828", new Action<object>((objects) =>
  276. {
  277. if (objects is int bools)
  278. {
  279. ml_morkf.ArmPositionX = bools;
  280. }
  281. }), 2);
  282. //获取坐标Y
  283. GetStatus("VD832", new Action<object>((objects) =>
  284. {
  285. if (objects is int bools)
  286. {
  287. ml_morkf.ArmPositionY = bools;
  288. }
  289. }), 2);
  290. //获取爪子到达位置
  291. GetStatus("M11.0", new Action<object>((objects) =>
  292. {
  293. if (objects is bool[] bools && bools.Length > 3)
  294. {
  295. ml_morkf.PawArrivePortOne = bools[0];
  296. ml_morkf.PawArrivePortTwo = bools[1];
  297. ml_morkf.PawArrivePortThree = bools[2];
  298. }
  299. }), 2);
  300. //获取爪子伸出退回到位
  301. GetStatus("M10.6", new Action<object>((objects) =>
  302. {
  303. if (objects is bool[] bools && bools.Length == 2)
  304. {
  305. ml_morkf.PawOutComplete = bools[0];
  306. ml_morkf.PawInComplete = bools[1];
  307. }
  308. }), 2);
  309. //获取总初始化完成
  310. GetStatus("M10.2", new Action<object>((objects) =>
  311. {
  312. if (objects is bool[] bools)
  313. {
  314. for (int i = 0; i < 1; i++)
  315. {
  316. ml_morkf.InitialComplete = bools[i];
  317. }
  318. }
  319. }), 2);
  320. //抓手初始化完成
  321. GetStatus("M10.3", new Action<object>((objects) =>
  322. {
  323. if (objects is bool[] bools)
  324. {
  325. for (int i = 0; i < 1; i++)
  326. {
  327. ml_morkf.PawInitialComplete = bools[i];
  328. }
  329. }
  330. }), 2);
  331. //抓手初始化完成
  332. GetStatus("I0.1", new Action<object>((objects) =>
  333. {
  334. if (objects is bool[] bools && bools.Length > 2)
  335. {
  336. ml_morkf.PawPositon_1 = bools[0];
  337. ml_morkf.PawPositon_2 = bools[1];
  338. ml_morkf.PawPositon_3 = bools[2];
  339. }
  340. }), 2);
  341. }
  342. public override void Stop()
  343. {
  344. IsHealth = false;
  345. }
  346. #region 调试代码
  347. public void CommandRegist()
  348. {
  349. #region 设备控制
  350. ActionManage.GetInstance.Register(PLCInite, "InitCommand");
  351. ActionManage.GetInstance.Register<object>(StartOrder, "StartOrder");
  352. ActionManage.GetInstance.Register<object>(StartOrderMain, "开始下单");
  353. ActionManage.GetInstance.Register<int>(StopLocalOrder, "StopLocalOrder");
  354. ActionManage.GetInstance.Register(new Action<object>((o) =>
  355. {
  356. if (o is string materialName)
  357. {
  358. NewStartLocalOrder(materialName);
  359. }
  360. }), "NewStartLocalOrder");
  361. #endregion
  362. #region 菜品库
  363. ActionManage.GetInstance.Register(new Action(() =>
  364. {
  365. TaskManage.GetInstance.Start(new Action(() =>
  366. {
  367. FoodLibInit();
  368. }), "FoodLibInit");
  369. }), "FoodLibInit");
  370. ActionManage.GetInstance.Register(new Action(() =>
  371. {
  372. isLocalFryingMode = !isLocalFryingMode;
  373. }), "ModeChange");
  374. ActionManage.GetInstance.Register(new Action(() =>
  375. {
  376. TaskManage.GetInstance.Start(new Action(() =>
  377. {
  378. if (!UpdateMaterialLibraryStock())
  379. {
  380. MessageLog.GetInstance.ShowEx("菜品库检测余量失败");
  381. }
  382. }), "SurplusCheck");
  383. }), "SurplusCheck");
  384. ActionManage.GetInstance.Register(new Action<object>((o) =>
  385. {
  386. TaskManage.GetInstance.Start(new Action(() =>
  387. {
  388. Electromagnetism(o);
  389. }), "Electromagnetism");
  390. }), "Electromagnetism");
  391. ActionManage.GetInstance.Register(new Action(() =>
  392. {
  393. TaskManage.GetInstance.Start(new Action(() =>
  394. {
  395. PawToPoint1();
  396. }), "PawToPoint1");
  397. }), "PawToPoint1");
  398. ActionManage.GetInstance.Register(new Action(() =>
  399. {
  400. TaskManage.GetInstance.Start(new Action(() =>
  401. {
  402. PawToPoint2();
  403. }), "PawToPoint2");
  404. }), "PawToPoint2");
  405. ActionManage.GetInstance.Register(new Action(() =>
  406. {
  407. TaskManage.GetInstance.Start(new Action(() =>
  408. {
  409. PawToPoint3();
  410. }), "PawToPoint3");
  411. }), "PawToPoint3");
  412. ActionManage.GetInstance.Register(new Action(() =>
  413. {
  414. TaskManage.GetInstance.Start(new Action(() =>
  415. {
  416. GetDistance_1();
  417. }), "GetDistance_1");
  418. }), "GetDistance_1");
  419. ActionManage.GetInstance.Register(new Action(() =>
  420. {
  421. TaskManage.GetInstance.Start(new Action(() =>
  422. {
  423. GetDistance_2();
  424. }), "GetDistance_2");
  425. }), "GetDistance_2");
  426. ActionManage.GetInstance.Register(new Action(() =>
  427. {
  428. TaskManage.GetInstance.Start(new Action(() =>
  429. {
  430. GetDistance_3();
  431. }), "GetDistance_3");
  432. }), "GetDistance_3");
  433. ActionManage.GetInstance.Register(new Action(() =>
  434. {
  435. TaskManage.GetInstance.Start(new Action(() =>
  436. {
  437. PawExtend();
  438. }), "PawTurnFront");
  439. }), "PawTurnFront");
  440. ActionManage.GetInstance.Register(new Action(() =>
  441. {
  442. TaskManage.GetInstance.Start(new Action(() =>
  443. {
  444. PawShrink();
  445. }), "PawTurnBack");
  446. }), "PawTurnBack");
  447. ActionManage.GetInstance.Register(new Action<object>((list) =>
  448. {
  449. TaskManage.GetInstance.Start(new Action(() =>
  450. {
  451. if (list is List<int> list_int)
  452. {
  453. if (list_int.Count == 2)
  454. {
  455. SetArmPosition(list_int[0], list_int[1]);
  456. }
  457. }
  458. }), "SetArmPosition");
  459. }), "SetArmPosition");
  460. ActionManage.GetInstance.Register(new Action<object>((list) =>
  461. {
  462. if (list is bool startOrStop)
  463. {
  464. ArmRunUp(startOrStop);
  465. }
  466. }), "ArmRunUp");
  467. ActionManage.GetInstance.Register(new Action<object>((list) =>
  468. {
  469. if (list is bool startOrStop)
  470. {
  471. ArmRunDown(startOrStop);
  472. }
  473. }), "ArmRunDown");
  474. ActionManage.GetInstance.Register(new Action<object>((list) =>
  475. {
  476. if (list is bool startOrStop)
  477. {
  478. ArmRunLeft(startOrStop);
  479. }
  480. }), "ArmRunLeft");
  481. ActionManage.GetInstance.Register(new Action<object>((list) =>
  482. {
  483. if (list is bool startOrStop)
  484. {
  485. ArmRunRight(startOrStop);
  486. }
  487. }), "ArmRunRight");
  488. ActionManage.GetInstance.Register(new Action<object>((list) =>
  489. {
  490. TaskManage.GetInstance.Start(new Action(() =>
  491. {
  492. if (list is List<int> list_int)
  493. {
  494. if (list_int.Count == 2)
  495. {
  496. SetArmPosition(list_int[0], list_int[1]);
  497. }
  498. }
  499. }), "SetNowPosition");
  500. }), "SetNowPosition");
  501. ActionManage.GetInstance.Register(new Action<object>((list) =>
  502. {
  503. TaskManage.GetInstance.Start(new Action(() =>
  504. {
  505. if (list is List<object> list_object)
  506. {
  507. if (list_object.Count != 3)
  508. {
  509. return;
  510. }
  511. if (list_object[0] is string No && list_object[1] is int x && list_object[2] is int y)
  512. {
  513. if (SetArmPosition(x, y))
  514. {
  515. ActionManage.GetInstance.Send(new List<string> { No }, "CalibrationCallBack");//设定机械臂当前位置
  516. }
  517. }
  518. }
  519. }), "CalibrationCoordination");
  520. }), "CalibrationCoordination");
  521. #endregion
  522. //ActionManage.GetInstance.Register(PLCInite, "InitCommand");
  523. #region 配料控制
  524. ActionManage.GetInstance.Register(new Action<object>((o) =>
  525. {
  526. TaskManage.GetInstance.Start(new Action(() =>
  527. {
  528. OutSeasoning(o, fryIndex);
  529. }), "OutMaterials");
  530. }), "OutMaterials");
  531. //ActionManage.GetInstance.Register(OutSeasoning, "OutMaterials");
  532. #endregion
  533. #region 炒锅
  534. ActionManage.GetInstance.Register(new Action(() =>
  535. {
  536. TaskManage.GetInstance.Start(new Action(() =>
  537. {
  538. Plc1Reset(fryIndex);
  539. }), "Plc1Reset");
  540. }), "Plc1Reset");
  541. ActionManage.GetInstance.Register(new Action(() =>
  542. {
  543. TaskManage.GetInstance.Start(new Action(() =>
  544. {
  545. AddOil();
  546. }), "AddOil");
  547. }), "AddOil");
  548. ActionManage.GetInstance.Register(new Action(() =>
  549. {
  550. TaskManage.GetInstance.Start(new Action(() =>
  551. {
  552. StartFire(fryIndex);
  553. }), "StartFire");
  554. }), "StartFire");
  555. ActionManage.GetInstance.Register(new Action(() =>
  556. {
  557. TaskManage.GetInstance.Start(new Action(() =>
  558. {
  559. StopFire(fryIndex);
  560. }), "StopFire");
  561. }), "StopFire");
  562. ActionManage.GetInstance.Register(new Action(() =>
  563. {
  564. TaskManage.GetInstance.Start(new Action(() =>
  565. {
  566. StartStir(fryIndex);
  567. }), "StartStir");
  568. }), "StartStir");
  569. ActionManage.GetInstance.Register(new Action(() =>
  570. {
  571. TaskManage.GetInstance.Start(new Action(() =>
  572. {
  573. StopStir(fryIndex);
  574. }), "StopStir");
  575. }), "StopStir");
  576. ActionManage.GetInstance.Register(new Action(() =>
  577. {
  578. TaskManage.GetInstance.Start(new Action(() =>
  579. {
  580. MagnetOn(fryIndex);
  581. }), "MagnetOn");
  582. }), "MagnetOn");
  583. ActionManage.GetInstance.Register(new Action(() =>
  584. {
  585. TaskManage.GetInstance.Start(new Action(() =>
  586. {
  587. MagnetOff(fryIndex);
  588. }), "MagnetOff");
  589. }), "MagnetOff");
  590. ActionManage.GetInstance.Register(new Action(() =>
  591. {
  592. TaskManage.GetInstance.Start(new Action(() =>
  593. {
  594. string error;
  595. OutFood(fryIndex, out error);
  596. }), "OutFood");
  597. }), "OutFood");
  598. ActionManage.GetInstance.Register(new Action(() =>
  599. {
  600. TaskManage.GetInstance.Start(new Action(() =>
  601. {
  602. StirArmGoOrigin(fryIndex);
  603. }), "StirArmGoOrigin");
  604. }), "StirArmGoOrigin");
  605. ActionManage.GetInstance.Register(new Action(() =>
  606. {
  607. TaskManage.GetInstance.Start(new Action(() =>
  608. {
  609. string error;
  610. StirArmGoWork(fryIndex, out error);
  611. }), "StirArmGoWork");
  612. }), "StirArmGoWork");
  613. ActionManage.GetInstance.Register(new Action(() =>
  614. {
  615. TaskManage.GetInstance.Start(new Action(() =>
  616. {
  617. HBOTGoWork(fryIndex);
  618. }), "HBOTGoWork");
  619. }), "HBOTGoWork");
  620. ActionManage.GetInstance.Register(new Action(() =>
  621. {
  622. TaskManage.GetInstance.Start(new Action(() =>
  623. {
  624. OutMeal(fryIndex);
  625. }), "OutMeal");
  626. }), "OutMeal");
  627. ActionManage.GetInstance.Register(new Action<object>((o) =>
  628. {
  629. TaskManage.GetInstance.Start(new Action(() =>
  630. {
  631. SetFire(o, fryIndex);
  632. }), "SetFire");
  633. }), "SetFire");
  634. ActionManage.GetInstance.Register(new Action<object>((o) =>
  635. {
  636. TaskManage.GetInstance.Start(new Action(() =>
  637. {
  638. SetFry(o);
  639. }), "SetFry");
  640. }), "SetFry");
  641. ActionManage.GetInstance.Register(new Action<object>((o) =>
  642. {
  643. TaskManage.GetInstance.Start(new Action(() =>
  644. {
  645. SetStir(o, fryIndex);
  646. }), "SetStir");
  647. }), "SetStir");
  648. #endregion
  649. }
  650. /// <summary>
  651. /// 根据菜品ID下单
  652. /// </summary>
  653. private void StartOrder(object o)
  654. {
  655. if (o == null) return;
  656. if (o is int goodId)
  657. {
  658. var res = LocalstirFryGoods?.FirstOrDefault(p => p.GoodsKey == goodId);//匹配订单对应制作流程
  659. if (res != null)
  660. {
  661. /* morkF.listStirBom.Add(res.StirFryBomInfo);*///添加订单制作流程
  662. if (StirFryGoodsQuenes.Count > 0) return;
  663. StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  664. {
  665. SuborderId = Guid.NewGuid().ToString(),
  666. StirPotActions = res.StirPotActions,
  667. GoodName = "本地菜品"
  668. });
  669. MessageLog.GetInstance.Show($"添加本地订单{res.GoodsKey}");
  670. }
  671. }
  672. }
  673. /// <summary>
  674. /// 主界面本地菜单下单
  675. /// </summary>
  676. private void StartOrderMain(object o)
  677. {
  678. if (o == null) return;
  679. //if (o is FoodMenuModel good)
  680. //{
  681. // NewStartLocalOrder(good.GoodName);
  682. //}
  683. //if (o == null) return;
  684. //if (o is string goodId)
  685. //{
  686. // var res = LocalstirFryGoods?.FirstOrDefault(p => p.GoodsKey.ToString() == goodId);//匹配订单对应制作流程
  687. // if (res != null)
  688. // {
  689. // /* morkF.listStirBom.Add(res.StirFryBomInfo);*///添加订单制作流程
  690. // if (StirFryGoodsQuenes.Count > 0) return;
  691. // StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  692. // {
  693. // SuborderId = Guid.NewGuid().ToString(),
  694. // StirPotActions = res.StirPotActions,
  695. // GoodName = "本地菜品"
  696. // });
  697. // MessageLog.GetInstance.Show($"添加本地订单{res.GoodsKey}");
  698. // }
  699. //}
  700. }
  701. /// <summary>
  702. /// 本地配置的订单
  703. /// </summary>
  704. /// <param name="materialName"></param>
  705. private void NewStartLocalOrder(string materialName)
  706. {
  707. //if (StirFryGoodsQuenes.Count > 0) return;//只能一个一个做
  708. //if (Json<LocalPotStep>.Data.LocalstirFryGoods.StirPotActions.Count > 0)
  709. //{
  710. // StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  711. // {
  712. // SuborderId = Guid.NewGuid().ToString(),
  713. // StirPotActions = Json<LocalPotStep>.Data.LocalstirFryGoods.StirPotActions,
  714. // GoodName = "本地菜品"
  715. // });
  716. // MessageLog.GetInstance.Show($"添加本地模拟的订单{Json<LocalPotStep>.Data.LocalstirFryGoods.GoodsKey}");
  717. //}
  718. if (Json<MaterialAndFryingTime>.Data.materials.Count > 0)
  719. {
  720. if (!Json<MaterialAndFryingTime>.Data.materials.ContainsKey(materialName))
  721. {
  722. return;
  723. }
  724. List<PotActions> potActions = new List<PotActions>();
  725. foreach (var item in Json<MaterialAndFryingTime>.Data.materials[materialName])
  726. {
  727. potActions.Add(item);
  728. }
  729. StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  730. {
  731. SuborderId = Guid.NewGuid().ToString(),
  732. StirPotActions = potActions,
  733. GoodName = materialName
  734. });
  735. MessageLog.GetInstance.Show($"添加本地模拟的订单{Json<LocalPotStep>.Data.LocalstirFryGoods.GoodsKey}");
  736. MessageBox.Show("下单成功");
  737. }
  738. }
  739. /// <summary>
  740. /// 停止本地菜单炒制
  741. /// </summary>
  742. private void StopLocalOrder(int num = -1)
  743. {
  744. //判断当前是否有炒制菜品
  745. if (nowStirFryGood == null) return;
  746. //根据morkFs中是否有num执行不同的停止操作
  747. if (!morkFs.ContainsKey(num))
  748. {
  749. //根据调试界面的当前炒锅编号停止炒制线程
  750. TaskManage.GetInstance.StopTask(String.Format(striConst, fryIndex.ToString(), nowStirFryGood[fryIndex].GoodName), new Action(() => { Plc1Reset(fryIndex); }));
  751. }
  752. else
  753. {
  754. //根据炒锅编号停止炒制线程
  755. TaskManage.GetInstance.StopTask(String.Format(striConst, fryIndex.ToString(), nowStirFryGood[num].GoodName), new Action(() => { Plc1Reset(num); }));
  756. }
  757. }
  758. /// <summary>
  759. /// 重置程序
  760. /// </summary>
  761. public override void ResetProgram()
  762. {
  763. IsHealth = true;
  764. morkFs.Clear();
  765. morkFs = new Dictionary<int, GVL_MorkF>();
  766. ml_morkf = new ML_MorkF();
  767. //根据编号new炒锅实例对象
  768. for (int i = 0; i < count; i++)
  769. {
  770. morkFs.Add(i, new GVL_MorkF());
  771. }
  772. }
  773. #endregion
  774. #region 公用PLC方法
  775. /// <summary>
  776. /// 获取设备PLC的所有状态
  777. /// </summary>
  778. /// <param name="key"></param>
  779. /// <param name="action"></param>
  780. /// <param name="num">炒锅编号</param>
  781. private void GetStatus(string key, Action<object> action, int num)
  782. {
  783. if (dicPort2peripheralStatus.ContainsKey(num))
  784. {
  785. if (dicPort2peripheralStatus[num].ContainsKey(key))
  786. {
  787. action((object)dicPort2peripheralStatus[num][key]);//获取PLC指定地址的状态值
  788. }
  789. }
  790. }
  791. /// <summary>
  792. /// PLC数据读取
  793. /// </summary>
  794. public override void ReadData()
  795. {
  796. for (int i = 0; i < morkFs.Count; i++)
  797. {
  798. GetStatus("LB50", new Action<object>((objects) =>
  799. {
  800. if (!morkFs.ContainsKey(i))
  801. {
  802. return;
  803. }
  804. if (objects is bool[] bools)
  805. {
  806. morkFs[i].FryPot1_InitialComplete = bools[0];
  807. morkFs[i].FryPot1_HOBTPut = bools[1];
  808. morkFs[i].FryPot1_HOBTGet = bools[2];
  809. morkFs[i].FryPot1_MaterialIntoPot = bools[3];
  810. morkFs[i].OutFoodCompelete = bools[4];
  811. morkFs[i].CanOutFood = bools[5];
  812. morkFs[i].GetFoodCompelete = bools[6];
  813. morkFs[i].CanOutPotWashingWater = bools[7];
  814. morkFs[i].ArmOnOrigin = bools[8];
  815. morkFs[i].ArmOnWorking = bools[9];
  816. morkFs[i].PotOnOrigin = bools[10];
  817. }
  818. }), i);
  819. }
  820. for (int j = 0; j < morkFs.Count; j++)
  821. {
  822. GetStatus("LB74", new Action<object>((objects) =>
  823. {
  824. if (!morkFs.ContainsKey(j))
  825. {
  826. return;
  827. }
  828. if (objects is bool[] bools)
  829. {
  830. for (int i = 0; i < 14; i++)
  831. {
  832. morkFs[j].PassWay1_Compelete[i] = bools[i];
  833. }
  834. }
  835. }), j);
  836. }
  837. for (int i = 0; i < morkFs.Count; i++)
  838. {
  839. if (!morkFs.ContainsKey(i))
  840. {
  841. return;
  842. }
  843. GetStatus("LB90", new Action<object>((objects) =>
  844. {
  845. if (objects is bool[] bools)
  846. {
  847. morkFs[i].AutoMode = bools[0];
  848. }
  849. }), i);
  850. }
  851. }
  852. #endregion
  853. #region 菜品库方法
  854. #region PLC操作
  855. /// <summary>
  856. /// 菜品库数据写入
  857. /// </summary>
  858. /// <param name="address"></param>
  859. /// <param name="value"></param>
  860. private void MaterailLibrary_Write(string address, object value, int num = 2)
  861. {
  862. WriteControlExact(address, value, num);
  863. }
  864. /// <summary>
  865. /// 菜品库初始化
  866. /// </summary>
  867. public bool FoodLibInit()
  868. {
  869. MaterailLibrary_Write("M0.2", true);
  870. Thread.Sleep(500);
  871. for (int i = 0; i < materialSleepCount && !ml_morkf.InitialComplete; i++)
  872. {
  873. Thread.Sleep(materialSleepTime);
  874. if (i >= materialSleepCount - 1)
  875. {
  876. MessageLog.GetInstance.ShowEx("菜品库初始化超时");
  877. return false;
  878. }
  879. }
  880. return true;
  881. }
  882. /// <summary>
  883. /// 爪子伸出
  884. /// </summary>
  885. /// <param name="o">电磁阀启停:true:启动。false:停止。</param>
  886. public bool PawExtend()
  887. {
  888. if (!ml_morkf.InitialComplete)
  889. {
  890. MessageLog.GetInstance.ShowEx("爪子伸出错误,菜品库未初始化");
  891. return false;
  892. }
  893. Thread.Sleep(500);
  894. MaterailLibrary_Write("M0.6", true);
  895. for (int i = 0; i < materialSleepCount && !ml_morkf.PawOutComplete; i++)//潘华小炒没有夹爪到位功能
  896. {
  897. Thread.Sleep(materialSleepTime);
  898. if (i >= materialSleepCount - 1)
  899. {
  900. MessageLog.GetInstance.ShowEx("爪子伸出超时");
  901. return false;
  902. }
  903. }
  904. return true;
  905. ////等待爪子伸出延时4s
  906. //Thread.Sleep(6000);
  907. }
  908. /// <summary>
  909. /// 爪子收缩
  910. /// </summary>
  911. /// <param name="o">电磁阀启停:true:启动。false:停止。</param>
  912. public bool PawShrink()
  913. {
  914. if (!ml_morkf.InitialComplete)
  915. {
  916. MessageLog.GetInstance.ShowEx("爪子伸出错误,菜品库未初始化");
  917. return false;
  918. }
  919. MaterailLibrary_Write("M0.7", true);
  920. Thread.Sleep(500);
  921. for (int i = 0; i < materialSleepCount && !ml_morkf.PawInComplete; i++)//潘华小炒没有夹爪到位功能
  922. {
  923. Thread.Sleep(materialSleepTime);
  924. if (i >= materialSleepCount - 1)
  925. {
  926. MessageLog.GetInstance.ShowEx("爪子伸出超时");
  927. return false;
  928. }
  929. }
  930. return true;
  931. //等待爪子收缩延时4s
  932. //Thread.Sleep(6000);
  933. }
  934. /// <summary>
  935. /// 电磁阀启停
  936. /// </summary>
  937. /// <param name="o">电磁阀启停:true:启动。false:停止。</param>
  938. public void Electromagnetism(object o)
  939. {
  940. if (!ml_morkf.InitialComplete)
  941. {
  942. MessageLog.GetInstance.ShowEx("电磁阀启停出错,菜品库未初始化");
  943. return;
  944. }
  945. if (o == null) return;
  946. if (o is List<bool> bs && bs.Count == 1)
  947. {
  948. MaterailLibrary_Write("M1.3", bs[0]);
  949. }
  950. }
  951. public bool PawToPoint1()
  952. {
  953. if (!ml_morkf.InitialComplete)
  954. {
  955. MessageLog.GetInstance.ShowEx("爪子去到1号位出错,菜品库未初始化");
  956. return false;
  957. }
  958. //MessageLog.GetInstance.Show("爪子去到1号位");
  959. MaterailLibrary_Write("M1.0", true);
  960. Thread.Sleep(500);
  961. for (int i = 0; i < materialSleepCount && !ml_morkf.PawArrivePortOne; i++)
  962. {
  963. Thread.Sleep(materialSleepTime);
  964. if (i >= materialSleepCount - 1)
  965. {
  966. if (i == 10)
  967. {
  968. MaterailLibrary_Write("M1.0", true);
  969. }
  970. MessageLog.GetInstance.ShowEx("爪子去到1号位超时");
  971. return false;
  972. }
  973. }
  974. Thread.Sleep(300);
  975. //MessageLog.GetInstance.Show("爪子去到1号位完成");
  976. return true;
  977. }
  978. public bool PawToPoint2()
  979. {
  980. if (!ml_morkf.InitialComplete)
  981. {
  982. MessageLog.GetInstance.ShowEx("爪子去到2号位出错,菜品库未初始化");
  983. return false;
  984. }
  985. MaterailLibrary_Write("M1.1", true);
  986. //MessageLog.GetInstance.Show("爪子去到2号位");
  987. Thread.Sleep(500);
  988. for (int i = 0; i < materialSleepCount && !ml_morkf.PawArrivePortTwo; i++)
  989. {
  990. Thread.Sleep(materialSleepTime);
  991. if (i >= materialSleepCount - 1)
  992. {
  993. if (i == 10)
  994. {
  995. MaterailLibrary_Write("M1.1", true);
  996. }
  997. MessageLog.GetInstance.ShowEx("爪子去到2号位超时");
  998. return false;
  999. }
  1000. }
  1001. Thread.Sleep(300);
  1002. //MessageLog.GetInstance.Show("爪子去到2号位完成");
  1003. return true;
  1004. }
  1005. public bool PawToPoint3()
  1006. {
  1007. if (!ml_morkf.InitialComplete)
  1008. {
  1009. MessageLog.GetInstance.ShowEx("爪子去到3号位出错,菜品库未初始化");
  1010. return false;
  1011. }
  1012. //MessageLog.GetInstance.Show("爪子去到3号位");
  1013. MaterailLibrary_Write("M1.2", true);
  1014. Thread.Sleep(500);
  1015. for (int i = 0; i < materialSleepCount && !ml_morkf.PawArrivePortThree; i++)
  1016. {
  1017. Thread.Sleep(materialSleepTime);
  1018. if (i == 30)
  1019. {
  1020. MaterailLibrary_Write("M1.2", true);
  1021. }
  1022. if (i >= materialSleepCount - 1)
  1023. {
  1024. MessageLog.GetInstance.ShowEx("爪子去到3号位超时");
  1025. }
  1026. }
  1027. if (!ml_morkf.PawPositon_3)
  1028. {
  1029. MaterailLibrary_Write("M1.2", true);
  1030. Thread.Sleep(3000);
  1031. }
  1032. Thread.Sleep(300);
  1033. //MessageLog.GetInstance.Show("爪子去到3号位完成");
  1034. return true;
  1035. }
  1036. public bool GetDistance_1()
  1037. {
  1038. if (!ml_morkf.InitialComplete)
  1039. {
  1040. MessageLog.GetInstance.ShowEx("1号测距出错,菜品库未初始化");
  1041. return false;
  1042. }
  1043. MaterailLibrary_Write("M0.3", true);
  1044. MaterailLibrary_Write("M0.3", false);
  1045. Thread.Sleep(3000);
  1046. //MessageLog.GetInstance.Show("1号测距开启完成");
  1047. //MessageLog.GetInstance.Show($"传感器的距离{ml_morkf.LaserDistance}");
  1048. ActionManage.GetInstance.Send(new List<string> { "1", ml_morkf.LaserDistance.ToString() }, "GetDistanceCallBack");//通知获取测距界面
  1049. return true;
  1050. }
  1051. public bool GetDistance_2()
  1052. {
  1053. if (!ml_morkf.InitialComplete)
  1054. {
  1055. MessageLog.GetInstance.ShowEx("2号测距出错,菜品库未初始化");
  1056. return false;
  1057. }
  1058. MaterailLibrary_Write("M0.4", true);
  1059. MaterailLibrary_Write("M0.4", false);
  1060. Thread.Sleep(3000);
  1061. //MessageLog.GetInstance.Show("2号测距开启完成");
  1062. //MessageLog.GetInstance.Show($"传感器的距离{ml_morkf.LaserDistance}");
  1063. ActionManage.GetInstance.Send(new List<string> { "2", ml_morkf.LaserDistance.ToString() }, "GetDistanceCallBack");//通知获取测距界面
  1064. return true;
  1065. }
  1066. public bool GetDistance_3()
  1067. {
  1068. if (!ml_morkf.InitialComplete)
  1069. {
  1070. MessageLog.GetInstance.ShowEx("3号测距出错,菜品库未初始化");
  1071. return false;
  1072. }
  1073. MaterailLibrary_Write("M0.5", true);
  1074. MaterailLibrary_Write("M0.5", false);
  1075. Thread.Sleep(3000);
  1076. //MessageLog.GetInstance.Show("3号测距开启完成");
  1077. //MessageLog.GetInstance.Show($"传感器的距离{ml_morkf.LaserDistance}");
  1078. ActionManage.GetInstance.Send(new List<string> { "3", ml_morkf.LaserDistance.ToString() }, "GetDistanceCallBack");//通知获取测距界面
  1079. return true;
  1080. }
  1081. /// <summary>
  1082. /// 写入传感器距离
  1083. /// </summary>
  1084. /// <param name="speed"></param>
  1085. public void WriteSpeed(int speed)
  1086. {
  1087. MaterailLibrary_Write("VD808", speed);
  1088. Thread.Sleep(400);
  1089. }
  1090. /// <summary>
  1091. /// 写入传感器距离
  1092. /// </summary>
  1093. /// <param name="distance"></param>
  1094. public void WriteDistance(int distance)
  1095. {
  1096. MaterailLibrary_Write("VW270", distance);
  1097. }
  1098. /// <summary>
  1099. /// 根据x坐标获取传感器距离
  1100. /// </summary>
  1101. /// <param name="x"></param>
  1102. /// <returns></returns>
  1103. public bool GetDistance(int x)
  1104. {
  1105. bool ret = true;
  1106. //是否在第一层菜品库
  1107. if (x > 0 && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X)
  1108. {
  1109. //获取传感器1的距离
  1110. ret &= GetDistance_1();
  1111. Thread.Sleep(400);
  1112. ////获取传感器1的距离
  1113. ret &= GetDistance_1();
  1114. }
  1115. //是否在第二层菜品库
  1116. else if (x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X)
  1117. {
  1118. //获取传感器2的距离
  1119. ret &= GetDistance_2();
  1120. Thread.Sleep(400);
  1121. ret &= GetDistance_2();
  1122. }
  1123. //是否在第三层菜品库
  1124. else if (x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["19"].X)
  1125. {
  1126. //获取传感器3的距离
  1127. ret &= GetDistance_3();
  1128. Thread.Sleep(400);
  1129. ret &= GetDistance_3();
  1130. }
  1131. if (!ret)
  1132. {
  1133. MessageLog.GetInstance.ShowEx($"错误:X轴:{x}获取传感器数据出错");
  1134. }
  1135. return ret;
  1136. }
  1137. /// <summary>
  1138. /// 设定机械臂的位置
  1139. /// </summary>
  1140. /// <param name="x"></param>
  1141. /// <param name="y"></param>
  1142. public bool SetArmPosition(int x, int y)
  1143. {
  1144. if (!ml_morkf.InitialComplete)
  1145. {
  1146. MessageLog.GetInstance.ShowEx($"机械臂移动出错,菜品库未初始化");
  1147. return false;
  1148. }
  1149. if (x > 212000 || y > 240000)
  1150. {
  1151. MessageLog.GetInstance.ShowEx("机械臂移动超出范围");
  1152. return false;
  1153. }
  1154. //取反
  1155. x = 0 - Math.Abs(x);
  1156. y = 0 - Math.Abs(y);
  1157. if (x > 0 || y > 0)
  1158. {
  1159. MessageLog.GetInstance.ShowEx($"机械臂移动到[{x},{y}]非法");
  1160. return false;
  1161. }
  1162. MaterailLibrary_Write("VD836", x);
  1163. Thread.Sleep(100);
  1164. MaterailLibrary_Write("VD840", y);
  1165. Thread.Sleep(200);
  1166. //MessageLog.GetInstance.Show($"机械臂移动到[{x},{y}]");
  1167. //到达置为false
  1168. ml_morkf.ArriveComplete = false;
  1169. //定位启动
  1170. MaterailLibrary_Write("M0.0", true);
  1171. Thread.Sleep(400);
  1172. for (int i = 0; i < materialSleepCount && (!ml_morkf.ArriveComplete); i++)
  1173. {
  1174. Thread.Sleep(materialSleepTime);
  1175. //若是目标点与当前坐标一致,跳出循环
  1176. if ((ml_morkf.ArmPositionX == x && ml_morkf.ArmPositionY == y))
  1177. {
  1178. MessageLog.GetInstance.Show($"机械臂已移动到[{ml_morkf.ArmPositionX},{ml_morkf.ArmPositionY}]");
  1179. break;
  1180. }
  1181. if (i >= materialSleepCount - 1)
  1182. {
  1183. MessageLog.GetInstance.ShowEx("机械臂移动操作超时");
  1184. return false;
  1185. }
  1186. }
  1187. //MessageLog.GetInstance.Show("机械臂移动操作完成");
  1188. Thread.Sleep(300);
  1189. return true;
  1190. }
  1191. /// <summary>
  1192. /// 设定机械臂的当前坐标
  1193. /// </summary>
  1194. /// <param name="x"></param>
  1195. /// <param name="y"></param>
  1196. public void SetNowPosition(int x, int y)
  1197. {
  1198. //取反
  1199. x -= 2 * x;
  1200. y -= 2 * y;
  1201. //MessageLog.GetInstance.Show($"设置机械臂当前坐标为[{x},{y}]");
  1202. MaterailLibrary_Write("VD828", x);
  1203. Thread.Sleep(200);
  1204. MaterailLibrary_Write("VD832", y);
  1205. Thread.Sleep(200);
  1206. }
  1207. /// <summary>
  1208. /// 机械臂向上移动开关
  1209. /// </summary>
  1210. /// <param name="startOrStop">true:开启,false:关闭</param>
  1211. public void ArmRunUp(bool startOrStop)
  1212. {
  1213. MaterailLibrary_Write("M5.3", startOrStop);
  1214. Thread.Sleep(200);
  1215. }
  1216. /// <summary>
  1217. /// 机械臂向下移动开关
  1218. /// </summary>
  1219. /// <param name="startOrStop">true:开启,false:关闭</param>
  1220. public void ArmRunDown(bool startOrStop)
  1221. {
  1222. MaterailLibrary_Write("M5.4", startOrStop);
  1223. Thread.Sleep(200);
  1224. }
  1225. /// <summary>
  1226. /// 机械臂向左移动开关
  1227. /// </summary>
  1228. /// <param name="startOrStop">true:开启,false:关闭</param>
  1229. public void ArmRunLeft(bool startOrStop)
  1230. {
  1231. MaterailLibrary_Write("M5.5", startOrStop);
  1232. Thread.Sleep(200);
  1233. }
  1234. /// <summary>
  1235. /// 机械臂向右移动开关
  1236. /// </summary>
  1237. /// <param name="startOrStop">true:开启,false:关闭</param>
  1238. public void ArmRunRight(bool startOrStop)
  1239. {
  1240. MaterailLibrary_Write("M5.6", startOrStop);
  1241. Thread.Sleep(200);
  1242. }
  1243. #endregion
  1244. //菜品库锁
  1245. object lock_Materail = new object();
  1246. /// <summary>
  1247. /// 取菜操作
  1248. /// </summary>
  1249. /// <param name="x">取菜x轴坐标</param>
  1250. /// <param name="y">取菜y轴坐标</param>
  1251. /// <param name="fryNum">炒锅编号</param>
  1252. public bool GetMaterail(int x, int y, int fryNum)
  1253. {
  1254. //设置到抓菜处
  1255. if (!SetArmPosition(x, y))
  1256. {
  1257. return false;
  1258. }
  1259. if (!GetDistance(x))
  1260. {
  1261. MessageLog.GetInstance.Show("错误:获取传感器数据出错");
  1262. return false;
  1263. }
  1264. Thread.Sleep(1000);
  1265. //获取传感器的距离,转换成坐标系的点
  1266. int laserHigh = ml_morkf.LaserDistance;
  1267. //秦工要求读取后置0
  1268. WriteDistance(0);
  1269. MessageLog.GetInstance.Show($"传感器的距离{laserHigh}");
  1270. int moveX = 0;
  1271. if (LaserDistance2Coordinate(laserHigh, x, out moveX) != Laser2CoordinateState.MaterialNormal)
  1272. {
  1273. MessageLog.GetInstance.ShowEx("错误:传感器距离转坐标值失败");
  1274. return false;
  1275. }
  1276. if (x < moveX)
  1277. {
  1278. MessageLog.GetInstance.ShowEx("错误:传感器距离转坐标值大于当前x轴坐标");
  1279. return false;
  1280. }
  1281. //设置到传感器感应的距离处
  1282. if (!SetArmPosition(x - moveX, y))
  1283. {
  1284. return false;
  1285. }
  1286. WriteSpeed(10000);
  1287. //关闭电磁阀
  1288. Electromagnetism(new List<bool> { true });
  1289. Thread.Sleep(500);
  1290. //爪子去1号位抓菜
  1291. if (!PawToPoint1())
  1292. {
  1293. return false;
  1294. }
  1295. //伸出爪子
  1296. if (!PawExtend())
  1297. {
  1298. return false;
  1299. }
  1300. //移动前开启电磁阀
  1301. Electromagnetism(new List<bool> { false });
  1302. Thread.Sleep(500);
  1303. //根据x轴所在坐标系,计算高度差。
  1304. if ((x > 0 && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X) &&
  1305. (MaterialCoordinate.GetInstance.MaterialOneX > 0 && MaterialCoordinate.GetInstance.MaterialOneX < x))
  1306. {
  1307. //菜品盒子出菜品库,往上移动一个盒子的距离
  1308. if (!SetArmPosition(MaterialCoordinate.GetInstance.MaterialOneX, y))
  1309. {
  1310. return false;
  1311. }
  1312. }
  1313. else if ((x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X) &&
  1314. (MaterialCoordinate.GetInstance.MaterialTwoX > 0 && MaterialCoordinate.GetInstance.MaterialTwoX < x))
  1315. {
  1316. //菜品盒子出菜品库,往上移动一个盒子的距离
  1317. if (!SetArmPosition(MaterialCoordinate.GetInstance.MaterialTwoX, y))
  1318. {
  1319. return false;
  1320. }
  1321. }
  1322. else if ((x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["20"].X) &&
  1323. (MaterialCoordinate.GetInstance.MaterialThreeX > 0 && MaterialCoordinate.GetInstance.MaterialThreeX < x))
  1324. {
  1325. //菜品盒子出菜品库,往上移动一个盒子的距离
  1326. if (!SetArmPosition(MaterialCoordinate.GetInstance.MaterialThreeX, y))
  1327. {
  1328. return false;
  1329. }
  1330. }
  1331. else
  1332. {
  1333. MessageLog.GetInstance.ShowEx("错误:未设置当前菜品库出菜位置");
  1334. return false;
  1335. }
  1336. //爪子去2号位放菜
  1337. if (!PawToPoint2())
  1338. {
  1339. return false;
  1340. }
  1341. WriteSpeed(50000);//移动速度
  1342. //TaskManage.GetInstance.Start(new Action(() =>
  1343. //{
  1344. // //收缩爪子
  1345. // PawShrink();
  1346. //}), "GetMaterialPawShrink");
  1347. //收缩爪子
  1348. if (!PawShrink()) return false;
  1349. //判断炒锅是否可以放盒
  1350. for (int i = 0; materialSleepCount > i && !morkFs[fryNum].FryPot1_HOBTPut; i++)
  1351. {
  1352. Thread.Sleep(materialSleepTime);
  1353. if (i >= materialSleepCount - 1)
  1354. {
  1355. MessageLog.GetInstance.ShowEx("等待炒锅允许放盒超时");
  1356. return false;
  1357. }
  1358. }
  1359. //关闭启磁吸
  1360. MagnetOff(fryNum);
  1361. //Thread.Sleep(2000);
  1362. //根据炒锅不同设置不同的出菜处
  1363. if (fryNum % 2 == 0)
  1364. {
  1365. x = MaterialCoordinate.GetInstance.frying1.X;
  1366. y = MaterialCoordinate.GetInstance.frying1.Y;
  1367. }
  1368. else
  1369. {
  1370. x = MaterialCoordinate.GetInstance.frying2.X;
  1371. y = MaterialCoordinate.GetInstance.frying2.Y;
  1372. }
  1373. //先设置到炒锅i出菜处上10000点
  1374. if (!SetArmPosition(x - materialToFryDistance, y))
  1375. {
  1376. return false;
  1377. }
  1378. //爪子去3号位放菜
  1379. if (!PawToPoint3())
  1380. {
  1381. return false;
  1382. }
  1383. //开启磁吸
  1384. MagnetOn(fryNum);
  1385. Thread.Sleep(500);
  1386. //设置到炒锅1出菜处
  1387. if (!SetArmPosition(x, y))
  1388. {
  1389. return false;
  1390. }
  1391. //伸出爪子
  1392. if (!PawExtend())
  1393. {
  1394. return false;
  1395. }
  1396. Thread.Sleep(300);
  1397. //关闭电磁阀
  1398. Electromagnetism(new List<bool> { true });
  1399. Thread.Sleep(300);
  1400. //收缩爪子
  1401. if (!PawShrink()) return false;
  1402. //设置到炒锅i出菜处
  1403. if (!SetArmPosition(x + materialToFryDistance, y))
  1404. {
  1405. return false;
  1406. }
  1407. //爪子回到2号位
  1408. if (!PawToPoint2())
  1409. {
  1410. return false;
  1411. }
  1412. //开启电磁阀
  1413. Electromagnetism(new List<bool> { false });
  1414. if (morkFs.ContainsKey(fryNum))
  1415. {
  1416. morkFs[fryNum].GetMaterialComplete = true;
  1417. }
  1418. return true;
  1419. }
  1420. /// <summary>
  1421. /// 更新菜品库存量
  1422. /// </summary>
  1423. /// <returns></returns>
  1424. public bool UpdateMaterialLibraryStock()
  1425. {
  1426. try
  1427. {
  1428. //判断是否初始化
  1429. if (!ml_morkf.InitialComplete)
  1430. {
  1431. MessageLog.GetInstance.Show("更新菜品库存量出错,菜品库未初始化");
  1432. return false;
  1433. }
  1434. if (MaterialCoordinate.GetInstance.dicNoMaterialCoordinate == null || MaterialCoordinate.GetInstance.dicNoMaterialCoordinate.Count != 27)
  1435. {
  1436. MessageLog.GetInstance.ShowEx("更新菜品库存量出错,菜品库坐标系数据未建立");
  1437. return false;
  1438. }
  1439. //关闭电磁阀
  1440. Electromagnetism(new List<bool> { true });
  1441. //爪子收回
  1442. if (!PawShrink())
  1443. {
  1444. return false;
  1445. }
  1446. //爪子去2号点位
  1447. if (!PawToPoint2())
  1448. {
  1449. return false;
  1450. }
  1451. //开启电磁阀
  1452. Electromagnetism(new List<bool> { false });
  1453. //遍历坐标系与位置,并根据位置更新菜品余量
  1454. foreach (var item in MaterialCoordinate.GetInstance.dicNoMaterialCoordinate)
  1455. {
  1456. bool ret = true;
  1457. switch (item.Key)
  1458. {
  1459. //遇到1 9 10 18 19 27号位置跳过不检测,因为这6个位置不放菜品
  1460. case "1":
  1461. case "9":
  1462. case "10":
  1463. case "18":
  1464. case "19":
  1465. case "27":
  1466. ret = false;
  1467. break;
  1468. }
  1469. if (!ret)
  1470. {
  1471. continue;
  1472. }
  1473. //设置到抓菜处
  1474. if (!SetArmPosition(item.Value.X, item.Value.Y))
  1475. {
  1476. return false;
  1477. }
  1478. //获取该处的距离
  1479. if (!GetDistance(item.Value.X))
  1480. {
  1481. MessageLog.GetInstance.ShowEx("错误:获取传感器数据出错");
  1482. return false;
  1483. }
  1484. Thread.Sleep(1000);
  1485. //获取传感器的距离
  1486. int laserHigh = ml_morkf.LaserDistance;
  1487. //秦工要求读取后置0
  1488. WriteDistance(0);
  1489. int surplus = 0;
  1490. //根据距离算出菜品余量
  1491. Laser2CoordinateState state = LaserDistance2MaterialCount(laserHigh, item.Value.X, out surplus);
  1492. if (state != Laser2CoordinateState.MaterialNormal && state != Laser2CoordinateState.MaterialEmpty)
  1493. {
  1494. return false;
  1495. }
  1496. //更新菜品余量
  1497. if (!MaterialSurplusOperation.GetInstance.UpdateSurplus(item.Key, surplus))
  1498. {
  1499. //return false;
  1500. }
  1501. }
  1502. return true;
  1503. }
  1504. catch (Exception ex)
  1505. {
  1506. return false;
  1507. }
  1508. }
  1509. /// <summary>
  1510. /// 传感器距离转为x轴坐标系
  1511. /// </summary>
  1512. /// <param name="distance"></param>
  1513. /// <param name="x_high"></param>
  1514. /// <returns></returns>
  1515. public Laser2CoordinateState LaserDistance2Coordinate(int distance, int x, out int x_high)
  1516. {
  1517. x_high = 0;
  1518. int boxCount = 0;
  1519. try
  1520. {
  1521. Laser2CoordinateState laser2CoordinateState = LaserDistance2MaterialCount(distance, x, out boxCount);
  1522. if (laser2CoordinateState == Laser2CoordinateState.MaterialNormal)
  1523. {
  1524. int compensateHeight = boxCount > 1 ? 500 : 0;//补偿高度,超过1层盒子增加补偿
  1525. //盒子高度计算除去起始位置的那个盒子
  1526. x_high = (boxCount - 1) * materialBoxHeight + compensateHeight;
  1527. }
  1528. return laser2CoordinateState;
  1529. }
  1530. catch (Exception ex)
  1531. {
  1532. return Laser2CoordinateState.MaterialUnkown;
  1533. }
  1534. }
  1535. /// <summary>
  1536. /// 传感器距离转为菜品数量
  1537. /// </summary>
  1538. /// <param name="distance"></param>
  1539. /// <param name="x"></param>
  1540. /// <returns></returns>
  1541. public Laser2CoordinateState LaserDistance2MaterialCount(int distance, int x, out int count)
  1542. {
  1543. count = 0;
  1544. try
  1545. {
  1546. //传感器高度小于80mm,无法移出,菜品库满
  1547. if (distance < 80)
  1548. {
  1549. MessageLog.GetInstance.ShowEx("错误:传感器距离不满足出菜高度");
  1550. return Laser2CoordinateState.MaterialOverdo;
  1551. }
  1552. int heightDifferent = 0;
  1553. //根据x轴所在坐标系,计算高度差。
  1554. if (x > 0 && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X)
  1555. {
  1556. heightDifferent = MaterialCoordinate.GetInstance.distance_1 - distance;
  1557. }
  1558. else if (x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["1"].X)
  1559. {
  1560. heightDifferent = MaterialCoordinate.GetInstance.distance_2 - distance;
  1561. }
  1562. else if (x > MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["10"].X && x <= MaterialCoordinate.GetInstance.dicNoMaterialCoordinate["20"].X)
  1563. {
  1564. heightDifferent = MaterialCoordinate.GetInstance.distance_3 - distance;
  1565. }
  1566. else
  1567. {
  1568. return Laser2CoordinateState.MaterialOverdo;
  1569. }
  1570. if (heightDifferent < 0)
  1571. {
  1572. MessageLog.GetInstance.ShowEx($"菜品库检测{x}处的菜品量时,传感器获取的高度差为负数,请校准该层高度");
  1573. return Laser2CoordinateState.MaterialEmpty; ;
  1574. }
  1575. //盒子高度为45,但是需要考虑到误差,不足35,则认为为空
  1576. int boxCount = (heightDifferent + 5) / 35;
  1577. count = boxCount;
  1578. if (count == 0)
  1579. {
  1580. MessageLog.GetInstance.ShowEx("菜品库为空");
  1581. return Laser2CoordinateState.MaterialEmpty;
  1582. }
  1583. else if (count > 6)
  1584. {
  1585. MessageLog.GetInstance.ShowEx("菜品库数量超量");
  1586. return Laser2CoordinateState.MaterialOverdo;
  1587. }
  1588. else
  1589. {
  1590. return Laser2CoordinateState.MaterialNormal;
  1591. }
  1592. }
  1593. catch (Exception ex)
  1594. {
  1595. return Laser2CoordinateState.MaterialUnkown;
  1596. }
  1597. }
  1598. /// <summary>
  1599. /// 获取菜品测试
  1600. /// </summary>
  1601. /// <param name="isGet"></param>
  1602. private void GetMaterailTest(MaterialOperation materialOperation)
  1603. {
  1604. TaskManage.GetInstance.Start(new Action(() =>
  1605. {
  1606. bool ret = false;
  1607. try
  1608. {
  1609. Coordinate myCoordinate = new Coordinate();
  1610. //获取坐标,根据菜品的位置信息
  1611. if (!NoMaterial2Coordinate(materialOperation.materialInfo.Loc, out myCoordinate))
  1612. {
  1613. MessageLog.GetInstance.ShowEx($"炒锅{materialOperation.fryNum}获取菜品[{materialOperation.materialInfo.Name}]失败,找不到对应位置");
  1614. return;
  1615. }
  1616. //取菜操作
  1617. ret = GetMaterail(myCoordinate.X, myCoordinate.Y, materialOperation.fryNum);
  1618. }
  1619. catch (Exception ex)
  1620. {
  1621. ret = false;
  1622. }
  1623. finally
  1624. {
  1625. //本地炒制不进行菜品数量检查
  1626. if (!isLocalFryingMode)
  1627. {
  1628. GoodBatchings goodBatchings = stagingGoodBatchings.Find(o => o.BatchingId == materialOperation.materialInfo.Key);
  1629. if (ret == true)
  1630. {
  1631. if (true)
  1632. {
  1633. if (goodBatchings != null)
  1634. {
  1635. //指定位置菜品减一
  1636. MaterialSurplusOperation.GetInstance.ReduceSurplus(materialOperation.materialInfo.Loc, goodBatchings.BatchingCount);
  1637. }
  1638. }
  1639. else
  1640. {
  1641. //指定位置菜品减一
  1642. MaterialSurplusOperation.GetInstance.ReduceSurplus(materialOperation.materialInfo.Loc);
  1643. }
  1644. SaveMaterialData();
  1645. }
  1646. //移出占用菜品
  1647. stagingGoodBatchings.Remove(goodBatchings);
  1648. }
  1649. ml_morkf.MaterailIsWorking = false;
  1650. }
  1651. }), $"菜品库操作");
  1652. }
  1653. #endregion
  1654. #region 炒锅PLC基本操作方法
  1655. /// <summary>
  1656. /// 炒锅写寄存器方法,num为炒锅对应编号,从0开始
  1657. /// </summary>
  1658. /// <param name="address">寄存器地址</param>
  1659. /// <param name="value">值</param>
  1660. /// <param name="num">炒锅编号</param>
  1661. private void FirePot_Write(string address, object value, int num)
  1662. {
  1663. WriteControlExact(address, value, num);
  1664. }
  1665. /// <summary>
  1666. /// 出调料
  1667. /// </summary>
  1668. /// <param name="o"></param>
  1669. public void OutSeasoning(object o, int num)
  1670. {
  1671. if (o == null) return;
  1672. if (o is List<int> ints && ints.Count == 2 && morkFs.ContainsKey(num))
  1673. {
  1674. FirePot_Write(morkFs[num].PassWayValue[ints[0]], (ushort)ints[1], num);//写入通道值
  1675. Thread.Sleep(400);
  1676. FirePot_Write(morkFs[num].StartPassWay[ints[0]], true, num);//开启通道
  1677. Thread.Sleep(400);
  1678. FirePot_Write(morkFs[num].StartPassWay[ints[0]], false, num);//开启通道
  1679. }
  1680. }
  1681. /// <summary>
  1682. /// 出多个调料
  1683. /// </summary>
  1684. public void OutSeasonings(List<SeasoningList> seasoningLists, int num)
  1685. {
  1686. //防止越界
  1687. if (!morkFs.ContainsKey(num))
  1688. {
  1689. return;
  1690. }
  1691. foreach (SeasoningList seasoning in seasoningLists)
  1692. {
  1693. FirePot_Write(morkFs[num].PassWayValue[seasoning.Loc], (ushort)seasoning.Qty, num);
  1694. Thread.Sleep(300);
  1695. }
  1696. foreach (SeasoningList seasoning in seasoningLists)
  1697. {
  1698. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], true, num);
  1699. Thread.Sleep(300);
  1700. }
  1701. foreach (SeasoningList seasoning in seasoningLists)
  1702. {
  1703. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], false, num);
  1704. Thread.Sleep(300);
  1705. }
  1706. foreach (SeasoningList seasoning in seasoningLists)
  1707. {
  1708. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], false, num);
  1709. Thread.Sleep(300);
  1710. }
  1711. }
  1712. /// <summary>
  1713. /// 复位
  1714. /// </summary>
  1715. public void Plc1Reset(int num)
  1716. {
  1717. TaskManage.GetInstance.Start(new Action(() =>
  1718. {
  1719. StopFire(num);
  1720. Thread.Sleep(200);
  1721. StopStir(num);
  1722. Thread.Sleep(200);
  1723. FirePot_Write("LB5", false, num);
  1724. Thread.Sleep(200);
  1725. FirePot_Write("LB3", false, num);
  1726. Thread.Sleep(200);
  1727. FirePot_Write("LB6", false, num);
  1728. Thread.Sleep(200);
  1729. FirePot_Write("LB7", false, num);
  1730. Thread.Sleep(200);
  1731. FirePot_Write("LB4", false, num);
  1732. Thread.Sleep(200);
  1733. FirePot_Write("LB53", false, num);
  1734. if (morkFs.ContainsKey(num))
  1735. {
  1736. foreach (var item in morkFs[num].StartPassWay.Values)
  1737. {
  1738. Thread.Sleep(200);
  1739. FirePot_Write(item, false, num);
  1740. }
  1741. }
  1742. }), $"炒锅{num}初始化");
  1743. }
  1744. /// <summary>
  1745. /// 炒锅初始化
  1746. /// </summary>
  1747. public void PLCInite()
  1748. {
  1749. for (int i = 0; i < morkFs.Count; i++)
  1750. {
  1751. FirePot_Write("LB0", true, i);
  1752. for (int j = 0; j < sleepCount && !morkFs[i].FryPot1_InitialComplete; j++)
  1753. {
  1754. Thread.Sleep(sleepTime);
  1755. if (j >= sleepCount - 1)
  1756. {
  1757. MessageLog.GetInstance.ShowEx($"炒锅{j}初始化超时");
  1758. }
  1759. }
  1760. FirePot_Write("LB0", false, i);
  1761. }
  1762. }
  1763. //加油
  1764. public void AddOil()
  1765. {
  1766. }
  1767. //加热启动
  1768. public void StartFire(int num)
  1769. {
  1770. FirePot_Write("LB1", true, num);
  1771. Thread.Sleep(200);
  1772. }
  1773. //加热停止
  1774. public void StopFire(int num)
  1775. {
  1776. FirePot_Write("LB1", false, num);
  1777. Thread.Sleep(200);
  1778. }
  1779. //搅拌启动
  1780. public void StartStir(int num)
  1781. {
  1782. FirePot_Write("LB2", true, num);
  1783. Thread.Sleep(200);
  1784. }
  1785. //搅拌启停止
  1786. public void StopStir(int num)
  1787. {
  1788. FirePot_Write("LB2", false, num);
  1789. Thread.Sleep(200);
  1790. }
  1791. //倒菜
  1792. public bool OutFood(int num, out string error, bool isMaterial = false)
  1793. {
  1794. bool ret = true;
  1795. error = string.Empty;
  1796. if (!morkFs.ContainsKey(num))
  1797. {
  1798. error = $"编号为{num}的炒锅无法找到";
  1799. return false;
  1800. }
  1801. int i = 0;
  1802. MessageLog.GetInstance.Show("倒菜启动开始");
  1803. if (isMaterial)
  1804. {
  1805. //判断是否完成取菜
  1806. for (i = 0; i < materialSleepCount * 2 && !morkFs[num].GetMaterialComplete; i++)
  1807. {
  1808. if (i == 10)
  1809. {
  1810. //停止搅拌
  1811. //StopStir(num);
  1812. //搅拌设置为1档
  1813. SetStir(new List<int> { 1 }, i);
  1814. //火力设置为2档
  1815. SetFire(new List<int> { 3 }, num);
  1816. }
  1817. Thread.Sleep(materialSleepTime);
  1818. if (i >= materialSleepCount * 2 - 1)
  1819. {
  1820. error = $"炒锅{num}倒菜超时:未能等到取菜完成,请检查菜品库是否正常运行";
  1821. MessageLog.GetInstance.ShowEx($"炒锅{num}倒菜超时:未能等到取菜完成");
  1822. ret &= false;
  1823. }
  1824. }
  1825. if (i > 9)
  1826. {
  1827. //开启搅拌
  1828. //StartStir(num);
  1829. //搅拌设置为原本搅拌档位
  1830. SetStir(new List<int> { morkFs[num].Stir }, i);
  1831. //火力设置回原本火力
  1832. SetFire(new List<int> { morkFs[num].Fire }, num);
  1833. }
  1834. }
  1835. if (!ret)
  1836. {
  1837. return ret;
  1838. }
  1839. FirePot_Write("LB3", true, num);
  1840. //MessageLog.GetInstance.Show("倒菜启动");
  1841. Thread.Sleep(500);
  1842. for (i = 0; i < materialSleepCount && !morkFs[num].FryPot1_MaterialIntoPot; i++)
  1843. {
  1844. Thread.Sleep(materialSleepTime);
  1845. if (i >= materialSleepCount - 1)
  1846. {
  1847. error = $"炒锅{num}倒菜超时,请联系相关工作人员";
  1848. MessageLog.GetInstance.ShowEx($"炒锅{num}倒菜超时");
  1849. ret &= false;
  1850. }
  1851. }
  1852. FirePot_Write("LB3", false, num);
  1853. Thread.Sleep(200);
  1854. //MessageLog.GetInstance.Show("倒菜完成");
  1855. morkFs[num].GetMaterialComplete = false;
  1856. return ret;
  1857. }
  1858. //搅拌臂去原点位
  1859. public void StirArmGoOrigin(int num)
  1860. {
  1861. if (!morkFs.ContainsKey(num))
  1862. {
  1863. return;
  1864. }
  1865. FirePot_Write("LB5", true, num);
  1866. //MessageLog.GetInstance.Show("搅拌臂去原点位");
  1867. for (int i = 0; i < sleepCount && !morkFs[num].ArmOnOrigin; i++)
  1868. {
  1869. Thread.Sleep(sleepTime);
  1870. if (i >= sleepCount - 1)
  1871. {
  1872. MessageLog.GetInstance.ShowEx($"炒锅{num}搅拌臂去原点位超时");
  1873. }
  1874. }
  1875. FirePot_Write("LB5", false, num);
  1876. Thread.Sleep(200);
  1877. //MessageLog.GetInstance.Show("搅拌臂到达原点位");
  1878. }
  1879. //搅拌臂去炒制位
  1880. public bool StirArmGoWork(int num, out string error)
  1881. {
  1882. error = string.Empty;
  1883. bool ret = true;
  1884. if (!morkFs.ContainsKey(num))
  1885. {
  1886. error = $"编号为{num}的炒锅无法找到";
  1887. return false;
  1888. }
  1889. if (!morkFs[num].ArmOnWorking/* && morkFs[num].PotOnOrigin*/)
  1890. {
  1891. FirePot_Write("LB6", true, num);
  1892. //MessageLog.GetInstance.Show("搅拌臂去工作位");
  1893. for (int i = 0; i < sleepCount && !morkFs[num].ArmOnWorking; i++)
  1894. {
  1895. Thread.Sleep(sleepTime);
  1896. if (i >= sleepCount - 1)
  1897. {
  1898. error = $"炒锅{num}搅拌臂去炒制位超时";
  1899. MessageLog.GetInstance.ShowEx($"炒锅{num}搅拌臂去炒制位超时");
  1900. ret &= false;
  1901. }
  1902. }
  1903. //while (!morkFs[num].ArmOnWorking)
  1904. //{
  1905. // Thread.Sleep(200);
  1906. //}
  1907. FirePot_Write("LB6", false, num);
  1908. Thread.Sleep(200);
  1909. //MessageLog.GetInstance.Show("搅拌臂到达工作位");
  1910. return ret;
  1911. }
  1912. return true;
  1913. }
  1914. //HBOT放盒子到位
  1915. public void HBOTGoWork(int num)
  1916. {
  1917. FirePot_Write("LB7", true, num);
  1918. Thread.Sleep(400);
  1919. FirePot_Write("LB7", false, num);
  1920. }
  1921. //出餐启动
  1922. public void OutMeal(int num)
  1923. {
  1924. if (!morkFs[num].ArmOnOrigin /*&& morkFs[num].PotOnOrigin*/)
  1925. {
  1926. MessageLog.GetInstance.ShowEx("搅拌臂不在原点位,无法完成出餐");
  1927. return;
  1928. }
  1929. FirePot_Write("LB4", true, num);
  1930. Thread.Sleep(500);
  1931. FirePot_Write("LB4", false, num);
  1932. }
  1933. //加热挡位设定
  1934. public void SetFire(object o, int num)
  1935. {
  1936. if (o == null) return;
  1937. if (o is List<int> ints && ints.Count == 1)
  1938. {
  1939. FirePot_Write("LW14", (ushort)ints[0], num);
  1940. Thread.Sleep(200);
  1941. }
  1942. }
  1943. public void SetFry(object o)
  1944. {
  1945. if (o == null) return;
  1946. if (o is List<int> ints && ints.Count == 1)
  1947. {
  1948. fryIndex = ints[0] - 1;
  1949. }
  1950. }
  1951. /// <summary>
  1952. /// 搅拌挡位设定
  1953. /// </summary>
  1954. /// <param name="o"></param>
  1955. public void SetStir(object o, int num)
  1956. {
  1957. if (o == null) return;
  1958. if (o is List<int> ints && ints.Count == 1)
  1959. {
  1960. FirePot_Write("LW15", (ushort)ints[0], num);
  1961. Thread.Sleep(200);
  1962. }
  1963. }
  1964. /// <summary>
  1965. /// 开启磁吸
  1966. /// </summary>
  1967. /// <param name="num"></param>
  1968. public void MagnetOn(int num)
  1969. {
  1970. FirePot_Write("LB8", false, num);
  1971. Thread.Sleep(200);
  1972. }
  1973. /// <summary>
  1974. /// 关闭磁吸
  1975. /// </summary>
  1976. /// <param name="num"></param>
  1977. public void MagnetOff(int num)
  1978. {
  1979. FirePot_Write("LB8", true, num);
  1980. Thread.Sleep(200);
  1981. }
  1982. #endregion
  1983. bool isInitialArrive = false;
  1984. bool isInitialPaw = false;
  1985. #region 联网交互
  1986. private void ServerInit()
  1987. {
  1988. //物料信息
  1989. EventBus.GetInstance.Subscribe<MaterialDeliveryEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  1990. {
  1991. if (@event == null) return;
  1992. if (@event is MaterialDeliveryEvent material)
  1993. {
  1994. orderMaterialDelivery = material.orderMaterialDelivery;
  1995. }
  1996. });
  1997. //配方数据信息
  1998. EventBus.GetInstance.Subscribe<RecipeBomEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  1999. {
  2000. if (@event == null) return;
  2001. if (@event is RecipeBomEvent recipe)
  2002. {
  2003. recipeBoms = recipe.recipeBoms;
  2004. }
  2005. });
  2006. //小炒流程信息
  2007. EventBus.GetInstance.Subscribe<StirFryGoodsEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callback)
  2008. {
  2009. if (@event == null) return;
  2010. if (@event is StirFryGoodsEvent stirFry)
  2011. {
  2012. if (stirFry.stirFrymessage != null)
  2013. {
  2014. if (stirFry.stirFrymessage.stirFryGoods.Count > 0)
  2015. {
  2016. foreach (var item in stirFry.stirFrymessage.stirFryGoods)
  2017. {
  2018. LocalstirFryGoods.Add(new StirFryGoods
  2019. {
  2020. GoodsKey = item.GoodsKey,
  2021. StirPotActions = OrderSort(item.StirPotActions),
  2022. });
  2023. }
  2024. }
  2025. MessageLog.GetInstance.Show("接收到小炒流程信息");
  2026. //流程解析
  2027. foreach (var item in LocalstirFryGoods)
  2028. {
  2029. MessageLog.GetInstance.Show($"添加菜谱{item.GoodsKey}");
  2030. // morkF.listStirBom.Add(item.StirFryBomInfo);//添加订单制作流程
  2031. string MenuStep = "菜单步骤:";
  2032. foreach (var items in item.StirPotActions)
  2033. {
  2034. switch (items.Actions)
  2035. {
  2036. case nameof(StirFryPotActionEnum.加热开启):
  2037. MenuStep += items.Actions + ",";
  2038. break;
  2039. case nameof(StirFryPotActionEnum.设置加热挡位1):
  2040. MenuStep += items.Actions + ",";
  2041. break;
  2042. case nameof(StirFryPotActionEnum.设置加热挡位2):
  2043. MenuStep += items.Actions + ",";
  2044. break;
  2045. case nameof(StirFryPotActionEnum.设置加热挡位3):
  2046. MenuStep += items.Actions + ",";
  2047. break;
  2048. case nameof(StirFryPotActionEnum.设置加热挡位4):
  2049. MenuStep += items.Actions + ",";
  2050. break;
  2051. case nameof(StirFryPotActionEnum.设置加热挡位5):
  2052. MenuStep += items.Actions + ",";
  2053. break;
  2054. case nameof(StirFryPotActionEnum.设置加热挡位6):
  2055. MenuStep += items.Actions + ",";
  2056. break;
  2057. case nameof(StirFryPotActionEnum.设置加热挡位7):
  2058. MenuStep += items.Actions + ",";
  2059. break;
  2060. case nameof(StirFryPotActionEnum.设置加热挡位8):
  2061. MenuStep += items.Actions + ",";
  2062. break;
  2063. case nameof(StirFryPotActionEnum.设置加热挡位9):
  2064. MenuStep += items.Actions + ",";
  2065. break;
  2066. case nameof(StirFryPotActionEnum.设置加热挡位10):
  2067. MenuStep += items.Actions + ",";
  2068. break;
  2069. case nameof(StirFryPotActionEnum.停止加热):
  2070. MenuStep += items.Actions + ",";
  2071. break;
  2072. case nameof(StirFryPotActionEnum.加调料):
  2073. MenuStep += items.Actions + ",";
  2074. break;
  2075. case nameof(StirFryPotActionEnum.取原料):
  2076. MenuStep += items.Actions + ",";
  2077. break;
  2078. case nameof(StirFryPotActionEnum.开启搅拌):
  2079. MenuStep += items.Actions + ",";
  2080. break;
  2081. case nameof(StirFryPotActionEnum.设置搅拌挡位1):
  2082. MenuStep += items.Actions + ",";
  2083. break;
  2084. case nameof(StirFryPotActionEnum.设置搅拌挡位2):
  2085. MenuStep += items.Actions + ",";
  2086. break;
  2087. case nameof(StirFryPotActionEnum.设置搅拌挡位3):
  2088. MenuStep += items.Actions + ",";
  2089. break;
  2090. case nameof(StirFryPotActionEnum.关闭搅拌):
  2091. MenuStep += items.Actions + ",";
  2092. break;
  2093. case nameof(StirFryPotActionEnum.出餐启动):
  2094. MenuStep += items.Actions + ",";
  2095. break;
  2096. case nameof(StirFryPotActionEnum.道菜启动):
  2097. MenuStep += items.Actions + ",";
  2098. break;
  2099. case nameof(StirFryPotActionEnum.炒制菜品):
  2100. MenuStep += items.Actions + ",";
  2101. break;
  2102. case nameof(StirFryPotActionEnum.搅拌臂原点位):
  2103. MenuStep += items.Actions + ",";
  2104. break;
  2105. case nameof(StirFryPotActionEnum.搅拌臂炒制位):
  2106. MenuStep += items.Actions + ",";
  2107. break;
  2108. case nameof(StirFryPotActionEnum.洗锅):
  2109. MenuStep += items.Actions + ",";
  2110. break;
  2111. default:
  2112. break;
  2113. }
  2114. }
  2115. MessageLog.GetInstance.Show(MenuStep);
  2116. }
  2117. if (stirFry.stirFrymessage.materials.Count > 0)
  2118. {
  2119. MaterialSurplusOperation.GetInstance.UpdateSurplusAll(stirFry.stirFrymessage.materials);
  2120. SaveMaterialData();
  2121. }
  2122. }
  2123. }
  2124. });
  2125. }
  2126. /// <summary>
  2127. /// 订单排序
  2128. /// </summary>
  2129. /// <param name="potActions"></param>
  2130. /// <returns></returns>
  2131. private List<PotActions> OrderSort(List<PotActions> potActions)
  2132. {
  2133. if (potActions.Count > 1)
  2134. {
  2135. potActions.Sort(
  2136. delegate (PotActions st1, PotActions st2)
  2137. {
  2138. //降序排列
  2139. //return st2.FryTime.CompareTo(st1.FryTime);
  2140. //升序版(颠倒 st1 和 st2 即可)
  2141. return st1.FryTime.CompareTo(st2.FryTime);
  2142. });
  2143. }
  2144. return potActions;
  2145. }
  2146. /// <summary>
  2147. /// 订单状态发布
  2148. /// </summary>
  2149. /// <param name="subid"></param>
  2150. /// <param name="oRDER_STATUS"></param>
  2151. private void OrderChange(string Id, string goodName, ORDER_STATUS oRDER_STATUS, int deviceId)
  2152. {
  2153. EventBus.GetInstance.Publish(new OrderStatusChangedEvent() { Status = oRDER_STATUS, GoodName = goodName, DeviceId = deviceId, SubOrderId = Id });
  2154. }
  2155. /// <summary>
  2156. /// 订单数据解析
  2157. /// </summary>
  2158. private void DataParse()
  2159. {
  2160. //if (!morkFs.ContainsKey(num))
  2161. //{
  2162. // return;
  2163. //}
  2164. EventBus.GetInstance.Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  2165. {
  2166. if (@event == null) return;
  2167. if (@event is DoOrderEvent order)
  2168. {
  2169. if (order.MorkOrder.GoodBatchings == null) return;
  2170. OrderCount++;
  2171. DeviceProcessLogShow($"接收到{OrderCount}次订单");
  2172. Enum.GetNames(typeof(StirFryPotActionEnum));
  2173. if (true)
  2174. {
  2175. var res = LocalstirFryGoods?.FirstOrDefault(p => p.GoodsKey == order.MorkOrder.GoodsKey);//匹配订单对应制作流程
  2176. if (order.MorkOrder.GoodBatchings.Count <= 0)
  2177. {
  2178. return;
  2179. }
  2180. MaterialSurplus materialSurplus = MaterialSurplusOperation.GetInstance.materialSurplus;
  2181. if (order.MorkOrder.DeviceId != DeviceId)
  2182. {
  2183. return;
  2184. }
  2185. ///遍历并增加到待用菜品库
  2186. foreach (var goodBatching in order.MorkOrder.GoodBatchings)
  2187. {
  2188. MaterialInfo materialInfo = MaterialSurplusOperation.GetInstance.materialSurplus.dicSurplus.Find(o => o.Key == goodBatching.BatchingId);
  2189. if (materialInfo != null)
  2190. {
  2191. //if
  2192. if (System.Convert.ToInt32(materialInfo.Qty) - goodBatching.BatchingCount < 0)
  2193. {
  2194. MessageLog.GetInstance.ShowEx($"{materialInfo.Name}不够,请更新菜品库,并点击检测");
  2195. return;
  2196. }
  2197. else
  2198. {
  2199. //查找是否有该菜品
  2200. GoodBatchings existingGoodBatchings = stagingGoodBatchings.Find(o => o.BatchingId == goodBatching.BatchingId);
  2201. //判断是否存在
  2202. if (existingGoodBatchings != null)
  2203. {
  2204. existingGoodBatchings.BatchingCount += goodBatching.BatchingCount;
  2205. }
  2206. else
  2207. {
  2208. stagingGoodBatchings.Add(goodBatching);
  2209. }
  2210. }
  2211. }
  2212. else
  2213. {
  2214. MessageLog.GetInstance.ShowEx($"ID为{goodBatching.BatchingId}的菜品无法找到,请联系售后人员");
  2215. return;
  2216. }
  2217. }
  2218. //var res = LocalstirFryGoods[0];
  2219. if (res != null)
  2220. {
  2221. /* morkF.listStirBom.Add(res.StirFryBomInfo);*///添加订单制作流程
  2222. //添加到带炒小炒队列
  2223. if (StirFryGoodsQuenes.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  2224. {
  2225. //待炒数量+1
  2226. StagingFryCount++;
  2227. lock (lock_MainProcessExcute)
  2228. {
  2229. StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  2230. {
  2231. SuborderId = order.MorkOrder.SuborderId,
  2232. StirPotActions = res.StirPotActions,
  2233. GoodName = order.MorkOrder.GoodsName
  2234. });
  2235. }
  2236. }
  2237. }
  2238. }
  2239. else
  2240. {
  2241. NewStartLocalOrder("莲白回锅");
  2242. }
  2243. ////暂时使用本地菜单
  2244. //StartLocalOrder();
  2245. }
  2246. });
  2247. }
  2248. #endregion
  2249. private object lock_MainProcessExcute = new object();
  2250. /// <summary>
  2251. /// 倒菜锁
  2252. /// </summary>
  2253. private object lock_OutMeal = new object();
  2254. /// <summary>
  2255. /// 炒锅主流程
  2256. /// </summary>
  2257. private void MainProcessExcute()
  2258. {
  2259. //判断是否有订单信息
  2260. if (StirFryGoodsQuenes.Count > 0)
  2261. {
  2262. //遍历炒锅,找到合适、空闲的炒锅
  2263. for (int i = 0; i < morkFs.Count; i++)
  2264. {
  2265. if (morkFs[i].AutoMode && morkFs[i].FryPot1_InitialComplete && ml_morkf.InitialComplete &&
  2266. !morkFs[i].FryWorking)//炒锅在自动状态&&初始化完成&&菜品库初始化&&是否在炒菜中
  2267. {
  2268. Thread.Sleep(4000);
  2269. lock (lock_MainProcessExcute)
  2270. {
  2271. //待炒小炒队列出队列
  2272. if (StirFryGoodsQuenes.TryDequeue(out var res))
  2273. {
  2274. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.WAIT, DeviceId = i);
  2275. //设置当前炒制菜品
  2276. nowStirFryGood[i] = res;
  2277. //炒锅工作状态置为正在工作中
  2278. morkFs[i].FryWorking = true;
  2279. //空闲炒锅入队列
  2280. morkFs[i].StirFryGoodsQuenes.Enqueue(res);
  2281. //炒锅取菜状态置为未取到
  2282. morkFs[i].GetMaterialComplete = false;
  2283. //开启线程进行炒制
  2284. TaskManage.GetInstance.Start(new Action(() =>
  2285. {
  2286. try
  2287. {
  2288. //待炒数量-1
  2289. StagingFryCount--;
  2290. //正在炒制数量+1
  2291. FryingCount++;
  2292. int testi = 0;
  2293. string error = string.Empty;
  2294. //初始化大屏
  2295. morkFs[i].ScreenInit();
  2296. bool ret = true;
  2297. MessageLog.GetInstance.Show($"炒锅{i}开始炒制菜品{res.GoodName}");
  2298. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.COOKING, DeviceId = i);
  2299. morkFs[i].GoodName = res.GoodName;
  2300. Coordinate myCoordinate = new Coordinate();
  2301. foreach (var potActions in res.StirPotActions)
  2302. {
  2303. if (TaskManage.GetInstance.IsComplete(String.Format(striConst, i.ToString(), nowStirFryGood[i].GoodName)))
  2304. {
  2305. return;
  2306. }
  2307. if (ret == false)
  2308. {
  2309. MessageLog.GetInstance.ShowEx("上一步操作未成功");
  2310. break;
  2311. }
  2312. ////调试大屏用代码
  2313. //Thread.Sleep(5000);
  2314. //更新
  2315. morkFs[i].UpdateProcess(potActions);
  2316. switch (potActions.Actions)
  2317. {
  2318. case nameof(StirFryPotActionEnum.加热开启):
  2319. StartFire(i);
  2320. MessageLog.GetInstance.Show(potActions.Actions);
  2321. break;
  2322. case nameof(StirFryPotActionEnum.设置加热挡位1):
  2323. morkFs[i].Fire = 1;
  2324. SetFire(new List<int> { 1 }, i);
  2325. MessageLog.GetInstance.Show(potActions.Actions);
  2326. break;
  2327. case nameof(StirFryPotActionEnum.设置加热挡位2):
  2328. morkFs[i].Fire = 2;
  2329. SetFire(new List<int> { 2 }, i);
  2330. MessageLog.GetInstance.Show(potActions.Actions);
  2331. break;
  2332. case nameof(StirFryPotActionEnum.设置加热挡位3):
  2333. morkFs[i].Fire = 3;
  2334. SetFire(new List<int> { 3 }, i);
  2335. MessageLog.GetInstance.Show(potActions.Actions);
  2336. break;
  2337. case nameof(StirFryPotActionEnum.设置加热挡位4):
  2338. morkFs[i].Fire = 4;
  2339. SetFire(new List<int> { 4 }, i);
  2340. MessageLog.GetInstance.Show(potActions.Actions);
  2341. break;
  2342. case nameof(StirFryPotActionEnum.设置加热挡位5):
  2343. morkFs[i].Fire = 5;
  2344. SetFire(new List<int> { 5 }, i);
  2345. MessageLog.GetInstance.Show(potActions.Actions);
  2346. break;
  2347. case nameof(StirFryPotActionEnum.设置加热挡位6):
  2348. morkFs[i].Fire = 6;
  2349. SetFire(new List<int> { 6 }, i);
  2350. MessageLog.GetInstance.Show(potActions.Actions);
  2351. break;
  2352. case nameof(StirFryPotActionEnum.设置加热挡位7):
  2353. morkFs[i].Fire = 7;
  2354. SetFire(new List<int> { 7 }, i);
  2355. MessageLog.GetInstance.Show(potActions.Actions);
  2356. break;
  2357. case nameof(StirFryPotActionEnum.设置加热挡位8):
  2358. morkFs[i].Fire = 8;
  2359. SetFire(new List<int> { 8 }, i);
  2360. MessageLog.GetInstance.Show(potActions.Actions);
  2361. break;
  2362. case nameof(StirFryPotActionEnum.设置加热挡位9):
  2363. morkFs[i].Fire = 9;
  2364. SetFire(new List<int> { 9 }, i);
  2365. MessageLog.GetInstance.Show(potActions.Actions);
  2366. break;
  2367. case nameof(StirFryPotActionEnum.设置加热挡位10):
  2368. morkFs[i].Fire = 10;
  2369. SetFire(new List<int> { 10 }, i);
  2370. MessageLog.GetInstance.Show(potActions.Actions);
  2371. break;
  2372. case nameof(StirFryPotActionEnum.停止加热):
  2373. StopFire(i);
  2374. MessageLog.GetInstance.Show(potActions.Actions);
  2375. break;
  2376. case nameof(StirFryPotActionEnum.加调料):
  2377. OutSeasonings(potActions.SeasoningLists, i);
  2378. MessageLog.GetInstance.Show(potActions.Actions);
  2379. break;
  2380. case nameof(StirFryPotActionEnum.取原料):
  2381. if (potActions.SeasoningLists[0].Loc == 1 ||
  2382. potActions.SeasoningLists[0].Loc == 9 ||
  2383. potActions.SeasoningLists[0].Loc == 10 ||
  2384. potActions.SeasoningLists[0].Loc == 18 ||
  2385. potActions.SeasoningLists[0].Loc == 19 ||
  2386. potActions.SeasoningLists[0].Loc == 27)
  2387. {
  2388. MessageLog.GetInstance.ShowEx("该取料位置禁止使用");
  2389. return;
  2390. }
  2391. //炒锅取菜状态置为未取到
  2392. morkFs[i].GetMaterialComplete = false;
  2393. if (isLocalFryingMode)
  2394. {
  2395. MaterialInfo materialInfo = new MaterialInfo();
  2396. materialInfo.Loc = potActions.SeasoningLists[0].Loc.ToString();
  2397. materialInfo.Id = "1232131";
  2398. materialInfo.Name = "本地炒制未知菜品";
  2399. materialOperationQuenes.Enqueue(new MaterialOperation { materialInfo = materialInfo, fryNum = i });
  2400. //testi++;
  2401. }
  2402. else
  2403. {
  2404. if (potActions.MaterialLists != null)
  2405. {
  2406. foreach (var item in potActions.MaterialLists)
  2407. {
  2408. //通过ID获取有效的菜品对象
  2409. MaterialInfo materialInfo = MaterialSurplusOperation.GetInstance.GetVailedMaterial(item.MaterialId);
  2410. if (materialInfo == null)
  2411. {
  2412. MessageLog.GetInstance.ShowEx($"炒锅{i}获取菜品[{item.MaterialId}]失败,库存不足");
  2413. continue;
  2414. }
  2415. materialOperationQuenes.Enqueue(new MaterialOperation { materialInfo = materialInfo, fryNum = i });
  2416. }
  2417. }
  2418. else
  2419. {
  2420. MessageLog.GetInstance.ShowEx($"炒锅{i}获取菜品失败,菜品列表为空");
  2421. }
  2422. }
  2423. MessageLog.GetInstance.Show(potActions.Actions);
  2424. break;
  2425. case nameof(StirFryPotActionEnum.开启搅拌):
  2426. StartStir(i);
  2427. MessageLog.GetInstance.Show(potActions.Actions);
  2428. break;
  2429. case nameof(StirFryPotActionEnum.设置搅拌挡位1):
  2430. SetStir(new List<int> { 1 }, i);
  2431. MessageLog.GetInstance.Show(potActions.Actions);
  2432. break;
  2433. case nameof(StirFryPotActionEnum.设置搅拌挡位2):
  2434. SetStir(new List<int> { 2 }, i);
  2435. MessageLog.GetInstance.Show(potActions.Actions);
  2436. break;
  2437. case nameof(StirFryPotActionEnum.设置搅拌挡位3):
  2438. SetStir(new List<int> { 3 }, i);
  2439. MessageLog.GetInstance.Show(potActions.Actions);
  2440. break;
  2441. case nameof(StirFryPotActionEnum.关闭搅拌):
  2442. StopStir(i);
  2443. MessageLog.GetInstance.Show(potActions.Actions);
  2444. break;
  2445. case nameof(StirFryPotActionEnum.出餐启动):
  2446. //停止搅拌
  2447. StopStir(i);
  2448. //回原点位
  2449. StirArmGoOrigin(i);
  2450. //出餐启动
  2451. OutMeal(i);
  2452. MessageLog.GetInstance.Show(potActions.Actions);
  2453. break;
  2454. case nameof(StirFryPotActionEnum.道菜启动):
  2455. ret = OutFood(i, out error, true);
  2456. if (ret == false)
  2457. {
  2458. alarmModel.Add(new BPA.Message.AlarmModel() { AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmMs = error });
  2459. }
  2460. break;
  2461. case nameof(StirFryPotActionEnum.炒制菜品):
  2462. Thread.Sleep(potActions.During * 1000);
  2463. break;
  2464. case nameof(StirFryPotActionEnum.搅拌臂原点位):
  2465. StirArmGoOrigin(i);
  2466. MessageLog.GetInstance.Show(potActions.Actions);
  2467. break;
  2468. case nameof(StirFryPotActionEnum.搅拌臂炒制位):
  2469. //出餐时,不允许搅拌臂去炒制位
  2470. lock (lock_OutMeal)
  2471. {
  2472. ret = StirArmGoWork(i, out error);
  2473. }
  2474. if (ret == false)
  2475. {
  2476. alarmModel.Add(new BPA.Message.AlarmModel() { AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmMs = error });
  2477. }
  2478. MessageLog.GetInstance.Show(potActions.Actions);
  2479. break;
  2480. case nameof(StirFryPotActionEnum.洗锅):
  2481. MessageLog.GetInstance.Show(potActions.Actions);
  2482. break;
  2483. default:
  2484. break;
  2485. }
  2486. }
  2487. Plc1Reset(i);//复位
  2488. Thread.Sleep(3000);
  2489. //回原点位
  2490. StirArmGoOrigin(i);
  2491. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.COMPLETED_COOK, DeviceId = i);
  2492. //同时只能允许有一个出餐
  2493. lock (lock_OutMeal)
  2494. {
  2495. //出餐启动
  2496. OutMeal(i);
  2497. //等待25s出餐完毕
  2498. Thread.Sleep(25000);
  2499. }
  2500. MessageLog.GetInstance.Show($"菜品{res.GoodName}完成");
  2501. //菜品统计数量+1
  2502. morkFs[i].orderCount++;
  2503. StatsModel statsModel = statsModels.FirstOrDefault(p => p.Name == res.GoodName);
  2504. if (statsModel != null)
  2505. {
  2506. statsModel.Count++;
  2507. }
  2508. else
  2509. {
  2510. statsModels.Add(new StatsModel() { Name = res.GoodName, Count = 0 });
  2511. }
  2512. }
  2513. catch (Exception ex)
  2514. {
  2515. nowStirFryGood[i] = null;
  2516. //炒完后出队列
  2517. morkFs[i].StirFryGoodsQuenes.TryDequeue(out var orderQueue);
  2518. morkFs[i].FryWorking = false;
  2519. //初始化大屏
  2520. morkFs[i].ScreenClear();
  2521. //异常菜品统计数量+1
  2522. morkFs[i].orderAbnormalCount++;
  2523. TaskManage.GetInstance.StopTask($"炒锅{i}{res.GoodName}炒制线程");
  2524. MessageLog.GetInstance.ShowEx($"炒锅{i}炒制菜品{res.GoodName}出错,错误信息:" + ex.Message);
  2525. }
  2526. finally
  2527. {
  2528. //正在炒制数量-1
  2529. FryingCount--;
  2530. nowStirFryGood[i] = null;
  2531. //炒完后出队列
  2532. morkFs[i].StirFryGoodsQuenes.TryDequeue(out var orderQueue);
  2533. morkFs[i].FryWorking = false;
  2534. //初始化大屏
  2535. morkFs[i].ScreenClear();
  2536. }
  2537. }), String.Format(striConst, i.ToString(), nowStirFryGood[i].GoodName)/*$"炒锅{i}炒制{res.GoodName}线程"*/, isRestart: true);
  2538. }
  2539. }
  2540. break;
  2541. }
  2542. }
  2543. }
  2544. }
  2545. /// <summary>
  2546. /// 更新菜品库的余量
  2547. /// </summary>
  2548. private void UpdateMaterialSurplus()
  2549. {
  2550. TaskManage.GetInstance.StartLong(new Action(() =>
  2551. {
  2552. List<MaterialInfo> listSurplus = MaterialSurplusOperation.GetInstance.materialSurplus.dicSurplus;
  2553. if (listSurplus == null)
  2554. {
  2555. return;
  2556. }
  2557. foreach (var surplus in listSurplus)
  2558. {
  2559. //找到已有的余量表
  2560. var batchingInfo = BatchingInfos.Find(o => o.BatchingId == surplus.Key);
  2561. //从当前下单
  2562. var stagingGoodBatching = stagingGoodBatchings.Find(o => o.BatchingId == surplus.Key);
  2563. //暂存的数量
  2564. int stagingCount = 0;
  2565. if (stagingGoodBatching != null)
  2566. {
  2567. stagingCount = stagingGoodBatching.BatchingCount;
  2568. }
  2569. if (batchingInfo == null)
  2570. {
  2571. //为空就新增
  2572. BatchingInfos.Add(new BatchingInfo() { BatchingCount = System.Convert.ToInt32(surplus.Qty) - stagingCount, BatchingLoc = surplus.Loc, BatchingId = surplus.Key });
  2573. }
  2574. else
  2575. {
  2576. batchingInfo.BatchingLoc = surplus.Loc;
  2577. batchingInfo.BatchingCount = System.Convert.ToInt32(surplus.Qty) - stagingCount;
  2578. }
  2579. }
  2580. Thread.Sleep(1000);
  2581. return;
  2582. }), "UpdateMaterialSurplus", true);
  2583. }
  2584. /// <summary>
  2585. /// 菜品库主流程
  2586. /// </summary>
  2587. private void MainProcessMaterial()
  2588. {
  2589. if (materialOperationQuenes.Count > 0)
  2590. {
  2591. //判断是否初始化与是否在工作中
  2592. if (ml_morkf.InitialComplete && !ml_morkf.MaterailIsWorking)
  2593. {
  2594. //待菜品库操作列出队列
  2595. if (materialOperationQuenes.TryDequeue(out var res))
  2596. {
  2597. Thread.Sleep(1000);
  2598. ml_morkf.MaterailIsWorking = true;
  2599. MessageLog.GetInstance.Show("开始操作菜品库");
  2600. //TaskManage.GetInstance.Start(new Action(()=>{
  2601. // GetMaterail(res.x_high, res.y, res.fryNum);
  2602. //}),"菜品库操作");
  2603. GetMaterailTest(res);
  2604. }
  2605. }
  2606. }
  2607. }
  2608. /// <summary>
  2609. /// 信号处理
  2610. /// </summary>
  2611. private void SingleProcess()
  2612. {
  2613. }
  2614. private void ScreenDataServer()
  2615. {
  2616. LocalMqtt.GetInstance.Init(ScreenDeviceType.小炒);
  2617. TaskManage.GetInstance.StartLong(new Action(() =>
  2618. {
  2619. //statsModels.Add(new StatsModel() { Name = "帝王蟹", Count = 666 });
  2620. ScreenModelMinWok maxWok = new ScreenModelMinWok
  2621. {
  2622. IsRun = IsHealth ? IsRun.运行 : IsRun.停止,//new Random().Next(0, 2) == 0 ? IsRun.运行 : IsRun.停止, //设备是否运行
  2623. WorkStatus_1 = morkFs[0].FryPot1_InitialComplete ? ((morkFs[0].Task != null) ? WorkStatus.工作 : WorkStatus.待机) : WorkStatus.停止,// (WorkStatus)new Random().Next(0, 3), //设备运行状态
  2624. WorkStatus_2 = morkFs[1].FryPot1_InitialComplete ? ((morkFs[1].Task != null) ? WorkStatus.工作 : WorkStatus.待机) : WorkStatus.停止,//(WorkStatus)new Random().Next(0, 3), //设备运行状态
  2625. RobotStatu = (WorkStatus)new Random().Next(0, 3), //机器人状态 待机 1 正常
  2626. Alarm = alarmModel, //告警集合
  2627. FailuresCount = alarmModel.Count, //故障数
  2628. StatsCount = statsModels, //统计菜品数量
  2629. MinWok_Dishes_1 = morkFs[0].GoodName,//"满汉全席",//当前炒制菜品名
  2630. MinWok_Dishes_2 = morkFs[1].GoodName,
  2631. MinWok_Task_1 = morkFs[0].Task,//当前任务
  2632. MinWok_Task_2 = morkFs[1].Task, //当前任务
  2633. //MinWok_Process_1 = new List<ProcessModel>() { new ProcessModel() { Id = 1, Name = "启动", Status = ProcessStatus.正在执行 }, new ProcessModel() { Id = 1, Name = "热油", Status = ProcessStatus.未执行 }, new ProcessModel() { Id = 1, Name = "炒制", Status = ProcessStatus.未执行 }, new ProcessModel() { Id = 1, Name = "出餐", Status = ProcessStatus.未执行 }, new ProcessModel() { Id = 1, Name = "结束", Status = ProcessStatus.未执行 } },
  2634. MinWok_Process_1 = morkFs[0].processModels, //炒锅当前任务流程
  2635. MinWok_Process_2 = morkFs[1].processModels, //炒锅当前任务流程
  2636. MinWok_HeatGear_1 = morkFs[0].FireNow, //炒锅加热档位
  2637. MinWok_HeatGear_2 = morkFs[1].FireNow, //炒锅加热档位
  2638. MinWok_Temp_1 = morkFs[0].TempNow, //炒锅1锅底温度
  2639. MinWok_Temp_2 = morkFs[1].TempNow, //炒锅1锅底温度
  2640. MinWok_StirGear_1 = morkFs[0].StirNow, //炒锅搅拌档位
  2641. MinWok_StirGear_2 = morkFs[1].StirNow, //炒锅搅拌档位
  2642. MinWok_OrderCount_1 = morkFs[0].orderCount, //订单数量
  2643. MinWok_OrderCount_2 = morkFs[1].orderCount, //订单数量
  2644. MinWok_ErrorOrderCount_1 = morkFs[0].orderAbnormalCount, //异常订单数量
  2645. MinWok_ErrorOrderCount_2 = morkFs[1].orderAbnormalCount, //异常订单数量
  2646. };
  2647. LocalMqtt.GetInstance.Publish(maxWok);
  2648. Thread.Sleep(1000);
  2649. }), "大屏数据上报", true);
  2650. }
  2651. public override void SimOrder()
  2652. {
  2653. }
  2654. /// <summary>
  2655. /// 菜品编号转换为坐标
  2656. /// </summary>
  2657. /// <param name="no"></param>
  2658. /// <param name="coordinate"></param>
  2659. /// <returns></returns>
  2660. public bool NoMaterial2Coordinate(string no, out Coordinate coordinate)
  2661. {
  2662. //默认返回0,0
  2663. coordinate = new Coordinate();
  2664. coordinate.X = 0;
  2665. coordinate.Y = 0;
  2666. try
  2667. {
  2668. if (MaterialCoordinate.GetInstance.dicNoMaterialCoordinate.ContainsKey(no))
  2669. {
  2670. coordinate = MaterialCoordinate.GetInstance.dicNoMaterialCoordinate[no];
  2671. return true;
  2672. }
  2673. else
  2674. {
  2675. return false;
  2676. }
  2677. }
  2678. catch (Exception ex)
  2679. {
  2680. return false;
  2681. }
  2682. finally
  2683. {
  2684. }
  2685. }
  2686. public enum Laser2CoordinateState
  2687. {
  2688. MaterialOverdo = 0,//菜品过量
  2689. MaterialNormal = 1,//菜品正常
  2690. MaterialEmpty = 2,//菜品为空
  2691. MaterialUnkown = 999,//菜品未知错误
  2692. }
  2693. }
  2694. }