diff --git a/BPA.Model/Recipe/RecipeData.cs b/BPA.Model/Recipe/RecipeData.cs index 706e454..b789bcf 100644 --- a/BPA.Model/Recipe/RecipeData.cs +++ b/BPA.Model/Recipe/RecipeData.cs @@ -26,7 +26,10 @@ namespace BPA.Model.Recipe /// 各个设备是否下料完成。 /// public bool[] IsMakeComplete { get; set; } - + /// + /// 下发时间 + /// + public DateTime IssueTime { get; set; } public Dictionary BatchStatus { get; set; } public RecipeData(string id,string name, Dictionary materialData,int stationCount=5) { @@ -35,7 +38,7 @@ namespace BPA.Model.Recipe MaterialData = materialData; //取决于工位数量,本案例中,有五个工位,但是第三个工位没有设备。 IsMakeComplete = new bool[stationCount]; - + IssueTime = DateTime.Now; BatchStatus = new(); for (int i = 1; i <= stationCount; i++) { diff --git a/BPA.Model/TaskServer.cs b/BPA.Model/TaskServer.cs index 1f86f3a..624f17b 100644 --- a/BPA.Model/TaskServer.cs +++ b/BPA.Model/TaskServer.cs @@ -1,4 +1,5 @@ -using System; +using BPA.Model.Recipe; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +13,10 @@ namespace BPA.Model /// public class TaskServer { - public int ID { get; set; } + /// + /// 任务ID,本程序中直接使用配方的下发时间Ticks做标识。 + /// + public long ID { get; set; } /// /// 任务名称 /// @@ -26,5 +30,9 @@ namespace BPA.Model /// 任务取消标识 /// public CancellationTokenSource Cts { get; set; } = new CancellationTokenSource(); + /// + /// 当前线程执行的配方。 + /// + public RecipeData CurrentRecipe { get; set; } } } diff --git a/BPA.SingleDevice/App.xaml.cs b/BPA.SingleDevice/App.xaml.cs index 339dd29..8aefde9 100644 --- a/BPA.SingleDevice/App.xaml.cs +++ b/BPA.SingleDevice/App.xaml.cs @@ -61,6 +61,7 @@ namespace BPA.SingleDevice protected override void OnExit(ExitEventArgs e) { base.OnExit(e); + //MainControl.GetInstance.Stop(); } diff --git a/BPA.SingleDevice/Business/Batcher.cs b/BPA.SingleDevice/Business/Batcher.cs index c572117..7580088 100644 --- a/BPA.SingleDevice/Business/Batcher.cs +++ b/BPA.SingleDevice/Business/Batcher.cs @@ -47,6 +47,7 @@ namespace BPA.SingleDevice.Business } catch (Exception ex) { + MessageLog.GetInstance.Show(ex.Message); return false; } } @@ -60,6 +61,7 @@ namespace BPA.SingleDevice.Business } catch(Exception ex) { + MessageLog.GetInstance.Show(ex.Message); return false; } } diff --git a/BPA.SingleDevice/Business/Conveyer.cs b/BPA.SingleDevice/Business/Conveyer.cs index d52fb97..c9ce1cf 100644 --- a/BPA.SingleDevice/Business/Conveyer.cs +++ b/BPA.SingleDevice/Business/Conveyer.cs @@ -25,8 +25,11 @@ namespace BPA.SingleDevice.Business public bool IsConnected => modbus.IsConnected(); + + private readonly object mocelock = new(); + string iP = "192.168.6.104"; - int port = 502; + int port = 508; ModbusTcp modbus = new(); public async Task Initial() { @@ -45,8 +48,8 @@ namespace BPA.SingleDevice.Business HaveVessel[0] = haveVessel.GetBitValue(1); HaveVessel[1] = haveVessel.GetBitValue(2); //HaveVessel[2] = false; - HaveVessel[3] = haveVessel.GetBitValue(4); - HaveVessel[4] = haveVessel.GetBitValue(5); + HaveVessel[3] = haveVessel.GetBitValue(3); + HaveVessel[4] = haveVessel.GetBitValue(4); }); modbus.Read("M0.2".ToModbusAdd()).OnSuccess((moveComplete) => @@ -76,23 +79,27 @@ namespace BPA.SingleDevice.Business } catch (Exception ex) { + MessageLog.GetInstance.Show(ex.Message); - } } } public bool MoveOnce() { - if (IsConnected) + if (IsConnected && AllowMove) { try { - return modbus.Write("VW0".ToModbusAdd(), 2).IsSuccess; + lock (mocelock) + { + return modbus.Write("VW0".ToModbusAdd(), 2).IsSuccess; + } + } catch (Exception ex) { - + MessageLog.GetInstance.Show(ex.Message); } } return false; @@ -110,7 +117,7 @@ namespace BPA.SingleDevice.Business } catch (Exception ex) { - + MessageLog.GetInstance.Show(ex.Message); } } return false; @@ -129,7 +136,23 @@ namespace BPA.SingleDevice.Business } catch (Exception ex) { + MessageLog.GetInstance.Show(ex.Message); + } + } + return false; + } + public bool InitalMoveParam() + { + if (IsConnected && AllowMove) + { + try + { + return modbus.Write("VW0".ToModbusAdd(), 0).IsSuccess; + } + catch (Exception ex) + { + MessageLog.GetInstance.Show(ex.Message); } } return false; diff --git a/BPA.SingleDevice/Business/ProcessControl.cs b/BPA.SingleDevice/Business/ProcessControl.cs index 7321133..e5ee00e 100644 --- a/BPA.SingleDevice/Business/ProcessControl.cs +++ b/BPA.SingleDevice/Business/ProcessControl.cs @@ -1,6 +1,8 @@ -using BPA.Model.Enums; +using Amazon.SecurityToken.Model; +using BPA.Model.Enums; using BPA.Model.Recipe; using BPA.SingleDevice.Interface; +using BPA.SingleDevice.Json; using BPA.SingleDevice.Services; using System; using System.Collections.Generic; @@ -27,62 +29,89 @@ namespace BPA.SingleDevice.Business /// ConcurrentDictionary batchers = new(); - //List currentTask = new(); + List currentTask = new(); //ConcurrentDictionary test = new(); + IConveyer conveyer = new Conveyer(); private readonly ILogService logService; private GlobalData global; - RecipeData currentRecipe; + //RecipeData currentRecipe; - CancellationTokenSource cts; + //CancellationTokenSource cts; - Task runTask; + //Task runTask; public async void Inital() { + Json.Read(); + if (Json.Data.BatcherConfigs.Count==0) + { + InitBatcherConfig(); + Json.Save(); + } + if (Json.Data.ConveyerConfigs.Count == 0) + { + InitConveyerConfig(); + Json.Save(); + } + #region 实例初始化配料机 batchers.TryAdd(1, new Batcher()); batchers.TryAdd(2, new Batcher()); 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"); - 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(); + currentTask.Clear(); ActionRegister(); - - TaskManage.GetInstance.StartLong(() => { - if (global.RecipeQueue.Count>0 && currentRecipe is null ) + InterActive(); + + for (int i = 0; i < currentTask.Count; i++) + { + if (currentTask[i].CurrentRecipe.IsMakeComplete.All(b=>b==true)) + { + currentTask.RemoveAt(i); + 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) + 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); - //currentTask.Add(new TaskServer() {RunTask=Task.Run(() => { Batching(recipe); }) ,TaskName=$"{recipe.Name}"}); + //global.RecipeQueue.TryDequeue(out currentRecipe); + //cts = new(); + //Task.Run(() => { Batching(currentRecipe); }, cts.Token); + //logService.LogRunInfo($"配方【{currentRecipe.Name}】-- 开始执行配料。"); - 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}】-- 开始执行配料。"); + } } } }, "MonitorRecipeIssue", true); @@ -102,9 +131,6 @@ namespace BPA.SingleDevice.Business { await StationBatching(recipe, 1); } - - - for (int stationNum = 2; stationNum <= 5; stationNum++) { await MoveOnceAndBatach(recipe, stationNum); @@ -112,7 +138,7 @@ namespace BPA.SingleDevice.Business //ToDo:如果最后需要移动一次才能出餐,在这里添加一次移动传送带。 logService.LogRunInfo($"配方【{recipe.Name}】配料完成。"); logService.LogRecipeCompleteInfo($"【{recipe.Name}】"); - currentRecipe = null; + //currentRecipe = null; } /// @@ -136,7 +162,7 @@ namespace BPA.SingleDevice.Business recipe.IsMakeComplete[stationNum - 1] = true; logService.LogRunInfo($"参数值为[{stationNum}],目前该工位无配料机或连接配料机失败。"); //工位3无到位检测。 - recipe.CurrentStation = stationNum; + //recipe.CurrentStation = stationNum; return; } #endregion @@ -231,6 +257,8 @@ namespace BPA.SingleDevice.Business switch (global.MoveConveyerStep) { case MoveConveyer.WaitMove: + conveyer.InitalMoveParam(); + await Task.Delay(500); if (conveyer.MoveOnce()) { logService.LogRunInfo($"配方【{recipe.Name}】控制传送带去下个工位,等待动作完成信号上升沿。"); @@ -238,7 +266,7 @@ namespace BPA.SingleDevice.Business } else { - logService.LogRunInfo($"配方【{recipe.Name}】控制传送带去下个工位失败,3S后重试。"); + logService.LogRunInfo($"配方【{recipe.Name}】控制传送带去下个工位失败,可能连接异常或不允许移动,3S后重试。"); await Task.Delay(3000); } break; @@ -246,6 +274,7 @@ namespace BPA.SingleDevice.Business if (moveCompleteTrig) { logService.LogRunInfo($"配方【{recipe.Name}】控制传送带移动结束。"); + conveyer.InitalMoveParam(); while (recipe.IsMakeComplete[stationNum - 1] == false) { await StationBatching(recipe, stationNum); @@ -284,8 +313,16 @@ namespace BPA.SingleDevice.Business ActionManage.GetInstance.Register(new Func(() => { //目前如果工位1 没有碗或者当前没配方就可以下配方。 - bool result =! (conveyer.HaveVessel[0]) || (currentRecipe==null); - return result; + //bool result =(currentTask.Count > 0 && !conveyer.HaveVessel[0]) || (currentTask.Count==0); + foreach (var item in currentTask) + { + //起始工位没完成的不允许下配方。 + if (!item.CurrentRecipe.IsMakeComplete[0]) + { + return false; + } + } + return true; }), "CanIssueRecipe", true); } /// @@ -294,18 +331,77 @@ namespace BPA.SingleDevice.Business private void InterActive() { #region 配料机 - + foreach (var batcher in batchers.Values) + { + batcher.AllowBatching = conveyer.HaveVessel[batcher.ID - 1]; + } #endregion #region 传送带 - conveyer.AllowMove = conveyer.MoveComplete; + conveyer.AllowMove = /*conveyer.MoveComplete &&*/ GetBatcherAllowMove(); #endregion } - + /// + /// 获取传送带的运行许可,仅通过配方的完成状态来判断。 + /// + /// + private bool GetBatcherAllowMove() + { + + foreach (var task in currentTask) + { + foreach (var item in task.CurrentRecipe.BatchStatus.Values) + { + switch (item) + { + case BatchStep.WaitBatch: + case BatchStep.BatchCompleted: + break; + default: + return false; + } + } + } + return true; + } private void SingleDetect() { //TODO:上升沿信号检测。 } + /// + /// 初始化传送带配置。 + /// + private void InitConveyerConfig() + { + ConveyerConfig conveyerConfig = new() { IP = "192.168.6.104", Port = 502, ID = 1, IsConnect = true }; + Json.Data.ConveyerConfigs.Add(conveyerConfig); + + + } + /// + /// 初始化配料机配置。 + /// + private void InitBatcherConfig() + { + for (int i = 1; i < 6; i++) + { + BatcherConfig batcherConfig = new() { StationID = i, IP = $"192.168.6.10{i - 1}", Port = 502, IsConnect = (i==3?false:true) }; + Json.Data.BatcherConfigs.Add(batcherConfig); + } + } + + private void InitalBatcher(IList configs) + { + foreach (var item in configs) + { + if (item.IsConnect) + { + batchers.TryAdd(item.StationID, new Batcher()); + SetBatcherComm(item.StationID, item.IP, item.Port); + batchers[item.StationID].Initial(); + } + } + } } } diff --git a/BPA.SingleDevice/Interface/IConveyer.cs b/BPA.SingleDevice/Interface/IConveyer.cs index 6c44f1f..23ef561 100644 --- a/BPA.SingleDevice/Interface/IConveyer.cs +++ b/BPA.SingleDevice/Interface/IConveyer.cs @@ -80,5 +80,6 @@ namespace BPA.SingleDevice.Interface /// 移动一次。 /// bool MoveOnce(); + bool InitalMoveParam(); } } diff --git a/BPA.SingleDevice/Json/ConnectConfig.cs b/BPA.SingleDevice/Json/ConnectConfig.cs index 48f4fba..7e49caa 100644 --- a/BPA.SingleDevice/Json/ConnectConfig.cs +++ b/BPA.SingleDevice/Json/ConnectConfig.cs @@ -6,11 +6,17 @@ using System.Threading.Tasks; namespace BPA.SingleDevice.Json { + /// + /// 设备连接设置。 + /// public class ConnectConfig { - + public List BatcherConfigs { get; set; } = new(); + public List ConveyerConfigs { get; set; } = new(); } - + /// + /// 配料机设置 + /// public class BatcherConfig { /// @@ -25,6 +31,27 @@ namespace BPA.SingleDevice.Json /// 端口号 /// public int Port { get; set; } - + public bool IsConnect { get; set; } + + } + /// + /// 传送带设置 + /// + public class ConveyerConfig + { + /// + /// 对应ID + /// + public int ID { get; set; } + /// + /// IP地址 + /// + public string IP { get; set; } + /// + /// 端口号 + /// + public int Port { get; set; } + public bool IsConnect { get; set; } + } }