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

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