终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

2926 lines
114 KiB

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