using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using BPA.Helper; using System.Collections.Concurrent; using System.Collections.ObjectModel; using System.Windows; using System.Threading; using BPASmartClient.CustomResource.Pages.Model; using BPASmartClient.CustomResource.UserControls.MessageShow; using BPASmartClient.CustomResource.UserControls; using BPASmartClient.Model.柔性味魔方; using BPASmartClient.Model; using System.Diagnostics; namespace BPASmartClient.DosingSystem.ViewModel { public class RecipeControlViewModel : NotifyBase { static ConcurrentQueue RecipeNames = new ConcurrentQueue(); static ObservableCollection StockStatus = new ObservableCollection(); public RecipeControlViewModel() { StartCommand = new BPARelayCommand(RecipeIssued); ChangeRecipeStateCommand = new BPARelayCommand(ChangeRecipeState); RecipeRun(); RecipeStatusInquire(); } /// /// 配方下发 /// private void RecipeIssued(object o) { if (o != null && o is string deviceName) { int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == deviceName); if (index >= 0 && index < Recipes.Count) { for (int i = 0; i < Recipes.ElementAt(index).RawMaterials.Count; i++) { if (Recipes.ElementAt(index).RawMaterials.ElementAt(i).RawMaterialSource == 1) { string ip = Recipes.ElementAt(index).RawMaterials.ElementAt(i).DeviceIp; var device = DeviceInquire.GetInstance.GetDevice(ip); //if (!device.IsConnected) //{ // MessageNotify.GetInstance.ShowDialog($"设备 【{device.DeviceName}】 未连接,不允许下发此配方", DialogType.Error); // return; //} } } Recipes.ElementAt(index).IsEnable = false; Json.Data.Recipes.ElementAt(index).IsEnable = false; } MessageNotify.GetInstance.ShowUserLog($"下发工单 {Recipes.ElementAt(index).RecipeName}"); RecipeNames.Enqueue(deviceName); var t = RecipeNames.GetHashCode(); var res = Recipes.FirstOrDefault(p => p.RecipeName == deviceName); UserTreeWait.Add(new RecipeModel { SerialNum = UserTreeWait.Count + 1, RecipeName = deviceName, RawMaterials = res.RawMaterials }); } NoticeDemoViewModel.OpenMsg(EnumPromptType.Success, App.MainWindow, "提示", $"配方下发成功!"); MessageNotify.GetInstance.ShowUserLog($"下发工单 {Guid.NewGuid().ToString()}"); } /// /// 配方业务执行 /// private void RecipeRun() { ThreadManage.GetInstance().StartLong(new Action(() => { if (RecipeNames.Count > 0) { int index = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == RecipeNames.ElementAt(0)); if (index >= 0 && index < Recipes.Count) { Recipes.ElementAt(index).Are.Reset(); Recipes.ElementAt(index).IsEnable = false; StockStatus.Clear(); App.Current.Dispatcher.Invoke(new Action(() => { recipeProcesses.Clear(); if (UserTreeWait.Count > 0) UserTreeWait.RemoveAt(0); })); CurrentRecipeName = Recipes.ElementAt(index).RecipeName; #region 配方下发到PLC操作相关 //配方数据写入到输送机 var res = Json.Data.Recipes.FirstOrDefault(p => p.RecipeName == CurrentRecipeName); List recipeData = new List(); if (res != null) { var tInfo = res.RawMaterials.GroupBy(p => p.Loc);//获取桶号信息 if (tInfo != null) { for (int i = 0; i < tInfo.Count(); i++) { int data = 0; for (int m = 0; m < tInfo.ElementAt(i).Count(); m++) { var TempName = tInfo.ElementAt(i).ElementAt(m).RawMaterialName; var tempDevice = DeviceInquire.GetInstance.devices.FirstOrDefault(p => p.DeviceName == TempName); if (tempDevice != null) { data = data.SetBitValue((byte)tempDevice.DeviceNum, true); } } recipeData.Add(data); } } } if (recipeData.Count <= 0) { MessageNotify.GetInstance.ShowRunLog("配方数据解析失败"); return; } int offset = 2; //写入配方数据 MessageNotify.GetInstance.ShowRunLog("开始写入配方数据"); recipeData.ForEach(item => { SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBD{offset}", item); offset = offset += 4; }); SiemensDevice.GetInstance.MySiemens.Write("DB4.DBD198", recipeData.Count);//配方使用桶数写入 SiemensDevice.GetInstance.MySiemens.Write("DB4.DBX0.1", true);//配方执行启动 Stopwatch sw = new Stopwatch(); var recipe = Recipes.ElementAt(index); ObservableCollection RawMater = new ObservableCollection(); foreach (var item in recipe.RawMaterials) { RawMater.Add(new RawMaterialModel() { RawMaterialName = item.RawMaterialName, DeviceIp = item.DeviceIp, DownLimtFeedback = item.DownLimtFeedback, Loc = item.Loc, RawMaterialId = item.RawMaterialId, RawMaterialSource = item.RawMaterialSource, RawMaterialType = item.RawMaterialType, RawMaterialWeight = item.RawMaterialWeight, RecipeStatus = item.RecipeStatus, SelectIndex = item.SelectIndex, Status = item.Status, UpLimtFeedback = item.UpLimtFeedback, UpLimtWeightFeedback = item.UpLimtWeightFeedback, WeightFeedback = item.WeightFeedback, }); } App.Current.Dispatcher.Invoke(() => { recipeProcesses.Add(new RecipeModel() { RawMaterials = RawMater, IsEnable = recipe.IsEnable, RecipeName = recipe.RecipeName, SerialNum = recipe.SerialNum, RecipCode = recipe.RecipCode, }); }); sw.Restart(); while (true) { if (sw.ElapsedMilliseconds >= 3000 && !GlobalDevice.PlcData.ResComplete) { MessageNotify.GetInstance.ShowRunLog("获取配方下发反馈超时"); break; } if (GlobalDevice.PlcData.ResComplete) { SiemensDevice.GetInstance.MySiemens.Write("DB3.DBX0.1", false); break; } Thread.Sleep(100); } #endregion Recipes.ElementAt(index).Are.WaitOne();//阻塞,直到当前配方完成 RecipeNames.TryDequeue(out string deviceName); var recipeComple = Recipes.ElementAt(index); ObservableCollection RawMaterComple = new ObservableCollection(); foreach (var item in recipeComple.RawMaterials) { RawMaterComple.Add(new RawMaterialModel() { RawMaterialName = item.RawMaterialName, DeviceIp = item.DeviceIp, DownLimtFeedback = item.DownLimtFeedback, Loc = item.Loc, RawMaterialId = item.RawMaterialId, RawMaterialSource = item.RawMaterialSource, RawMaterialType = item.RawMaterialType, RawMaterialWeight = item.RawMaterialWeight, RecipeStatus = item.RecipeStatus, SelectIndex = item.SelectIndex, Status = item.Status, UpLimtFeedback = item.UpLimtFeedback, UpLimtWeightFeedback = item.UpLimtWeightFeedback, WeightFeedback = item.WeightFeedback, }); } App.Current.Dispatcher.Invoke(() => { UserTreeCompelete.Add(new RecipeModel() { RawMaterials = RawMaterComple, IsEnable = recipeComple.IsEnable, RecipeName = recipeComple.RecipeName, SerialNum = UserTreeCompelete.Count + 1, RecipCode = recipeComple.RecipCode, }); }); App.Current.Dispatcher.Invoke(new Action(() => { recipeProcesses.Clear(); CurrentRecipeName = string.Empty; }));//完成后清空当前配方 } } Thread.Sleep(100); }), "启动配方下发"); } /// /// 配方执行状态监听 /// private void RecipeStatusInquire() { ThreadManage.GetInstance().StartLong(new Action(() => { for (int i = 0; i < Recipes.Count; i++) { for (int m = 0; m < Recipes.ElementAt(i).RawMaterials.Count; m++) { var RunStatus = DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp).deviceStatus.RunStatus; //设备状态显示 if (Recipes.ElementAt(i).RecipeName == CurrentRecipeName) { string tempRawMaterialName = DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp).DeviceName; int recIndex = recipeProcesses.ToList().FindIndex(p => p.RecipeName == CurrentRecipeName); if (recIndex >= 0 && recIndex < recipeProcesses.Count) { int index = recipeProcesses.ElementAt(recIndex).RawMaterials.ToList().FindIndex(p => p.RawMaterialName == tempRawMaterialName); if (index >= 0 && index < recipeProcesses.ElementAt(recIndex).RawMaterials.Count) { //测试使用 //recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(index).RecipeStatus = RunStatus; } for (int j = 0; j < GlobalDevice.PlcData.IsAllowIngredients.Length; j++) { if (GlobalDevice.PlcData.IsAllowIngredients[j]) { int cnt = j + 1;//获取允许配料信号桶号的料仓位置 int Raw_Loc = Array.FindIndex(Recipes.ElementAt(i).RawMaterials.ToArray(), p => p.Loc == cnt); int Device_Loc = Array.FindIndex(DeviceInquire.GetInstance.devices.ToArray(), p => p.DeviceNum == cnt); if (Raw_Loc >= 0 && Device_Loc >= 0) { float weight = Recipes.ElementAt(i).RawMaterials.ElementAt(Raw_Loc).RawMaterialWeight; string deviceName = DeviceInquire.GetInstance.devices.ElementAt(Device_Loc).DeviceName; int loc = Array.FindIndex(Recipes.ElementAt(i).RawMaterials.ToArray(), p => p.RawMaterialName == deviceName); if (cnt > 0 && loc >= 0 && deviceName != null && weight >= 0) { int St_index = Array.FindIndex(StockStatus.ToArray(), p => p.MaterialName == deviceName); if (St_index < 0) { StockStatus.Add(new StockStatusModel() { MaterialName = deviceName, IssueWeight = weight, IssueStatus = 0, }); } St_index = Array.FindIndex(StockStatus.ToArray(), p => p.MaterialName == deviceName); if (St_index >= 0) { if (recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(loc).RecipeStatus == 1 && StockStatus.ElementAt(St_index).IssueStatus == 0) { StockStatus.ElementAt(St_index).IssueStatus = 1; DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp).Start(weight); MessageNotify.GetInstance.ShowRunLog($"柔性味魔方{Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp},开始出料"); } if (recipeProcesses.ElementAt(recIndex).RawMaterials.ElementAt(loc).RecipeStatus == 3 && StockStatus.ElementAt(St_index).IssueStatus == 1) { GlobalDevice.PlcData.IsAllowIngredients[j] = false;//测试使用 StockStatus.ElementAt(St_index).IssueStatus = 2; DeviceInquire.GetInstance.GetDevice(Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp).StatusReset(); SiemensDevice.GetInstance.MySiemens.Write("DB4.DBD130", 0.SetBitValue((byte)loc, true)); MessageNotify.GetInstance.ShowRunLog($"柔性味魔方{Recipes.ElementAt(i).RawMaterials.ElementAt(loc).DeviceIp},出料完成,状态复位"); } } } } } } int Finish_Count = StockStatus.Where(s => s.IssueStatus == 2).Count(); if (StockStatus.Count >= Recipes.ElementAt(i).RawMaterials.Count && Finish_Count >= Recipes.ElementAt(i).RawMaterials.Count) //配方配料完成 { StockStatus.Clear(); SiemensDevice.GetInstance.MySiemens.Write("DB4.DBX202.1", true);//配方使用桶数写入 int recipIndex = Array.FindIndex(Recipes.ToArray(), p => p.RecipeName == CurrentRecipeName); App.Current.Dispatcher.Invoke(new Action(() => { recipeProcesses.Clear(); })); Recipes.ElementAt(recipIndex).IsEnable = true; Json.Data.Recipes.ElementAt(recipIndex).IsEnable = true; Recipes.ElementAt(recipIndex).Are.Set(); Thread.Sleep(100); } } } } } Thread.Sleep(100); }), "RecipeControlViewModelStatusInquire"); } public BPARelayCommand StartCommand { get; set; } public BPARelayCommand ChangeRecipeStateCommand { get; set; } public static ObservableCollection Recipes { get; set; } = Json.Data.Recipes; public static string CurrentRecipeName { get { return _RecipeName; } set { _RecipeName = value; OnStaticPropertyChanged(); } } private static string _RecipeName; /// /// 当前正在制作的配方 /// public static ObservableCollection recipeProcesses { get; set; } = new ObservableCollection(); /// /// 等待制作的配方 /// public static ObservableCollection UserTreeWait { get; set; } = new ObservableCollection(); /// /// 已完成的配方 /// public static ObservableCollection UserTreeCompelete { get; set; } = new ObservableCollection(); private void ChangeRecipeState(object o) { if (o == null) return; if (o is string id) { var Recipe = recipeProcesses.FirstOrDefault(p => p.RecipeName == CurrentRecipeName); if (Recipe != null) { var res = Recipe.RawMaterials.FirstOrDefault(p => p.RawMaterialId == id); if (res != null) { if (res.RecipeStatus == 3) { res.RecipeStatus = 1; } else { res.RecipeStatus = 3; } } } } } } }