终端一体化运控平台
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

476 行
23 KiB

  1. //#define ModelSwitch
  2. using BPA.Helper;
  3. using BPASmartClient.SmallBatchingSystem;
  4. using System;
  5. using System.Collections.Concurrent;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using BPASmartClient.CustomResource.Pages.Model;
  13. using BPASmartClient.CustomResource.UserControls.MessageShow;
  14. using BPASmartClient.CustomResource.UserControls;
  15. namespace BPASmartClient.SmallBatchingSystem
  16. {
  17. public class Control
  18. {
  19. private volatile static Control _Instance;
  20. public static Control GetInstance => _Instance ?? (_Instance = new Control());
  21. private Control() { }
  22. public ConcurrentQueue<RecipeInfo> MakeOrderQueue { get; set; } = new ConcurrentQueue<RecipeInfo>();
  23. public bool IsCancel { get; set; }
  24. public void Init()
  25. {
  26. TaskManage.GetInstance.Start(new Action(() =>
  27. {
  28. PlcServer.GetInstance.Connect();
  29. }), "设备初始化");
  30. TaskManage.GetInstance.StartLong(new Action(() =>
  31. {
  32. while (MakeOrderQueue.Count > 0)
  33. {
  34. if (MakeOrderQueue.TryDequeue(out RecipeInfo recipeInfo))
  35. {
  36. ProcessOne(recipeInfo);
  37. //ProcessTwo(recipeInfo);
  38. }
  39. }
  40. Thread.Sleep(10);
  41. }), "配方流程控制");
  42. }
  43. private void ProcessOne(RecipeInfo recipeInfo)
  44. {
  45. IsCancel = false;
  46. List<int> OutletInfo = new List<int>();
  47. recipeInfo.SiloInfoModels.ToList()?.ForEach(item =>
  48. {
  49. var res = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s.Contains(item.SiloName)) != null);
  50. if (res != null) if (!OutletInfo.Contains(res.OutletLoc)) OutletInfo.Add(res.OutletLoc);
  51. });
  52. foreach (var temp in OutletInfo)
  53. {
  54. PlcServer.GetInstance.WriteData("VW302", (ushort)temp);//设置出料口位置
  55. PlcServer.GetInstance.WriteData("M10.0", true);//定位启动
  56. RunLog($"启动定位,出料口位置:{temp}");
  57. int index = temp - 1;
  58. if (index >= 0)
  59. {
  60. RunLog("等待定位完成");
  61. while (!PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);//等待定位反馈
  62. if (IsCancel) break;
  63. RunLog("定位完成");
  64. PlcServer.GetInstance.WriteData("M20.0", false);
  65. while (PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);
  66. if (IsCancel) break;
  67. RunLog("定位完成,复位成功");
  68. foreach (var temp1 in recipeInfo.SiloInfoModels)
  69. {
  70. var rest = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s.Contains(temp1.SiloName)) != null);
  71. if (rest != null && rest.OutletLoc == temp)
  72. {
  73. var res = Json<ConfigInfoModel>.Data.SiloInfoModels.FirstOrDefault(p => p.SiloName == temp1.SiloName);
  74. if (res != null)
  75. {
  76. StatusNotify(res.SiloName, Status.正在配料);
  77. RunLog($"写重量地址:{GetWeightAdd(res.SiloLoc)},重量:{temp1.SiloWeight * 10}");
  78. PlcServer.GetInstance.WriteData(GetWeightAdd(res.SiloLoc), (ushort)(temp1.SiloWeight * 10));
  79. RunLog($"写启动信号地址:{GetStartSingleAdd(res.SiloLoc)}");
  80. PlcServer.GetInstance.WriteData(GetStartSingleAdd(res.SiloLoc), true);
  81. while (!PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成
  82. if (IsCancel) break;
  83. RunLog("出料完成,复位出料完成状态");
  84. PlcServer.GetInstance.WriteData("M4.0", false);//复位出料完成信号
  85. while (PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成信号复位成功
  86. if (IsCancel) break;
  87. RunLog("出料完成复位成功");
  88. StatusNotify(res.SiloName, Status.配料完成);
  89. }
  90. }
  91. }
  92. if (IsCancel) return;
  93. }
  94. }
  95. if (!IsCancel)
  96. {
  97. RunLog($"写入配方执行完成信号");
  98. PlcServer.GetInstance.WriteData("M10.4", true);
  99. RunLog("等待配方执行完成");
  100. while (!PlcDataModel.RecipeBatchingComplete && !IsCancel) Thread.Sleep(1);
  101. if (IsCancel) return;
  102. RunLog($"【{recipeInfo.RecipeName}】配方执行完成");
  103. ActionManage.GetInstance.Send("GrindArenaceousCancel");
  104. }
  105. // IsCancel = false;
  106. // Dictionary<int, List<int>> DeviceSoilInfo = new Dictionary<int, List<int>>();
  107. // List<int> OutletInfo = new List<int>();
  108. // recipeInfo.SiloInfoModels.ToList()?.ForEach(item =>
  109. // {
  110. // var res = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s == item.SiloName) != null);
  111. // if (res != null)
  112. // {
  113. // var soliInfo = Json<ConfigInfoModel>.Data.SiloInfoModels.FirstOrDefault(p => p.SiloName == item.SiloName);
  114. // if (soliInfo != null)
  115. // {
  116. // if (!DeviceSoilInfo.ContainsKey(res.OutletLoc))
  117. // {
  118. // DeviceSoilInfo.Add(res.OutletLoc, new List<int>());
  119. // DeviceSoilInfo[res.OutletLoc].Add(soliInfo.SiloLoc);
  120. // }
  121. // else
  122. // {
  123. // DeviceSoilInfo[res.OutletLoc].Add(soliInfo.SiloLoc);
  124. // }
  125. // }
  126. // }
  127. // });
  128. // foreach (var temp in DeviceSoilInfo)
  129. // {
  130. // PlcServer.GetInstance.WriteData("VW302", (ushort)temp.Key);//设置出料口位置
  131. //#if ModelSwitch
  132. // PlcServer.GetInstance.WriteData("M10.4", true);//定位启动
  133. //#else
  134. // PlcServer.GetInstance.WriteData("M10.0", true);//定位启动
  135. //#endif
  136. // RunLog($"启动定位,出料口位置:{temp.Key}");
  137. // int index = temp.Key - 1;
  138. // if (index >= 0)
  139. // {
  140. // RunLog("等待定位完成");
  141. // while (!PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);//等待定位反馈
  142. // if (IsCancel) break;
  143. // RunLog("定位完成");
  144. // PlcServer.GetInstance.WriteData("M20.0", false);
  145. // while (PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);
  146. // if (IsCancel) break;
  147. // RunLog("定位完成,复位成功");
  148. // foreach (var temp1 in temp.Value)
  149. // {
  150. // //var rest = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s.Contains(temp1.SiloName)) != null);
  151. // //if (rest != null && rest.OutletLoc == temp)
  152. // //{
  153. // var res = Json<ConfigInfoModel>.Data.SiloInfoModels.FirstOrDefault(p => p.SiloLoc == temp1);
  154. // if (res != null)
  155. // {
  156. // var tempRecipe = recipeInfo.SiloInfoModels.FirstOrDefault(p => p.SiloName == res.SiloName);
  157. // if (tempRecipe != null)
  158. // {
  159. // StatusNotify(res.SiloName, Status.正在配料);
  160. // RunLog($"写重量地址:{GetWeightAdd(res.SiloLoc)},重量:{tempRecipe.SiloWeight}");
  161. // PlcServer.GetInstance.WriteData(GetWeightAdd(res.SiloLoc), (ushort)(tempRecipe.SiloWeight * 10));
  162. // RunLog($"写启动信号地址:{GetStartSingleAdd(res.SiloLoc)}");
  163. // PlcServer.GetInstance.WriteData(GetStartSingleAdd(res.SiloLoc), true);
  164. // while (!PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成
  165. // if (IsCancel) break;
  166. // RunLog("出料完成,复位出料完成状态");
  167. //#if ModelSwitch
  168. // PlcServer.GetInstance.WriteData("M10.0", false);//复位出料完成信号
  169. //#else
  170. // PlcServer.GetInstance.WriteData("M4.0", false);//复位出料完成信号
  171. //#endif
  172. // while (PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成信号复位成功
  173. // if (IsCancel) break;
  174. // RunLog("出料完成复位成功");
  175. // StatusNotify(res.SiloName, Status.配料完成);
  176. // }
  177. // }
  178. // //}
  179. // }
  180. // if (IsCancel) return;
  181. // }
  182. // }
  183. }
  184. /// <summary>
  185. /// 计时配料
  186. /// </summary>
  187. /// <param name="recipeInfo"></param>
  188. private void ProcessTwo(RecipeInfo recipeInfo)
  189. {
  190. IsCancel = false;
  191. Dictionary<int, List<int>> DeviceSoilInfo = new Dictionary<int, List<int>>();
  192. List<int> OutletInfo = new List<int>();
  193. recipeInfo.SiloInfoModels.ToList()?.ForEach(item =>
  194. {
  195. var res = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s == item.SiloName) != null);
  196. if (res != null)
  197. {
  198. var soliInfo = Json<ConfigInfoModel>.Data.SiloInfoModels.FirstOrDefault(p => p.SiloName == item.SiloName);
  199. if (soliInfo != null)
  200. {
  201. if (!DeviceSoilInfo.ContainsKey(res.OutletLoc))
  202. {
  203. DeviceSoilInfo.Add(res.OutletLoc, new List<int>());
  204. DeviceSoilInfo[res.OutletLoc].Add(soliInfo.SiloLoc);
  205. }
  206. else
  207. {
  208. DeviceSoilInfo[res.OutletLoc].Add(soliInfo.SiloLoc);
  209. }
  210. }
  211. }
  212. });
  213. foreach (var temp in DeviceSoilInfo)
  214. {
  215. PlcServer.GetInstance.WriteData("VW302", (ushort)temp.Key);//设置出料口位置
  216. //PlcServer.GetInstance.WriteData("M10.0", true);//定位启动
  217. PlcServer.GetInstance.WriteData("M10.4", true);//定位启动
  218. RunLog($"启动定位,出料口位置:{temp}");
  219. int index = temp.Key - 1;
  220. if (index >= 0)
  221. {
  222. RunLog("等待定位完成");
  223. while (!PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);//等待定位反馈
  224. if (IsCancel) break;
  225. RunLog("定位完成");
  226. PlcServer.GetInstance.WriteData("M20.0", false);
  227. while (PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);
  228. if (IsCancel) break;
  229. RunLog("定位完成,复位成功");
  230. foreach (var temp1 in temp.Value)
  231. {
  232. //var rest = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s.Contains(temp1.SiloName)) != null);
  233. //if (rest != null && rest.OutletLoc == temp)
  234. //{
  235. var res = Json<ConfigInfoModel>.Data.SiloInfoModels.FirstOrDefault(p => p.SiloLoc == temp1);
  236. if (res != null)
  237. {
  238. var tempRecipe = recipeInfo.SiloInfoModels.FirstOrDefault(p => p.SiloName == res.SiloName);
  239. if (tempRecipe != null)
  240. {
  241. StatusNotify(res.SiloName, Status.正在配料);
  242. RunLog($"写重量地址:{GetWeightAdd(res.SiloLoc)},重量:{tempRecipe.SiloWeight}");
  243. PlcServer.GetInstance.WriteData(GetWeightAdd(res.SiloLoc), (ushort)(tempRecipe.SiloWeight * 10));
  244. RunLog($"写启动信号地址:{GetStartSingleAdd(res.SiloLoc)}");
  245. PlcServer.GetInstance.WriteData(GetStartSingleAdd(res.SiloLoc), true);
  246. while (!PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成
  247. if (IsCancel) break;
  248. RunLog("出料完成,复位出料完成状态");
  249. #if ModelSwitch
  250. PlcServer.GetInstance.WriteData("M10.0", false);//复位出料完成信号
  251. #else
  252. PlcServer.GetInstance.WriteData("M4.0", false);//复位出料完成信号
  253. #endif
  254. while (PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成信号复位成功
  255. if (IsCancel) break;
  256. RunLog("出料完成复位成功");
  257. StatusNotify(res.SiloName, Status.配料完成);
  258. }
  259. }
  260. //}
  261. }
  262. if (IsCancel) return;
  263. }
  264. }
  265. //IsCancel = false;
  266. //List<int> OutletInfo = new List<int>();
  267. //recipeInfo.SiloInfoModels.ToList()?.ForEach(item =>
  268. //{
  269. // var res = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s.Contains(item.SiloName)) != null);
  270. // if (res != null) if (!OutletInfo.Contains(res.OutletLoc)) OutletInfo.Add(res.OutletLoc);
  271. //});
  272. //foreach (var temp in OutletInfo)
  273. //{
  274. // PlcServer.GetInstance.WriteData("VW302", (ushort)temp);//设置出料口位置
  275. // //PlcServer.GetInstance.WriteData("M10.0", true);//定位启动
  276. // PlcServer.GetInstance.WriteData("M10.4", true);//定位启动
  277. // RunLog($"启动定位,出料口位置:{temp}");
  278. // int index = temp - 1;
  279. // if (index >= 0)
  280. // {
  281. // RunLog("等待定位完成");
  282. // while (!PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);//等待定位反馈
  283. // if (IsCancel) break;
  284. // RunLog("定位完成");
  285. // PlcServer.GetInstance.WriteData("M20.0", false);
  286. // while (PlcDataModel.TargetLocComplete && !IsCancel) Thread.Sleep(1);
  287. // if (IsCancel) break;
  288. // RunLog("定位完成,复位成功");
  289. // foreach (var temp1 in recipeInfo.SiloInfoModels)
  290. // {
  291. // var rest = Json<ConfigInfoModel>.Data.OutletInfoModels.FirstOrDefault(p => p.SiloInfos.FirstOrDefault(s => s.Contains(temp1.SiloName)) != null);
  292. // if (rest != null && rest.OutletLoc == temp)
  293. // {
  294. // var res = Json<ConfigInfoModel>.Data.SiloInfoModels.FirstOrDefault(p => p.SiloName == temp1.SiloName);
  295. // if (res != null)
  296. // {
  297. // StatusNotify(res.SiloName, Status.正在配料);
  298. // RunLog($"写重量地址:{GetWeightAdd(res.SiloLoc)},重量:{temp1.SiloWeight}");
  299. // PlcServer.GetInstance.WriteData(GetWeightAdd(res.SiloLoc), (ushort)(temp1.SiloWeight * 10));
  300. // RunLog($"写启动信号地址:{GetStartSingleAdd(res.SiloLoc)}");
  301. // PlcServer.GetInstance.WriteData(GetStartSingleAdd(res.SiloLoc), true);
  302. // while (!PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成
  303. // if (IsCancel) break;
  304. // RunLog("出料完成,复位出料完成状态");
  305. //#if test
  306. // PlcServer.GetInstance.WriteData("M10.0", false);//复位出料完成信号
  307. //#else
  308. //PlcServer.GetInstance.WriteData("M4.0", false);//复位出料完成信号
  309. //#endif
  310. // while (PlcDataModel.BatchingCompleted && !IsCancel) Thread.Sleep(1);//等待出料完成信号复位成功
  311. // if (IsCancel) break;
  312. // RunLog("出料完成复位成功");
  313. // StatusNotify(res.SiloName, Status.配料完成);
  314. // }
  315. // }
  316. // }
  317. // if (IsCancel) return;
  318. // }
  319. //}
  320. if (!IsCancel)
  321. {
  322. RunLog($"写入配方执行完成信号");
  323. //PlcServer.GetInstance.WriteData("M10.4", true);
  324. PlcServer.GetInstance.WriteData("M10.5", true);
  325. RunLog("等待配方执行完成");
  326. while (!PlcDataModel.RecipeBatchingComplete && !IsCancel) Thread.Sleep(1);
  327. if (IsCancel) return;
  328. RunLog($"【{recipeInfo.RecipeName}】配方执行完成");
  329. ActionManage.GetInstance.Send("GrindArenaceousCancel");
  330. }
  331. }
  332. /// <summary>
  333. /// 获取重量设置地址
  334. /// </summary>
  335. /// <param name="num"></param>
  336. /// <returns></returns>
  337. private string GetWeightAdd(int num)
  338. {
  339. #if ModelSwitch
  340. if (num > 0)
  341. {
  342. int add = 0;
  343. if (num >= 1 && num <= 18)
  344. {
  345. add = 200 + (num - 1) * 2;
  346. }
  347. return $"VW{add}";
  348. }
  349. return default;
  350. #else
  351. if (num > 0)
  352. {
  353. int add = 0;
  354. if (num >= 1 && num <= 8)
  355. {
  356. add = 100 + (num - 1) * 2;
  357. }
  358. else if (num >= 9 && num <= 18)
  359. {
  360. add = 102 + (num - 1) * 2;
  361. }
  362. return $"VW{add}";
  363. }
  364. return default;
  365. #endif
  366. }
  367. private void StatusNotify(string SiloName, Status Status)
  368. {
  369. ActionManage.GetInstance.Send("StatusNotify", new RecipeStatus() { RawMaterialName = SiloName, Status = Status.ToString() });
  370. }
  371. public void RunLog(string info)
  372. {
  373. BPA.Helper.MessageLog.GetInstance.Show(info);
  374. BPASmartClient.CustomResource.Pages.Model.MessageNotify.GetInstance.ShowRunLog(info);
  375. Debug.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}:{info}");
  376. }
  377. public void OperationLog(string info)
  378. {
  379. BPA.Helper.MessageLog.GetInstance.Show(info);
  380. BPASmartClient.CustomResource.Pages.Model.MessageNotify.GetInstance.ShowUserLog(info);
  381. Debug.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")}:{info}");
  382. }
  383. public void DebugLog(string info)
  384. {
  385. MessageLog.GetInstance.Show(info);
  386. }
  387. public void NotifyPrompt(string info)
  388. {
  389. App.Current.Dispatcher.Invoke(() =>
  390. {
  391. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, App.MainWindow, "提示", info);
  392. });
  393. }
  394. /// <summary>
  395. /// 获取启动信号地址
  396. /// </summary>
  397. /// <param name="num"></param>
  398. /// <returns></returns>
  399. private string GetStartSingleAdd(int num)
  400. {
  401. #if ModelSwitch
  402. if (num > 0)
  403. {
  404. string Add = string.Empty;
  405. var t = num / 8;
  406. var c = (num % 8);
  407. if (c == 0)
  408. {
  409. t--;
  410. c = 7;
  411. }
  412. else c--;
  413. Add = $"M{t + 4}.{c}";
  414. return Add;
  415. }
  416. return default;
  417. #else
  418. if (num > 0)
  419. {
  420. string Add = string.Empty;
  421. var t = num / 8;
  422. var c = (num % 8);
  423. if (c == 0)
  424. {
  425. t--;
  426. c = 7;
  427. }
  428. else c--;
  429. Add = $"M{t}.{c}";
  430. return Add;
  431. }
  432. return default;
  433. #endif
  434. }
  435. }
  436. }