@@ -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<TaskServer> currentTask = new();
//ConcurrentDictionary<int, TaskServer> test = new();
List<RecipeData> 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);
}
/// <summary>
/// 配料。
/// </summary>
/// <param name="recipe">需要配料的配方</param>
[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
/// </summary>
/// <param name="recipe">配方</param>
/// <param name="stationNum">工位数。</param>
private async Task StationBatching(RecipeData recipe,int stationNum)
private void StationBatching(RecipeData recipe,int stationNum)
{
#region 数据验证
if (recipe is null)
{
logService.LogRunInfo($"参数<recipe>值为null,配料流程结束。");
return;
}
// if (recipe is null)
// {
// logService.LogRunInfo($"参数<recipe>值为null,配料流程结束。");
// return;
// }
//如果配料机里没连接该工位的配料机,则直接完成。
if (!batchers.ContainsKey(stationNum))
{
recipe.BatchStatus[stationNum] = BatchStep.BatchCompleted;
recipe.IsMakeComplete[stationNum - 1] = true;
logService.LogRunInfo($"参数<stationNum>值为[{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>值为[{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
}
/// <summary>
/// 移动传送带。
/// </summary>
/// <returns></returns>
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;
}
//}
}
/// <summary>
/// 设置相应设备ID的配料机的通讯参数。
/// </summary>
/// <param name="id">该设备对应的工位ID。</param>
@@ -313,11 +381,20 @@ namespace BPA.SingleDevice.Business
ActionManage.GetInstance.Register<bool>(new Func<bool>(() =>
{
//目前如果工位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;
}
/// <summary>
/// 2023.10.14:新增,所有在队列的配方,必须等当前工位的配料完成后才可以移动,否则不允许移动。
/// </summary>
/// <returns></returns>
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<ConnectConfig>.Data.ConveyerConfigs.Add(conveyerConfig);
}
/// <summary>
/// 初始化配料机配置。
@@ -389,7 +479,10 @@ namespace BPA.SingleDevice.Business
Json<ConnectConfig>.Data.BatcherConfigs.Add(batcherConfig);
}
}
/// <summary>
/// 初始化配料机。
/// </summary>
/// <param name="configs"></param>
private void InitalBatcher(IList<BatcherConfig> configs)
{
foreach (var item in configs)
@@ -402,6 +495,48 @@ namespace BPA.SingleDevice.Business
}
}
}
/// <summary>
/// 刷新配方的当前工站。
/// </summary>
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++;
}
}
}
/// <summary>
/// 适用于多配方的配料。
/// </summary>
private void Batching()
{
if (currentRecipes.Count>0 && IsAllowConveyerMove())
{
MoveConveyer();
}
foreach (var item in currentRecipes)
{
if (!item.IsMakeComplete[item.CurrentStation-1])
{
StationBatching(item, item.CurrentStation);
}
}
}
}
}