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

404 lines
16 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 ConcurrentQueue<long> RecipeQueue = new ConcurrentQueue<long>();
  38. /// <summary>
  39. /// AGV到达工站队列
  40. /// </summary>
  41. public ConcurrentQueue<int> AGVToWorkStationQueue = new ConcurrentQueue<int>();
  42. /// <summary>
  43. /// 接收原料数据
  44. /// </summary>
  45. public RecipeRawMaterial RawMaterial;
  46. public void Init()
  47. {
  48. ActionManage.GetInstance.Register(new Action(() =>
  49. {
  50. if (SiemensDevice.IsConnected)
  51. {
  52. var res = SiemensDevice.Siemens_PLC_S7.Read<string>(SiemensCommAddress.RecipeName);
  53. var res1 = SiemensDevice.Siemens_PLC_S7.Read<uint>(SiemensCommAddress.RecipeID);
  54. var res2 = SiemensDevice.Siemens_PLC_S7.ReadClass<RecipeRawMaterial>(0, 0);
  55. if ((res != null && res is string recipeName) && (res1 != null && res1 is uint recipeID))
  56. {
  57. int index = Array.FindIndex(Json<RemoteRecipeDataColl>.Data.Recipes.ToArray(), p => p.RecipeCode == recipeID);
  58. if (index == -1)
  59. {
  60. RawMaterials.Clear();
  61. for (int i = 0; i < 15; i++)
  62. {
  63. RawMaterials.Add(new RemoteRecipeRawMaterial()
  64. {
  65. RawMaterialBarrelNum = res2.RawMaterialBarrelNum[i],
  66. RawMaterialLocation = res2.RawMaterialLocation[i],
  67. RawMaterialWeight = res2.RawMaterialWeight[i]
  68. });
  69. }
  70. Json<RemoteRecipeDataColl>.Data.Recipes.Add(new RemoteRecipeData()
  71. {
  72. RecipeName = recipeName,
  73. RecipeCode = recipeID,
  74. RawMaterial = RawMaterials
  75. });
  76. }
  77. else
  78. {
  79. MessageLog.GetInstance.AlarmLog("配方列表中存在该配方ID");
  80. }
  81. }
  82. }
  83. }), "西门子下发配方", true);
  84. ActionManage.GetInstance.Register(new Action(() =>
  85. {
  86. if (SiemensDevice.IsConnected)
  87. {
  88. var res = SiemensDevice.Siemens_PLC_S7.Read<int>(SiemensCommAddress.TrayLocationNum);
  89. var res1 = SiemensDevice.Siemens_PLC_S7.Read<int>(SiemensCommAddress.RecipeID);
  90. if (res != null && res is int TrayLocation && res1 != null && res1 is int recipeId)
  91. {
  92. int index = Array.FindIndex(RemoteRecipes.ToArray(), p => p.RecipeCode == recipeId);
  93. if (index >= 0 && index < RemoteRecipes.Count)
  94. {
  95. RemoteRecipes.ElementAt(index).TrayCode = TrayLocation;
  96. MessageLog.GetInstance.RunLog($"接收到AGV进站信号=>配方编码:{recipeId} 、托盘位置:{TrayLocation}");
  97. AGVToWorkStationQueue.Enqueue(recipeId);
  98. }
  99. }
  100. }
  101. }), "AGV到位信号", true);//根据下发的配方ID将 托盘的位置信息添加到配方中
  102. string HK_PLC_IP = ConfigurationManager.AppSettings["HKPlc_IP"];
  103. string Siemens_PLC_IP = ConfigurationManager.AppSettings["Siemens_IP"];
  104. try
  105. {
  106. //HKDevice.HK_PLC_S7.Connect(S7.Net.CpuType.S71500, HK_PLC_IP);
  107. //SiemensDevice.Siemens_PLC_S7.Connect(S7.Net.CpuType.S71500, Siemens_PLC_IP);
  108. if (HKDevice.IsConnected)
  109. {
  110. HKDevice.Init();
  111. }
  112. if (SiemensDevice.IsConnected)
  113. {
  114. SiemensDevice.Init();
  115. }
  116. }
  117. catch (Exception ex)
  118. {
  119. }
  120. RecipeQueue.Clear();
  121. Json<RemoteRecipeDataColl>.Data.Recipes = TestData.GetInstance.Recipes;//添加测试数据
  122. ThreadManage.GetInstance().StartLong(new Action(() =>
  123. {
  124. ReceviceData();
  125. RecipeInfoToHKPLC();
  126. Thread.Sleep(10);
  127. }), "流程处理", true);
  128. ThreadManage.GetInstance().StartLong(new Action(() =>
  129. {
  130. if (HKDevice.IsConnected && SiemensDevice.IsConnected)
  131. {
  132. AgvGetInOut();
  133. }
  134. Thread.Sleep(10);
  135. }), "AGV进站送取货", true);
  136. ThreadManage.GetInstance().StartLong(new Action(() =>
  137. {
  138. ReadSiemensCommData();
  139. ReadHKPLCCommData();
  140. }), "读取西门子和海科PLC的数据", true);
  141. }
  142. /// <summary>
  143. /// AGV送货
  144. /// </summary>
  145. /// <param name="bitNum"></param>
  146. private void AGV_Delivery(int bitNum)
  147. {
  148. if ((ReadSiemens("M4002." + bitNum) is bool) && BigStation.AgvDeliveryPosition == 0)
  149. {
  150. BigStation.AgvDeliveryPosition = 1;
  151. WriteHKPLC("M4002." + bitNum, true);
  152. WriteSiemens("M4002." + bitNum, false);
  153. }
  154. else if (ReadHK("M5002." + bitNum) is bool && BigStation.AgvDeliveryPosition == 1)
  155. {
  156. BigStation.AgvDeliveryPosition = 2;
  157. WriteSiemens("M5002." + bitNum, true);
  158. WriteHKPLC("M5002." + bitNum, false);
  159. }
  160. else if (ReadSiemens("M4004." + bitNum) is bool && BigStation.AgvDeliveryPosition == 2)
  161. {
  162. BigStation.AgvDeliveryPosition = 3;
  163. WriteHKPLC("M4004." + bitNum, true);
  164. WriteSiemens("M4004." + bitNum, false);
  165. }
  166. else if (ReadHK("M5004." + bitNum) is bool && BigStation.AgvDeliveryPosition == 3)
  167. {
  168. BigStation.AgvDeliveryPosition = 4;
  169. WriteSiemens("M5004." + bitNum, true);
  170. WriteHKPLC("M5004." + bitNum, false);
  171. }
  172. else if (ReadSiemens("M4005." + bitNum) is bool && BigStation.AgvDeliveryPosition == 4)
  173. {
  174. BigStation.AgvDeliveryPosition = 5;
  175. WriteHKPLC("M4005." + bitNum, true);
  176. WriteSiemens("M4005." + bitNum, false);
  177. }
  178. else if (ReadHK("M5005." + bitNum) is bool && BigStation.AgvDeliveryPosition == 5)
  179. {
  180. WriteSiemens("M5005." + bitNum, true);
  181. WriteHKPLC("M5005." + bitNum, false);
  182. }
  183. }
  184. /// <summary>
  185. /// AGV取货
  186. /// </summary>
  187. /// <param name="bitNum"></param>
  188. private void AGV_Pick(int bitNum)
  189. {
  190. if (ReadSiemens("M4003" + bitNum) is bool && BigStation.AgvPickUpPosition == 0)
  191. {
  192. BigStation.AgvPickUpPosition = 1;
  193. WriteHKPLC("M4003." + bitNum, true);
  194. WriteSiemens("M4003." + bitNum, false);
  195. }
  196. if (ReadHK("M5003" + bitNum) is bool && BigStation.AgvPickUpPosition == 1)
  197. {
  198. BigStation.AgvPickUpPosition = 2;
  199. WriteSiemens("M5003" + bitNum, true);
  200. WriteHKPLC("M5003" + bitNum, false);
  201. }
  202. if (ReadSiemens("M4006." + bitNum) is bool && BigStation.AgvPickUpPosition == 2)
  203. {
  204. BigStation.AgvPickUpPosition = 3;
  205. WriteHKPLC("M4006." + bitNum, true);
  206. WriteSiemens("M4006." + bitNum, false);
  207. }
  208. if (ReadHK("M5006." + bitNum) is bool && BigStation.AgvPickUpPosition == 3)
  209. {
  210. WriteSiemens("M5006." + bitNum, true);
  211. WriteHKPLC("M5006." + bitNum, false);
  212. }
  213. }
  214. /// <summary>
  215. /// AGV进站送货
  216. /// </summary>
  217. private void AgvGetInOut()
  218. {
  219. //获取工位上是否有小车
  220. SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.StationIsExistCar, (bool)
  221. HKDevice.HK_PLC_S7.Read<bool>(HKPlcCommAddress.StationIsExistCar));
  222. //检测AGV到站信号
  223. if (AGVToWorkStationQueue.Count > 0)
  224. {
  225. int index = Array.FindIndex(RemoteRecipes.ToArray(), p => p.RecipeCode == AGVToWorkStationQueue.ElementAt(0));
  226. int TrayLocation = RemoteRecipes.ElementAt(index).TrayCode;//根据配方编号,找到托盘的ID 托盘ID1-6
  227. int RecipeCode = (int)RemoteRecipes.ElementAt(index).RecipeCode;
  228. if (TrayLocation > 0 && TrayLocation < 7)
  229. {
  230. AGV_Delivery(TrayLocation - 1);
  231. if (BigStation.AgvDeliveryPosition == 5)
  232. {
  233. BigStation.AgvDeliveryPosition = 0;
  234. //AGVToWorkStationQueue.TryDequeue(out RecipeCode);
  235. }
  236. AGV_Pick(TrayLocation - 1);
  237. if (BigStation.AgvPickUpPosition == 3)
  238. {
  239. BigStation.AgvPickUpPosition = 0;
  240. AGVToWorkStationQueue.TryDequeue(out RecipeCode);
  241. }
  242. }
  243. }
  244. }
  245. private void ReceviceData()
  246. {
  247. RemoteRecipes = Json<RemoteRecipeDataColl>.Data.Recipes;
  248. if (RemoteRecipes.Count > 0)
  249. {
  250. foreach (var data in RemoteRecipes)
  251. {
  252. if (!(RecipeQueue.Contains(data.RecipeCode)))
  253. RecipeQueue.Enqueue(data.RecipeCode);
  254. }
  255. }
  256. }
  257. ushort[] BarrelNum = new ushort[15];
  258. ushort[] Location = new ushort[15];
  259. ushort[] Weight = new ushort[15];
  260. private void RecipeInfoToHKPLC()
  261. {
  262. if (RecipeQueue.Count > 0)
  263. {
  264. int index = Array.FindIndex(RemoteRecipes.ToArray(), p => p.RecipeCode == RecipeQueue.ElementAt(0));
  265. if (index >= 0 && index <= RemoteRecipes.Count)
  266. {
  267. long code = RemoteRecipes.ElementAt(index).RecipeCode;
  268. if (HKDevice.HK_PLC_S7.Read<bool>("M5001.0") is bool)//配方1是否允许下发配发
  269. {
  270. for (int i = 0; i < RemoteRecipes.ElementAt(index).RawMaterial.Count; i++)
  271. {
  272. BarrelNum[i] = (ushort)RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(i).RawMaterialBarrelNum;
  273. Location[i] = (ushort)RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(i).RawMaterialLocation;
  274. Weight[i] = (ushort)RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(i).RawMaterialWeight;
  275. }
  276. HKDevice.StockBinPar(BarrelNum, Location, Weight);
  277. HKDevice.HK_PLC_S7.Write("M4001.0", 1);//配发下发完成,to plc
  278. HKDevice.HK_PLC_S7.Write("M5001.0", 0);//复位允许下发配方1信号
  279. //BigStation.IssueRecipeFinish = true;
  280. }
  281. if (RTrig.GetInstance("StockState").Start(HKDevice.HK_PLC_S7.Read<bool>(HKPlcCommAddress.RecipeDosingFinish) is bool))
  282. {
  283. HKDevice.RecipeDosingFinishReset();
  284. RecipeQueue.TryDequeue(out code);
  285. IssuedComplete.Add(RemoteRecipes.ElementAt(index));//将该配方添加到下
  286. Json<RemoteRecipeDataColl>.Data.Recipes.RemoveAt(index);//制作完成,移除当前配方
  287. }
  288. }
  289. }
  290. }
  291. public ConcurrentDictionary<string, Object> ReadHKPLCData = new ConcurrentDictionary<string, object>();
  292. public ConcurrentDictionary<string, Object> ReadSiemensData = new ConcurrentDictionary<string, object>();
  293. private void ReadSiemensCommData()
  294. {
  295. if (SiemensDevice.IsConnected)
  296. {
  297. GetSiemensStatus("", new Action<object>((obj) =>
  298. {
  299. if (obj is bool[] bools && bools.Length > 0)
  300. {
  301. }
  302. }));
  303. }
  304. }
  305. private void ReadHKPLCCommData()
  306. {
  307. if (HKDevice.IsConnected)
  308. {
  309. GetSiemensStatus("", new Action<object>((obj) =>
  310. {
  311. if (obj is bool[] bools && bools.Length > 0)
  312. {
  313. }
  314. }));
  315. }
  316. }
  317. private void GetHKStatus(string key, Action<object> action)
  318. {
  319. if (ReadHKPLCData.ContainsKey(key))
  320. {
  321. if (ReadHKPLCData[key] != null)
  322. {
  323. action?.Invoke(ReadHKPLCData[key]);
  324. }
  325. }
  326. }
  327. private void GetSiemensStatus(string key, Action<object> action)
  328. {
  329. if (ReadSiemensData.ContainsKey(key))
  330. {
  331. if (ReadSiemensData[key] != null)
  332. {
  333. action?.Invoke(ReadSiemensData[key]);
  334. }
  335. }
  336. }
  337. private void WriteSiemens(string Address, object Value)
  338. {
  339. if (SiemensDevice.IsConnected)
  340. {
  341. SiemensDevice.Siemens_PLC_S7.Write(Address, Value);
  342. }
  343. }
  344. private void WriteHKPLC(string Address, object Value)
  345. {
  346. HKDevice.HK_PLC_S7.Write(Address, Value);
  347. }
  348. private object ReadSiemens(string Address)
  349. {
  350. if (SiemensDevice.IsConnected)
  351. {
  352. return SiemensDevice.Siemens_PLC_S7.Read<object>(Address);
  353. }
  354. else
  355. {
  356. return null;
  357. }
  358. }
  359. private bool[] ReadBoolsSiemens(int address, int count)
  360. {
  361. if (SiemensDevice.IsConnected)
  362. {
  363. return SiemensDevice.Siemens_PLC_S7.ReadBools(address, count);
  364. }
  365. else
  366. {
  367. return null;
  368. }
  369. }
  370. private object ReadHK(string Address)
  371. {
  372. if (HKDevice.IsConnected)
  373. {
  374. return HKDevice.HK_PLC_S7.Read<object>(Address);
  375. }
  376. else
  377. {
  378. return null;
  379. }
  380. }
  381. private bool[] ReadBoolsHK(int address, int count)
  382. {
  383. if (HKDevice.IsConnected)
  384. {
  385. return HKDevice.HK_PLC_S7.ReadBools(address, count);
  386. }
  387. else
  388. {
  389. return null;
  390. }
  391. }
  392. }
  393. }