diff --git a/BPA.Model/Enums/MoveConveyer.cs b/BPA.Model/Enums/MoveConveyerStep.cs similarity index 86% rename from BPA.Model/Enums/MoveConveyer.cs rename to BPA.Model/Enums/MoveConveyerStep.cs index 66fa5c9..75b61ea 100644 --- a/BPA.Model/Enums/MoveConveyer.cs +++ b/BPA.Model/Enums/MoveConveyerStep.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace BPA.Model.Enums { - public enum MoveConveyer:int + public enum MoveConveyerStep:int { WaitMove=0, Moveing=100, diff --git a/BPA.Model/GlobalData.cs b/BPA.Model/GlobalData.cs index 5dc6c5d..b45b3de 100644 --- a/BPA.Model/GlobalData.cs +++ b/BPA.Model/GlobalData.cs @@ -22,7 +22,7 @@ namespace BPA.Model #endregion #region 传送带 - public MoveConveyer MoveConveyerStep { get; set; } + public MoveConveyerStep MoveConveyerStep { get; set; } #endregion } } diff --git a/BPA.Model/Recipe/RecipeData.cs b/BPA.Model/Recipe/RecipeData.cs index b789bcf..8e1705f 100644 --- a/BPA.Model/Recipe/RecipeData.cs +++ b/BPA.Model/Recipe/RecipeData.cs @@ -37,6 +37,8 @@ namespace BPA.Model.Recipe Name = name; MaterialData = materialData; //取决于工位数量,本案例中,有五个工位,但是第三个工位没有设备。 + + CurrentStation = 1;//初始默认为1。 IsMakeComplete = new bool[stationCount]; IssueTime = DateTime.Now; BatchStatus = new(); diff --git a/BPA.SingleDevice/Business/Conveyer.cs b/BPA.SingleDevice/Business/Conveyer.cs index c9ce1cf..01fb6c6 100644 --- a/BPA.SingleDevice/Business/Conveyer.cs +++ b/BPA.SingleDevice/Business/Conveyer.cs @@ -47,7 +47,7 @@ namespace BPA.SingleDevice.Business { HaveVessel[0] = haveVessel.GetBitValue(1); HaveVessel[1] = haveVessel.GetBitValue(2); - //HaveVessel[2] = false; + HaveVessel[2] = true; HaveVessel[3] = haveVessel.GetBitValue(3); HaveVessel[4] = haveVessel.GetBitValue(4); }); diff --git a/BPA.SingleDevice/Business/ProcessControl.cs b/BPA.SingleDevice/Business/ProcessControl.cs index e5ee00e..812ca15 100644 --- a/BPA.SingleDevice/Business/ProcessControl.cs +++ b/BPA.SingleDevice/Business/ProcessControl.cs @@ -1,6 +1,7 @@ using Amazon.SecurityToken.Model; using BPA.Model.Enums; using BPA.Model.Recipe; +using BPA.Model.Table; using BPA.SingleDevice.Interface; using BPA.SingleDevice.Json; using BPA.SingleDevice.Services; @@ -32,6 +33,8 @@ namespace BPA.SingleDevice.Business List currentTask = new(); //ConcurrentDictionary test = new(); + List currentRecipes = new(); + IConveyer conveyer = new Conveyer(); private readonly ILogService logService; private GlobalData global; @@ -60,23 +63,23 @@ namespace BPA.SingleDevice.Business batchers.TryAdd(4, new Batcher()); batchers.TryAdd(5, new Batcher()); - SetBatcherComm(1, "192.168.6.100"); - SetBatcherComm(2, "192.168.6.101"); - SetBatcherComm(4, "192.168.6.102"); - SetBatcherComm(5, "192.168.6.103"); + //SetBatcherComm(1, "192.168.6.100"); + //SetBatcherComm(2, "192.168.6.101"); + //SetBatcherComm(4, "192.168.6.102"); + //SetBatcherComm(5, "192.168.6.103"); - //SetBatcherComm(1, "127.0.0.1", 503); - //SetBatcherComm(2, "127.0.0.1", 504); - //SetBatcherComm(4, "127.0.0.1", 505); - //SetBatcherComm(5, "127.0.0.1", 506); + SetBatcherComm(1, "127.0.0.1", 503); + SetBatcherComm(2, "127.0.0.1", 504); + SetBatcherComm(4, "127.0.0.1", 505); + SetBatcherComm(5, "127.0.0.1", 506); foreach (var batcher in batchers.Values) { await batcher.Initial(); } #endregion - conveyer.SetCommParam(1, "192.168.6.104",508); - //conveyer.SetCommParam(1, "127.0.0.1",510); + //conveyer.SetCommParam(1, "192.168.6.104",508); + conveyer.SetCommParam(1, "127.0.0.1",510); await conveyer.Initial(); currentTask.Clear(); @@ -86,40 +89,68 @@ namespace BPA.SingleDevice.Business { InterActive(); - for (int i = 0; i < currentTask.Count; i++) + //for (int i = 0; i < currentTask.Count; i++) + //{ + // if (currentTask[i].CurrentRecipe.IsMakeComplete.All(b=>b==true)) + // { + // currentTask.RemoveAt(i); + // break; + // } + //} + + for (int i = 0; i < currentRecipes.Count; i++) { - if (currentTask[i].CurrentRecipe.IsMakeComplete.All(b=>b==true)) + if (currentRecipes[i].IsMakeComplete.All(b => b == true)) { - currentTask.RemoveAt(i); + var recipeName = currentRecipes[i].Name; + var time = DateTime.Now.Subtract(currentRecipes[i].IssueTime); + currentRecipes.RemoveAt(i); + logService.LogRecipeCompleteInfo($"【{recipeName}】,耗时【{time.Seconds}】秒。"); + logService.LogRunInfo($"配方【{recipeName}】-- 整体配料完成,已从配料队列移除。"); break; } } + if (global.RecipeQueue.Count>0/* && currentRecipe is null*/ ) { //多配方情况下,必须在工位1没有碗位置,才能进行下发,否则会与之前的配方冲突。 - if (/*!conveyer.HaveVessel[0] &&*/ global.RecipeQueue.ElementAt(0) is not null && global.RecipeQueue.ElementAt(0) is RecipeData && currentTask.Count <5 ) - { + //if (/*!conveyer.HaveVessel[0] &&*/ global.RecipeQueue.ElementAt(0) is not null && global.RecipeQueue.ElementAt(0) is RecipeData && currentTask.Count <5 ) + //{ + + //global.RecipeQueue.TryDequeue(out currentRecipe); + //cts = new(); + //Task.Run(() => { Batching(currentRecipe); }, cts.Token); + //logService.LogRunInfo($"配方【{currentRecipe.Name}】-- 开始执行配料。"); - //global.RecipeQueue.TryDequeue(out currentRecipe); - //cts = new(); - //Task.Run(() => { Batching(currentRecipe); }, cts.Token); - //logService.LogRunInfo($"配方【{currentRecipe.Name}】-- 开始执行配料。"); + //global.RecipeQueue.TryDequeue(out RecipeData recipe); + //if (recipe !=null) + //{ + // currentTask.Add(new TaskServer() { RunTask = Task.Run(() => { Batching(recipe); }), + // ID = recipe.IssueTime.Ticks,CurrentRecipe=recipe }); + // logService.LogRunInfo($"配方【{recipe.Name}】-- 开始执行配料。"); + //} + //} + + if (/*!conveyer.HaveVessel[0] &&*/ global.RecipeQueue.ElementAt(0) is not null && global.RecipeQueue.ElementAt(0) is RecipeData && currentRecipes.Count <5 ) + { global.RecipeQueue.TryDequeue(out RecipeData recipe); - if (recipe !=null) + if (recipe != null) { - currentTask.Add(new TaskServer() { RunTask = Task.Run(() => { Batching(recipe); }), - ID = recipe.IssueTime.Ticks,CurrentRecipe=recipe }); + currentRecipes.Add(recipe); logService.LogRunInfo($"配方【{recipe.Name}】-- 开始执行配料。"); } } } + + Batching(); }, "MonitorRecipeIssue", true); } /// /// 配料。 /// /// 需要配料的配方 + [Obsolete("流程有错误")] private async void Batching(RecipeData recipe) { if (recipe is null) @@ -129,7 +160,7 @@ namespace BPA.SingleDevice.Business } while (recipe.IsMakeComplete[0] == false) { - await StationBatching(recipe, 1); + //await StationBatching(recipe, 1); } for (int stationNum = 2; stationNum <= 5; stationNum++) { @@ -146,23 +177,21 @@ namespace BPA.SingleDevice.Business /// /// 配方 /// 工位数。 - private async Task StationBatching(RecipeData recipe,int stationNum) + private void StationBatching(RecipeData recipe,int stationNum) { #region 数据验证 - if (recipe is null) - { - logService.LogRunInfo($"参数值为null,配料流程结束。"); - return; - } + //if (recipe is null) + //{ + // logService.LogRunInfo($"参数值为null,配料流程结束。"); + // return; + //} //如果配料机里没连接该工位的配料机,则直接完成。 if (!batchers.ContainsKey(stationNum)) { recipe.BatchStatus[stationNum] = BatchStep.BatchCompleted; recipe.IsMakeComplete[stationNum - 1] = true; - logService.LogRunInfo($"参数值为[{stationNum}],目前该工位无配料机或连接配料机失败。"); - //工位3无到位检测。 - //recipe.CurrentStation = stationNum; + logService.LogRunInfo($"参数【工位】值为[{stationNum}],目前该工位无配料机或连接配料机失败。"); return; } #endregion @@ -170,7 +199,6 @@ namespace BPA.SingleDevice.Business //数组起始索引是0,工位起始ID是1。 if (conveyer.HaveVessel[stationNum-1]) { - recipe.CurrentStation = stationNum; ushort[] materialList=new ushort[14]; //获取工位需要的配料数据。 if (recipe.MaterialData.ContainsKey(stationNum)) @@ -185,7 +213,7 @@ namespace BPA.SingleDevice.Business logService.LogRunInfo($"参数值为[{stationNum}],该配方无该工位配料需求。"); return; } - //配料完成的上升沿检测。 + //配料机配料完成的上升沿检测。 var completeTrig =RTrig.GetInstance($"Batchers[{stationNum}].BatchComplete").Start(batchers[stationNum].BatchComplete); //配料流程。 @@ -205,7 +233,7 @@ namespace BPA.SingleDevice.Business else { logService.LogRunInfo($"配方【{recipe.Name}】写入工位【{stationNum}】的下料参数失败,稍后重试。"); - await Task.Delay(3000); + Task.Delay(3000).Wait(); } } else @@ -218,18 +246,15 @@ namespace BPA.SingleDevice.Business if (batchers[stationNum].StartBatching()) { recipe.BatchStatus[stationNum] = BatchStep.WaitBatchComplete; - logService.LogRunInfo($"配方【{recipe.Name}】工位【{stationNum}】的开始配料,等待配料完成信号上升沿。"); + logService.LogRunInfo($"配方【{recipe.Name}】工位【{stationNum}】开始配料,等待配料完成信号上升沿。"); } else { - logService.LogRunInfo($"配方【{recipe.Name}】写入工位【{stationNum}】的开始配料失败,3S后重试。"); - await Task.Delay(3000); + logService.LogRunInfo($"配方【{recipe.Name}】写入工位【{stationNum}】开始配料失败,3S后重试。"); + Task.Delay(3000).Wait(); } break; case BatchStep.WaitBatchComplete: - //先延时,以免味魔方还没开始工作,未把配料完成写为false。 - //await Task.Delay(500); - //if (batchers[stationNum].BatchComplete) if (completeTrig) { logService.LogRunInfo($"配方【{recipe.Name}】工位【{stationNum}】的配料完成。"); @@ -244,25 +269,25 @@ namespace BPA.SingleDevice.Business else { logService.LogRunInfo($"配方【{recipe.Name}】工位【{stationNum}】未检测到容器到位,请检查,3秒后重新检测。"); - await Task.Delay(3000); + Task.Delay(3000).Wait(); } } - + [Obsolete("流程有错误")] private async Task MoveOnceAndBatach(RecipeData recipe,int stationNum) { - global.MoveConveyerStep = MoveConveyer.WaitMove; - while (global.MoveConveyerStep != MoveConveyer.MoveComplete) + global.MoveConveyerStep = MoveConveyerStep.WaitMove; + while (global.MoveConveyerStep != MoveConveyerStep.MoveComplete) { var moveCompleteTrig = RTrig.GetInstance("MoveCompleted").Start(conveyer.MoveComplete); switch (global.MoveConveyerStep) { - case MoveConveyer.WaitMove: + case MoveConveyerStep.WaitMove: conveyer.InitalMoveParam(); await Task.Delay(500); if (conveyer.MoveOnce()) { logService.LogRunInfo($"配方【{recipe.Name}】控制传送带去下个工位,等待动作完成信号上升沿。"); - global.MoveConveyerStep = MoveConveyer.Moveing; + global.MoveConveyerStep = MoveConveyerStep.Moveing; } else { @@ -270,19 +295,19 @@ namespace BPA.SingleDevice.Business await Task.Delay(3000); } break; - case MoveConveyer.Moveing: + case MoveConveyerStep.Moveing: if (moveCompleteTrig) { logService.LogRunInfo($"配方【{recipe.Name}】控制传送带移动结束。"); conveyer.InitalMoveParam(); while (recipe.IsMakeComplete[stationNum - 1] == false) { - await StationBatching(recipe, stationNum); + //await StationBatching(recipe, stationNum); } - global.MoveConveyerStep = MoveConveyer.MoveComplete; + global.MoveConveyerStep = MoveConveyerStep.MoveComplete; } break; - case MoveConveyer.MoveComplete: + case MoveConveyerStep.MoveComplete: //logService.LogRunInfo($"配方【{recipe.Name}】控制传送带移动结束。"); //await StationBatching(recipe, stationNum); break; @@ -291,6 +316,49 @@ namespace BPA.SingleDevice.Business } /// + /// 移动传送带。 + /// + /// + private void MoveConveyer() + { + //global.MoveConveyerStep = MoveConveyerStep.WaitMove; + //while (global.MoveConveyerStep != MoveConveyerStep.MoveComplete) + //{ + var moveCompleteTrig = RTrig.GetInstance("MoveCompleted").Start(conveyer.MoveComplete); + switch (global.MoveConveyerStep) + { + case MoveConveyerStep.WaitMove: + conveyer.InitalMoveParam(); + Task.Delay(500).Wait(); + if (conveyer.MoveOnce()) + { + logService.LogRunInfo($"控制传送带去下个工位,等待动作完成信号上升沿。"); + global.MoveConveyerStep = MoveConveyerStep.Moveing; + } + else + { + logService.LogRunInfo($"控制传送带去下个工位失败,可能连接异常或不允许移动,3S后重试。"); + Task.Delay(3000).Wait(); + } + break; + case MoveConveyerStep.Moveing: + if (moveCompleteTrig) + { + logService.LogRunInfo($"控制传送带移动结束。"); + + global.MoveConveyerStep = MoveConveyerStep.MoveComplete; + } + break; + case MoveConveyerStep.MoveComplete: + conveyer.InitalMoveParam(); + UpdateRecipe(); + global.MoveConveyerStep = MoveConveyerStep.WaitMove; + //不会执行该步骤,会直接跳出循环。 + break; + } + //} + } + /// /// 设置相应设备ID的配料机的通讯参数。 /// /// 该设备对应的工位ID。 @@ -313,11 +381,20 @@ namespace BPA.SingleDevice.Business ActionManage.GetInstance.Register(new Func(() => { //目前如果工位1 没有碗或者当前没配方就可以下配方。 - //bool result =(currentTask.Count > 0 && !conveyer.HaveVessel[0]) || (currentTask.Count==0); - foreach (var item in currentTask) + //foreach (var item in currentTask) + //{ + // //起始工位没完成的不允许下配方。 + // if (!item.CurrentRecipe.IsMakeComplete[0]) + // { + // return false; + // } + //} + //return true; + + //2023.10.14修改:如果在配方队列里,有配方的当前工位是1,则不允许下发新的配方。 + foreach (var item in currentRecipes) { - //起始工位没完成的不允许下配方。 - if (!item.CurrentRecipe.IsMakeComplete[0]) + if (item.CurrentStation==1) { return false; } @@ -364,6 +441,21 @@ namespace BPA.SingleDevice.Business } return true; } + /// + /// 2023.10.14:新增,所有在队列的配方,必须等当前工位的配料完成后才可以移动,否则不允许移动。 + /// + /// + private bool IsAllowConveyerMove() + { + foreach (var item in currentRecipes) + { + if (item.IsMakeComplete[item.CurrentStation-1]==false) + { + return false; + } + } + return true; + } private void SingleDetect() { //TODO:上升沿信号检测。 @@ -375,8 +467,6 @@ namespace BPA.SingleDevice.Business { ConveyerConfig conveyerConfig = new() { IP = "192.168.6.104", Port = 502, ID = 1, IsConnect = true }; Json.Data.ConveyerConfigs.Add(conveyerConfig); - - } /// /// 初始化配料机配置。 @@ -389,7 +479,10 @@ namespace BPA.SingleDevice.Business Json.Data.BatcherConfigs.Add(batcherConfig); } } - + /// + /// 初始化配料机。 + /// + /// private void InitalBatcher(IList configs) { foreach (var item in configs) @@ -402,6 +495,48 @@ namespace BPA.SingleDevice.Business } } } + + /// + /// 刷新配方的当前工站。 + /// + private void UpdateRecipe() + { + foreach (var item in currentRecipes) + { + //if (item.CurrentStation<5 && conveyer.HaveVessel[item.CurrentStation]) + //{ + // item.CurrentStation++; + //} + + if (item.CurrentStation<5) + { + while (!conveyer.HaveVessel[item.CurrentStation]) + { + logService.LogRunInfo($"未检测到配方【{item.Name}】在工位【{item.CurrentStation + 1}】的容器到位信号,请检查。"); + Task.Delay(3000).Wait(); + } + item.CurrentStation++; + } + } + } + /// + /// 适用于多配方的配料。 + /// + private void Batching() + { + if (currentRecipes.Count>0 && IsAllowConveyerMove()) + { + MoveConveyer(); + } + foreach (var item in currentRecipes) + { + if (!item.IsMakeComplete[item.CurrentStation-1]) + { + StationBatching(item, item.CurrentStation); + } + } + + } } } diff --git a/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml b/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml index cb57591..cc7bdf7 100644 --- a/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml +++ b/BPA.SingleDevice/View/AddRawMaterialDialogView.xaml @@ -38,7 +38,7 @@ diff --git a/BPA.SingleDevice/View/DebugView.xaml b/BPA.SingleDevice/View/DebugView.xaml index ac5a487..18a2cf5 100644 --- a/BPA.SingleDevice/View/DebugView.xaml +++ b/BPA.SingleDevice/View/DebugView.xaml @@ -12,32 +12,77 @@ mc:Ignorable="d"> + + + + - -