using System; using System.Collections.Generic; using BPA.Message.Enum; using BPASmartClient.Device; using BPASmartClient.Model; using BPASmartClient.Peripheral; using BPA.Helper; using System.Threading; using BPA.Message; using System.Linq; using BPASmartClient.Model.PLC; using System.Threading.Tasks; using System.Reflection; using BPASmartClient.MorkMV1.Model; using System.Collections.ObjectModel; using BPASmartClient.MorkMV1.ViewModel; using BPASmartClient.Business; using BPASmartClient.Model.小炒机; using BPA.Models; using System.Windows.Forms; using System.Media; using BPASmartClient.CustomResource; using Microsoft.EntityFrameworkCore.Metadata.Internal; using static BPA.Helper.EventBus; using BPASmartClient.MorkMV1.Event; using System.Collections.Concurrent; //using BPA.Helper; namespace BPASmartClient.MorkMV1 { public class Control_MorkMV1 : BaseDevice { public override DeviceClientType DeviceType => DeviceClientType.MORKM; GVL_MorkMV1 mORKM = new GVL_MorkMV1(); Alarm alarm = new Alarm(); public override void DoMain() { MonitorViewModel.DeviceId = DeviceId; ServerInit(); DataParse(); Json.Read(); Json.Read(); if (Json.Data.parSets == null) Json.Data.parSets = new ObservableCollection(); if (Json.Data.parSets.Count < 6) { Json.Data.parSets.Clear(); for (int i = 0; i < 6; i++) { Json.Data.parSets.Add(new ParSet() { CheckBoxContext = $"煮面口{i + 1}屏蔽", Minute = 1, Second = 0, IsShield = false, TextBlockContext = $"煮面口{i + 1}时间设定" }); } } ActionManage.GetInstance.Register(new Action((o) => { if (o.Length > 0) { Random rd = new Random(); TaskManage.GetInstance.StartLong(new Action(() => { string guid = Guid.NewGuid().ToString(); //模拟订单的素菜和荤菜计数。[0]为荤菜,[1]为素菜。 int[] materialCount = new int[] { 0, 0 }; int allCount = 0; if (o[0] is List noodleLocs) { //如果是随机素材,则随机添加2到4个素材。 if (noodleLocs.Count == 0) { for (int i = 0; i < rd.Next(2, 5); i++) { noodleLocs.Add(0); } } for (int i = 0; i <= 1; i++) { foreach (var loc in noodleLocs) { //如果是随机素材,则每个素材的位置随机。 int NoodleLoc = loc == 0 ? rd.Next(1, 6) : loc; if (NoodleLoc >= 1 && NoodleLoc <= 5) { var x = Json.Data.DishLibraryParSets.FirstOrDefault(p => p.TextBlockContext == NoodleLoc.ToString()); if (x.LocDishType == i) { mORKM.RBTakeNoodleTask.Enqueue(new MOrderLocInfo() { Loc = (ushort)NoodleLoc, SuborderId = guid, LocDishType = x.LocDishType, Minute = x.Minute, Second = x.Second }); allCount++; materialCount[i]++; MessageLog.GetInstance.Show($"添加模拟订单:素材位置【{(ushort)NoodleLoc}】"); } } } } //int BowlLoc = (int)o[1] == 0 ? rd.Next(10, 12) : (int)o[1]; int BowlLoc = (int)o[1] == 0 ? 11 : (int)o[1]; mORKM.TakeBowlTask.Enqueue(new MOrderLocInfo() { Loc = (ushort)BowlLoc, SuborderId = guid }); MessageLog.GetInstance.Show($"添加模拟订单:碗位置【{BowlLoc}】"); if (!mORKM.SuborderCount.ContainsKey(guid)) { mORKM.SuborderCount.TryAdd(guid, new SuborderInfo() { ActualCount = allCount, AcMeatDishesCount = materialCount[0], AcVegetableCount = materialCount[1], }); } } Thread.Sleep(60000); }), "ForOrder"); } }), "EnableForOrder"); ActionManage.GetInstance.Register(new Action((o) => { if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value); }), "WriteVW"); ActionManage.GetInstance.Register(new Action((o) => { if (o != null && o is WritePar writePar) WriteData(writePar.Address, writePar.Value); }), "WriteBools"); ActionManage.GetInstance.Register(new Action(() => { DeviceInit(); }), "InitDevice"); } public override void ResetProgram() { mORKM = null; mORKM = new GVL_MorkMV1(); } public override void Stop() { } private void ServerInit() { //物料信息 EventBus.GetInstance.Subscribe(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack) { if (@event == null) return; if (@event is MaterialDeliveryEvent material) { orderMaterialDelivery = material.orderMaterialDelivery; } }); //配方数据信息 EventBus.GetInstance.Subscribe(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack) { if (@event == null) return; if (@event is RecipeBomEvent recipe) { recipeBoms = recipe.recipeBoms; } }); OrderNotifyInit(); } private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS) { osm.Enqueue(new OrderStatusModel() { SubOrderId = subid, Status = oRDER_STATUS }); return; var res = mORKM.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid); string goodName = string.Empty; string SortNum = string.Empty; if (res != null) { goodName = res.MorkOrder.GoodsName; SortNum = res.MorkOrder.SortNum.ToString(); } if (!string.IsNullOrEmpty(goodName) && !string.IsNullOrEmpty(SortNum)) { EventBus.GetInstance.Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType }); var index = DataServer.GetInstance.morkS.MakeOrder.FindIndex(p => p.SortNum == SortNum); if (index >= 0 && index < DataServer.GetInstance.morkS.MakeOrder.Count) { if (oRDER_STATUS == ORDER_STATUS.COMPLETED_COOK) { DataServer.GetInstance.morkS.MakeOrder.RemoveAt(index); DataServer.GetInstance.morkS.MakeOrderOver.Add(new OrderMakeModel() { Status = oRDER_STATUS, GoodName = goodName, SortNum = SortNum, StopTime = DateTime.Now.ToString("HH:mm:ss") }); } else if (oRDER_STATUS == ORDER_STATUS.COMPLETED_TAKE) { var temp = DataServer.GetInstance.morkS.MakeOrderOver.FirstOrDefault(p => p.SortNum == SortNum); if (temp != null) DataServer.GetInstance.morkS.MakeOrderOver.Remove(temp); } else { DataServer.GetInstance.morkS.MakeOrder.ElementAt(index).Status = oRDER_STATUS; } } else { DataServer.GetInstance.morkS.MakeOrder.Add(new OrderMakeModel() { Status = oRDER_STATUS, GoodName = goodName, SortNum = SortNum, StartTime = DateTime.Now.ToString("HH:mm:ss") }); } } } #region 接口通知任务处理 ConcurrentQueue osm = new ConcurrentQueue(); private void OrderNotifyInit() { TaskManage.GetInstance.StartLong(() => { while (osm.Count > 0) { TempOrderChange(osm.ElementAt(0).SubOrderId, osm.ElementAt(0).Status, () => { osm.TryDequeue(out OrderStatusModel tempOSM); DeviceProcessLogShow($"订单:【{tempOSM.SubOrderId}】, 状态:【{tempOSM.Status}】, API状态修改成功"); }); } Thread.Sleep(100); }, $"订单状态更新接口{DeviceId}", true); } private void TempOrderChange(string subid, ORDER_STATUS oRDER_STATUS, Action complete) { var res = mORKM.doOrderEvents.FirstOrDefault(p => p.MorkOrder.SuborderId == subid); string goodName = string.Empty; string SortNum = string.Empty; if (res != null) { goodName = res.MorkOrder.GoodsName; SortNum = res.MorkOrder.SortNum.ToString(); } if (!string.IsNullOrEmpty(goodName) && !string.IsNullOrEmpty(SortNum)) { EventBus.GetInstance.Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType }, e => { complete?.Invoke(); }); var index = DataServer.GetInstance.morkS.MakeOrder.FindIndex(p => p.SortNum == SortNum); if (index >= 0 && index < DataServer.GetInstance.morkS.MakeOrder.Count) { if (oRDER_STATUS == ORDER_STATUS.COMPLETED_COOK) { DataServer.GetInstance.morkS.MakeOrder.RemoveAt(index); DataServer.GetInstance.morkS.MakeOrderOver.Add(new OrderMakeModel() { Status = oRDER_STATUS, GoodName = goodName, SortNum = SortNum, StopTime = DateTime.Now.ToString("HH:mm:ss") }); } else if (oRDER_STATUS == ORDER_STATUS.COMPLETED_TAKE) { var temp = DataServer.GetInstance.morkS.MakeOrderOver.FirstOrDefault(p => p.SortNum == SortNum); if (temp != null) DataServer.GetInstance.morkS.MakeOrderOver.Remove(temp); } else { DataServer.GetInstance.morkS.MakeOrder.ElementAt(index).Status = oRDER_STATUS; } } else { DataServer.GetInstance.morkS.MakeOrder.Add(new OrderMakeModel() { Status = oRDER_STATUS, GoodName = goodName, SortNum = SortNum, StartTime = DateTime.Now.ToString("HH:mm:ss") }); } } } #endregion private void GetStatus(string key, Action action) { if (peripheralStatus.ContainsKey(key)) { if (peripheralStatus[key] != null) { action?.Invoke(peripheralStatus[key]); } } } public override void ReadData() { //DataServer.GetInstance.morkS.Alarm.Clear(); //alarms.ForEach(item => //{ // DataServer.GetInstance.morkS.Alarm.Add(new AlarmModel() // { // AlarmTime = $"{item.Date} {item.Time}", // AlarmMs = item.Info // }); //}); GetStatus("M0.1", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 7) { Initing = !bools[0]; mORKM.InitComplete = bools[0]; mORKM.MoveScrewRodInitCom = bools[1]; mORKM.SacrificialVesselInitCom = bools[2]; mORKM.CylinderInitCom = bools[3]; mORKM.NoodleCookerInitCom = bools[4]; mORKM.RobotInitCom = bools[5]; mORKM.SiloInitCom = bools[6]; alarm.DeviceNoInit = !mORKM.InitComplete; alarm.MoveScrewRodNoInit = !mORKM.MoveScrewRodInitCom; alarm.SacrificialVesselNoInit = !mORKM.SacrificialVesselInitCom; alarm.CylinderNoInit = !mORKM.CylinderInitCom; alarm.NoodleCookerNoInit = !mORKM.NoodleCookerInitCom; alarm.RobotNoInit = !mORKM.RobotInitCom; alarm.SiloNoInit = !mORKM.SiloInitCom; } })); GetStatus("M10.0", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 2) { mORKM.AllowInvertedFace = bools[0]; mORKM.DiningComplete = bools[1]; } })); GetStatus("M10.4", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1) { mORKM.DropBowlMechanismStatus = bools[0]; } })); GetStatus("M12.2", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1) { mORKM.FixedFlag = bools[0]; } })); GetStatus("M13.5", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1) { mORKM.SiloInPlace = bools[0]; } })); GetStatus("M16.6", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 2) { mORKM.RobotInvertedSurfaceCom = bools[0]; mORKM.RobotTakeNoodleCom = bools[1]; } })); GetStatus("M17.4", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1) { mORKM.RobotStatus = bools[0]; } })); GetStatus("M18.0", new Action((obj) => { if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 5) { mORKM.SmallBowlYesOrNoCheck = bools[0]; mORKM.LargeBowYesOrNoCheck = bools[1]; mORKM.TurntableLowPosition = bools[2]; mORKM.TurntableHighPosition = bools[3]; alarm.Supply2_LossBowl = !mORKM.SmallBowlYesOrNoCheck; alarm.Supply1_LossBowl = !mORKM.LargeBowYesOrNoCheck; } })); GetStatus("VW17", new Action((obj) => { if (obj is ushort[] ushorts && ushorts.Length > 0 && ushorts.Length <= 1) { var tt = ushorts.ToBytes().ToUShorts(); for (byte i = 0; i < 6; i++) { if (RTrig.GetInstance($"CookNoodleCom{i + 1}").Start(tt[0].GetBitValue((byte)(i + 1)))) { if (!string.IsNullOrEmpty(mORKM.CookNodelId[i])) mORKM.CookNoodleCom[i] = true; } } mORKM.Heating = ushorts[0].GetBitValue(15); mORKM.TemperatureReaches = ushorts[0].GetBitValue(16); alarm.MachineLowTemperature = !mORKM.TemperatureReaches; } })); GetStatus("VW770", new Action((obj) => { if (obj is ushort[] ushorts && ushorts.Length > 0 && ushorts.Length <= 1) { mORKM.CurrentFeedbackLoc = ushorts[0]; } })); mORKM.TakeBowlTaskCount = mORKM.TakeBowlTask.Count; mORKM.RBTakeNoodleTaskCount = mORKM.RBTakeNoodleTask.Count; for (int i = 0; i < Json.Data.parSets.Count; i++) { mORKM.nsm.ElementAt(i).IsShield = Json.Data.parSets.ElementAt(i).IsShield; mORKM.nsm.ElementAt(i).NoodleCookerStatus = mORKM.NoodleCookerStatus[i]; } } /// /// 数据解析 /// private void DataParse() { EventBus.GetInstance.Subscribe(DeviceId, delegate (IEvent @event, EventCallBackHandle callBackHandle) { if (@event == null) return; if (@event is DoOrderEvent order) { mORKM.doOrderEvents.Add(order); if (order.MorkOrder.GoodBatchings == null) return; if (mORKM.HistorySuborderId.Contains(order.MorkOrder.SuborderId)) return; OrderCount++; if (DateTime.Now.Subtract(Json.Data.StatisticsTime).Days != 0) Json.Data.Count = 0; Json.Data.StatisticsTime = DateTime.Now; Json.Data.Count++; Json.Save(); OrderChange(order.MorkOrder.SuborderId, ORDER_STATUS.WAIT); DeviceProcessLogShow($"接收到{OrderCount}次订单,订单ID:{order.MorkOrder.SuborderId}"); mORKM.HistorySuborderId.Add(order.MorkOrder.SuborderId); List oli = new List(); foreach (var item in order.MorkOrder.GoodBatchings) { var res = orderMaterialDelivery?.BatchingInfo?.FirstOrDefault(p => p.BatchingId == item.BatchingId); if (res != null) { if (ushort.TryParse(res.BatchingLoc, out ushort loc)) { if (loc >= 1 && loc <= 5) { var x = Json.Data.DishLibraryParSets.FirstOrDefault(p => p.TextBlockContext == loc.ToString()); if (x != null) { for (int i = 0; i < item.BatchingCount; i++) { oli.Add(new MOrderLocInfo() { GoodName = order.MorkOrder.GoodsName, Loc = ushort.Parse(res.BatchingLoc), SuborderId = order.MorkOrder.SuborderId, SortNum = order.MorkOrder.SortNum, BatchingId = res.BatchingId, Minute = x.Minute, Second = x.Second, LocDishType = x.LocDishType }); } } } } } } for (int i = 0; i <= 1; i++) { oli.Where(p => p.LocDishType == i).ToList()?.ForEach(y => { mORKM.RBTakeNoodleTask.Enqueue(new MOrderLocInfo() { GoodName = y.GoodName, Loc = y.Loc, SuborderId = y.SuborderId, SortNum = y.SortNum, BatchingId = y.BatchingId, LocDishType = y.LocDishType, Minute = y.Minute, RecipeId = y.RecipeId, RecipeNumber = y.RecipeNumber, Recipes = y.Recipes, Second = y.Second }); }); } if (mORKM.TakeBowlTask.FirstOrDefault(p => p.SuborderId == order.MorkOrder.SuborderId) == null) mORKM.TakeBowlTask.Enqueue(new OrderLocInfo() { GoodName = order.MorkOrder.GoodsName, Loc = 11, SuborderId = order.MorkOrder.SuborderId, SortNum = order.MorkOrder.SortNum, }); if (!mORKM.SuborderCount.ContainsKey(order.MorkOrder.SuborderId)) { mORKM.SuborderCount.TryAdd(order.MorkOrder.SuborderId, new SuborderInfo() { ActualCount = oli.Count, AcMeatDishesCount = oli.Where(p => p.LocDishType == 0).ToList().Count, AcVegetableCount = oli.Where(p => p.LocDishType == 1).ToList().Count, }); } } }); } public override void MainTask() { mORKM.AllowRun = mORKM.InitComplete; if (Json.Data.IsVerify) IsHealth = mORKM.InitComplete; else IsHealth = true; TakeBowlTask(); TakeNoodleTask(); OutNoodleTask(); SingleDetect(); TurntableControl(); } private void BowlControl(OrderLocInfo orderLocInfo) { if (orderLocInfo.Loc >= 10 && orderLocInfo.Loc <= 11) { mORKM.TakeBowlId = orderLocInfo.SuborderId; mORKM.TakeBowName = orderLocInfo.GoodName; mORKM.TakeBowSortNum = orderLocInfo.SortNum; TakeBowlControl(orderLocInfo.Loc); OrderChange(mORKM.TakeBowlId, ORDER_STATUS.COOKING); DeviceProcessLogShow($"订单【{mORKM.TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]"); mORKM.TakeBowlInterlock = true; } } /// /// 取碗控制 /// private void TakeBowlTask() { if (mORKM.AllowRun && mORKM.TakeBowlTask.Count > 0 && !mORKM.DropBowlMechanismStatus && !mORKM.TakeBowlInterlock) { ushort BowLoc = 0; var res = orderMaterialDelivery?.BatchingInfo?.Where(p => p.BatchingId == mORKM.TakeBowlTask.ElementAt(0).BatchingId).ToList(); if (res == null || res?.Count == 0) { if (mORKM.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo)) BowlControl(orderLocInfo); } else { foreach (var item in res) { if (ushort.TryParse(item.BatchingLoc, out ushort loc)) { if (loc == 10 && mORKM.SmallBowlYesOrNoCheck) { BowLoc = loc; break; } else if (loc == 11 && mORKM.LargeBowYesOrNoCheck) { BowLoc = loc; break; } } } if (BowLoc >= 10 && BowLoc <= 11) { if (mORKM.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo)) { orderLocInfo.Loc = BowLoc; BowlControl(orderLocInfo); } } } } } /// /// 转台控制 /// private void TurntableControl() { if (Global.EnableLocalSimOrder) { //不做轮询,直接取面,模拟订单使用 if (mORKM.SiloInPlace && !mORKM.Feeding && mORKM.InitComplete && !mORKM.AllowTakeNoodle && mORKM.RBTakeNoodleTask.Count > 0) { if (mORKM.TurntableLowPosition) { TurntableStart(mORKM.RBTakeNoodleTask.ElementAt(0).Loc); mORKM.TurntableLocLists.Clear(); mORKM.AllowTakeNoodle = true; DeviceProcessLogShow($"控制机器人去转台【{mORKM.RBTakeNoodleTask.ElementAt(0).Loc}】号位置取面"); } } } else { //正常轮询 if (Delay.GetInstance("到位检测延时").Start(mORKM.SiloInPlace, 2)) { if (mORKM.SiloInPlace && !mORKM.Feeding && mORKM.InitComplete && !mORKM.AllowTakeNoodle && mORKM.RBTakeNoodleTask.Count > 0) { var result = orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKM.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList(); if (result != null) { var res = result.FirstOrDefault(P => P.BatchingLoc == mORKM.CurrentFeedbackLoc.ToString()); if (mORKM.TurntableLowPosition && res != null) { TurntableStart(mORKM.CurrentFeedbackLoc); mORKM.TurntableLocLists.Clear(); mORKM.AllowTakeNoodle = true; DeviceProcessLogShow($"控制机器人去转台【{mORKM.CurrentFeedbackLoc}】号位置取面"); } else { if (!mORKM.TurntableInterlock) { foreach (var item in result) { if (ushort.TryParse(item.BatchingLoc, out ushort loc)) { if (mORKM.CurrentFeedbackLoc != loc && !mORKM.TurntableLocLists.Contains(loc)) { if (!mORKM.TurntableLowPosition) { DeviceProcessLogShow($"执行了转台启动互锁信号复位"); } TurntableStart(loc); DeviceProcessLogShow($"没有物料检测的启动转台控制,转台位置:[{loc}]"); break; } else if (mORKM.CurrentFeedbackLoc == loc && !mORKM.TurntableLocLists.Contains(loc)) mORKM.TurntableLocLists.Add(loc); } } } } } else DeviceProcessLogShow("未找到可用的物料信息"); } } } //补料中检测 if (RTrig.GetInstance("mORKS.Feeding").Start(mORKM.Feeding)) { mORKM.AllowTakeNoodle = false; mORKM.TakeNoodleInterlock = false; } //转台到位检测 if (RTrig.GetInstance("TurntableInPlace").Start(mORKM.SiloInPlace && mORKM.CurrentLoc == mORKM.CurrentFeedbackLoc)) { mORKM.TurntableInterlock = false; DeviceProcessLogShow("转台到位检测"); } //补料完成检测 if (RTrig.GetInstance("FeedComplete").Start(mORKM.FeedComplete)) { if (!mORKM.AllowTakeNoodle && mORKM.TurntableLocLists.Count > 0) { mORKM.TurntableLocLists.Clear(); mORKM.TurntableInterlock = false; DeviceProcessLogShow("补料完成检测"); } } } /// /// 取面任务 /// private void TakeNoodleTask() { //取面控制 if (mORKM.AllowRun && mORKM.RobotStatus && !mORKM.RobotOutDinnigLock && !mORKM.Feeding && !mORKM.RobotTaskInterlock && mORKM.AllowTakeNoodle && mORKM.SiloInPlace && !mORKM.TakeNoodleInterlock && mORKM.RBTakeNoodleTask.Count > 0) { if (mORKM.CurrentLoc == mORKM.CurrentFeedbackLoc) { int loc = mORKM.nsm.ToList().FindIndex(p => p.NoodleCookerStatus == false && p.IsShield == false);//查找煮面炉空闲位置 if (loc >= 0 && loc <= 5) { if (mORKM.RBTakeNoodleTask.TryDequeue(out MOrderLocInfo orderLocInfo)) { //写入煮面时间 List values = new List(); values.Add(orderLocInfo.Minute); values.Add(orderLocInfo.Second); WriteData($"VW{324 + (loc * 4)}", values.ToArray()); mORKM.CurrentLoc = 0; mORKM.CookNodelId[loc] = orderLocInfo.SuborderId; mORKM.NoodleCookerStatus[loc] = true; SetFallNoodleLoc((ushort)(loc + 1)); //机器人开始取面 OrderChange(orderLocInfo.SuborderId, ORDER_STATUS.COOKING); DeviceProcessLogShow($"订单【{orderLocInfo.SuborderId}】,机器人倒面至【{loc + 1}】号煮面栏"); if (mORKM.SuborderCount.ContainsKey(orderLocInfo.SuborderId)) { if (orderLocInfo.LocDishType == 0) mORKM.SuborderCount[orderLocInfo.SuborderId].MeatDishesLoc.Add(loc + 1); else if (orderLocInfo.LocDishType == 1) mORKM.SuborderCount[orderLocInfo.SuborderId].VegetableLoc.Add(loc + 1); } mORKM.TakeNoodleInterlock = true; } } } } } /// /// 出餐控制 /// private void OutNoodleTask() { if (mORKM.AllowInvertedFace && !mORKM.RobotOutDinnigLock && mORKM.RobotTaskInterlock && !mORKM.TakeNoodleInterlock && mORKM.RobotStatus) { for (int i = 0; i < mORKM.CookNodelId.Length; i++) { if (mORKM.CookNodelId[i] == mORKM.IngredientsCompleteId && !string.IsNullOrEmpty(mORKM.CookNodelId[i])) { if (mORKM.CookNoodleCom[i] && mORKM.SuborderCount.ContainsKey(mORKM.CookNodelId[i])) { var x = mORKM.SuborderCount[mORKM.CookNodelId[i]]; //执行取素菜操作 if (!mORKM.RobotOutDinnigLock && x.AcVegetableCount != x.CuVegetableCount) { int index = x.VegetableLoc.FindIndex(p => p == i + 1); if (index >= 0) { SetTakeNoodleLoc((ushort)(x.VegetableLoc.ElementAt(index))); mORKM.NoodleCookerStatus[i] = false; WriteData($"VW260", (ushort)0);//设置出汤时间 DeviceProcessLogShow($"{x.VegetableLoc.ElementAt(index)} 号位置-[素菜]-出餐控制,订单ID:{mORKM.CookNodelId[i]}"); mORKM.CookNodelId[i] = string.Empty; mORKM.CookNoodleCom[i] = false; x.VegetableLoc.RemoveAt(index); x.CuVegetableCount++; mORKM.RobotOutDinnigLock = true; } } //执行取荤菜 if (!mORKM.RobotOutDinnigLock && x.AcVegetableCount == x.CuVegetableCount && x.AcMeatDishesCount != x.CuMeatDishesCount) { int index = x.MeatDishesLoc.FindIndex(p => p == i + 1); if (index >= 0) { SetTakeNoodleLoc((ushort)(x.MeatDishesLoc.ElementAt(index))); mORKM.NoodleCookerStatus[i] = false; WriteData($"VW260", (ushort)0);//设置出汤时间 DeviceProcessLogShow($"{x.MeatDishesLoc.ElementAt(index)} 号位置-[荤菜]-出餐控制,订单ID:{mORKM.CookNodelId[i]}"); mORKM.CookNodelId[i] = string.Empty; mORKM.CookNoodleCom[i] = false; x.MeatDishesLoc.RemoveAt(index); x.CuMeatDishesCount++; mORKM.RobotOutDinnigLock = true; } } } } } } } /// /// 验证是否可以出餐 /// /// private bool IsCanDiningOut(bool condition) { if (mORKM.AllowInvertedFace && condition && !mORKM.RobotOutDinnigLock && !mORKM.TakeNoodleInterlock && mORKM.RobotStatus) { for (int i = 0; i < mORKM.CookNodelId.Length; i++) { if (mORKM.CookNodelId[i] == mORKM.IngredientsCompleteId && !string.IsNullOrEmpty(mORKM.CookNodelId[i])) { if (mORKM.CookNoodleCom[i] && mORKM.SuborderCount.ContainsKey(mORKM.CookNodelId[i])) { var x = mORKM.SuborderCount[mORKM.CookNodelId[i]]; //执行取素菜操作 if (x.AcVegetableCount != x.CuVegetableCount) { int index = x.VegetableLoc.FindIndex(p => p == i + 1); if (index >= 0) { return true; } } //执行取荤菜 if (!mORKM.RobotOutDinnigLock && x.AcVegetableCount == x.CuVegetableCount && x.AcMeatDishesCount != x.CuMeatDishesCount) { int index = x.MeatDishesLoc.FindIndex(p => p == i + 1); if (index >= 0) { return true; } } } } } } return false; } /// /// 信号检测 /// private void SingleDetect() { //允许倒面信号检测 if (RTrig.GetInstance("AllowFallNoodle").Start(mORKM.AllowInvertedFace)) { mORKM.IngredientsCompleteId = mORKM.TakeBowlId; mORKM.IngredientsCompleteName = mORKM.TakeBowName; mORKM.IngredientsCompleteSortNum = mORKM.TakeBowSortNum; mORKM.TakeBowSortNum = 0; mORKM.TakeBowlId = string.Empty; mORKM.TakeBowName = string.Empty; DeviceProcessLogShow($"碗到位,允许到面,{mORKM.IngredientsCompleteId}"); mORKM.TakeBowlInterlock = false; } //取餐完成逻辑处理 if (RTrig.GetInstance("CompleteChange1").Start(mORKM.DiningComplete) && mORKM.CookCompleteFlatBit == true) { OrderChange(mORKM.OutMealId, ORDER_STATUS.COMPLETED_TAKE); DeviceProcessLogShow($"订单【{mORKM.OutMealId}】取餐完成"); WriteData("M10.1", false); DeviceProcessLogShow($"出餐订单序号【{mORKM.OutMealSortNum}】"); VoiceAPI.Speak(mORKM.OutMealSortNum.ToString()); mORKM.CookCompleteFlatBit = false; mORKM.OutMealId = string.Empty; mORKM.OutMealName = string.Empty; mORKM.OutMealSortNum = 0; } //机器人取面完成信号检测 if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKM.RobotTakeNoodleCom)) { mORKM.TakeNoodleInterlock = false; mORKM.AllowTakeNoodle = false; mORKM.TurntableInterlock = false; DeviceProcessLogShow("机器人取面完成信号检测"); } //机器人倒面完成信号检测 if (RTrig.GetInstance("RobotInvertedSurfaceCom").Start(mORKM.RobotInvertedSurfaceCom)) { if (mORKM.SuborderCount.ContainsKey(mORKM.IngredientsCompleteId)) { var x = mORKM.SuborderCount[mORKM.IngredientsCompleteId]; if (x.CuMeatDishesCount + x.CuVegetableCount == x.ActualCount) { OrderChange(mORKM.IngredientsCompleteId, ORDER_STATUS.COMPLETED_COOK); DeviceProcessLogShow($"订单【{mORKM.IngredientsCompleteId}】制作完成"); mORKM.SuborderCount.Remove(mORKM.IngredientsCompleteId, out _); mORKM.CookCompleteFlatBit = true; mORKM.OutMealId = mORKM.IngredientsCompleteId; mORKM.OutMealName = mORKM.IngredientsCompleteName; mORKM.OutMealSortNum = mORKM.IngredientsCompleteSortNum; mORKM.IngredientsCompleteId = string.Empty; CookComplete(); DeviceProcessLogShow($"倒面完成"); } } mORKM.RobotOutDinnigLock = false; } int OutMealRequstCount = mORKM.CookNoodleCom.Where(p => p == true).ToList().Count; int BusyCount = mORKM.nsm.Where(p => p.NoodleCookerStatus == true && p.IsShield == false).ToList().Count;//忙碌数量 int IdleCount = mORKM.nsm.Where(p => p.NoodleCookerStatus == false && p.IsShield == false).ToList().Count;//空闲数量 bool isok = false; for (int i = 0; i < mORKM.CookNodelId.Length; i++) { if (mORKM.CookNodelId[i] == mORKM.IngredientsCompleteId && mORKM.CookNoodleCom[i]) { isok = true; break; } } mORKM.PriorityJudgment = Delay.GetInstance("取餐优先级判断").Start(mORKM.TurntableLocLists.Count > 0 && !mORKM.TurntableLowPosition, 4); mORKM.RobotTaskInterlock = IsCanDiningOut(isok && IdleCount >= 0) && (BusyCount >= 2 || mORKM.RBTakeNoodleTask.Count == 0 || mORKM.PriorityJudgment); } /// /// 语音提醒取餐 /// /// private void WaitMeaLSpeak(string meal) { //VoiceAPI.m_SystemPlayWav(@"Vioce\电子提示音.wav"); //Thread.Sleep(1000); //if (meal != null) mORKS.speech.Speak(meal); //VoiceAPI.m_SystemPlayWav(@"Vioce\取餐通知.wav"); } #region PLC 控制函数 private void WriteData(string address, object value) { EventBus.GetInstance.Publish(new WriteModel() { DeviceId = DeviceId, Address = address, Value = value }); } /// /// 设备初始化 /// public async void DeviceInit() { WriteData("M0.0", true); await Task.Delay(1000); WriteData("M0.0", false); } /// /// 取碗控制 /// /// private void TakeBowlControl(ushort loc) { if (loc == 10)//一次性碗 { WriteData("M9.1", true); } else if (loc == 11)//大碗 { WriteData("M9.0", true); } } /// /// 启动转台 /// /// private void TurntableStart(ushort loc) { if (loc >= 1 && loc <= 5) { mORKM.CurrentLoc = loc; mORKM.TurntableInterlock = true; mORKM.TurntableLocLists.Add(loc); WriteData($"M13.{loc - 1}", true); } } /// /// 设置倒面位置 /// /// private void SetFallNoodleLoc(ushort loc) { if (loc >= 1 && loc <= 6) WriteData($"M14.{loc - 1}", true); } /// /// 设置取面位置 /// /// private void SetTakeNoodleLoc(ushort loc) { if (loc >= 1 && loc <= 6) WriteData($"M15.{loc - 1}", true); } /// /// 上位机单订单执行完成 /// private void CookComplete() { WriteData("M11.0", true); } /// /// 模拟订单事件订阅。 /// public override void SimOrder() { EventBus.GetInstance.Subscribe(0, delegate (IEvent @event, EventCallBackHandle callBackHandle) { if (@event != null && @event is MorkMV1SimorderModel msm) { string guid = Guid.NewGuid().ToString(); //模拟订单的素菜和荤菜计数。[0]为荤菜,[1]为素菜。 int[] materialCount = new int[] { 0, 0 }; int allCount = 0; for (int i = 0; i <= 1; i++) { foreach (var loc in msm.NoodleLoc) { if (loc >= 1 && loc <= 5) { var x = Json.Data.DishLibraryParSets.FirstOrDefault(p => p.TextBlockContext == loc.ToString()); if (x.LocDishType == i) { mORKM.RBTakeNoodleTask.Enqueue(new MOrderLocInfo() { Loc = (ushort)loc, SuborderId = guid, LocDishType = x.LocDishType, Minute = x.Minute, Second = x.Second }); //对菜的数量计数。 materialCount[i]++; allCount++; MessageLog.GetInstance.Show($"添加模拟订单:素材位置【{(ushort)loc}】"); } } } } if (msm.BowlLoc >= 10 && msm.BowlLoc <= 11) { mORKM.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)msm.BowlLoc, SuborderId = guid }); MessageLog.GetInstance.Show($"添加模拟订单:碗位置【{(ushort)msm.BowlLoc}】"); } if (!mORKM.SuborderCount.ContainsKey(guid)) { mORKM.SuborderCount.TryAdd(guid, new SuborderInfo() { ActualCount = allCount, AcMeatDishesCount = materialCount[0], AcVegetableCount = materialCount[1], }); } } }); } #endregion } }