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

370 lines
20 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using BPA.Helper;
  7. using System.Collections.Concurrent;
  8. using System.Collections.ObjectModel;
  9. using System.Windows;
  10. using System.Threading;
  11. using BPASmartClient.CustomResource.Pages.Model;
  12. using BPASmartClient.CustomResource.UserControls.MessageShow;
  13. using BPASmartClient.CustomResource.UserControls;
  14. using BPASmartClient.Model.柔性味魔方;
  15. using BPASmartClient.Model;
  16. using System.Diagnostics;
  17. namespace BPASmartClient.DosingSystem.ViewModel
  18. {
  19. public class RecipeControlViewModel : NotifyBase
  20. {
  21. static ConcurrentQueue<string> RecipeNames = new ConcurrentQueue<string>();
  22. static ObservableCollection<StockStatusModel> StockStatus = new ObservableCollection<StockStatusModel>();
  23. public RecipeControlViewModel()
  24. {
  25. StartCommand = new BPARelayCommand<object>(RecipeIssued);
  26. ChangeRecipeStateCommand = new BPARelayCommand<object>(ChangeRecipeState);
  27. RecipeRun();
  28. RecipeStatusInquire();
  29. }
  30. /// <summary>
  31. /// 配方下发
  32. /// </summary>
  33. private void RecipeIssued(object o)
  34. {
  35. if (o != null && o is string deviceName)
  36. {
  37. int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == deviceName);
  38. if (index >= 0 && index < Recipes.Count)
  39. {
  40. for (int i = 0; i < Recipes.ElementAt(index).RawMaterials.Count; i++)
  41. {
  42. if (Recipes.ElementAt(index).RawMaterials.ElementAt(i).RawMaterialSource == 1)
  43. {
  44. string ip = Recipes.ElementAt(index).RawMaterials.ElementAt(i).DeviceIp;
  45. var device = DeviceInquire.GetInstance.GetDevice(ip);
  46. //if (!device.IsConnected)
  47. //{
  48. // MessageNotify.GetInstance.ShowDialog($"设备 【{device.DeviceName}】 未连接,不允许下发此配方", DialogType.Error);
  49. // return;
  50. //}
  51. }
  52. }
  53. Recipes.ElementAt(index).IsEnable = false;
  54. Json<LocaPar>.Data.Recipes.ElementAt(index).IsEnable = false;
  55. }
  56. MessageNotify.GetInstance.ShowUserLog($"下发工单 {Recipes.ElementAt(index).RecipeName}");
  57. RecipeNames.Enqueue(deviceName);
  58. var t = RecipeNames.GetHashCode();
  59. var res = Recipes.FirstOrDefault(p => p.RecipeName == deviceName);
  60. UserTreeWait.Add(new RecipeModel { SerialNum = UserTreeWait.Count + 1, RecipeName = deviceName, RawMaterials = res.RawMaterials });
  61. }
  62. NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, App.MainWindow, "提示", $"配方下发成功!");
  63. MessageNotify.GetInstance.ShowUserLog($"下发工单 {Guid.NewGuid().ToString()}");
  64. }
  65. /// <summary>
  66. /// 配方业务执行
  67. /// </summary>
  68. private void RecipeRun()
  69. {
  70. ThreadManage.GetInstance().StartLong(new Action(() =>
  71. {
  72. if (RecipeNames.Count > 0)
  73. {
  74. int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == RecipeNames.ElementAt(0));
  75. if (index >= 0 && index < Recipes.Count)
  76. {
  77. Recipes.ElementAt(index).Are.Reset();
  78. Recipes.ElementAt(index).IsEnable = false;
  79. StockStatus.Clear();
  80. App.Current.Dispatcher.Invoke(new Action(() =>
  81. {
  82. recipeProcesses.Clear();
  83. if (UserTreeWait.Count > 0) UserTreeWait.RemoveAt(0);
  84. }));
  85. CurrentRecipeName = Recipes.ElementAt(index).RecipeName;
  86. #region 配方下发到PLC操作相关
  87. //配方数据写入到输送机
  88. var res = Json<LocaPar>.Data.Recipes.FirstOrDefault(p => p.RecipeName == CurrentRecipeName);
  89. List<int> recipeData = new List<int>();
  90. if (res != null)
  91. {
  92. var tInfo = res.RawMaterials.GroupBy(p => p.Loc);//获取桶号信息
  93. if (tInfo != null)
  94. {
  95. for (int i = 0; i < tInfo.Count(); i++)
  96. {
  97. int data = 0;
  98. for (int m = 0; m < tInfo.ElementAt(i).Count(); m++)
  99. {
  100. var TempName = tInfo.ElementAt(i).ElementAt(m).RawMaterialName;
  101. var tempDevice = DeviceInquire.GetInstance.devices.FirstOrDefault(p => p.DeviceName == TempName);
  102. if (tempDevice != null)
  103. {
  104. data = data.SetBitValue((byte)tempDevice.DeviceNum, true);
  105. }
  106. }
  107. recipeData.Add(data);
  108. }
  109. }
  110. }
  111. if (recipeData.Count <= 0)
  112. {
  113. MessageNotify.GetInstance.ShowRunLog("配方数据解析失败");
  114. return;
  115. }
  116. int offset = 2;
  117. //写入配方数据
  118. MessageNotify.GetInstance.ShowRunLog("开始写入配方数据");
  119. recipeData.ForEach(item =>
  120. {
  121. SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBD{offset}", item);
  122. offset = offset += 4;
  123. });
  124. SiemensDevice.GetInstance.MySiemens.Write("DB4.DBD198", recipeData.Count);//配方使用桶数写入
  125. SiemensDevice.GetInstance.MySiemens.Write("DB4.DBX0.1", true);//配方执行启动
  126. Stopwatch sw = new Stopwatch();
  127. var recipe = Recipes.ElementAt(index);
  128. ObservableCollection<RawMaterialModel> RawMater = new ObservableCollection<RawMaterialModel>();
  129. foreach (var item in recipe.RawMaterials)
  130. {
  131. RawMater.Add(new RawMaterialModel()
  132. {
  133. RawMaterialName = item.RawMaterialName,
  134. DeviceIp = item.DeviceIp,
  135. DownLimtFeedback = item.DownLimtFeedback,
  136. Loc = item.Loc,
  137. RawMaterialId = item.RawMaterialId,
  138. RawMaterialSource = item.RawMaterialSource,
  139. RawMaterialType = item.RawMaterialType,
  140. RawMaterialWeight = item.RawMaterialWeight,
  141. RecipeStatus = item.RecipeStatus,
  142. SelectIndex = item.SelectIndex,
  143. Status = item.Status,
  144. UpLimtFeedback = item.UpLimtFeedback,
  145. UpLimtWeightFeedback = item.UpLimtWeightFeedback,
  146. WeightFeedback = item.WeightFeedback,
  147. });
  148. }
  149. App.Current.Dispatcher.Invoke(() =>
  150. {
  151. recipeProcesses.Add(new RecipeModel()
  152. {
  153. RawMaterials = RawMater,
  154. IsEnable = recipe.IsEnable,
  155. RecipeName = recipe.RecipeName,
  156. SerialNum = recipe.SerialNum,
  157. RecipCode = recipe.RecipCode,
  158. });
  159. });
  160. sw.Restart();
  161. while (true)
  162. {
  163. if (sw.ElapsedMilliseconds >= 3000 && !GlobalDevice.PlcData.ResComplete)
  164. {
  165. MessageNotify.GetInstance.ShowRunLog("获取配方下发反馈超时");
  166. break;
  167. }
  168. if (GlobalDevice.PlcData.ResComplete)
  169. {
  170. SiemensDevice.GetInstance.MySiemens.Write("DB3.DBX0.1", false);
  171. break;
  172. }
  173. Thread.Sleep(100);
  174. }
  175. #endregion
  176. Recipes.ElementAt(index).Are.WaitOne();//阻塞,直到当前配方完成
  177. RecipeNames.TryDequeue(out string deviceName);
  178. var recipeComple = Recipes.ElementAt(index);
  179. ObservableCollection<RawMaterialModel> RawMaterComple = new ObservableCollection<RawMaterialModel>();
  180. foreach (var item in recipeComple.RawMaterials)
  181. {
  182. RawMaterComple.Add(new RawMaterialModel()
  183. {
  184. RawMaterialName = item.RawMaterialName,
  185. DeviceIp = item.DeviceIp,
  186. DownLimtFeedback = item.DownLimtFeedback,
  187. Loc = item.Loc,
  188. RawMaterialId = item.RawMaterialId,
  189. RawMaterialSource = item.RawMaterialSource,
  190. RawMaterialType = item.RawMaterialType,
  191. RawMaterialWeight = item.RawMaterialWeight,
  192. RecipeStatus = item.RecipeStatus,
  193. SelectIndex = item.SelectIndex,
  194. Status = item.Status,
  195. UpLimtFeedback = item.UpLimtFeedback,
  196. UpLimtWeightFeedback = item.UpLimtWeightFeedback,
  197. WeightFeedback = item.WeightFeedback,
  198. });
  199. }
  200. App.Current.Dispatcher.Invoke(() =>
  201. {
  202. UserTreeCompelete.Add(new RecipeModel()
  203. {
  204. RawMaterials = RawMaterComple,
  205. IsEnable = recipeComple.IsEnable,
  206. RecipeName = recipeComple.RecipeName,
  207. SerialNum = UserTreeCompelete.Count + 1,
  208. RecipCode = recipeComple.RecipCode,
  209. });
  210. });
  211. App.Current.Dispatcher.Invoke(new Action(() =>
  212. {
  213. recipeProcesses.Clear();
  214. CurrentRecipeName = string.Empty;
  215. }));//完成后清空当前配方
  216. }
  217. }
  218. Thread.Sleep(100);
  219. }), "启动配方下发");
  220. }
  221. /// <summary>
  222. /// 配方执行状态监听
  223. /// </summary>
  224. private void RecipeStatusInquire()
  225. {
  226. ThreadManage.GetInstance().StartLong(new Action(() =>
  227. {
  228. for (int i = 0; i < Recipes.Count; i++)
  229. {
  230. for (int m = 0; m < Recipes.ElementAt(i).RawMaterials.Count; m++)
  231. {
  232. var RunStatus = DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp).deviceStatus.RunStatus;
  233. //设备状态显示
  234. if (Recipes.ElementAt(i).RecipeName == CurrentRecipeName)
  235. {
  236. string tempRawMaterialName = DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp).DeviceName;
  237. int recIndex = recipeProcesses.ToList().FindIndex(p => p.RecipeName == CurrentRecipeName);
  238. if (recIndex >= 0 && recIndex < recipeProcesses.Count)
  239. {
  240. int index = recipeProcesses.ElementAt(recIndex).RawMaterials.ToList().FindIndex(p => p.RawMaterialName == tempRawMaterialName);
  241. if (index >= 0 && index < recipeProcesses.ElementAt(recIndex).RawMaterials.Count)
  242. {
  243. //测试使用
  244. //recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(index).RecipeStatus = RunStatus;
  245. }
  246. for (int j = 0; j < GlobalDevice.PlcData.IsAllowIngredients.Length; j++)
  247. {
  248. if (GlobalDevice.PlcData.IsAllowIngredients[j])
  249. {
  250. int cnt = j + 1;//获取允许配料信号桶号的料仓位置
  251. int Raw_Loc = Array.FindIndex(Recipes.ElementAt(i).RawMaterials.ToArray(), p => p.Loc == cnt);
  252. int Device_Loc = Array.FindIndex(DeviceInquire.GetInstance.devices.ToArray(), p => p.DeviceNum == cnt);
  253. if (Raw_Loc >= 0 && Device_Loc >= 0)
  254. {
  255. float weight = Recipes.ElementAt(i).RawMaterials.ElementAt(Raw_Loc).RawMaterialWeight;
  256. string deviceName = DeviceInquire.GetInstance.devices.ElementAt(Device_Loc).DeviceName;
  257. int loc = Array.FindIndex(Recipes.ElementAt(i).RawMaterials.ToArray(), p => p.RawMaterialName == deviceName);
  258. if (cnt > 0 && loc >= 0 && deviceName != null && weight >= 0)
  259. {
  260. int St_index = Array.FindIndex(StockStatus.ToArray(), p => p.MaterialName == deviceName);
  261. if (St_index < 0)
  262. {
  263. StockStatus.Add(new StockStatusModel()
  264. {
  265. MaterialName = deviceName,
  266. IssueWeight = weight,
  267. IssueStatus = 0,
  268. });
  269. }
  270. St_index = Array.FindIndex(StockStatus.ToArray(), p => p.MaterialName == deviceName);
  271. if (St_index >= 0)
  272. {
  273. if (recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(loc).RecipeStatus == 1 && StockStatus.ElementAt(St_index).IssueStatus == 0)
  274. {
  275. StockStatus.ElementAt(St_index).IssueStatus = 1;
  276. DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp).Start(weight);
  277. MessageNotify.GetInstance.ShowRunLog($"柔性味魔方{Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp},开始出料");
  278. }
  279. if (recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(loc).RecipeStatus == 3 && StockStatus.ElementAt(St_index).IssueStatus == 1)
  280. {
  281. GlobalDevice.PlcData.IsAllowIngredients[j] = false;//测试使用
  282. StockStatus.ElementAt(St_index).IssueStatus = 2;
  283. DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp).StatusReset();
  284. SiemensDevice.GetInstance.MySiemens.Write("DB4.DBD130", 0.SetBitValue((byte)loc, true));
  285. MessageNotify.GetInstance.ShowRunLog($"柔性味魔方{Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp},出料完成,状态复位");
  286. }
  287. }
  288. }
  289. }
  290. }
  291. }
  292. int Finish_Count = StockStatus.Where(s => s.IssueStatus == 2).Count();
  293. if (StockStatus.Count >= Recipes.ElementAt(i).RawMaterials.Count && Finish_Count >= Recipes.ElementAt(i).RawMaterials.Count) //配方配料完成
  294. {
  295. StockStatus.Clear();
  296. SiemensDevice.GetInstance.MySiemens.Write("DB4.DBX202.1", true);//配方使用桶数写入
  297. int recipIndex = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == CurrentRecipeName);
  298. App.Current.Dispatcher.Invoke(new Action(() => { recipeProcesses.Clear(); }));
  299. Recipes.ElementAt(recipIndex).IsEnable = true;
  300. Json<LocaPar>.Data.Recipes.ElementAt(recipIndex).IsEnable = true;
  301. Recipes.ElementAt(recipIndex).Are.Set();
  302. Thread.Sleep(100);
  303. }
  304. }
  305. }
  306. }
  307. }
  308. Thread.Sleep(100);
  309. }), "RecipeControlViewModelStatusInquire");
  310. }
  311. public BPARelayCommand<object> StartCommand { get; set; }
  312. public BPARelayCommand<object> ChangeRecipeStateCommand { get; set; }
  313. public static ObservableCollection<RecipeModel> Recipes { get; set; } = Json<LocaPar>.Data.Recipes;
  314. public static string CurrentRecipeName { get { return _RecipeName; } set { _RecipeName = value; OnStaticPropertyChanged(); } }
  315. private static string _RecipeName;
  316. /// <summary>
  317. /// 当前正在制作的配方
  318. /// </summary>
  319. public static ObservableCollection<RecipeModel> recipeProcesses { get; set; } = new ObservableCollection<RecipeModel>();
  320. /// <summary>
  321. /// 等待制作的配方
  322. /// </summary>
  323. public static ObservableCollection<RecipeModel> UserTreeWait { get; set; } = new ObservableCollection<RecipeModel>();
  324. /// <summary>
  325. /// 已完成的配方
  326. /// </summary>
  327. public static ObservableCollection<RecipeModel> UserTreeCompelete { get; set; } = new ObservableCollection<RecipeModel>();
  328. private void ChangeRecipeState(object o)
  329. {
  330. if (o == null) return;
  331. if (o is string id)
  332. {
  333. var Recipe = recipeProcesses.FirstOrDefault(p => p.RecipeName == CurrentRecipeName);
  334. if (Recipe != null)
  335. {
  336. var res = Recipe.RawMaterials.FirstOrDefault(p => p.RawMaterialId == id);
  337. if (res != null)
  338. {
  339. if (res.RecipeStatus == 3)
  340. {
  341. res.RecipeStatus = 1;
  342. }
  343. else
  344. {
  345. res.RecipeStatus = 3;
  346. }
  347. }
  348. }
  349. }
  350. }
  351. }
  352. }