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

493 lines
21 KiB

  1. using BPASmartClient.CustomResource.Pages.Model;
  2. using BPASmartClient.Helper;
  3. using BPASmartClient.JXJFoodBigStation.Model.HK_PLC;
  4. using BPASmartClient.JXJFoodBigStation.Model.Siemens;
  5. using BPASmartClient.Modbus;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using System.Configuration;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. namespace BPASmartClient.JXJFoodBigStation.Model
  16. {
  17. public class ProcessControl
  18. {
  19. private volatile static ProcessControl _Instance;
  20. public static ProcessControl GetInstance => _Instance ?? (_Instance = new ProcessControl());
  21. private ProcessControl() { }
  22. public ObservableCollection<RemoteRecipeRawMaterial> RawMaterials { get; set; } = new ObservableCollection<RemoteRecipeRawMaterial>();
  23. public SiemensDeviceStatus SiemensDevice = new SiemensDeviceStatus();
  24. public HKDeviceStatus HKDevice = new HKDeviceStatus();
  25. GVL_BigStation BigStation = new GVL_BigStation();
  26. /// <summary>
  27. /// 配方数据
  28. /// </summary>
  29. public ObservableCollection<RemoteRecipeData> RemoteRecipes = new ObservableCollection<RemoteRecipeData>();
  30. /// <summary>
  31. /// 配方数据
  32. /// </summary>
  33. public ObservableCollection<RemoteRecipeData> IssuedComplete = new ObservableCollection<RemoteRecipeData>();
  34. /// <summary>
  35. /// 原料的名称和料仓的位置对应
  36. /// </summary>
  37. public Dictionary<string, short> RawMaterialsNamePos = new Dictionary<string, short>();
  38. /// <summary>
  39. /// 配方队列
  40. /// </summary>
  41. public ConcurrentQueue<string> RecipeQueue = new ConcurrentQueue<string>();
  42. /// <summary>
  43. /// AGV到达工站队列
  44. /// </summary>
  45. public ConcurrentQueue<string> AGVToWorkStationQueue = new ConcurrentQueue<string>();
  46. /// <summary>
  47. /// 接收原料数据
  48. /// </summary>
  49. public RecipeRawMaterial RawMaterial;
  50. public void Init()
  51. {
  52. ActionManage.GetInstance.Register(new Action<DL_Start_DB>((res) =>
  53. {
  54. if (SiemensDevice.IsConnected)
  55. {
  56. if (res != null)
  57. {
  58. RawMaterials.Clear();
  59. for (int i = 0; i < 15; i++)
  60. {
  61. if (RawMaterialsNamePos.ContainsKey(res.RecipeName)
  62. {
  63. RawMaterials.Add(new RemoteRecipeRawMaterial()
  64. {
  65. RawMaterialName = res.Material[i].Material_Name,
  66. RawMaterialBarrelNum = res.Material[i].Material_BarrelNum,
  67. RawMaterialWeight = res.Material[i].Material_Weight,
  68. RawMaterialLocation = (int)RawMaterialsNamePos[res.Material[i].Material_Name]
  69. });
  70. }
  71. else
  72. {
  73. //报警,配方的原料名称下发和设备不一致
  74. }
  75. }
  76. Json<RemoteRecipeDataColl>.Data.Recipes.Add(new RemoteRecipeData()
  77. {
  78. RecipeName = res.RecipeName,
  79. RecipeCode = res.RecipeCode,
  80. RawMaterial = RawMaterials,
  81. TrayCode = res.TrayCode
  82. });
  83. }
  84. }
  85. }), "西门子下发配方", true);
  86. ActionManage.GetInstance.Register(new Action<RecipeModel>((res) =>
  87. {
  88. if (SiemensDevice.IsConnected)
  89. {
  90. if (res != null)
  91. {
  92. RawMaterials.Clear();
  93. for (int i = 0; i < 15; i++)
  94. {
  95. if (RawMaterialsNamePos.ContainsKey(res.Material[i].Material_Name))
  96. {
  97. RawMaterials.Add(new RemoteRecipeRawMaterial()
  98. {
  99. RawMaterialName = res.Material[i].Material_Name,
  100. RawMaterialBarrelNum = res.Material[i].Material_BarrelNum,
  101. RawMaterialWeight = res.Material[i].Material_Weight,
  102. RawMaterialLocation = (int)RawMaterialsNamePos[res.Material[i].Material_Name]
  103. });
  104. }
  105. else
  106. {
  107. //报警,配方的原料名称下发和设备不一致
  108. }
  109. }
  110. Json<RemoteRecipeDataColl>.Data.Recipes.Add(new RemoteRecipeData()
  111. {
  112. RecipeName = res.RecipeName,
  113. RecipeCode = res.RecipeCode,
  114. RawMaterial = RawMaterials,
  115. TrayCode = res.TrayCode
  116. });
  117. }
  118. }
  119. }), "西门子下发配方", true);
  120. string HK_PLC_IP = ConfigurationManager.AppSettings["HKPlc_IP"];
  121. string Siemens_PLC_IP = ConfigurationManager.AppSettings["Siemens_IP"];
  122. try
  123. {
  124. //HKDevice.HK_PLC_S7.Connect(S7.Net.CpuType.S71500, HK_PLC_IP);
  125. //SiemensDevice.Siemens_PLC_S7.Connect(S7.Net.CpuType.S71500, Siemens_PLC_IP);
  126. if (HKDevice.IsConnected)
  127. {
  128. HKDevice.Init();
  129. }
  130. if (SiemensDevice.IsConnected)
  131. {
  132. SiemensDevice.Init();
  133. }
  134. }
  135. catch (Exception ex)
  136. {
  137. }
  138. RecipeQueue.Clear();
  139. //Json<RemoteRecipeDataColl>.Data.Recipes = TestData.GetInstance.Recipes;//添加测试数据
  140. ThreadManage.GetInstance().StartLong(new Action(() =>
  141. {
  142. ReceviceData();
  143. RecipeInfoToHKPLC();
  144. Thread.Sleep(10);
  145. }), "流程处理", true);
  146. ThreadManage.GetInstance().StartLong(new Action(() =>
  147. {
  148. if (HKDevice.IsConnected && SiemensDevice.IsConnected)
  149. {
  150. AgvGetInOut();
  151. }
  152. Thread.Sleep(10);
  153. }), "AGV进站送取货", true);
  154. ThreadManage.GetInstance().StartLong(new Action(() =>
  155. {
  156. ReadSiemensCommData();
  157. ReadHKPLCCommData();
  158. Thread.Sleep(10);
  159. }), "读取西门子和海科PLC的数据", true);
  160. }
  161. /// <summary>
  162. /// AGV送货
  163. /// </summary>
  164. /// <param name="bitNum"></param>
  165. private void AGV_Delivery(int bitNum)
  166. {
  167. if ((ReadSiemens("M4002." + bitNum) is bool) && BigStation.AgvDeliveryPosition == 0)
  168. {
  169. BigStation.AgvDeliveryPosition = 1;
  170. WriteHKPLC("M4002." + bitNum, true);
  171. WriteSiemens("M4002." + bitNum, false);
  172. }
  173. else if (ReadHK("M5002." + bitNum) is bool && BigStation.AgvDeliveryPosition == 1)
  174. {
  175. BigStation.AgvDeliveryPosition = 2;
  176. WriteSiemens("M5002." + bitNum, true);
  177. WriteHKPLC("M5002." + bitNum, false);
  178. }
  179. else if (ReadSiemens("M4004." + bitNum) is bool && BigStation.AgvDeliveryPosition == 2)
  180. {
  181. BigStation.AgvDeliveryPosition = 3;
  182. WriteHKPLC("M4004." + bitNum, true);
  183. WriteSiemens("M4004." + bitNum, false);
  184. }
  185. else if (ReadHK("M5004." + bitNum) is bool && BigStation.AgvDeliveryPosition == 3)
  186. {
  187. BigStation.AgvDeliveryPosition = 4;
  188. WriteSiemens("M5004." + bitNum, true);
  189. WriteHKPLC("M5004." + bitNum, false);
  190. }
  191. else if (ReadSiemens("M4005." + bitNum) is bool && BigStation.AgvDeliveryPosition == 4)
  192. {
  193. BigStation.AgvDeliveryPosition = 5;
  194. WriteHKPLC("M4005." + bitNum, true);
  195. WriteSiemens("M4005." + bitNum, false);
  196. }
  197. else if (ReadHK("M5005." + bitNum) is bool && BigStation.AgvDeliveryPosition == 5)
  198. {
  199. WriteSiemens("M5005." + bitNum, true);
  200. WriteHKPLC("M5005." + bitNum, false);
  201. }
  202. }
  203. /// <summary>
  204. /// AGV取货
  205. /// </summary>
  206. /// <param name="bitNum"></param>
  207. private void AGV_Pick(int bitNum)
  208. {
  209. if (ReadSiemens("M4003" + bitNum) is bool && BigStation.AgvPickUpPosition == 0)
  210. {
  211. BigStation.AgvPickUpPosition = 1;
  212. WriteHKPLC("M4003." + bitNum, true);
  213. WriteSiemens("M4003." + bitNum, false);
  214. }
  215. if (ReadHK("M5003" + bitNum) is bool && BigStation.AgvPickUpPosition == 1)
  216. {
  217. BigStation.AgvPickUpPosition = 2;
  218. WriteSiemens("M5003" + bitNum, true);
  219. WriteHKPLC("M5003" + bitNum, false);
  220. }
  221. if (ReadSiemens("M4006." + bitNum) is bool && BigStation.AgvPickUpPosition == 2)
  222. {
  223. BigStation.AgvPickUpPosition = 3;
  224. WriteHKPLC("M4006." + bitNum, true);
  225. WriteSiemens("M4006." + bitNum, false);
  226. }
  227. if (ReadHK("M5006." + bitNum) is bool && BigStation.AgvPickUpPosition == 3)
  228. {
  229. WriteSiemens("M5006." + bitNum, true);
  230. WriteHKPLC("M5006." + bitNum, false);
  231. }
  232. }
  233. /// <summary>
  234. /// AGV进站送货
  235. /// </summary>
  236. private void AgvGetInOut()
  237. {
  238. //获取工位上是否有小车
  239. SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.StationIsExistCar, (bool)
  240. HKDevice.HK_PLC_S7.Read<bool>(HKPlcCommAddress.StationIsExistTray));
  241. //检测AGV到站信号
  242. if (AGVToWorkStationQueue.Count > 0)
  243. {
  244. int index = Array.FindIndex(RemoteRecipes.ToArray(), p => p.RecipeCode == AGVToWorkStationQueue.ElementAt(0));
  245. int TrayLocation = RemoteRecipes.ElementAt(index).TrayCode;//根据配方编号,找到托盘的ID 托盘ID1-6
  246. string RecipeCode = (string)RemoteRecipes.ElementAt(index).RecipeCode;
  247. if (TrayLocation > 0 && TrayLocation < 7)
  248. {
  249. AGV_Delivery(TrayLocation - 1);
  250. if (BigStation.AgvDeliveryPosition == 5)
  251. {
  252. BigStation.AgvDeliveryPosition = 0;
  253. //AGVToWorkStationQueue.TryDequeue(out RecipeCode);
  254. }
  255. AGV_Pick(TrayLocation - 1);
  256. if (BigStation.AgvPickUpPosition == 3)
  257. {
  258. BigStation.AgvPickUpPosition = 0;
  259. AGVToWorkStationQueue.TryDequeue(out RecipeCode);
  260. }
  261. }
  262. }
  263. }
  264. private void ReceviceData()
  265. {
  266. if (!BigStation.IsAllowManual && RemoteRecipes.Count == 0)//一个配方执行完成后,再获取配方数据
  267. {
  268. RemoteRecipes = Json<RemoteRecipeDataColl>.Data.Recipes;
  269. }
  270. else if (BigStation.IsAllowManual && RemoteRecipes.Count == 0)
  271. {
  272. RemoteRecipes = Json<LocalRecipeDataColl>.Data.Recipes;
  273. }
  274. if (RemoteRecipes.Count > 0)
  275. {
  276. foreach (var data in RemoteRecipes)
  277. {
  278. if (!(RecipeQueue.Contains(data.RecipeCode)))
  279. RecipeQueue.Enqueue(data.RecipeCode);
  280. }
  281. }
  282. }
  283. short[] BarrelNum = new short[15];
  284. short[] Location = new short[15];
  285. short[] Weight = new short[15];
  286. private void RecipeInfoToHKPLC()
  287. {
  288. if (RecipeQueue.Count > 0)
  289. {
  290. int index = Array.FindIndex(RemoteRecipes.ToArray(), p => p.RecipeCode == RecipeQueue.ElementAt(0));
  291. if (index >= 0 && index <= RemoteRecipes.Count)
  292. {
  293. string code = RemoteRecipes.ElementAt(index).RecipeCode;
  294. if (HKDevice.HK_PLC_S7.Read<bool>("M5001.0") && BigStation.RecipeDosingStatus == 0)//配方1是否允许下发配发
  295. {
  296. MessageLog.GetInstance.ShowRunLog($"配方状态:{code}允许下发");
  297. BigStation.RecipeDosingStatus = 1;
  298. for (int i = 0; i < RemoteRecipes.ElementAt(index).RawMaterial.Count; i++)
  299. {
  300. BarrelNum[i] = (short)RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(i).RawMaterialBarrelNum;
  301. Location[i] = (short)RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(i).RawMaterialLocation;
  302. Weight[i] = (short)RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(i).RawMaterialWeight;
  303. }
  304. HKDevice.StockBinPar(BarrelNum, Location, Weight);
  305. HKDevice.HK_PLC_S7.Write("M4001.0", 1);//配发下发完成,to plc
  306. HKDevice.HK_PLC_S7.Write("M5001.0", 0);//复位允许下发配方1信号
  307. BigStation.RecipeDosingStatus = 2;
  308. MessageLog.GetInstance.ShowRunLog($"配方状态:{code}下发完成");
  309. }
  310. if (HKDevice.HK_PLC_S7.Read<bool>("M5001.4") && BigStation.RecipeDosingStatus == 2)
  311. {
  312. BigStation.RecipeDosingStatus = 3;
  313. HKDevice.HK_PLC_S7.Write("M5001.4", 0);//复位允许下发配方1信号
  314. MessageLog.GetInstance.ShowRunLog($"配方状态:{code}配方配料");
  315. }
  316. if (BigStation.RecipeDosingStatus == 3)
  317. {
  318. for (int i = 0; i < 12; i++)
  319. {
  320. if (i >= 0 && i < 8)
  321. {
  322. if (HKDevice.HK_PLC_S7.Read<bool>("M5008." + (i)))//根据配料完成信号,
  323. {
  324. int a = Array.FindIndex(RemoteRecipes.ElementAt(index).RawMaterial.ToArray(), p => p.RawMaterialLocation == i);
  325. if (a >= 0)
  326. {
  327. int barrelNum = RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(a).RawMaterialBarrelNum;
  328. string address = "MD" + 5060 + i * 4 + (barrelNum - 1) * 48;
  329. float weight = HKDevice.HK_PLC_S7.Read<float>(address);
  330. }
  331. }
  332. }
  333. else
  334. {
  335. if (HKDevice.HK_PLC_S7.Read<bool>("M5009." + (i - 8)))
  336. {
  337. int a = Array.FindIndex(RemoteRecipes.ElementAt(index).RawMaterial.ToArray(), p => p.RawMaterialLocation == i);
  338. if (a >= 0)
  339. {
  340. int barrelNum = RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(a).RawMaterialBarrelNum;
  341. string address = "MD" + 5060 + i * 4 + (barrelNum - 1) * 48;
  342. float weight = HKDevice.HK_PLC_S7.Read<float>(address);
  343. }
  344. }
  345. }
  346. }
  347. if (RTrig.GetInstance("StockState").Start(HKDevice.HK_PLC_S7.Read<bool>(HKPlcCommAddress.RecipeDosingFinish)) || true)
  348. {
  349. BigStation.RecipeDosingStatus = 4;
  350. MessageLog.GetInstance.ShowRunLog($"配方状态:{code}配料完成");
  351. HKDevice.RecipeDosingFinishReset();
  352. RecipeQueue.TryDequeue(out code);
  353. IssuedComplete.Add(RemoteRecipes.ElementAt(index));//将该配方添加到下
  354. if (!BigStation.IsAllowManual)
  355. {
  356. Json<RemoteRecipeDataColl>.Data.Recipes.RemoveAt(index);//制作完成,移除当前配方
  357. }
  358. else
  359. {
  360. Json<LocalRecipeDataColl>.Data.Recipes.RemoveAt(index);//制作完成,移除当前配方
  361. }
  362. BigStation.RecipeDosingStatus = 0;
  363. }
  364. }
  365. }
  366. }
  367. }
  368. public ConcurrentDictionary<string, Object> ReadHKPLCData = new ConcurrentDictionary<string, object>();
  369. public ConcurrentDictionary<string, Object> ReadSiemensData = new ConcurrentDictionary<string, object>();
  370. private void ReadSiemensCommData()
  371. {
  372. if (SiemensDevice.IsConnected)
  373. {
  374. GetSiemensStatus("", new Action<object>((obj) =>
  375. {
  376. if (obj is bool[] bools && bools.Length > 0)
  377. {
  378. }
  379. }));
  380. }
  381. }
  382. private void ReadHKPLCCommData()
  383. {
  384. if (HKDevice.IsConnected)
  385. {
  386. GetSiemensStatus("", new Action<object>((obj) =>
  387. {
  388. if (obj is bool[] bools && bools.Length > 0)
  389. {
  390. }
  391. }));
  392. }
  393. }
  394. private void GetHKStatus(string key, Action<object> action)
  395. {
  396. if (ReadHKPLCData.ContainsKey(key))
  397. {
  398. if (ReadHKPLCData[key] != null)
  399. {
  400. action?.Invoke(ReadHKPLCData[key]);
  401. }
  402. }
  403. }
  404. private void GetSiemensStatus(string key, Action<object> action)
  405. {
  406. if (ReadSiemensData.ContainsKey(key))
  407. {
  408. if (ReadSiemensData[key] != null)
  409. {
  410. action?.Invoke(ReadSiemensData[key]);
  411. }
  412. }
  413. }
  414. private void WriteSiemens(string Address, object Value)
  415. {
  416. if (SiemensDevice.IsConnected)
  417. {
  418. SiemensDevice.Siemens_PLC_S7.Write(Address, Value);
  419. }
  420. }
  421. private void WriteHKPLC(string Address, object Value)
  422. {
  423. HKDevice.HK_PLC_S7.Write(Address, Value);
  424. }
  425. private object ReadSiemens(string Address)
  426. {
  427. if (SiemensDevice.IsConnected)
  428. {
  429. return SiemensDevice.Siemens_PLC_S7.Read<object>(Address);
  430. }
  431. else
  432. {
  433. return null;
  434. }
  435. }
  436. private bool[] ReadBoolsSiemens(int address, int count)
  437. {
  438. if (SiemensDevice.IsConnected)
  439. {
  440. return SiemensDevice.Siemens_PLC_S7.ReadBools(address, count);
  441. }
  442. else
  443. {
  444. return null;
  445. }
  446. }
  447. private object ReadHK(string Address)
  448. {
  449. if (HKDevice.IsConnected)
  450. {
  451. return HKDevice.HK_PLC_S7.Read<object>(Address);
  452. }
  453. else
  454. {
  455. return null;
  456. }
  457. }
  458. private bool[] ReadBoolsHK(int address, int count)
  459. {
  460. if (HKDevice.IsConnected)
  461. {
  462. return HKDevice.HK_PLC_S7.ReadBools(address, count);
  463. }
  464. else
  465. {
  466. return null;
  467. }
  468. }
  469. /// <summary>
  470. /// 获取料仓的原料名称和原料位置
  471. /// </summary>
  472. private void ReadPLCDeviceInfo()
  473. {
  474. for (int i = 0; i < 12; i++)
  475. {
  476. string RawMaterialName = HKDevice.HK_PLC_S7.Read<string>("");
  477. short RawMaterialLocation = HKDevice.HK_PLC_S7.Read<short>("");
  478. if (RawMaterialsNamePos.ContainsKey(RawMaterialName))
  479. RawMaterialsNamePos.Add(RawMaterialName, RawMaterialLocation);
  480. }
  481. }
  482. }
  483. }