终端一体化运控平台
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

3028 líneas
118 KiB

  1. using BPA.Message;
  2. using System;
  3. using BPA.Message.Enum;
  4. using BPASmartClient.Device;
  5. using BPASmartClient.EventBus;
  6. using BPASmartClient.Helper;
  7. using BPASmartClient.Message;
  8. using BPASmartClient.Model;
  9. using BPASmartClient.Model.PLC;
  10. using BPA.Models;
  11. using static BPASmartClient.EventBus.EventBus;
  12. using BPASmartClient.Model.小炒机;
  13. using BPASmartClient.MorkF.Model;
  14. using System.Text;
  15. using System.Collections.Concurrent;
  16. using System.Windows.Documents;
  17. using BPASmartClient.Business;
  18. using Microsoft.CodeAnalysis;
  19. using BPASmartClient.MorkF.ViewModel;
  20. using BPASmartClient.ViewModel;
  21. using System.Windows;
  22. namespace BPASmartClient.MorkF
  23. {
  24. public class Control_MorkF : BaseDevice
  25. {
  26. #region 常数定义
  27. /// <summary>
  28. /// while循环最大sleep次数
  29. /// </summary>
  30. private const int sleepCount = 20;
  31. /// <summary>
  32. /// while循环每次sleep时间
  33. /// </summary>
  34. private const int sleepTime = 500;
  35. /// <summary>
  36. /// 菜品库while循环最大sleep次数
  37. /// </summary>
  38. private const int materialSleepCount = 600;
  39. /// <summary>
  40. /// 菜品库while循环每次sleep时间
  41. /// </summary>
  42. private const int materialSleepTime = 100;
  43. /// <summary>
  44. /// 初始化炒锅数量
  45. /// </summary>
  46. private int count = 2;
  47. /// <summary>
  48. /// 菜品盒下移高度,相对于坐标系
  49. /// </summary>
  50. //private const int materialBoxHigh = 4080;
  51. ////菜品库出餐高度
  52. //private const int materialHigh = 33000;
  53. ////传感器到菜品库的高度(坐标系)
  54. //private const int materialLaserHigh = 34500;
  55. /// <summary>
  56. /// 菜品盒坐标系高度
  57. /// </summary>
  58. private const int materialBoxHeight = 9700;
  59. //传感器1到菜品库的高度(厘米)
  60. //private const int materialLaserHighCM_1 = 22;
  61. ////传感器2到菜品库的高度(厘米)
  62. //private const int materialLaserHighCM_2 = 27;
  63. ////传感器3到菜品库的高度(厘米)
  64. //private const int materialLaserHighCM_3 = 31;
  65. /// <summary>
  66. /// 传感器到隔板的距离(坐标系)
  67. /// </summary>
  68. private const int clapboardLaserHigh = 10000;
  69. ////炒锅1倒菜的xy坐标
  70. //private const int materialPutPositionXFry1 = 70000;
  71. //private const int materialPutPositionYFry1 = 40000;
  72. ////炒锅2倒菜的xy坐标
  73. //private const int materialPutPositionXFry2 = 70000;
  74. //private const int materialPutPositionYFry2 = 40000;
  75. //菜品库机械爪放置菜品距离
  76. private const int materialToFryDistance = 10000;
  77. //当前炒锅,默认为1号炒锅
  78. private int fryIndex = 0;
  79. #endregion
  80. public override DeviceClientType DeviceType => DeviceClientType.MORKCS;
  81. public AutoResetEvent minorReset = new AutoResetEvent(false);
  82. public AutoResetEvent mainReset = new AutoResetEvent(false);
  83. /// <summary>
  84. /// 等待炒制数量
  85. /// </summary>
  86. private int StagingFryCount { get; set; }
  87. /// <summary>
  88. /// 正在炒制数量
  89. /// </summary>
  90. private int FryingCount { get; set; }
  91. /// <summary>
  92. /// 炒锅编号与炒锅实例
  93. /// </summary>
  94. Dictionary<int, GVL_MorkF> morkFs = new Dictionary<int, GVL_MorkF>();//全局对象声明
  95. /// <summary>
  96. /// 菜品库对象
  97. /// </summary>
  98. ML_MorkF ml_morkf = new ML_MorkF();
  99. /// <summary>
  100. /// 小炒菜单集合
  101. /// </summary>f
  102. public static List<StirFryGoods> LocalstirFryGoods = new List<StirFryGoods>();
  103. /// <summary>
  104. /// 待炒小炒队列
  105. /// </summary>
  106. private ConcurrentQueue<OrderLocInfo> StirFryGoodsQuenes = new ConcurrentQueue<OrderLocInfo>();
  107. /// <summary>
  108. /// 炒锅炒制线程名称
  109. /// </summary>
  110. private const String striConst = "炒锅{0}炒制{1}线程";
  111. /// <summary>
  112. /// 当前炒制菜品
  113. /// </summary>
  114. private OrderLocInfo[] nowStirFryGood = new OrderLocInfo[2];
  115. /// <summary>
  116. /// 待取菜队列
  117. /// </summary>
  118. private ConcurrentQueue<MaterialOperation> materialOperationQuenes = new ConcurrentQueue<MaterialOperation>();
  119. List<int> resultorder = new List<int>();//调试变量
  120. /// <summary>
  121. /// 告警列表
  122. /// </summary>
  123. private List<BPA.Message.AlarmModel> alarmModel = new List<BPA.Message.AlarmModel>();
  124. /// <summary>
  125. ///
  126. /// </summary>
  127. private List<StatsModel> statsModels = new List<StatsModel>();
  128. /// <summary>
  129. /// 暂存使用菜品量
  130. /// </summary>
  131. private List<GoodBatchings> stagingGoodBatchings = new List<GoodBatchings>();
  132. /// <summary>
  133. /// 是否为本地炒菜模式,默认为联网的
  134. /// </summary>
  135. private bool isLocalFryingMode { get; set; } = true;
  136. /// <summary>
  137. /// 入口
  138. /// </summary>
  139. public override void DoMain()
  140. {
  141. IsHealth = true;
  142. for (int i = 0; i < count; i++)
  143. {
  144. morkFs.Add(i, new GVL_MorkF());
  145. }
  146. DataParse();//数据解析
  147. CommandRegist();//调试
  148. ServerInit();
  149. DeviceProcessLogShow("MORKF 设备初始化完成");
  150. ///初始化菜品库
  151. //FoodLibInit();
  152. Task2ReadMaterialData();
  153. ScreenDataServer();
  154. Json<MaterialAndFryingTime>.Read();
  155. //更新菜品余量
  156. UpdateMaterialSurplus();
  157. //读取坐标系
  158. MaterialCoordinate materialCoordinate = ReadMaterialCoordinate();
  159. if(materialCoordinate != null)
  160. {
  161. MaterialCoordinate.GetInstance().dicNoMaterialCoordinate = materialCoordinate.dicNoMaterialCoordinate;
  162. MaterialCoordinate.GetInstance().MLCoordinateList = materialCoordinate.MLCoordinateList;
  163. MaterialCoordinate.GetInstance().distance_1 = materialCoordinate.distance_1;
  164. MaterialCoordinate.GetInstance().distance_2 = materialCoordinate.distance_2;
  165. MaterialCoordinate.GetInstance().distance_3 = materialCoordinate.distance_3;
  166. MaterialCoordinate.GetInstance().frying1 = materialCoordinate.frying1;
  167. MaterialCoordinate.GetInstance().frying2 = materialCoordinate.frying2;
  168. MaterialCoordinate.GetInstance().materialHeight = materialCoordinate.materialHeight;
  169. MaterialCoordinate.GetInstance().MaterialOneX = materialCoordinate.MaterialOneX;
  170. MaterialCoordinate.GetInstance().MaterialTwoX = materialCoordinate.MaterialTwoX;
  171. MaterialCoordinate.GetInstance().MaterialThreeX = materialCoordinate.MaterialThreeX;
  172. }
  173. ////菜品库编号与坐标系对象存储
  174. //SaveMaterialCoordinate();
  175. }
  176. /// <summary>
  177. /// 主任务
  178. /// </summary>
  179. public override void MainTask()
  180. {
  181. //炒锅炒制线程
  182. MainProcessExcute();
  183. //菜品库操作线程
  184. MainProcessMaterial();
  185. //MinorProcessExcute();
  186. //SingleProcess();
  187. }
  188. private static object saveMaterialLock = new object();
  189. private void SaveMaterialData()
  190. {
  191. lock (saveMaterialLock)
  192. {
  193. Json<MaterialSurplus>.Data = MaterialSurplusOperation.GetInstance().materialSurplus;
  194. Json<MaterialSurplus>.Save();
  195. }
  196. }
  197. private static object saveMaterialCoordinateLock = new object();
  198. /// <summary>
  199. /// 保存当前的坐标系
  200. /// </summary>
  201. public void SaveMaterialCoordinate()
  202. {
  203. lock (saveMaterialLock)
  204. {
  205. Json<MaterialCoordinate>.Data = MaterialCoordinate.GetInstance();
  206. Json<MaterialCoordinate>.Save();
  207. }
  208. }
  209. /// <summary>
  210. /// 读取坐标系
  211. /// </summary>
  212. /// <returns></returns>
  213. private MaterialCoordinate ReadMaterialCoordinate()
  214. {
  215. try
  216. {
  217. lock (saveMaterialLock)
  218. {
  219. Json<MaterialCoordinate>.Read();
  220. MaterialCoordinate materialCoordinate = Json<MaterialCoordinate>.Data;
  221. return materialCoordinate;
  222. }
  223. }
  224. catch(Exception ex)
  225. {
  226. return null;
  227. }
  228. }
  229. private void Task2ReadMaterialData()
  230. {
  231. ThreadManage.GetInstance().StartLong(new Action(() => {
  232. //获取定位到达状态
  233. GetStatus("M10.0", new Action<object>((objects) =>
  234. {
  235. if (objects is bool[] bools)
  236. {
  237. //ml_morkf.ArriveComplete = bools[i];
  238. //小炒定点到达上升沿信号捕获
  239. if (RTrig.GetInstance("SmartArriveComplete").Start(bools[0]))
  240. {
  241. if (isInitialArrive == false)
  242. {
  243. //MessageLog.GetInstance.Show("到达上升沿为true,isInitialArrive is false");
  244. isInitialArrive = true;
  245. }
  246. else
  247. {
  248. //MessageLog.GetInstance.Show("到达上升沿为true");
  249. ml_morkf.ArriveComplete = true;
  250. isInitialArrive = true;
  251. }
  252. }
  253. }
  254. }), 2);
  255. }), "ReadMaterialSmartArriveCompleteData", true);
  256. ThreadManage.GetInstance().StartLong(new Action(() => {
  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(StartOrder, "StartOrder");
  352. ActionManage.GetInstance.Register(StartOrderMain, "开始下单");
  353. ActionManage.GetInstance.Register(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. ThreadManage.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. ThreadManage.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. ThreadManage.GetInstance().Start(new Action(() =>
  387. {
  388. Electromagnetism(o);
  389. }), "Electromagnetism");
  390. }), "Electromagnetism");
  391. ActionManage.GetInstance.Register(new Action(() =>
  392. {
  393. ThreadManage.GetInstance().Start(new Action(() =>
  394. {
  395. PawToPoint1();
  396. }), "PawToPoint1");
  397. }), "PawToPoint1");
  398. ActionManage.GetInstance.Register(new Action(() =>
  399. {
  400. ThreadManage.GetInstance().Start(new Action(() =>
  401. {
  402. PawToPoint2();
  403. }), "PawToPoint2");
  404. }), "PawToPoint2");
  405. ActionManage.GetInstance.Register(new Action(() =>
  406. {
  407. ThreadManage.GetInstance().Start(new Action(() =>
  408. {
  409. PawToPoint3();
  410. }), "PawToPoint3");
  411. }), "PawToPoint3");
  412. ActionManage.GetInstance.Register(new Action(() =>
  413. {
  414. ThreadManage.GetInstance().Start(new Action(() =>
  415. {
  416. GetDistance_1();
  417. }), "GetDistance_1");
  418. }), "GetDistance_1");
  419. ActionManage.GetInstance.Register(new Action(() =>
  420. {
  421. ThreadManage.GetInstance().Start(new Action(() =>
  422. {
  423. GetDistance_2();
  424. }), "GetDistance_2");
  425. }), "GetDistance_2");
  426. ActionManage.GetInstance.Register(new Action(() =>
  427. {
  428. ThreadManage.GetInstance().Start(new Action(() =>
  429. {
  430. GetDistance_3();
  431. }), "GetDistance_3");
  432. }), "GetDistance_3");
  433. ActionManage.GetInstance.Register(new Action(() =>
  434. {
  435. ThreadManage.GetInstance().Start(new Action(() =>
  436. {
  437. PawExtend();
  438. }), "PawTurnFront");
  439. }), "PawTurnFront");
  440. ActionManage.GetInstance.Register(new Action(() =>
  441. {
  442. ThreadManage.GetInstance().Start(new Action(() =>
  443. {
  444. PawShrink();
  445. }), "PawTurnBack");
  446. }), "PawTurnBack");
  447. ActionManage.GetInstance.Register(new Action<object>((list) =>
  448. {
  449. ThreadManage.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. ThreadManage.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. ThreadManage.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("CalibrationCallBack", new List<string> { No });//设定机械臂当前位置
  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. ThreadManage.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. ThreadManage.GetInstance().Start(new Action(() =>
  537. {
  538. Plc1Reset(fryIndex);
  539. }), "Plc1Reset");
  540. }), "Plc1Reset");
  541. ActionManage.GetInstance.Register(new Action(() =>
  542. {
  543. ThreadManage.GetInstance().Start(new Action(() =>
  544. {
  545. AddOil();
  546. }), "AddOil");
  547. }), "AddOil");
  548. ActionManage.GetInstance.Register(new Action(() =>
  549. {
  550. ThreadManage.GetInstance().Start(new Action(() =>
  551. {
  552. StartFire(fryIndex);
  553. }), "StartFire");
  554. }), "StartFire");
  555. ActionManage.GetInstance.Register(new Action(() =>
  556. {
  557. ThreadManage.GetInstance().Start(new Action(() =>
  558. {
  559. StopFire(fryIndex);
  560. }), "StopFire");
  561. }), "StopFire");
  562. ActionManage.GetInstance.Register(new Action(() =>
  563. {
  564. ThreadManage.GetInstance().Start(new Action(() =>
  565. {
  566. StartStir(fryIndex);
  567. }), "StartStir");
  568. }), "StartStir");
  569. ActionManage.GetInstance.Register(new Action(() =>
  570. {
  571. ThreadManage.GetInstance().Start(new Action(() =>
  572. {
  573. StopStir(fryIndex);
  574. }), "StopStir");
  575. }), "StopStir");
  576. ActionManage.GetInstance.Register(new Action(() =>
  577. {
  578. ThreadManage.GetInstance().Start(new Action(() =>
  579. {
  580. MagnetOn(fryIndex);
  581. }), "MagnetOn");
  582. }), "MagnetOn");
  583. ActionManage.GetInstance.Register(new Action(() =>
  584. {
  585. ThreadManage.GetInstance().Start(new Action(() =>
  586. {
  587. MagnetOff(fryIndex);
  588. }), "MagnetOff");
  589. }), "MagnetOff");
  590. ActionManage.GetInstance.Register(new Action(() =>
  591. {
  592. ThreadManage.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. ThreadManage.GetInstance().Start(new Action(() =>
  601. {
  602. StirArmGoOrigin(fryIndex);
  603. }), "StirArmGoOrigin");
  604. }), "StirArmGoOrigin");
  605. ActionManage.GetInstance.Register(new Action(() =>
  606. {
  607. ThreadManage.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. ThreadManage.GetInstance().Start(new Action(() =>
  616. {
  617. HBOTGoWork(fryIndex);
  618. }), "HBOTGoWork");
  619. }), "HBOTGoWork");
  620. ActionManage.GetInstance.Register(new Action(() =>
  621. {
  622. ThreadManage.GetInstance().Start(new Action(() =>
  623. {
  624. OutMeal(fryIndex);
  625. }), "OutMeal");
  626. }), "OutMeal");
  627. ActionManage.GetInstance.Register(new Action<object>((o) =>
  628. {
  629. ThreadManage.GetInstance().Start(new Action(() =>
  630. {
  631. SetFire(o, fryIndex);
  632. }), "SetFire");
  633. }), "SetFire");
  634. ActionManage.GetInstance.Register(new Action<object>((o) =>
  635. {
  636. ThreadManage.GetInstance().Start(new Action(() =>
  637. {
  638. SetFry(o);
  639. }), "SetFry");
  640. }), "SetFry");
  641. ActionManage.GetInstance.Register(new Action<object>((o) =>
  642. {
  643. ThreadManage.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. ThreadManage.GetInstance().StopTask(String.Format(striConst, fryIndex.ToString(), nowStirFryGood[fryIndex].GoodName), new Action(() => { Plc1Reset(fryIndex); }));
  751. }
  752. else
  753. {
  754. //根据炒锅编号停止炒制线程
  755. ThreadManage.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("GetDistanceCallBack", new List<string> { "1",ml_morkf.LaserDistance.ToString() });//通知获取测距界面
  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("GetDistanceCallBack", new List<string> { "2", ml_morkf.LaserDistance.ToString() });//通知获取测距界面
  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("GetDistanceCallBack", new List<string> { "3", ml_morkf.LaserDistance.ToString() });//通知获取测距界面
  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. //ThreadManage.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. ThreadManage.GetInstance().Start(new Action(() => {
  1605. bool ret = false;
  1606. try
  1607. {
  1608. Coordinate myCoordinate = new Coordinate();
  1609. //获取坐标,根据菜品的位置信息
  1610. if (!NoMaterial2Coordinate(materialOperation.materialInfo.Loc, out myCoordinate))
  1611. {
  1612. MessageLog.GetInstance.ShowEx($"炒锅{materialOperation.fryNum}获取菜品[{materialOperation.materialInfo.Name}]失败,找不到对应位置");
  1613. return;
  1614. }
  1615. //取菜操作
  1616. ret = GetMaterail(myCoordinate.X, myCoordinate.Y, materialOperation.fryNum);
  1617. }
  1618. catch (Exception ex)
  1619. {
  1620. ret = false;
  1621. }
  1622. finally
  1623. {
  1624. //本地炒制不进行菜品数量检查
  1625. if(!isLocalFryingMode)
  1626. {
  1627. GoodBatchings goodBatchings = stagingGoodBatchings.Find(o => o.BatchingId == materialOperation.materialInfo.Key);
  1628. if (ret == true)
  1629. {
  1630. if (true)
  1631. {
  1632. if (goodBatchings != null)
  1633. {
  1634. //指定位置菜品减一
  1635. MaterialSurplusOperation.GetInstance().ReduceSurplus(materialOperation.materialInfo.Loc, goodBatchings.BatchingCount);
  1636. }
  1637. }
  1638. else
  1639. {
  1640. //指定位置菜品减一
  1641. MaterialSurplusOperation.GetInstance().ReduceSurplus(materialOperation.materialInfo.Loc);
  1642. }
  1643. SaveMaterialData();
  1644. }
  1645. //移出占用菜品
  1646. stagingGoodBatchings.Remove(goodBatchings);
  1647. }
  1648. ml_morkf.MaterailIsWorking = false;
  1649. }
  1650. }), $"菜品库操作");
  1651. }
  1652. #endregion
  1653. #region 炒锅PLC基本操作方法
  1654. /// <summary>
  1655. /// 炒锅写寄存器方法,num为炒锅对应编号,从0开始
  1656. /// </summary>
  1657. /// <param name="address">寄存器地址</param>
  1658. /// <param name="value">值</param>
  1659. /// <param name="num">炒锅编号</param>
  1660. private void FirePot_Write(string address, object value, int num)
  1661. {
  1662. WriteControlExact(address, value, num);
  1663. }
  1664. /// <summary>
  1665. /// 出调料
  1666. /// </summary>
  1667. /// <param name="o"></param>
  1668. public void OutSeasoning(object o, int num)
  1669. {
  1670. if (o == null) return;
  1671. if (o is List<int> ints && ints.Count == 2 && morkFs.ContainsKey(num))
  1672. {
  1673. FirePot_Write(morkFs[num].PassWayValue[ints[0]], (ushort)ints[1], num);//写入通道值
  1674. Thread.Sleep(400);
  1675. FirePot_Write(morkFs[num].StartPassWay[ints[0]], true, num);//开启通道
  1676. Thread.Sleep(400);
  1677. FirePot_Write(morkFs[num].StartPassWay[ints[0]], false, num);//开启通道
  1678. }
  1679. }
  1680. /// <summary>
  1681. /// 出多个调料
  1682. /// </summary>
  1683. public void OutSeasonings(List<SeasoningList> seasoningLists, int num)
  1684. {
  1685. //防止越界
  1686. if (!morkFs.ContainsKey(num))
  1687. {
  1688. return;
  1689. }
  1690. foreach (SeasoningList seasoning in seasoningLists)
  1691. {
  1692. FirePot_Write(morkFs[num].PassWayValue[seasoning.Loc], (ushort)seasoning.Qty, num);
  1693. Thread.Sleep(300);
  1694. }
  1695. foreach (SeasoningList seasoning in seasoningLists)
  1696. {
  1697. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], true, num);
  1698. Thread.Sleep(300);
  1699. }
  1700. foreach (SeasoningList seasoning in seasoningLists)
  1701. {
  1702. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], false, num);
  1703. Thread.Sleep(300);
  1704. }
  1705. foreach (SeasoningList seasoning in seasoningLists)
  1706. {
  1707. FirePot_Write(morkFs[num].StartPassWay[seasoning.Loc], false, num);
  1708. Thread.Sleep(300);
  1709. }
  1710. }
  1711. /// <summary>
  1712. /// 复位
  1713. /// </summary>
  1714. public void Plc1Reset(int num)
  1715. {
  1716. ThreadManage.GetInstance().Start(new Action(() =>
  1717. {
  1718. StopFire(num);
  1719. Thread.Sleep(200);
  1720. StopStir(num);
  1721. Thread.Sleep(200);
  1722. FirePot_Write("LB5", false, num);
  1723. Thread.Sleep(200);
  1724. FirePot_Write("LB3", false, num);
  1725. Thread.Sleep(200);
  1726. FirePot_Write("LB6", false, num);
  1727. Thread.Sleep(200);
  1728. FirePot_Write("LB7", false, num);
  1729. Thread.Sleep(200);
  1730. FirePot_Write("LB4", false, num);
  1731. Thread.Sleep(200);
  1732. FirePot_Write("LB53", false, num);
  1733. if (morkFs.ContainsKey(num))
  1734. {
  1735. foreach (var item in morkFs[num].StartPassWay.Values)
  1736. {
  1737. Thread.Sleep(200);
  1738. FirePot_Write(item, false, num);
  1739. }
  1740. }
  1741. }), $"炒锅{num}初始化");
  1742. }
  1743. /// <summary>
  1744. /// 炒锅初始化
  1745. /// </summary>
  1746. public void PLCInite()
  1747. {
  1748. for (int i = 0; i < morkFs.Count; i++)
  1749. {
  1750. FirePot_Write("LB0", true, i);
  1751. for (int j = 0; j < sleepCount && !morkFs[i].FryPot1_InitialComplete; j++)
  1752. {
  1753. Thread.Sleep(sleepTime);
  1754. if (j >= sleepCount - 1)
  1755. {
  1756. MessageLog.GetInstance.ShowEx($"炒锅{j}初始化超时");
  1757. }
  1758. }
  1759. FirePot_Write("LB0", false, i);
  1760. }
  1761. }
  1762. //加油
  1763. public void AddOil()
  1764. {
  1765. }
  1766. //加热启动
  1767. public void StartFire(int num)
  1768. {
  1769. FirePot_Write("LB1", true, num);
  1770. Thread.Sleep(200);
  1771. }
  1772. //加热停止
  1773. public void StopFire(int num)
  1774. {
  1775. FirePot_Write("LB1", false, num);
  1776. Thread.Sleep(200);
  1777. }
  1778. //搅拌启动
  1779. public void StartStir(int num)
  1780. {
  1781. FirePot_Write("LB2", true, num);
  1782. Thread.Sleep(200);
  1783. }
  1784. //搅拌启停止
  1785. public void StopStir(int num)
  1786. {
  1787. FirePot_Write("LB2", false, num);
  1788. Thread.Sleep(200);
  1789. }
  1790. //倒菜
  1791. public bool OutFood(int num,out string error,bool isMaterial = false)
  1792. {
  1793. bool ret = true;
  1794. error = string.Empty;
  1795. if (!morkFs.ContainsKey(num))
  1796. {
  1797. error = $"编号为{num}的炒锅无法找到";
  1798. return false;
  1799. }
  1800. int i = 0;
  1801. MessageLog.GetInstance.Show("倒菜启动开始");
  1802. if (isMaterial)
  1803. {
  1804. //判断是否完成取菜
  1805. for (i = 0; i < materialSleepCount*2 && !morkFs[num].GetMaterialComplete; i++)
  1806. {
  1807. if (i == 10)
  1808. {
  1809. //停止搅拌
  1810. //StopStir(num);
  1811. //搅拌设置为1档
  1812. SetStir(new List<int> { 1 }, i);
  1813. //火力设置为2档
  1814. SetFire(new List<int> { 3 }, num);
  1815. }
  1816. Thread.Sleep(materialSleepTime);
  1817. if (i >= materialSleepCount * 2 - 1)
  1818. {
  1819. error = $"炒锅{num}倒菜超时:未能等到取菜完成,请检查菜品库是否正常运行";
  1820. MessageLog.GetInstance.ShowEx($"炒锅{num}倒菜超时:未能等到取菜完成");
  1821. ret &= false;
  1822. }
  1823. }
  1824. if (i > 9)
  1825. {
  1826. //开启搅拌
  1827. //StartStir(num);
  1828. //搅拌设置为原本搅拌档位
  1829. SetStir(new List<int> { morkFs[num].Stir }, i);
  1830. //火力设置回原本火力
  1831. SetFire(new List<int> { morkFs[num].Fire }, num);
  1832. }
  1833. }
  1834. if(!ret)
  1835. {
  1836. return ret;
  1837. }
  1838. FirePot_Write("LB3", true, num);
  1839. //MessageLog.GetInstance.Show("倒菜启动");
  1840. Thread.Sleep(500);
  1841. for (i = 0; i < materialSleepCount && !morkFs[num].FryPot1_MaterialIntoPot; i++)
  1842. {
  1843. Thread.Sleep(materialSleepTime);
  1844. if (i >= materialSleepCount - 1)
  1845. {
  1846. error = $"炒锅{num}倒菜超时,请联系相关工作人员";
  1847. MessageLog.GetInstance.ShowEx($"炒锅{num}倒菜超时");
  1848. ret &= false;
  1849. }
  1850. }
  1851. FirePot_Write("LB3", false, num);
  1852. Thread.Sleep(200);
  1853. //MessageLog.GetInstance.Show("倒菜完成");
  1854. morkFs[num].GetMaterialComplete = false;
  1855. return ret;
  1856. }
  1857. //搅拌臂去原点位
  1858. public void StirArmGoOrigin(int num)
  1859. {
  1860. if (!morkFs.ContainsKey(num))
  1861. {
  1862. return;
  1863. }
  1864. FirePot_Write("LB5", true, num);
  1865. //MessageLog.GetInstance.Show("搅拌臂去原点位");
  1866. for (int i = 0; i < sleepCount && !morkFs[num].ArmOnOrigin; i++)
  1867. {
  1868. Thread.Sleep(sleepTime);
  1869. if (i >= sleepCount - 1)
  1870. {
  1871. MessageLog.GetInstance.ShowEx($"炒锅{num}搅拌臂去原点位超时");
  1872. }
  1873. }
  1874. FirePot_Write("LB5", false, num);
  1875. Thread.Sleep(200);
  1876. //MessageLog.GetInstance.Show("搅拌臂到达原点位");
  1877. }
  1878. //搅拌臂去炒制位
  1879. public bool StirArmGoWork(int num,out string error)
  1880. {
  1881. error = string.Empty;
  1882. bool ret = true;
  1883. if (!morkFs.ContainsKey(num))
  1884. {
  1885. error = $"编号为{num}的炒锅无法找到";
  1886. return false;
  1887. }
  1888. if (!morkFs[num].ArmOnWorking/* && morkFs[num].PotOnOrigin*/)
  1889. {
  1890. FirePot_Write("LB6", true, num);
  1891. //MessageLog.GetInstance.Show("搅拌臂去工作位");
  1892. for (int i = 0; i < sleepCount && !morkFs[num].ArmOnWorking; i++)
  1893. {
  1894. Thread.Sleep(sleepTime);
  1895. if (i >= sleepCount - 1)
  1896. {
  1897. error = $"炒锅{num}搅拌臂去炒制位超时";
  1898. MessageLog.GetInstance.ShowEx($"炒锅{num}搅拌臂去炒制位超时");
  1899. ret &= false;
  1900. }
  1901. }
  1902. //while (!morkFs[num].ArmOnWorking)
  1903. //{
  1904. // Thread.Sleep(200);
  1905. //}
  1906. FirePot_Write("LB6", false, num);
  1907. Thread.Sleep(200);
  1908. //MessageLog.GetInstance.Show("搅拌臂到达工作位");
  1909. return ret;
  1910. }
  1911. return true;
  1912. }
  1913. //HBOT放盒子到位
  1914. public void HBOTGoWork(int num)
  1915. {
  1916. FirePot_Write("LB7", true, num);
  1917. Thread.Sleep(400);
  1918. FirePot_Write("LB7", false, num);
  1919. }
  1920. //出餐启动
  1921. public void OutMeal(int num)
  1922. {
  1923. if (!morkFs[num].ArmOnOrigin /*&& morkFs[num].PotOnOrigin*/)
  1924. {
  1925. MessageLog.GetInstance.ShowEx("搅拌臂不在原点位,无法完成出餐");
  1926. return;
  1927. }
  1928. FirePot_Write("LB4", true, num);
  1929. Thread.Sleep(500);
  1930. FirePot_Write("LB4", false, num);
  1931. }
  1932. //加热挡位设定
  1933. public void SetFire(object o, int num)
  1934. {
  1935. if (o == null) return;
  1936. if (o is List<int> ints && ints.Count == 1)
  1937. {
  1938. FirePot_Write("LW14", (ushort)ints[0], num);
  1939. Thread.Sleep(200);
  1940. }
  1941. }
  1942. public void SetFry(object o)
  1943. {
  1944. if (o == null) return;
  1945. if (o is List<int> ints && ints.Count == 1)
  1946. {
  1947. fryIndex = ints[0] - 1;
  1948. }
  1949. }
  1950. /// <summary>
  1951. /// 搅拌挡位设定
  1952. /// </summary>
  1953. /// <param name="o"></param>
  1954. public void SetStir(object o, int num)
  1955. {
  1956. if (o == null) return;
  1957. if (o is List<int> ints && ints.Count == 1)
  1958. {
  1959. FirePot_Write("LW15", (ushort)ints[0], num);
  1960. Thread.Sleep(200);
  1961. }
  1962. }
  1963. /// <summary>
  1964. /// 开启磁吸
  1965. /// </summary>
  1966. /// <param name="num"></param>
  1967. public void MagnetOn(int num)
  1968. {
  1969. FirePot_Write("LB8", false, num);
  1970. Thread.Sleep(200);
  1971. }
  1972. /// <summary>
  1973. /// 关闭磁吸
  1974. /// </summary>
  1975. /// <param name="num"></param>
  1976. public void MagnetOff(int num)
  1977. {
  1978. FirePot_Write("LB8", true, num);
  1979. Thread.Sleep(200);
  1980. }
  1981. #endregion
  1982. bool isInitialArrive = false;
  1983. bool isInitialPaw = false;
  1984. #region 联网交互
  1985. private void ServerInit()
  1986. {
  1987. //物料信息
  1988. EventBus.EventBus.GetInstance().Subscribe<MaterialDeliveryEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  1989. {
  1990. if (@event == null) return;
  1991. if (@event is MaterialDeliveryEvent material)
  1992. {
  1993. orderMaterialDelivery = material.orderMaterialDelivery;
  1994. }
  1995. });
  1996. //配方数据信息
  1997. EventBus.EventBus.GetInstance().Subscribe<RecipeBomEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack)
  1998. {
  1999. if (@event == null) return;
  2000. if (@event is RecipeBomEvent recipe)
  2001. {
  2002. recipeBoms = recipe.recipeBoms;
  2003. }
  2004. });
  2005. //小炒流程信息
  2006. EventBus.EventBus.GetInstance().Subscribe<StirFryGoodsEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callback)
  2007. {
  2008. if (@event == null) return;
  2009. if (@event is StirFryGoodsEvent stirFry)
  2010. {
  2011. if(stirFry.stirFrymessage != null)
  2012. {
  2013. if (stirFry.stirFrymessage.stirFryGoods.Count > 0)
  2014. {
  2015. foreach (var item in stirFry.stirFrymessage.stirFryGoods)
  2016. {
  2017. LocalstirFryGoods.Add(new StirFryGoods
  2018. {
  2019. GoodsKey = item.GoodsKey,
  2020. StirPotActions = OrderSort(item.StirPotActions),
  2021. });
  2022. }
  2023. }
  2024. MessageLog.GetInstance.Show("接收到小炒流程信息");
  2025. //流程解析
  2026. foreach (var item in LocalstirFryGoods)
  2027. {
  2028. MessageLog.GetInstance.Show($"添加菜谱{item.GoodsKey}");
  2029. // morkF.listStirBom.Add(item.StirFryBomInfo);//添加订单制作流程
  2030. string MenuStep = "菜单步骤:";
  2031. foreach (var items in item.StirPotActions)
  2032. {
  2033. switch (items.Actions)
  2034. {
  2035. case nameof(StirFryPotActionEnum.加热开启):
  2036. MenuStep += items.Actions + ",";
  2037. break;
  2038. case nameof(StirFryPotActionEnum.设置加热挡位1):
  2039. MenuStep += items.Actions + ",";
  2040. break;
  2041. case nameof(StirFryPotActionEnum.设置加热挡位2):
  2042. MenuStep += items.Actions + ",";
  2043. break;
  2044. case nameof(StirFryPotActionEnum.设置加热挡位3):
  2045. MenuStep += items.Actions + ",";
  2046. break;
  2047. case nameof(StirFryPotActionEnum.设置加热挡位4):
  2048. MenuStep += items.Actions + ",";
  2049. break;
  2050. case nameof(StirFryPotActionEnum.设置加热挡位5):
  2051. MenuStep += items.Actions + ",";
  2052. break;
  2053. case nameof(StirFryPotActionEnum.设置加热挡位6):
  2054. MenuStep += items.Actions + ",";
  2055. break;
  2056. case nameof(StirFryPotActionEnum.设置加热挡位7):
  2057. MenuStep += items.Actions + ",";
  2058. break;
  2059. case nameof(StirFryPotActionEnum.设置加热挡位8):
  2060. MenuStep += items.Actions + ",";
  2061. break;
  2062. case nameof(StirFryPotActionEnum.设置加热挡位9):
  2063. MenuStep += items.Actions + ",";
  2064. break;
  2065. case nameof(StirFryPotActionEnum.设置加热挡位10):
  2066. MenuStep += items.Actions + ",";
  2067. break;
  2068. case nameof(StirFryPotActionEnum.停止加热):
  2069. MenuStep += items.Actions + ",";
  2070. break;
  2071. case nameof(StirFryPotActionEnum.加调料):
  2072. MenuStep += items.Actions + ",";
  2073. break;
  2074. case nameof(StirFryPotActionEnum.取原料):
  2075. MenuStep += items.Actions + ",";
  2076. break;
  2077. case nameof(StirFryPotActionEnum.开启搅拌):
  2078. MenuStep += items.Actions + ",";
  2079. break;
  2080. case nameof(StirFryPotActionEnum.设置搅拌挡位1):
  2081. MenuStep += items.Actions + ",";
  2082. break;
  2083. case nameof(StirFryPotActionEnum.设置搅拌挡位2):
  2084. MenuStep += items.Actions + ",";
  2085. break;
  2086. case nameof(StirFryPotActionEnum.设置搅拌挡位3):
  2087. MenuStep += items.Actions + ",";
  2088. break;
  2089. case nameof(StirFryPotActionEnum.关闭搅拌):
  2090. MenuStep += items.Actions + ",";
  2091. break;
  2092. case nameof(StirFryPotActionEnum.出餐启动):
  2093. MenuStep += items.Actions + ",";
  2094. break;
  2095. case nameof(StirFryPotActionEnum.道菜启动):
  2096. MenuStep += items.Actions + ",";
  2097. break;
  2098. case nameof(StirFryPotActionEnum.炒制菜品):
  2099. MenuStep += items.Actions + ",";
  2100. break;
  2101. case nameof(StirFryPotActionEnum.搅拌臂原点位):
  2102. MenuStep += items.Actions + ",";
  2103. break;
  2104. case nameof(StirFryPotActionEnum.搅拌臂炒制位):
  2105. MenuStep += items.Actions + ",";
  2106. break;
  2107. case nameof(StirFryPotActionEnum.洗锅):
  2108. MenuStep += items.Actions + ",";
  2109. break;
  2110. default:
  2111. break;
  2112. }
  2113. }
  2114. MessageLog.GetInstance.Show(MenuStep);
  2115. }
  2116. if (stirFry.stirFrymessage.materials.Count > 0)
  2117. {
  2118. MaterialSurplusOperation.GetInstance().UpdateSurplusAll(stirFry.stirFrymessage.materials);
  2119. SaveMaterialData();
  2120. }
  2121. }
  2122. }
  2123. });
  2124. }
  2125. /// <summary>
  2126. /// 订单排序
  2127. /// </summary>
  2128. /// <param name="potActions"></param>
  2129. /// <returns></returns>
  2130. private List<PotActions> OrderSort(List<PotActions> potActions)
  2131. {
  2132. if (potActions.Count > 1)
  2133. {
  2134. potActions.Sort(
  2135. delegate (PotActions st1, PotActions st2)
  2136. {
  2137. //降序排列
  2138. //return st2.FryTime.CompareTo(st1.FryTime);
  2139. //升序版(颠倒 st1 和 st2 即可)
  2140. return st1.FryTime.CompareTo(st2.FryTime);
  2141. });
  2142. }
  2143. return potActions;
  2144. }
  2145. /// <summary>
  2146. /// 订单状态发布
  2147. /// </summary>
  2148. /// <param name="subid"></param>
  2149. /// <param name="oRDER_STATUS"></param>
  2150. private void OrderChange(string Id , string goodName, ORDER_STATUS oRDER_STATUS,int deviceId)
  2151. {
  2152. EventBus.EventBus.GetInstance().Publish(new OrderStatusChangedEvent() { Status = oRDER_STATUS, GoodName = goodName,DeviceId = deviceId, SubOrderId =Id });
  2153. }
  2154. /// <summary>
  2155. /// 订单数据解析
  2156. /// </summary>
  2157. private void DataParse()
  2158. {
  2159. //if (!morkFs.ContainsKey(num))
  2160. //{
  2161. // return;
  2162. //}
  2163. EventBus.EventBus.GetInstance().Subscribe<DoOrderEvent>(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle)
  2164. {
  2165. if (@event == null) return;
  2166. if (@event is DoOrderEvent order)
  2167. {
  2168. if (order.MorkOrder.GoodBatchings == null) return;
  2169. OrderCount++;
  2170. DeviceProcessLogShow($"接收到{OrderCount}次订单");
  2171. Enum.GetNames(typeof(StirFryPotActionEnum));
  2172. if(true)
  2173. {
  2174. var res = LocalstirFryGoods?.FirstOrDefault(p => p.GoodsKey == order.MorkOrder.GoodsKey);//匹配订单对应制作流程
  2175. if(order.MorkOrder.GoodBatchings.Count <= 0)
  2176. {
  2177. return;
  2178. }
  2179. MaterialSurplus materialSurplus = MaterialSurplusOperation.GetInstance().materialSurplus;
  2180. if (order.MorkOrder.DeviceId != DeviceId)
  2181. {
  2182. return;
  2183. }
  2184. ///遍历并增加到待用菜品库
  2185. foreach(var goodBatching in order.MorkOrder.GoodBatchings)
  2186. {
  2187. MaterialInfo materialInfo = MaterialSurplusOperation.GetInstance().materialSurplus.dicSurplus.Find( o => o.Key == goodBatching.BatchingId);
  2188. if (materialInfo != null)
  2189. {
  2190. //if
  2191. if(System.Convert.ToInt32(materialInfo.Qty) - goodBatching.BatchingCount < 0)
  2192. {
  2193. MessageLog.GetInstance.ShowEx($"{materialInfo.Name}不够,请更新菜品库,并点击检测");
  2194. return;
  2195. }
  2196. else
  2197. {
  2198. //查找是否有该菜品
  2199. GoodBatchings existingGoodBatchings = stagingGoodBatchings.Find( o => o.BatchingId== goodBatching.BatchingId );
  2200. //判断是否存在
  2201. if (existingGoodBatchings != null)
  2202. {
  2203. existingGoodBatchings.BatchingCount += goodBatching.BatchingCount;
  2204. }
  2205. else
  2206. {
  2207. stagingGoodBatchings.Add(goodBatching);
  2208. }
  2209. }
  2210. }
  2211. else
  2212. {
  2213. MessageLog.GetInstance.ShowEx($"ID为{goodBatching.BatchingId}的菜品无法找到,请联系售后人员");
  2214. return;
  2215. }
  2216. }
  2217. //var res = LocalstirFryGoods[0];
  2218. if (res != null)
  2219. {
  2220. /* morkF.listStirBom.Add(res.StirFryBomInfo);*///添加订单制作流程
  2221. //添加到带炒小炒队列
  2222. if (StirFryGoodsQuenes.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null)
  2223. {
  2224. //待炒数量+1
  2225. StagingFryCount++;
  2226. lock (lock_MainProcessExcute)
  2227. {
  2228. StirFryGoodsQuenes.Enqueue(new OrderLocInfo()
  2229. {
  2230. SuborderId = order.MorkOrder.SuborderId,
  2231. StirPotActions = res.StirPotActions,
  2232. GoodName = order.MorkOrder.GoodsName
  2233. });
  2234. }
  2235. }
  2236. }
  2237. }
  2238. else
  2239. {
  2240. NewStartLocalOrder("莲白回锅");
  2241. }
  2242. ////暂时使用本地菜单
  2243. //StartLocalOrder();
  2244. }
  2245. });
  2246. }
  2247. #endregion
  2248. private object lock_MainProcessExcute = new object();
  2249. /// <summary>
  2250. /// 倒菜锁
  2251. /// </summary>
  2252. private object lock_OutMeal = new object();
  2253. /// <summary>
  2254. /// 炒锅主流程
  2255. /// </summary>
  2256. private void MainProcessExcute()
  2257. {
  2258. //判断是否有订单信息
  2259. if(StirFryGoodsQuenes.Count > 0)
  2260. {
  2261. //遍历炒锅,找到合适、空闲的炒锅
  2262. for(int i = 0;i<morkFs.Count;i++)
  2263. {
  2264. if (morkFs[i].AutoMode && morkFs[i].FryPot1_InitialComplete && ml_morkf.InitialComplete &&
  2265. !morkFs[i].FryWorking)//炒锅在自动状态&&初始化完成&&菜品库初始化&&是否在炒菜中
  2266. {
  2267. Thread.Sleep(4000);
  2268. lock(lock_MainProcessExcute)
  2269. {
  2270. //待炒小炒队列出队列
  2271. if (StirFryGoodsQuenes.TryDequeue(out var res))
  2272. {
  2273. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.WAIT, DeviceId = i);
  2274. //设置当前炒制菜品
  2275. nowStirFryGood[i] = res;
  2276. //炒锅工作状态置为正在工作中
  2277. morkFs[i].FryWorking = true;
  2278. //空闲炒锅入队列
  2279. morkFs[i].StirFryGoodsQuenes.Enqueue(res);
  2280. //炒锅取菜状态置为未取到
  2281. morkFs[i].GetMaterialComplete = false;
  2282. //开启线程进行炒制
  2283. ThreadManage.GetInstance().Start(new Action(() =>
  2284. {
  2285. try
  2286. {
  2287. //待炒数量-1
  2288. StagingFryCount--;
  2289. //正在炒制数量+1
  2290. FryingCount++;
  2291. int testi = 0;
  2292. string error = string.Empty;
  2293. //初始化大屏
  2294. morkFs[i].ScreenInit();
  2295. bool ret = true;
  2296. MessageLog.GetInstance.Show($"炒锅{i}开始炒制菜品{res.GoodName}");
  2297. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.COOKING, DeviceId = i);
  2298. morkFs[i].GoodName = res.GoodName;
  2299. Coordinate myCoordinate = new Coordinate();
  2300. foreach (var potActions in res.StirPotActions)
  2301. {
  2302. if (ThreadManage.GetInstance().IsCanncel(String.Format(striConst, i.ToString(), nowStirFryGood[i].GoodName)))
  2303. {
  2304. return;
  2305. }
  2306. if(ret == false)
  2307. {
  2308. MessageLog.GetInstance.ShowEx("上一步操作未成功");
  2309. break;
  2310. }
  2311. ////调试大屏用代码
  2312. //Thread.Sleep(5000);
  2313. //更新
  2314. morkFs[i].UpdateProcess(potActions);
  2315. switch (potActions.Actions)
  2316. {
  2317. case nameof(StirFryPotActionEnum.加热开启):
  2318. StartFire(i);
  2319. MessageLog.GetInstance.Show(potActions.Actions);
  2320. break;
  2321. case nameof(StirFryPotActionEnum.设置加热挡位1):
  2322. morkFs[i].Fire = 1;
  2323. SetFire(new List<int> { 1 }, i);
  2324. MessageLog.GetInstance.Show(potActions.Actions);
  2325. break;
  2326. case nameof(StirFryPotActionEnum.设置加热挡位2):
  2327. morkFs[i].Fire = 2;
  2328. SetFire(new List<int> { 2 }, i);
  2329. MessageLog.GetInstance.Show(potActions.Actions);
  2330. break;
  2331. case nameof(StirFryPotActionEnum.设置加热挡位3):
  2332. morkFs[i].Fire = 3;
  2333. SetFire(new List<int> { 3 }, i);
  2334. MessageLog.GetInstance.Show(potActions.Actions);
  2335. break;
  2336. case nameof(StirFryPotActionEnum.设置加热挡位4):
  2337. morkFs[i].Fire = 4;
  2338. SetFire(new List<int> { 4 }, i);
  2339. MessageLog.GetInstance.Show(potActions.Actions);
  2340. break;
  2341. case nameof(StirFryPotActionEnum.设置加热挡位5):
  2342. morkFs[i].Fire = 5;
  2343. SetFire(new List<int> { 5 }, i);
  2344. MessageLog.GetInstance.Show(potActions.Actions);
  2345. break;
  2346. case nameof(StirFryPotActionEnum.设置加热挡位6):
  2347. morkFs[i].Fire = 6;
  2348. SetFire(new List<int> { 6 }, i);
  2349. MessageLog.GetInstance.Show(potActions.Actions);
  2350. break;
  2351. case nameof(StirFryPotActionEnum.设置加热挡位7):
  2352. morkFs[i].Fire = 7;
  2353. SetFire(new List<int> { 7 }, i);
  2354. MessageLog.GetInstance.Show(potActions.Actions);
  2355. break;
  2356. case nameof(StirFryPotActionEnum.设置加热挡位8):
  2357. morkFs[i].Fire = 8;
  2358. SetFire(new List<int> { 8 }, i);
  2359. MessageLog.GetInstance.Show(potActions.Actions);
  2360. break;
  2361. case nameof(StirFryPotActionEnum.设置加热挡位9):
  2362. morkFs[i].Fire = 9;
  2363. SetFire(new List<int> { 9 }, i);
  2364. MessageLog.GetInstance.Show(potActions.Actions);
  2365. break;
  2366. case nameof(StirFryPotActionEnum.设置加热挡位10):
  2367. morkFs[i].Fire = 10;
  2368. SetFire(new List<int> { 10 }, i);
  2369. MessageLog.GetInstance.Show(potActions.Actions);
  2370. break;
  2371. case nameof(StirFryPotActionEnum.停止加热):
  2372. StopFire(i);
  2373. MessageLog.GetInstance.Show(potActions.Actions);
  2374. break;
  2375. case nameof(StirFryPotActionEnum.加调料):
  2376. OutSeasonings(potActions.SeasoningLists, i);
  2377. MessageLog.GetInstance.Show(potActions.Actions);
  2378. break;
  2379. case nameof(StirFryPotActionEnum.取原料):
  2380. if(potActions.SeasoningLists[0].Loc == 1 ||
  2381. potActions.SeasoningLists[0].Loc == 9 ||
  2382. potActions.SeasoningLists[0].Loc == 10 ||
  2383. potActions.SeasoningLists[0].Loc == 18 ||
  2384. potActions.SeasoningLists[0].Loc == 19 ||
  2385. potActions.SeasoningLists[0].Loc == 27 )
  2386. {
  2387. MessageLog.GetInstance.ShowEx("该取料位置禁止使用");
  2388. return;
  2389. }
  2390. //炒锅取菜状态置为未取到
  2391. morkFs[i].GetMaterialComplete = false;
  2392. if (isLocalFryingMode)
  2393. {
  2394. MaterialInfo materialInfo = new MaterialInfo();
  2395. materialInfo.Loc = potActions.SeasoningLists[0].Loc.ToString();
  2396. materialInfo.Id = "1232131";
  2397. materialInfo.Name = "本地炒制未知菜品";
  2398. materialOperationQuenes.Enqueue(new MaterialOperation { materialInfo = materialInfo, fryNum = i });
  2399. //testi++;
  2400. }
  2401. else
  2402. {
  2403. if (potActions.MaterialLists != null)
  2404. {
  2405. foreach (var item in potActions.MaterialLists)
  2406. {
  2407. //通过ID获取有效的菜品对象
  2408. MaterialInfo materialInfo = MaterialSurplusOperation.GetInstance().GetVailedMaterial(item.MaterialId);
  2409. if (materialInfo == null)
  2410. {
  2411. MessageLog.GetInstance.ShowEx($"炒锅{i}获取菜品[{item.MaterialId}]失败,库存不足");
  2412. continue;
  2413. }
  2414. materialOperationQuenes.Enqueue(new MaterialOperation { materialInfo = materialInfo, fryNum = i });
  2415. }
  2416. }
  2417. else
  2418. {
  2419. MessageLog.GetInstance.ShowEx($"炒锅{i}获取菜品失败,菜品列表为空");
  2420. }
  2421. }
  2422. MessageLog.GetInstance.Show(potActions.Actions);
  2423. break;
  2424. case nameof(StirFryPotActionEnum.开启搅拌):
  2425. StartStir(i);
  2426. MessageLog.GetInstance.Show(potActions.Actions);
  2427. break;
  2428. case nameof(StirFryPotActionEnum.设置搅拌挡位1):
  2429. SetStir(new List<int> { 1 }, i);
  2430. MessageLog.GetInstance.Show(potActions.Actions);
  2431. break;
  2432. case nameof(StirFryPotActionEnum.设置搅拌挡位2):
  2433. SetStir(new List<int> { 2 }, i);
  2434. MessageLog.GetInstance.Show(potActions.Actions);
  2435. break;
  2436. case nameof(StirFryPotActionEnum.设置搅拌挡位3):
  2437. SetStir(new List<int> { 3 }, i);
  2438. MessageLog.GetInstance.Show(potActions.Actions);
  2439. break;
  2440. case nameof(StirFryPotActionEnum.关闭搅拌):
  2441. StopStir(i);
  2442. MessageLog.GetInstance.Show(potActions.Actions);
  2443. break;
  2444. case nameof(StirFryPotActionEnum.出餐启动):
  2445. //停止搅拌
  2446. StopStir(i);
  2447. //回原点位
  2448. StirArmGoOrigin(i);
  2449. //出餐启动
  2450. OutMeal(i);
  2451. MessageLog.GetInstance.Show(potActions.Actions);
  2452. break;
  2453. case nameof(StirFryPotActionEnum.道菜启动):
  2454. ret = OutFood(i, out error, true);
  2455. if(ret == false)
  2456. {
  2457. alarmModel.Add(new BPA.Message.AlarmModel() { AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmMs = error });
  2458. }
  2459. break;
  2460. case nameof(StirFryPotActionEnum.炒制菜品):
  2461. Thread.Sleep(potActions.During * 1000);
  2462. break;
  2463. case nameof(StirFryPotActionEnum.搅拌臂原点位):
  2464. StirArmGoOrigin(i);
  2465. MessageLog.GetInstance.Show(potActions.Actions);
  2466. break;
  2467. case nameof(StirFryPotActionEnum.搅拌臂炒制位):
  2468. //出餐时,不允许搅拌臂去炒制位
  2469. lock (lock_OutMeal)
  2470. {
  2471. ret = StirArmGoWork(i, out error);
  2472. }
  2473. if (ret == false)
  2474. {
  2475. alarmModel.Add(new BPA.Message.AlarmModel() { AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), AlarmMs = error });
  2476. }
  2477. MessageLog.GetInstance.Show(potActions.Actions);
  2478. break;
  2479. case nameof(StirFryPotActionEnum.洗锅):
  2480. MessageLog.GetInstance.Show(potActions.Actions);
  2481. break;
  2482. default:
  2483. break;
  2484. }
  2485. }
  2486. Plc1Reset(i);//复位
  2487. Thread.Sleep(3000);
  2488. //回原点位
  2489. StirArmGoOrigin(i);
  2490. OrderChange(res.SuborderId, res.GoodName, ORDER_STATUS.COMPLETED_COOK, DeviceId = i);
  2491. //同时只能允许有一个出餐
  2492. lock (lock_OutMeal)
  2493. {
  2494. //出餐启动
  2495. OutMeal(i);
  2496. //等待25s出餐完毕
  2497. Thread.Sleep(25000);
  2498. }
  2499. MessageLog.GetInstance.Show($"菜品{res.GoodName}完成");
  2500. //菜品统计数量+1
  2501. morkFs[i].orderCount++;
  2502. StatsModel statsModel = statsModels.FirstOrDefault(p => p.Name == res.GoodName);
  2503. if (statsModel != null)
  2504. {
  2505. statsModel.Count++;
  2506. }
  2507. else
  2508. {
  2509. statsModels.Add(new StatsModel() { Name = res.GoodName, Count = 0 });
  2510. }
  2511. }
  2512. catch (Exception ex)
  2513. {
  2514. nowStirFryGood[i] = null;
  2515. //炒完后出队列
  2516. morkFs[i].StirFryGoodsQuenes.TryDequeue(out var orderQueue);
  2517. morkFs[i].FryWorking = false;
  2518. //初始化大屏
  2519. morkFs[i].ScreenClear();
  2520. //异常菜品统计数量+1
  2521. morkFs[i].orderAbnormalCount++;
  2522. ThreadManage.GetInstance().StopTask($"炒锅{i}{res.GoodName}炒制线程");
  2523. MessageLog.GetInstance.ShowEx($"炒锅{i}炒制菜品{res.GoodName}出错,错误信息:" + ex.Message);
  2524. }
  2525. finally
  2526. {
  2527. //正在炒制数量-1
  2528. FryingCount--;
  2529. nowStirFryGood[i] = null;
  2530. //炒完后出队列
  2531. morkFs[i].StirFryGoodsQuenes.TryDequeue(out var orderQueue);
  2532. morkFs[i].FryWorking = false;
  2533. //初始化大屏
  2534. morkFs[i].ScreenClear();
  2535. }
  2536. }), String.Format(striConst, i.ToString(), nowStirFryGood[i].GoodName)/*$"炒锅{i}炒制{res.GoodName}线程"*/, true);
  2537. }
  2538. }
  2539. break;
  2540. }
  2541. }
  2542. }
  2543. }
  2544. /// <summary>
  2545. /// 更新菜品库的余量
  2546. /// </summary>
  2547. private void UpdateMaterialSurplus()
  2548. {
  2549. ThreadManage.GetInstance().StartLong(new Action(() => {
  2550. List<MaterialInfo> listSurplus = MaterialSurplusOperation.GetInstance().materialSurplus.dicSurplus;
  2551. if (listSurplus == null)
  2552. {
  2553. return;
  2554. }
  2555. foreach (var surplus in listSurplus)
  2556. {
  2557. //找到已有的余量表
  2558. var batchingInfo = BatchingInfos.Find(o => o.BatchingId == surplus.Key);
  2559. //从当前下单
  2560. var stagingGoodBatching = stagingGoodBatchings.Find(o => o.BatchingId == surplus.Key);
  2561. //暂存的数量
  2562. int stagingCount = 0;
  2563. if(stagingGoodBatching != null)
  2564. {
  2565. stagingCount = stagingGoodBatching.BatchingCount;
  2566. }
  2567. if (batchingInfo == null)
  2568. {
  2569. //为空就新增
  2570. BatchingInfos.Add(new BatchingInfo() { BatchingCount = System.Convert.ToInt32(surplus.Qty) - stagingCount, BatchingLoc = surplus.Loc, BatchingId = surplus.Key });
  2571. }
  2572. else
  2573. {
  2574. batchingInfo.BatchingLoc = surplus.Loc;
  2575. batchingInfo.BatchingCount = System.Convert.ToInt32(surplus.Qty) - stagingCount;
  2576. }
  2577. }
  2578. Thread.Sleep(1000);
  2579. return;
  2580. }), "UpdateMaterialSurplus", true);
  2581. }
  2582. /// <summary>
  2583. /// 菜品库主流程
  2584. /// </summary>
  2585. private void MainProcessMaterial()
  2586. {
  2587. if(materialOperationQuenes.Count > 0)
  2588. {
  2589. //判断是否初始化与是否在工作中
  2590. if (ml_morkf.InitialComplete && !ml_morkf.MaterailIsWorking)
  2591. {
  2592. //待菜品库操作列出队列
  2593. if (materialOperationQuenes.TryDequeue(out var res))
  2594. {
  2595. Thread.Sleep(1000);
  2596. ml_morkf.MaterailIsWorking = true;
  2597. MessageLog.GetInstance.Show("开始操作菜品库");
  2598. //ThreadManage.GetInstance().Start(new Action(()=>{
  2599. // GetMaterail(res.x_high, res.y, res.fryNum);
  2600. //}),"菜品库操作");
  2601. GetMaterailTest(res);
  2602. }
  2603. }
  2604. }
  2605. }
  2606. /// <summary>
  2607. /// 信号处理
  2608. /// </summary>
  2609. private void SingleProcess()
  2610. {
  2611. }
  2612. private void ScreenDataServer()
  2613. {
  2614. LocalMqtt.GetInstance.Init(ScreenDeviceType.小炒);
  2615. ThreadManage.GetInstance().StartLong(new Action(() =>
  2616. {
  2617. //statsModels.Add(new StatsModel() { Name = "帝王蟹", Count = 666 });
  2618. ScreenModelMinWok maxWok = new ScreenModelMinWok
  2619. {
  2620. IsRun = IsHealth ? IsRun.运行 : IsRun.停止,//new Random().Next(0, 2) == 0 ? IsRun.运行 : IsRun.停止, //设备是否运行
  2621. WorkStatus_1 = morkFs[0].FryPot1_InitialComplete ? ((morkFs[0].Task != null)? WorkStatus.工作:WorkStatus.待机) : WorkStatus.停止,// (WorkStatus)new Random().Next(0, 3), //设备运行状态
  2622. WorkStatus_2 = morkFs[1].FryPot1_InitialComplete ? ((morkFs[1].Task != null) ? WorkStatus.工作 : WorkStatus.待机) : WorkStatus.停止,//(WorkStatus)new Random().Next(0, 3), //设备运行状态
  2623. RobotStatu = (WorkStatus)new Random().Next(0, 3), //机器人状态 待机 1 正常
  2624. Alarm = alarmModel, //告警集合
  2625. FailuresCount = alarmModel.Count, //故障数
  2626. StatsCount = statsModels, //统计菜品数量
  2627. MinWok_Dishes_1 = morkFs[0].GoodName,//"满汉全席",//当前炒制菜品名
  2628. MinWok_Dishes_2 = morkFs[1].GoodName,
  2629. MinWok_Task_1 = morkFs[0].Task,//当前任务
  2630. MinWok_Task_2 = morkFs[1].Task, //当前任务
  2631. //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.未执行 } },
  2632. MinWok_Process_1 = morkFs[0].processModels, //炒锅当前任务流程
  2633. MinWok_Process_2 = morkFs[1].processModels, //炒锅当前任务流程
  2634. MinWok_HeatGear_1 = morkFs[0].FireNow, //炒锅加热档位
  2635. MinWok_HeatGear_2 = morkFs[1].FireNow, //炒锅加热档位
  2636. MinWok_Temp_1 = morkFs[0].TempNow, //炒锅1锅底温度
  2637. MinWok_Temp_2 = morkFs[1].TempNow, //炒锅1锅底温度
  2638. MinWok_StirGear_1 = morkFs[0].StirNow, //炒锅搅拌档位
  2639. MinWok_StirGear_2 = morkFs[1].StirNow, //炒锅搅拌档位
  2640. MinWok_OrderCount_1 = morkFs[0].orderCount, //订单数量
  2641. MinWok_OrderCount_2 = morkFs[1].orderCount, //订单数量
  2642. MinWok_ErrorOrderCount_1 = morkFs[0].orderAbnormalCount, //异常订单数量
  2643. MinWok_ErrorOrderCount_2 = morkFs[1].orderAbnormalCount, //异常订单数量
  2644. };
  2645. LocalMqtt.GetInstance.Publish(maxWok);
  2646. Thread.Sleep(1000);
  2647. }), "大屏数据上报",true);
  2648. }
  2649. public override void SimOrder()
  2650. {
  2651. }
  2652. /// <summary>
  2653. /// 菜品编号转换为坐标
  2654. /// </summary>
  2655. /// <param name="no"></param>
  2656. /// <param name="coordinate"></param>
  2657. /// <returns></returns>
  2658. public bool NoMaterial2Coordinate(string no,out Coordinate coordinate)
  2659. {
  2660. //默认返回0,0
  2661. coordinate = new Coordinate();
  2662. coordinate.X = 0;
  2663. coordinate.Y = 0;
  2664. try
  2665. {
  2666. if(MaterialCoordinate.GetInstance().dicNoMaterialCoordinate.ContainsKey(no))
  2667. {
  2668. coordinate = MaterialCoordinate.GetInstance().dicNoMaterialCoordinate[no];
  2669. return true;
  2670. }
  2671. else
  2672. {
  2673. return false;
  2674. }
  2675. }
  2676. catch (Exception ex)
  2677. {
  2678. return false;
  2679. }
  2680. finally
  2681. {
  2682. }
  2683. }
  2684. public enum Laser2CoordinateState
  2685. {
  2686. MaterialOverdo = 0,//菜品过量
  2687. MaterialNormal = 1,//菜品正常
  2688. MaterialEmpty = 2,//菜品为空
  2689. MaterialUnkown = 999,//菜品未知错误
  2690. }
  2691. }
  2692. }