using System; using HBLConsole.Interface; using HBLConsole.Service; using HBLConsole.Communication; using BPA.Message; using HBLConsole.Model; using System.Linq; using System.Threading; using HBLConsole.Factory; using BPA.Message.Enum; using BPA.Message.IOT; using System.Collections.Generic; using System.Diagnostics; namespace HBLConsole.MORKD { public class Control_MORKD : IControl { GVL_MORKD mORKD = new GVL_MORKD(); Alarm_MORKD alarm = new Alarm_MORKD(); public void ConnectOk() { Main(); ReadData(); ResetProgram(); } public void DataParse(T order) { if (order is MorkOrderPush morkOrderPush) { foreach (var item in morkOrderPush.GoodBatchings) { var res = Json.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingId == item.BatchingId); if (res != null) { if (ushort.TryParse(res.BatchingLoc, out ushort loc)) { if (loc >= 1 && loc <= 5) { mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = loc, SuborderId = morkOrderPush.SuborderId, BatchingId = res.BatchingId }); } else if (loc >= 6 && loc <= 10) { mORKD.TakeSoupTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(loc - 5), SuborderId = morkOrderPush.SuborderId }); } else if (loc >= 11 && loc <= 12) { mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(loc - 10), SuborderId = morkOrderPush.SuborderId }); } } } } } } public void Init() { ActionManage.GetInstance.Register(new Action(() => { mORKD.InitControl(); }), "InitCommand"); } /// /// 复位程序 /// private void ResetProgram() { ThreadManage.GetInstance.StartLong(new Action(() => { if (RTrig.GetInstance("ResetProgram").Start(DeviceData.Initing)) { ThreadManage.GetInstance.StopTask("MainTask", new Action(() => { ThreadManage.GetInstance.StopTask("ReadPLCData", new Action(() => { mORKD = null; mORKD = new GVL_MORKD(); ActionManage.GetInstance.Send("ResetProgram"); ReadData(); Main(); })); })); } Thread.Sleep(10); }), "ResetProgram"); } public void Main() { ThreadManage.GetInstance.StartLong(new Action(() => { mORKD.AllowRun = mORKD.InitComplete && !mORKD.TemperatureReached; TakeBowlTask(); TakeNoodleTask(); OutNoodleTask(); SingleDetect(); TurntableControl(); OutSoupTask(); TakeSoupTask(); Thread.Sleep(10); }), "MainTask"); } public void ReadData() { ThreadManage.GetInstance.StartLong(new Action(() => { ModbusTcpHelper.GetInstance.Readbool(1120, 30, new Action((bools) => { mORKD.InitComplete = bools[0]; mORKD.TurntableInPlace = bools[1]; mORKD.RBTakeNoodleComplete = bools[2]; for (int i = 0; i < 2; i++) { mORKD.AxisIdle[i] = bools[3 + i]; mORKD.AxisAllowInvertedNoodle[i] = bools[5 + i]; mORKD.AxisAllowInvertedSoup[i] = bools[7 + i]; mORKD.SoupHeatComplete[i] = bools[9 + i]; mORKD.BreakMechanismIdle[i] = bools[25 + i]; } for (int i = 0; i < 6; i++) { mORKD.CookNoodleBasketIdle[i] = bools[11 + i]; mORKD.CookNoodleComplete[i] = bools[17 + i]; } mORKD.TakeNoodleRobotIdle = bools[23]; mORKD.TakeSoupRobotIdle = bools[24]; mORKD.TakeSoupComplete = bools[27]; mORKD.PutNoodleTakeMealComplete = bools[28]; DeviceData.Initing = bools[29]; })); ModbusTcpHelper.GetInstance.Readbool(1280, 11, new Action((bools) => { mORKD.TurntableLowerLimit = bools[0]; mORKD.TurntableUpLimit = bools[1]; for (int i = 0; i < 5; i++) { mORKD.SoupMaterialShortage[i] = bools[2 + i]; } for (int i = 0; i < 3; i++) { mORKD.OutMealDetect[i] = bools[7 + i]; } mORKD.TemperatureReached = bools[10]; })); var ResLoc = ModbusTcpHelper.GetInstance.Read(720, ReadType.HoldingRegisters); if (ResLoc != null) { if (ResLoc is ushort loc) { mORKD.TurntableFeedbackloc = loc; } } /** 读取Alarm 报警信息 2022.4.2 */ ModbusTcpHelper.GetInstance.Readbool(1570, 20, new Action((bools) => { // 0 -- 1570 //10 -- 1580 int bit1570 = 1570; alarm.MachineLeftLowTemperature = bools[bit1570]; alarm.MachineRightLowTemperature = bools[bit1570 + 1]; alarm.Supply1_LossBowl = bools[bit1570 + 2]; alarm.Supply2_LossBowl = bools[bit1570 + 3]; alarm.Supply1_ErrorOutBowl = bools[bit1570 + 4]; alarm.Supply2_ErrorOutBowl = bools[bit1570 + 5]; alarm.PushBowlCylinderError = bools[bit1570 + 6]; alarm.NoodleMacCommunicateError = bools[bit1570 + 7]; // int bit1580 = 1580; alarm.DosingMacCommunicateError = bools[bit1580]; alarm.RobotMacCommunicateError = bools[bit1580 + 1]; alarm.RobotInitError = bools[bit1580 + 3]; alarm.RobotUrgentStop = bools[bit1580 + 4]; alarm.RobotNotInRemoteMode = bools[bit1580 + 5]; alarm.RobotNotInReady = bools[bit1580 + 6]; alarm.RobotSelfInException = bools[bit1580 + 7]; })); Thread.Sleep(100); }), "ReadPLCData"); } public void SimOrder(T simOrder) { if (simOrder != null) { if (simOrder is List locs) { string subId = Guid.NewGuid().ToString(); foreach (var item in locs) { if (item >= 1 && item <= 5) { //临时变量batchId int tBatchId = item; mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, BatchingId = tBatchId, SuborderId = subId }); MessageLog.GetInstance.Show($"添加订单:面条位置【{item}】"); //先注释,暂时不从服务器获取 2022.3.29 //BPA.Models.BatchingInfo res = Json.Data.orderMaterialDelivery.BatchingInfo.FirstOrDefault(p => p.BatchingLoc == item.ToString()); //if (res != null) //{ // mORKD.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, BatchingId = res.BatchingId, SuborderId = subId }); // MessageLog.GetInstance.Show($"添加订单:面条位置【{item}】"); //} } if (item >= 6 && item <= 10) { mORKD.TakeSoupTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(item - 5), SuborderId = subId }); MessageLog.GetInstance.Show($"添加订单:浇头位置【{item}】"); } if (item >= 11 && item <= 12) { mORKD.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)(item - 10), SuborderId = subId }); MessageLog.GetInstance.Show($"添加订单:碗位置【{item - 10}】"); } } } } } /// /// IOT 广播消息命令 /// public void IotBroadcast(T broadcast) { if (broadcast != null && broadcast is IOTCommandModel iOTCommand) { switch (iOTCommand.CommandName) { case 0://控制类 if (iOTCommand.CommandValue != null) { if (iOTCommand.CommandValue.ContainsKey("SimOrder")) { SimOrder(new SimOrderData { NoodleLoc = 1, BowlLoc = 10 }); } } break; case 1://设置属性 break; case 2://通知消息 break; default: break; } } } /// /// 取碗控制 /// private void TakeBowlTask() { mORKD.AxisIdleIndex = mORKD.AxisIdle.GetIndex(true); mORKD.AxisIdleLockIndex = mORKD.AxisIdleLock.GetIndex(false); if (mORKD.AxisIdleLockIndex == mORKD.AxisIdleIndex) { if (mORKD.AxisIdleIndex >= 0 && mORKD.AxisIdleIndex <= 1) { if (mORKD.AllowRun && mORKD.TakeBowlTask.Count > 0) { if (mORKD.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo)) { mORKD.AxisAllowInvertedNoodleID[mORKD.AxisIdleIndex] = orderLocInfo.SuborderId; mORKD.DropBowlStart((ushort)(mORKD.AxisIdleIndex + 1), orderLocInfo.Loc); mORKD.AxisIdleLock[mORKD.AxisIdleLockIndex] = true; MessageLog.GetInstance.Show($"执行取碗控制,碗位置:[{orderLocInfo.Loc}],轴位置:[{mORKD.AxisIdleIndex + 1}]"); MessageLog.GetInstance.Show($"{mORKD.AxisIdleIndex + 1}号轴订单ID:[{orderLocInfo.SuborderId}]"); } } } } } /// /// 转台控制 /// private void TurntableControl() { if (mORKD.TurntableInPlace && mORKD.InitComplete && !mORKD.AllowTakeNoodle && mORKD.RBTakeNoodleTask.Count > 0) { var result = Json.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKD.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList(); if (mORKD.TurntableLowerLimit) { if (mORKD.TurntableFeedbackloc == mORKD.RBTakeNoodleTask.ElementAt(0).Loc || (result?.Count > 0 && result?.Count == mORKD.TurntableLocLists.Count)) { mORKD.TurntableLocLists.Clear(); mORKD.AllowTakeNoodle = true; MessageLog.GetInstance.Show("转台位置OK,执行机器人取面"); } else { if (!mORKD.TurntableInterlock) { mORKD.TurntableStart(mORKD.RBTakeNoodleTask.ElementAt(0).Loc); MessageLog.GetInstance.Show($"有物料检测,反馈位置不同的转台启动控制,转台位置:[{mORKD.RBTakeNoodleTask.ElementAt(0).Loc}]"); } } } else { if (!mORKD.TurntableInterlock) { if (result != null) { foreach (var item in result) { if (ushort.TryParse(item.BatchingLoc, out ushort loc)) { if (mORKD.TurntableFeedbackloc != loc && !mORKD.TurntableLocLists.Contains(loc)) { mORKD.TurntableStart(loc); MessageLog.GetInstance.Show($"没有物料检测的启动转台控制,转台位置:[{loc}]"); break; } else if (mORKD.TurntableFeedbackloc == loc && !mORKD.TurntableLocLists.Contains(loc)) mORKD.TurntableLocLists.Add(loc); } } } //result?.ForEach(item => //{ // if (ushort.TryParse(item.BatchingLoc, out ushort loc)) // { // if (mORKD.TurntableFeedbackloc != loc && !mORKD.TurntableLocLists.Contains(loc)) // { // mORKD.TurntableStart(loc); // MessageLog.GetInstance.Show($"没有物料检测的启动转台控制,转台位置:[{loc}]"); // return; // } // else if (mORKD.TurntableFeedbackloc == loc) mORKD.TurntableLocLists.Add(loc); // } //}); } } } //转台到位检测 if (RTrig.GetInstance("TurntableInPlace").Start(mORKD.TurntableInPlace)) { mORKD.TurntableInterlock = false; } } bool isNotTakeNoodle = false; //true-无法取面,false-可以取面 /// /// 取面任务 /// private void TakeNoodleTask() { //取面控制 if (mORKD.AllowRun && mORKD.TakeNoodleRobotIdle && !mORKD.RobotTaskInterlock && mORKD.AllowTakeNoodle) { if (mORKD.TurntableInPlace && !mORKD.OutNoodleing && mORKD.RBTakeNoodleTask.Count > 0) { int loc = mORKD.CookNoodleBasketIdle.GetIndex(false);//查找煮面炉空闲位置 int IdleLoc = mORKD.CookNodeState.GetIndex(false);//获取煮面炉空闲状态互锁位置 if (loc >= 0 && loc <= 5) { if (isNotTakeNoodle) { return; } if (mORKD.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo)) { mORKD.RBTakeNoodleStart((ushort)(loc + 1), orderLocInfo.Loc); mORKD.CookNodeState[loc] = true; mORKD.CookNodelId[loc] = orderLocInfo.SuborderId; SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING); //MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,煮面栏:[{loc + 1}]"); mORKD.TakeNoodleInterlock = true; MessageLog.GetInstance.Show($"{loc + 1}号煮面篮订单ID:[{orderLocInfo.SuborderId}]"); Trace.WriteLine($"%%%开始下面。。。" + $"{loc + 1}号煮面篮订单ID:[{orderLocInfo.SuborderId}]"); isNotTakeNoodle = true; } } } } //机器人取面完成信号检测 if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKD.RBTakeNoodleComplete)) { mORKD.TakeNoodleInterlock = false; mORKD.AllowTakeNoodle = false; MessageLog.GetInstance.Show("转台取面完成"); mORKD.TakeNoodleCompleteReset(); isNotTakeNoodle = false; } } /// /// 出面控制 /// private void OutNoodleTask() { for (ushort i = 0; i < 6; i++) { if (RTrig.GetInstance($"CookNoodleCompleteTask{i}").Start(mORKD.CookNoodleComplete[i] && mORKD.CookNodeState[i])) { mORKD.CookNoodleCompleteTask.Enqueue(i); MessageLog.GetInstance.Show($"{i + 1}号煮面口请求出面"); } } if (mORKD.RobotTaskInterlock && !mORKD.TakeNoodleInterlock && mORKD.TakeNoodleRobotIdle) { if (mORKD.CookNoodleCompleteTask.Count > 0) { RevertOutNoodleQueue(); //交换出面台位顺序 2022.3.30 string id = mORKD.CookNodelId[mORKD.CookNoodleCompleteTask.ElementAt(0)]; int index = mORKD.AxisAllowInvertedNoodleID.GetIndex(id); if (index >= 0 && index <= 1) { if (mORKD.AxisAllowInvertedNoodle[index]) { if (mORKD.CookNoodleCompleteTask.TryDequeue(out ushort loc)) { mORKD.OutNoodleing = true; mORKD.RBOutNoodleStart((ushort)(loc + 1), (ushort)(index + 1)); mORKD.CookNodeState[loc] = false; mORKD.AxisIdleLock[index] = false; mORKD.AxisAllowInvertedSoupID[index] = mORKD.AxisAllowInvertedNoodleID[index]; mORKD.AxisAllowInvertedNoodleID[index] = string.Empty; MessageLog.GetInstance.Show($"从{loc + 1}号位置取面"); MessageLog.GetInstance.Show($"倒入{index + 1}号碗位置"); MessageLog.GetInstance.Show($"{index + 1}号轴允许倒浇头ID:[{ mORKD.AxisAllowInvertedSoupID[index]}]"); //Trace.WriteLine($"###出面控制。。。"); } } } } } int mlCount = mORKD.CookNoodleBasketIdle.Where(p => p == true).ToList().Count; mORKD.RobotTaskInterlock = mORKD.CookNoodleCompleteTask.Count > 0 && (mlCount >= 2 || mORKD.RBTakeNoodleTask.Count == 0); } public int tCount = 0; /// /// 交换出面台位优先级 /// void RevertOutNoodleQueue() { string id = mORKD.CookNodelId[mORKD.CookNoodleCompleteTask.ElementAt(0)]; int index = mORKD.AxisAllowInvertedNoodleID.GetIndex(id); if (index == -1) { tCount++; if (tCount == 100) { //交换取面位置 mORKD.CookNoodleCompleteTask.TryDequeue(out ushort result2); mORKD.CookNoodleCompleteTask.Enqueue(result2); tCount = 0; } } else { tCount = 0; } } /// /// 取浇头控制 /// private void TakeSoupTask() { int index = mORKD.BreakMechanismIdle.GetIndex(true); if (index >= 0 && index <= 1) { if (mORKD.TakeSoupTask.Count > 0 && !mORKD.AllowTakeSoup && mORKD.TakeSoupRobotIdle && mORKD.AllowRun) { if (mORKD.TakeSoupTask.TryDequeue(out OrderLocInfo orderLocInfo)) { mORKD.SoupHeatLocID[index] = orderLocInfo.SuborderId; mORKD.RBTakeSoupStart(orderLocInfo.Loc, (ushort)(index + 1)); SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING); MessageLog.GetInstance.Show($"{index + 1}号浇头加热位ID:[{ mORKD.SoupHeatLocID[index]}]"); } } } if (RTrig.GetInstance("TakeSoupComplete").Start(mORKD.TakeSoupComplete)) { mORKD.AllowTakeSoup = false; MessageLog.GetInstance.Show("取浇头完成"); mORKD.TakeSoupCompleteReset(); } } /// /// 浇头加热完成出浇头控制 /// private void OutSoupTask() { if (!mORKD.AllowTakeSoup && !mORKD.AllowPutSoup && mORKD.TakeSoupRobotIdle) { mORKD.PutNoodleLoc = mORKD.OutMealDetect.GetIndex(false); if (mORKD.PutNoodleLoc >= 0 && mORKD.PutNoodleLoc <= 2) { for (int i = 0; i < 2; i++) { if (mORKD.SoupHeatComplete[i] && mORKD.SoupHeatLocID[i].Length > 0) { for (int m = 0; m < 2; m++) { if (mORKD.AxisAllowInvertedSoup[m] && mORKD.AxisAllowInvertedSoupID[m].Length > 0) { if (mORKD.SoupHeatLocID[i] == mORKD.AxisAllowInvertedSoupID[m]) { mORKD.HeatCompleteTakeSoupStart((ushort)(i + 1), (ushort)(m + 1), (ushort)(mORKD.PutNoodleLoc + 1)); mORKD.OutMealId[mORKD.PutNoodleLoc] = mORKD.AxisAllowInvertedSoupID[m]; mORKD.AxisAllowInvertedSoupID[m] = string.Empty; mORKD.SoupHeatLocID[i] = string.Empty; MessageLog.GetInstance.Show($"取浇头机器人往{m + 1}号轴到浇头"); MessageLog.GetInstance.Show($"{mORKD.PutNoodleLoc + 1}号出餐口订单ID:[{ mORKD.OutMealId[mORKD.PutNoodleLoc]}]"); } } } } } } } if (RTrig.GetInstance("PutNoodleTakeMealComplete").Start(mORKD.PutNoodleTakeMealComplete)) { mORKD.AllowPutSoup = false; SimpleFactory.GetInstance.OrderChanged(mORKD.OutMealId[mORKD.PutNoodleLoc], ORDER_STATUS.COMPLETED_COOK); mORKD.PutNoodleTakeMealCompleteReset(); } } /// /// 信号检测 /// private void SingleDetect() { //取餐完成 //var RemoveItem = Json.Data.morkOrderPushes.FirstOrDefault(p => p.OrderPush.SuborderId == "取餐口订单ID"); //if (RemoveItem != null) // Json.Data.morkOrderPushes.Remove(RemoveItem); } } }