diff --git a/BPASmartClient.Device/HardwareStatusAttribute.cs b/BPASmartClient.Device/HardwareStatusAttribute.cs new file mode 100644 index 00000000..8e322a07 --- /dev/null +++ b/BPASmartClient.Device/HardwareStatusAttribute.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.Device +{ + public class HardwareStatusAttribute : Attribute + { + public HardwareStatusAttribute(string describe, string address) + { + Describe = describe; + this.Address = address; + } + + /// + /// 描述 + /// + public string Describe { get; set; } + + + /// + /// 地址 + /// + public string Address { get; set; } + } +} diff --git a/BPASmartClient.Device/IHardwareStatus.cs b/BPASmartClient.Device/IHardwareStatus.cs new file mode 100644 index 00000000..b9a95b53 --- /dev/null +++ b/BPASmartClient.Device/IHardwareStatus.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.Device +{ + /// + /// 硬件状态接口 + /// + public interface IHardwareStatus + { + } +} diff --git a/BPASmartClient.MorkM/Alarm.cs b/BPASmartClient.MorkM/Alarm.cs new file mode 100644 index 00000000..3bf2d5d7 --- /dev/null +++ b/BPASmartClient.MorkM/Alarm.cs @@ -0,0 +1,207 @@ +using BPASmartClient.Device; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.MorkM +{ + public class Alarm : IAlarm + { + + /// + /// 煮面机左侧低温报警 + /// PLC ---> M230.0 + /// ModbusTcp --> 1570 + /// + [Alarm("煮面机左侧低温报警")] + public bool MachineLeftLowTemperature { get; set; } + + /// + /// 煮面机左侧低温报警 + /// PLC ---> M230.1 + /// ModbusTcp --> 1571 + /// + [Alarm("煮面机右侧低温报警")] + public bool MachineRightLowTemperature { get; set; } + + /// + /// 供碗1缺碗 + /// PLC ---> 230.2 + /// ModbusTcp --> 1572 + /// + [Alarm("供碗1缺碗")] + public bool Supply1_LossBowl { get; set; } + + /// + /// 供碗2缺碗 + /// PLC ---> M230.3 + /// ModbusTcp --> 1573 + /// + [Alarm("供碗2缺碗")] + public bool Supply2_LossBowl { get; set; } + + /// + /// 供碗1出碗检测异常 + /// PLC ---> M230.4 + /// ModbusTcp --> 1574 + /// + [Alarm("供碗1出碗检测异常")] + public bool Supply1_ErrorOutBowl { get; set; } + + /// + /// 供碗2出碗检测异常 + /// PLC ---> M230.5 + /// ModbusTcp --> 1575 + /// + [Alarm("供碗2出碗检测异常")] + public bool Supply2_ErrorOutBowl { get; set; } + + /// + /// 推碗气缸故障 + /// PLC ---> M230.6 + /// ModbusTcp --> 1576 + /// + [Alarm("推碗气缸故障")] + public bool PushBowlCylinderError { get; set; } + + /// + /// 煮面机通讯异常 + /// PLC ---> M230.7 + /// ModbusTcp --> 1577 + /// + [Alarm("煮面机通讯异常")] + public bool NoodleMacCommunicateError { get; set; } + + /// + /// 配料机通讯异常 + /// PLC ---> M231.0 + /// ModbusTcp --> 1580 + /// + [Alarm("配料机通讯异常")] + public bool DosingMacCommunicateError { get; set; } + + /// + /// 机器人通讯异常 + /// PLC ---> M231.1 + /// ModbusTcp --> 1581 + /// + [Alarm("机器人通讯异常")] + public bool RobotMacCommunicateError { get; set; } + + /// + /// 机器人通讯异常 + /// PLC ---> M231.2 + /// ModbusTcp --> 1581 + /// + [Alarm("设备急停")] + public bool DeviceEstop { get; set; } + + /// + /// PLC电池电压低 + /// PLC ---> M231.3 + /// ModbusTcp --> 1583 + /// + [Alarm("PLC电池电压低")] + public bool RobotInitError { get; set; } + + /// + /// 机器人急停 + /// PLC ---> M231.4 + /// ModbusTcp --> 1584 + /// + [Alarm("机器人急停")] + public bool RobotUrgentStop { get; set; } + + /// + /// 机器人不在远程模式 + /// PLC ---> M231.5 + /// ModbusTcp --> 1585 + /// + [Alarm("机器人不在远程模式")] + public bool RobotNotInRemoteMode { get; set; } + + /// + /// 机器人伺服未就绪 + /// PLC ---> M231.6 + /// ModbusTcp --> 1586 + /// + [Alarm("机器人伺服未就绪")] + public bool RobotNotInReady { get; set; } + + /// + /// 机器人本体异常 + /// PLC ---> M231.7 + /// ModbusTcp --> 1587 + /// + [Alarm("机器人本体异常")] + public bool RobotSelfInException { get; set; } + + /// + /// 煮面机左侧缺水 + /// PLC ---> M232.0 + /// ModbusTcp --> 1570 + /// + [Alarm("煮面机左侧缺水报警")] + public bool LeftLackWater { get; set; } + + /// + /// 煮面机右侧缺水 + /// PLC ---> M232.1 + /// ModbusTcp --> 1571 + /// + [Alarm("煮面机右侧缺水报警")] + public bool RightLackWater { get; set; } + + /// + /// 丝杆初始化失败 + /// PLC ---> M232.2 + /// ModbusTcp --> 1571 + /// + [Alarm("丝杆初始化失败")] + public bool SvrewInitFail { get; set; } + + /// + /// 转盘初始化失败 + /// PLC ---> M232.3 + /// ModbusTcp --> 1571 + /// + [Alarm("转盘初始化失败")] + public bool TurntableInitFail { get; set; } + + /// + /// 机器人初始化失败 + /// PLC ---> M232.4 + /// ModbusTcp --> 1571 + /// + [Alarm("机器人初始化失败")] + public bool RobotInitFail { get; set; } + + /// + /// 煮面机初始化失败 + /// PLC ---> M232.5 + /// ModbusTcp --> 1571 + /// + [Alarm("煮面机初始化失败")] + public bool NoodleCookerInitFail { get; set; } + + /// + /// 推碗1步进推杆初始化失败 + /// PLC ---> M232.6 + /// ModbusTcp --> 1571 + /// + [Alarm("推碗1步进推杆初始化失败")] + public bool PushBowlInitFail1 { get; set; } + + /// + /// 推碗2步进推杆初始化失败 + /// PLC ---> M232.7 + /// ModbusTcp --> 1571 + /// + [Alarm("推碗2步进推杆初始化失败")] + public bool PushBowlInitFail2 { get; set; } + + + } +} diff --git a/BPASmartClient.MorkM/BPASmartClient.MorkM.csproj b/BPASmartClient.MorkM/BPASmartClient.MorkM.csproj new file mode 100644 index 00000000..7eaf6836 --- /dev/null +++ b/BPASmartClient.MorkM/BPASmartClient.MorkM.csproj @@ -0,0 +1,40 @@ + + + + net6.0-windows + enable + true + + + + + + + + + Code + + + Code + + + Code + + + + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + Designer + + + + diff --git a/BPASmartClient.MorkM/Control_MORKM.cs b/BPASmartClient.MorkM/Control_MORKM.cs new file mode 100644 index 00000000..27eb253a --- /dev/null +++ b/BPASmartClient.MorkM/Control_MORKM.cs @@ -0,0 +1,1148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Diagnostics; +using BPASmartClient.Device; +using BPASmartClient.Helper; +using BPA.Message.Enum; +using BPASmartClient.Model; +using BPASmartClient.EventBus; +using static BPASmartClient.EventBus.EventBus; +using BPASmartClient.MorkS.ViewModel; +using BPASmartClient.MorkM.Model; + +namespace BPASmartClient.MorkM +{ + public class Control_MORKM : BaseDevice + { + + GVL_MORKM mORKS = new GVL_MORKM(); + Alarm alarm = new Alarm(); + HardwareStatus hardwareStatus = new HardwareStatus(); + + public void Init() + { + ActionManage.GetInstance.Register(new Action(() => { WriteRecipeBoms(); }), "recipeBom"); + ActionManage.GetInstance.Register(new Action(() => { DeviceInit(); }), "InitCommand"); + } + //public void ConnectOk() + //{ + // WriteRecipeBoms(); + // ReadData(); + // Main(); + // ResetProgram(); + // ActionManage.GetInstance.Register(new Action(() => + // { + // Random rd = new Random(); + // ThreadManage.GetInstance().StartLong(new Action(() => + // { + // int NoodleLoc = rd.Next(1, 6); + // int BowlLoc = rd.Next(10, 11); + // string guid = new Guid().ToString(); + + // mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = (ushort)NoodleLoc, SuborderId = guid }); + // MessageLog.GetInstance.Show($"添加订单:面条位置【{NoodleLoc}】"); + + // mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = (ushort)BowlLoc, SuborderId = guid }); + // MessageLog.GetInstance.Show($"添加订单:碗位置【{BowlLoc}】"); + // Thread.Sleep(60000); + // }), "ForOrder"); + // }), "EnableForOrder"); + + // ActionManage.GetInstance.Register(new Action(() => + // { + // ThreadManage.GetInstance.StopTask("ForOrder", new Action(() => + // { + // mORKS.RBTakeNoodleTask.Clear(); + // mORKS.TakeBowlTask.Clear(); + // })); + // }), "StopForOrder"); + + // MessageLog.GetInstance.Show("MORKM 设备初始化完成"); + //} + + //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(() => + // { + // mORKS = null; + // mORKS = new GVL_MORKM(); + // ActionManage.GetInstance.Send("ResetProgram"); + // ActionManage.GetInstance.Send("ClearOrders"); + // ReadData(); + // Main(); + // })); + // })); + // } + + // Thread.Sleep(10); + // }), "ResetProgram"); + //} + + /// + /// 数据读取 + /// + //public void ReadData() + //{ + // ThreadManage.GetInstance.StartLong(new Action(() => + // { + // ModbusTcpHelper.GetInstance.Readbool(323, 3, new Action((bools) => + // { + // mORKS.RobotTakeNoodle = bools[0]; + // mORKS.RobotOutMeal = bools[1]; + // mORKS.MoveTurntable = bools[2]; + // })); + + // ModbusTcpHelper.GetInstance.Readbool(1120, 16, new Action((bools) => + // { + // mORKS.InitComplete = bools[0]; + // mORKS.TakeBowlIdle = bools[1]; + // mORKS.TemperatureReached = bools[2]; + // mORKS.AllowFallNoodle = bools[3]; + // mORKS.RbTakeNoodleComplete = bools[4]; + // mORKS.RbFallNoodleComplete = bools[5]; + // mORKS.RbOutMealComplete = bools[6]; + // mORKS.RobotIdle = bools[7]; + // mORKS.TakeMealDetect = bools[8]; + // mORKS.MissingBowl = bools[9]; + // DeviceData.Initing = bools[10]; + // mORKS.TurntableLowerLimit = bools[11]; + // mORKS.MissingBowlSignal2 = bools[12]; + // mORKS.TurntableUpLimit = bools[13]; + // mORKS.FeedComplete = bools[14]; + // mORKS.TurntableMoveInPlace = bools[15]; + // })); + + // var errorStatus = ModbusTcpHelper.GetInstance.Read((ushort)ModbusTcpHelper.GetInstance.GetBoolAddress("M235.0"), ReadType.Coils, 1); + // if (errorStatus != null && errorStatus is bool error) mORKS.Error = error; + + // ModbusTcpHelper.GetInstance.Readbool(1136, 7, new Action((bools) => + // { + // for (int i = 0; i < 6; i++) + // { + // mORKS.NoodleCookerStatus[i] = bools[i]; + // } + // mORKS.Feeding = bools[6]; + // })); + + // ModbusTcpHelper.GetInstance.Readbool(1144, 6, new Action((bools) => + // { + // for (int i = 0; i < 6; i++) + // { + // mORKS.CookNoodlesComplete[i] = bools[i]; + // } + // })); + + // ModbusTcpHelper.GetInstance.Readbool(1570, 20, new Action((bools) => + // { + // alarm.MachineLeftLowTemperature = bools[0]; + // alarm.MachineRightLowTemperature = bools[1]; + // alarm.Supply1_LossBowl = bools[2]; + // alarm.Supply2_LossBowl = bools[3]; + // alarm.Supply1_ErrorOutBowl = bools[4]; + // alarm.Supply2_ErrorOutBowl = bools[5]; + // alarm.PushBowlCylinderError = bools[6]; + // alarm.NoodleMacCommunicateError = bools[7]; + // alarm.DosingMacCommunicateError = bools[8]; + // alarm.RobotMacCommunicateError = bools[9]; + // alarm.RobotInitError = bools[11]; + // alarm.RobotUrgentStop = bools[12]; + // alarm.RobotNotInRemoteMode = bools[13]; + // alarm.RobotNotInReady = bools[14]; + // alarm.RobotSelfInException = bools[15]; + // })); + + + // var ResLoc = ModbusTcpHelper.GetInstance.Read(286, ReadType.HoldingRegisters); + // if (ResLoc != null) + // { + // if (ResLoc is ushort loc) + // { + // mORKS.TurntableFeedbackloc = loc; + // } + // } + + // Thread.Sleep(500); + // }), "ReadPLCData"); + //} + + //public void SimOrder(T simOrder) + //{ + + // if (simOrder != null) + // { + + // if (simOrder is List locs) + // { + // OrderInformation newOrder = new OrderInformation();//新加 + // List orders = new List(); + // string subId = Guid.NewGuid().ToString(); + // foreach (var item in locs) + // { + // if (item >= 1 && item <= 5) + // { + // orders.Add(new OrderLocInfo() { Loc = item, SuborderId = subId, MakeType = false }); + // //mORKS.RBTakeNoodleTask.Enqueue(new OrderLocInfo() { Loc = item, SuborderId = subId }); + // //MessageLog.GetInstance.Show($"添加订单:面条位置【{item}】"); + // } + // if (item >= 10 && item <= 11) + // { + // mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() { Loc = item, SuborderId = subId, MakeType = false }); + // MessageLog.GetInstance.Show($"添加订单:碗位置【{item}】"); + // } + // } + // mORKS.DishNumber = orders.Count;//订单中配菜的数量 + // while (orders.Count > 0) + // { + // for (int i = 0; i < orders.Count; i++) + // { + // var res = orders.FirstOrDefault(p => p.Loc % 2 != 0); + // if (res != null) + // { + // //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == res.SuborderId) == null) + // mORKS.RBTakeNoodleTask.Enqueue(res); + + // orders.Remove(res); + + // } + // else + // { + // //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == orders[i].SuborderId) == null) + // mORKS.RBTakeNoodleTask.Enqueue(orders[i]); + // mORKS.VegtabNum++; + // orders.RemoveAt(i); + + // } + // } + // } + // Dictionary dic = new Dictionary(); + // newOrder.DishNum = mORKS.DishNumber; + // newOrder.VegatableNumber = mORKS.VegtabNum; + // dic.Add(subId, newOrder); + // mORKS.Conqueue.Enqueue(dic); + // mORKS.VegtabNum = 0; + // mORKS.DishNumber = 0; + // } + // } + //} + + ///// + ///// IOT 广播消息命令 + ///// + //public void IotBroadcast(T broadcast) + //{ + // if (broadcast != null && broadcast is IOTCommandModel iOTCommand) + // { + // MessageLog.GetInstance.Show($"IOT 广播消息命令 {iOTCommand.deviceName} 设备命令 {iOTCommand.CommandName} 控制变量{iOTCommand.CommandValue.Keys.First()}{iOTCommand.CommandValue[iOTCommand.CommandValue.Keys.First()]}"); + // switch (iOTCommand.CommandName) + // { + // case 0://控制类 + // if (iOTCommand.CommandValue != null) + // { + // if (iOTCommand.CommandValue.ContainsKey("order")) + // { + // List vs = new List(); + // vs.Add((ushort)(new Random().Next(1, 5))); + // vs.Add(ushort.Parse(iOTCommand.CommandValue["order"])); + // SimOrder(vs); + // } + // else if (iOTCommand.CommandValue.ContainsKey("init")) + // { + // DeviceInit(); + // } + // else if (iOTCommand.CommandValue.ContainsKey("stop")) + // { + // } + // else if (iOTCommand.CommandValue.ContainsKey("start")) + // { + // } + // } + // break; + // case 1://设置属性 + + // break; + // case 2://通知消息 + + // break; + // default: + // break; + // } + // } + //} + + int OrderCount = 0; + + public override DeviceClientType DeviceType => DeviceClientType.MORKM; + + ///// + ///// 数据解析 + ///// + //public void DataParse(T order) + //{ + // OrderCount++; + // MessageLog.GetInstance.Show($"接收到{OrderCount}次订单"); + // if (order is MorkOrderPush morkOrderPush) + // { + // OrderInformation newOrder = new OrderInformation();//2022.4.30 修改 + // List locs = new List(); + // 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) + // { + // locs.Add(new OrderLocInfo() { Loc = ushort.Parse(res.BatchingLoc), SuborderId = morkOrderPush.SuborderId, BatchingId = res.BatchingId, MakeType = morkOrderPush.MakeID == "2" }); //新增冒菜干拌or加汤 + // } + // else if (loc >= 10 && loc <= 11) + // { + // int index = 0; + // if (Json.Data.recipeBoms != null) + // { + // index = Array.FindIndex(Json.Data.recipeBoms?.RecipeIds.ToArray(), p => p.RecipeId == morkOrderPush.RecipeId); + // index++; + // } + // if (mORKS.TakeBowlTask.FirstOrDefault(p => p.SuborderId == morkOrderPush.SuborderId) == null) + // mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() + // { + // Loc = 11, + // SuborderId = morkOrderPush.SuborderId, + // RecipeNumber = (index >= 1 && index <= 10) ? (ushort)index : (ushort)0 + // }); + // } + // } + // } + // } + // //手动供碗 调试用 + // mORKS.TakeBowlTask.Enqueue(new OrderLocInfo() + // { + // Loc = 11, + // SuborderId = morkOrderPush.SuborderId, + // MakeType = morkOrderPush.MakeID == "2" + // }); + // mORKS.DishNumber = locs.Count;//订单中配菜的数量 2022.4.30 修改 + // while (locs.Count > 0) + // { + // for (int i = 0; i < locs.Count; i++) + // { + // var res = locs.FirstOrDefault(p => p.Loc % 2 != 0); + // if (res != null) + // { + // //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == res.SuborderId) == null) + // mORKS.RBTakeNoodleTask.Enqueue(res); + // locs.Remove(res); + + // } + // else + // { + // //if (mORKS.RBTakeNoodleTask.FirstOrDefault(p => p.SuborderId == locs[i].SuborderId) == null) + // mORKS.RBTakeNoodleTask.Enqueue(locs[i]); + // mORKS.VegtabNum++; + // locs.RemoveAt(i); + + // } + // } + // } + + // Dictionary dic = new Dictionary(); + // newOrder.DishNum = mORKS.DishNumber; + // newOrder.VegatableNumber = mORKS.VegtabNum; + // //newOrder.MakeType = morkOrderPush.MakeType; + // dic.Add(morkOrderPush.SuborderId, newOrder); + // mORKS.Conqueue.Enqueue(dic); + // mORKS.VegtabNum = 0; + // mORKS.DishNumber = 0; + // } + //} + + public void Main() + { + //ThreadManage.GetInstance.StartLong(new Action(() => + //{ + // mORKS.AllowRun = mORKS.InitComplete; + // GeneralConfig.Healthy = mORKS.Error && mORKS.InitComplete && !GeneralConfig.EnableLocalSimOrder; + // //GeneralConfig.Healthy = true; + // TakeBowlTask(); + + // TakeNoodleTask(); + + // OutNoodleTask(); + + // SingleDetect(); + + // TurntableControl(); + + // Thread.Sleep(100); + + //}), "MainTask"); + } + + /// + /// 取碗控制 + /// + private void TakeBowlTask() + { + if (mORKS.AllowRun && mORKS.TakeBowlTask.Count > 0 && !mORKS.TakeBowlIdle && !mORKS.TakeBowlInterlock) + { + if (mORKS.TakeBowlTask.TryDequeue(out OrderLocInfo orderLocInfo)) + { + mORKS.TakeBowlId = orderLocInfo.SuborderId; + mORKS.OutMealType = orderLocInfo.MakeType;//新增冒菜干拌or加汤 + TakeBowlControl(orderLocInfo.Loc); + SetRecipeNumber(orderLocInfo.RecipeNumber); + SimpleFactory.GetInstance.OrderChanged(mORKS.TakeBowlId, ORDER_STATUS.COOKING); + MessageLog.GetInstance.Show($"订单【{ mORKS.TakeBowlId}】执行取碗控制,位置:[{orderLocInfo.Loc}]"); + } + mORKS.TakeBowlInterlock = true; + } + } + + /// + /// 转台控制 + /// + private void TurntableControl() + { + if (GeneralConfig.EnableLocalSimOrder) + { + //不做轮询,直接取面,模拟订单使用 + if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0) + { + if (mORKS.TurntableLowerLimit) + { + TurntableStart(mORKS.RBTakeNoodleTask.ElementAt(0).Loc); + if (mORKS.RBTakeNoodleTask.ElementAt(0).Loc == mORKS.TurntableFeedbackloc) + { + mORKS.TurntableLocLists.Clear(); + mORKS.AllowTakeNoodle = true; + MessageLog.GetInstance.Show($"控制机器人去转台【{mORKS.RBTakeNoodleTask.ElementAt(0).Loc}】号位置取面"); + } + } + } + } + else + { + //正常轮询 + if (mORKS.TurntableMoveInPlace && !mORKS.Feeding && mORKS.InitComplete && !mORKS.AllowTakeNoodle && mORKS.RBTakeNoodleTask.Count > 0) + { + var result = Json.Data.orderMaterialDelivery.BatchingInfo.Where(p => p.BatchingId == mORKS.RBTakeNoodleTask.ElementAt(0).BatchingId).ToList(); + if (result != null) + { + var res = result.FirstOrDefault(P => P.BatchingLoc == mORKS.TurntableFeedbackloc.ToString()); + if (mORKS.TurntableLowerLimit && res != null) + { + //if (mORKS.RBTakeNoodleTask.ElementAt(0).Loc != mORKS.TurntableFeedbackloc) + TurntableStart(mORKS.TurntableFeedbackloc); + mORKS.TurntableLocLists.Clear(); + mORKS.AllowTakeNoodle = true; + MessageLog.GetInstance.Show($"控制机器人去转台【{mORKS.TurntableFeedbackloc}】号位置取面"); + } + else + { + if (!mORKS.TurntableInterlock) + { + foreach (var item in result) + { + if (ushort.TryParse(item.BatchingLoc, out ushort loc)) + { + if (mORKS.TurntableFeedbackloc != loc && !mORKS.TurntableLocLists.Contains(loc)) + { + TurntableStart(loc); + MessageLog.GetInstance.Show($"没有物料检测的启动转台控制,转台位置:[{loc}]"); + break; + } + else if (mORKS.TurntableFeedbackloc == loc && !mORKS.TurntableLocLists.Contains(loc)) mORKS.TurntableLocLists.Add(loc); + } + } + } + } + } + else MessageLog.GetInstance.Show("未找到可用的物料信息"); + } + } + + //转台到位检测 + if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace && mORKS.CurrentLoc == mORKS.TurntableFeedbackloc)) + { + mORKS.CurrentLoc = 0; + mORKS.TurntableInterlock = false; + MessageLog.GetInstance.Show("转台到位检测"); + } + + //补料完成检测 + if (RTrig.GetInstance("FeedComplete").Start(mORKS.FeedComplete)) + { + if (!mORKS.AllowTakeNoodle && mORKS.TurntableLocLists.Count > 0) + { + mORKS.TurntableLocLists.Clear(); + mORKS.TurntableInterlock = false; + MessageLog.GetInstance.Show("补料完成检测"); + } + } + } + /// + /// 取面任务 + /// + private void TakeNoodleTask() + { + //取面控制 + if (mORKS.AllowRun && mORKS.RobotIdle && !mORKS.Feeding && (!mORKS.RobotTaskInterlock || !mORKS.VegNoodlesLock && mORKS.relock) && mORKS.AllowTakeNoodle && mORKS.TurntableMoveInPlace && !mORKS.TakeNoodleInterlock && !mORKS.OutNoodleing && mORKS.RBTakeNoodleTask.Count > 0) + { + + int loc = Array.FindIndex(mORKS.NoodleCookerStatus, p => p == false);//查找煮面炉空闲位置 + if (loc >= 0 && loc <= 5) + { + + if (mORKS.RBTakeNoodleTask.TryDequeue(out OrderLocInfo orderLocInfo)) + { + + // mORKS.CookNodelId[loc] = orderLocInfo.SuborderId; + mORKS.orderLocInfos[loc] = orderLocInfo; + SetFallNoodleLoc((ushort)(loc + 1)); + //机器人开始取面 + RobotTakeNoodle(); + // SimpleFactory.GetInstance.OrderChanged(orderLocInfo.SuborderId, ORDER_STATUS.COOKING); + MessageLog.GetInstance.Show($"订单【{orderLocInfo.SuborderId}】,机器人倒面至【{loc + 1}】号煮面栏"); + + //写入煮菜时间 + List values = new List(); + if (mORKS.orderLocInfos[loc].Loc % 2 == 0)//素菜 + { + values.Add(2);//分 + values.Add(0);//秒 + ModbusTcpHelper.GetInstance.Write((ushort)ModbusTcpHelper.GetInstance.GetWordAddress($"VW{116 + (loc * 6)}"), WriteType.HoldingRegisters, values.ToArray()); + } + else //荤菜 + { + values.Add(4);//分 + values.Add(0);//秒 + ModbusTcpHelper.GetInstance.Write((ushort)ModbusTcpHelper.GetInstance.GetWordAddress($"VW{116 + (loc * 6)}"), WriteType.HoldingRegisters, values.ToArray()); + } + + + mORKS.TakeNoodleInterlock = true; + } + } + + } + } + + /// + /// 出餐控制 + /// + private void OutNoodleTask() + { + if (mORKS.AllowFallNoodle && mORKS.RobotTaskInterlock && !mORKS.TakeNoodleInterlock && mORKS.RobotIdle && !mORKS.TakeMealDetect) + { + // var list= mORKS.CookNoodlesComplete.Where(p => p == true).ToList(); + mORKS.HasVeg = false; + for (int i = 0; i < mORKS.CookNoodlesComplete.Length; i++) + { + if (mORKS.CookNoodlesComplete[i] && mORKS.orderLocInfos[i] != null && mORKS.orderLocInfos[i].SuborderId == mORKS.IngredientsCompleteId) + { + if (!mORKS.relock) + { + if (mORKS.Conqueue.TryDequeue(out Dictionary dic)) + { + mORKS.Vnum = dic[mORKS.orderLocInfos[i].SuborderId].VegatableNumber; + mORKS.TotalNum = dic[mORKS.orderLocInfos[i].SuborderId].DishNum; + mORKS.relock = true; + } + } + if (mORKS.orderLocInfos[i].Loc % 2 == 0) + { + mORKS.HasVeg = true; + mORKS.ListOrder.Add(i, mORKS.orderLocInfos[i]);//找出当前订单煮熟的素菜 + } + else if (!mORKS.HasVeg) + { + mORKS.ListOrderMeat.Add(i, mORKS.orderLocInfos[i]);//找出当前订单煮熟的荤菜 + } + } + } + if (mORKS.ListOrder.Count > 0) + { + foreach (KeyValuePair item in mORKS.ListOrder) + { + while (!mORKS.RobotIdle) + { + + } + int location = item.Key; //煮面炉位置 + ushort number = item.Value.Loc;//荤素编号 + SetTakeNoodleLoc((ushort)(location + 1)); + RobotOutMeal(); + CookNoodleStatusReset((ushort)(location + 1)); + // ResetAllowFallNoodle(); + mORKS.OutMealId = mORKS.IngredientsCompleteId; + // mORKS.CookNodelId[loc] = string.Empty; + mORKS.orderLocInfos[location] = null; + + MessageLog.GetInstance.Show($"{location + 1}号位置出餐控制"); + mORKS.OutNoodleing = true; + mORKS.Count++; + CheckLastDish(); + } + + } + if (mORKS.ListOrderMeat.Count > 0 && mORKS.Count == mORKS.Vnum && mORKS.ListOrder.Count == 0) + { + foreach (KeyValuePair item in mORKS.ListOrderMeat) + { + while (!mORKS.RobotIdle) + { + + } + int location = item.Key; //煮面炉位置 + ushort number = item.Value.Loc;//荤素编号 + SetTakeNoodleLoc((ushort)(location + 1)); + RobotOutMeal(); + CookNoodleStatusReset((ushort)(location + 1)); + // ResetAllowFallNoodle(); + mORKS.OutMealId = mORKS.IngredientsCompleteId; + // mORKS.CookNodelId[loc] = string.Empty; + mORKS.orderLocInfos[location] = null; + // mORKS.Count++; + MessageLog.GetInstance.Show($"{location + 1}号位置出餐控制"); + mORKS.OutNoodleing = true; + mORKS.CountMeat++; + CheckLastDish(); + } + + } + mORKS.ListOrder.Clear(); + mORKS.ListOrderMeat.Clear(); + } + } + + /// + /// 检查是否是当前订单最后一个配菜 + /// + public void CheckLastDish() + { + mORKS.Num = 0; + foreach (var item1 in mORKS.orderLocInfos) + { + if (item1 != null) + { + if (item1.SuborderId == mORKS.OutMealId) + { + mORKS.Num++; + //mORKS.Count++; + //mORKS.CountMeat++; + } + } + + } + if (mORKS.Num == 0 && mORKS.Count + mORKS.CountMeat == mORKS.TotalNum) + { + if (mORKS.OutMealType) + { + AddSoup();//加汤 + MessageLog.GetInstance.Show("正在加汤"); + } + else + { + //不加汤 + } + CookComplete(); //告诉机器人冒菜已经煮完 + ResetAllowFallNoodle(); + //mORKS.VegNoodlesLock = false; + mORKS.VegN = 0; + mORKS.relock = false; + mORKS.Count = 0; + mORKS.CountMeat = 0; + mORKS.IngredientsCompleteId = string.Empty; + mORKS.TakeBowlId = string.Empty; + mORKS.TakeBowlInterlock = false; + + } + else + { + + while (mORKS.RobotIdle) + { + + } + // Thread.Sleep(3000); + } + + } + /// + /// 信号检测 + /// + private void SingleDetect() + { + + //允许倒面信号检测 + if (RTrig.GetInstance("AllowFallNoodle").Start(mORKS.AllowFallNoodle)) + { + + mORKS.IngredientsCompleteId = mORKS.TakeBowlId; + // mORKS.TakeBowlId = string.Empty; + // MessageLog.GetInstance.Show("碗到位,允许到面"); + MessageLog.GetInstance.Show($"碗到位,允许到面,{mORKS.IngredientsCompleteId}"); + // mORKS.TakeBowlInterlock = false; + } + + //出餐完成信号检测 + if (RTrig.GetInstance("CompleteChange").Start(mORKS.RbOutMealComplete)) + { + + SimpleFactory.GetInstance.OrderChanged(mORKS.OutMealId, ORDER_STATUS.COMPLETED_COOK); + MessageLog.GetInstance.Show($"订单【{mORKS.OutMealId}】制作完成"); + mORKS.OutNoodleing = false; + } + + //取餐完成逻辑处理 + if (DelayRTrig.GetInstance("CompleteChange1").Start(mORKS.RbOutMealComplete && !mORKS.TakeMealDetect, 2)) + { + SimpleFactory.GetInstance.OrderChanged(mORKS.OutMealId, ORDER_STATUS.COMPLETED_TAKE); + MessageLog.GetInstance.Show($"订单【{mORKS.OutMealId}】取餐完成"); + ResetCookComplete(); + mORKS.OutMealId = string.Empty; + } + + //机器人取面完成信号检测 + if (RTrig.GetInstance("TakeNoodleComplete").Start(mORKS.RbTakeNoodleComplete)) + { + mORKS.TakeNoodleInterlock = false; + mORKS.AllowTakeNoodle = false; + mORKS.TurntableInterlock = false; + MessageLog.GetInstance.Show("机器人取面完成信号检测"); + TakeNoodleCompleteReset(); + } + + //转台到位检测 + //if (RTrig.GetInstance("TurntableInPlace").Start(mORKS.TurntableMoveInPlace)) + //{ + // mORKS.TurntableInterlock = false; + //} + + mORKS.VegNoodlesLock = false; + + for (int i = 0; i < mORKS.CookNoodlesComplete.Length; i++) + { + if (mORKS.CookNoodlesComplete[i] && mORKS.orderLocInfos[i] != null && mORKS.orderLocInfos[i].SuborderId == mORKS.IngredientsCompleteId) + { + if ((mORKS.orderLocInfos[i].Loc % 2 == 0 || mORKS.Vnum == 0) && mORKS.relock) + { + mORKS.VegNoodlesLock = true; + mORKS.VegN++; + break; + } + + + } + } + if (mORKS.VegN == mORKS.Vnum && mORKS.VegN < mORKS.TotalNum && mORKS.relock) + { + mORKS.VegNoodlesLock = true; + } + int OutMealRequstCount = mORKS.CookNoodlesComplete.Where(p => p == true).ToList().Count; + int mlCount = mORKS.NoodleCookerStatus.Where(p => p == true).ToList().Count; + mORKS.RobotTaskInterlock = OutMealRequstCount > 0 && mORKS.AllowFallNoodle && (mlCount >= 1 || mORKS.RBTakeNoodleTask.Count == 0); + if (mORKS.RobotIdle && mORKS.RobotTaskInterlock == false) + { + mORKS.OutNoodleing = false; + } + } + + + #region PLC 控制函数 + + /// + /// 写入配方数据到 PLC + /// + private void WriteRecipeBoms() + { + List recipeBoms = new List(); + if (Json.Data.recipeBoms == null) return; + foreach (var item in Json.Data.recipeBoms.RecipeIds) + { + foreach (var rec in item.Recipes) + { + recipeBoms.Add((ushort)rec); + } + } + if (recipeBoms.Count > 0) + { + if (ModbusTcpHelper.GetInstance.Write(1100, WriteType.HoldingRegisters, recipeBoms.ToArray())) + { + MessageLog.GetInstance.Show("成功写入配方数据"); + } + } + else { MessageLog.GetInstance.Show("配方数据为空"); } + } + + /// + /// 取面完成复位 + /// + private void TakeNoodleCompleteReset() + { + ModbusTcpHelper.GetInstance.Write(1124, WriteType.Coils, false); + } + + /// + /// 指定煮面口状态复位 + /// + /// + private void CookNoodleStatusReset(int num) + { + if (num >= 1 && num <= 6) + { + ushort addRess = (ushort)(1136 + num - 1); + ModbusTcpHelper.GetInstance.Write(addRess, WriteType.Coils, false); + MessageLog.GetInstance.Show($"{num}号煮面口占用复位"); + } + + } + + /// + /// 写配方编号 + /// + /// + private void SetRecipeNumber(ushort num) + { + ModbusTcpHelper.GetInstance.Write(100, WriteType.HoldingRegisters, num); + } + + /// + /// 启动转台 + /// + /// + private void TurntableStart(ushort loc) + { + mORKS.CurrentLoc = loc; + mORKS.TurntableInterlock = true; + mORKS.TurntableLocLists.Add(loc); + ModbusTcpHelper.GetInstance.Write(101, WriteType.HoldingRegisters, loc); + ModbusTcpHelper.GetInstance.Write(325, WriteType.Coils, true); + } + + /// + /// 设置倒面位置 + /// + /// + private void SetFallNoodleLoc(ushort loc) + { + ModbusTcpHelper.GetInstance.Write(102, WriteType.HoldingRegisters, loc); + } + + /// + /// 设置取面位置 + /// + /// + private void SetTakeNoodleLoc(ushort loc) + { + ModbusTcpHelper.GetInstance.Write(103, WriteType.HoldingRegisters, loc); + } + + /// + /// 取碗控制 + /// + /// + private void TakeBowlControl(ushort loc) + { + if (loc == 10)//小碗 + { + ModbusTcpHelper.GetInstance.Write(321, WriteType.Coils, true); + } + else if (loc == 11)//大碗 + { + ModbusTcpHelper.GetInstance.Write(322, WriteType.Coils, true); + } + } + + /// + /// 机器人取面 + /// + private void RobotTakeNoodle() + { + ModbusTcpHelper.GetInstance.Write(323, WriteType.Coils, true); + } + + /// + /// 机器人取餐 + /// + private void RobotOutMeal() + { + ModbusTcpHelper.GetInstance.Write(324, WriteType.Coils, true); + var result = ModbusTcpHelper.GetInstance.Read(324, ReadType.Coils); + if (result is bool res) + while (!res) + { + ModbusTcpHelper.GetInstance.Write(324, WriteType.Coils, true); + } + } + + /// + /// 制作完成信号复位 + /// + private void ResetCookComplete() + { + ModbusTcpHelper.GetInstance.Write(1126, WriteType.Coils, false); + } + + /// + /// 复位允许取面信号 + /// + private void ResetAllowFallNoodle() + { + ModbusTcpHelper.GetInstance.Write(1123, WriteType.Coils, false); + } + + /// + /// 设备初始化 + /// + public async void DeviceInit() + { + ModbusTcpHelper.GetInstance.Write(320, WriteType.Coils, true); + await Task.Delay(1000); + ModbusTcpHelper.GetInstance.Write(320, WriteType.Coils, false); + + } + + /// + /// 制作完成,允许机器人往外推碗 + /// + public void CookComplete() + { + ModbusTcpHelper.GetInstance.Write((ushort)ModbusTcpHelper.GetInstance.GetBoolAddress("M0.6"), WriteType.Coils, true); + } + + /// + /// 是否加汤 + /// + public void AddSoup() + { + ModbusTcpHelper.GetInstance.Write((ushort)ModbusTcpHelper.GetInstance.GetBoolAddress("M0.7"), WriteType.Coils, true); + } + + private void ServerInit() + { + //物料信息 + EventBus.EventBus.GetInstance().Subscribe(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack) + { + if (@event == null) return; + if (@event is MaterialDeliveryEvent material) + { + orderMaterialDelivery = material.orderMaterialDelivery; + } + }); + + //配方数据信息 + EventBus.EventBus.GetInstance().Subscribe(DeviceId, delegate (IEvent @event, EventCallBackHandle callBack) + { + if (@event == null) return; + if (@event is RecipeBomEvent recipe) + { + recipeBoms = recipe.recipeBoms; + WriteRecipeBoms(); + } + }); + } + + public override void DoMain() + { + MonitorViewModel.DeviceId = DeviceId; + ServerInit(); + DataParse(); + + 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 != 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() + { + mORKS = null; + mORKS = new GVL_MORKM(); + } + + private void GetStatus(string key, Action action) + { + if (peripheralStatus.ContainsKey(key)) + { + if (peripheralStatus[key] != null) + { + action?.Invoke(peripheralStatus[key]); + } + } + } + + private void OrderChange(string subid, ORDER_STATUS oRDER_STATUS) + { + var res = mORKS.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(); + } + EventBus.EventBus.GetInstance().Publish(new OrderStatusChangedEvent() { SortNum = SortNum, GoodName = goodName, Status = oRDER_STATUS, SubOrderId = subid, deviceClientType = DeviceType }); + } + + + public override void Stop() + { + throw new NotImplementedException(); + } + + public override void ReadData() + { + GetStatus("M230.0", new Action((obj) => + { + if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 24) + { + alarm.MachineLeftLowTemperature = bools[0]; + alarm.MachineRightLowTemperature = bools[1]; + alarm.Supply1_LossBowl = bools[2]; + alarm.Supply2_LossBowl = bools[3]; + alarm.Supply1_ErrorOutBowl = bools[4]; + alarm.Supply2_ErrorOutBowl = bools[5]; + alarm.PushBowlCylinderError = bools[6]; + alarm.NoodleMacCommunicateError = bools[7]; + alarm.DosingMacCommunicateError = bools[8]; + alarm.RobotMacCommunicateError = bools[9]; + alarm.DeviceEstop = bools[10]; + alarm.RobotInitError = bools[11]; + alarm.RobotUrgentStop = bools[12]; + alarm.RobotNotInRemoteMode = bools[13]; + alarm.RobotNotInReady = bools[14]; + alarm.RobotSelfInException = bools[15]; + alarm.LeftLackWater = bools[16]; + alarm.RightLackWater = bools[17]; + alarm.SvrewInitFail = bools[18]; + alarm.TurntableInitFail = bools[19]; + alarm.RobotInitFail = bools[20]; + alarm.NoodleCookerInitFail = bools[21]; + alarm.PushBowlInitFail1 = bools[22]; + alarm.PushBowlInitFail2 = bools[23]; + } + })); + + GetStatus("M0.3", new Action((obj) => + { + if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 3) + { + mORKS.RobotTakeNoodle = bools[0]; + mORKS.RobotOutMeal = bools[1]; + mORKS.MoveTurntable = bools[2]; + } + })); + + GetStatus("M100.0", new Action((obj) => + { + if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 16) + { + mORKS.InitComplete = bools[0]; + mORKS.TakeBowlIdle = bools[1]; + mORKS.TemperatureReached = bools[2]; + mORKS.AllowFallNoodle = bools[3]; + mORKS.RbTakeNoodleComplete = bools[4]; + mORKS.RbFallNoodleComplete = bools[5]; + mORKS.RbOutMealComplete = bools[6]; + mORKS.RobotIdle = bools[7]; + mORKS.TakeMealDetect = bools[8]; + mORKS.MissingBowl = bools[9]; + Initing = bools[10]; + mORKS.TurntableLowerLimit = bools[11]; + mORKS.MissingBowlSignal2 = bools[12]; + mORKS.TurntableUpLimit = bools[13]; + mORKS.FeedComplete = bools[14]; + mORKS.TurntableMoveInPlace = bools[15]; + } + + })); + + GetStatus("M235.0", new Action((obj) => + { + if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 1) + { + mORKS.Error = bools[0]; + } + })); + + + GetStatus("M102.0", new Action((obj) => + { + if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 7) + { + for (int i = 0; i < 6; i++) + { + mORKS.NoodleCookerStatus[i] = bools[i]; + } + mORKS.Feeding = bools[6]; + } + })); + + GetStatus("M103.0", new Action((obj) => + { + if (obj is bool[] bools && bools.Length > 0 && bools.Length <= 6) + { + for (int i = 0; i < 6; i++) + { + mORKS.CookNoodlesComplete[i] = bools[i]; + } + } + + })); + + GetStatus("VW372", new Action((obj) => + { + if (obj is ushort[] UshortValue && UshortValue.Length > 0 && UshortValue.Length <= 1) + mORKS.TurntableFeedbackloc = UshortValue[0]; + })); + } + + public override void MainTask() + { + throw new NotImplementedException(); + } + + + #endregion + + + + } + +} + + diff --git a/BPASmartClient.MorkM/GVL_MORKM.cs b/BPASmartClient.MorkM/GVL_MORKM.cs new file mode 100644 index 00000000..27aaf9b0 --- /dev/null +++ b/BPASmartClient.MorkM/GVL_MORKM.cs @@ -0,0 +1,402 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using BPA.Message; +using BPASmartClient.Device; +using BPASmartClient.Model; + +namespace BPASmartClient.MorkM +{ + /// + /// MORKS 设备数据 + /// + public class GVL_MORKM : IStatus + { + public GVL_MORKM() + { + for (int i = 0; i < 6; i++) + { + CookNodelId.Add(new CookNodleLocAndId() { CookNodelId = "", Loc = -1 }); + } + } + + /// + /// 机器人取面 + /// PLC -> M0.3 + /// ModbusTcp -> 323 + /// + public bool RobotTakeNoodle { get; set; } + + /// + /// 机器人出餐 + /// PLC -> M0.4 + /// ModbusTcp -> 324 + /// + public bool RobotOutMeal { get; set; } + + /// + /// 移动转台 + /// PLC -> M0.5 + /// ModbusTcp -> 325 + /// + public bool MoveTurntable { get; set; } + + + #region 临时变量 + /// + /// 允许运行 + /// + [VariableMonitor("允许运行")] + public bool AllowRun { get; set; } + + /// + /// //机器人任务互锁信号 + /// + [VariableMonitor("机器人任务互锁信号")] + public bool RobotTaskInterlock { get; set; } + + /// + /// 取碗互锁信号 + /// + [VariableMonitor("取碗互锁信号")] + public bool TakeBowlInterlock { get; set; } + + /// + /// 取面互锁信号 + /// + [VariableMonitor("取面互锁信号")] + public bool TakeNoodleInterlock { get; set; } + + /// + /// 出面中 + /// + [VariableMonitor("出面中")] + public bool OutNoodleing { get; set; } + + /// + /// 允许取面 + /// + [VariableMonitor("允许取面")] + public bool AllowTakeNoodle { get; set; } + + /// + /// 转台互锁信号 + /// + [VariableMonitor("转台互锁信号")] + public bool TurntableInterlock { get; set; } + + /// + /// 荤素出餐互锁 + /// + [VariableMonitor("荤素出餐互锁")] + public bool ERLoc { get; set; } = false; + + /// + /// 当前取餐位置 + /// + [VariableMonitor("当前取餐位置")] + public int CurrentTakeMeakLoc { get; set; } = -1; + #endregion + + + /// + /// 初始化完成 + /// PLC -> M100.0 + /// ModbusTcp -> 1120 + /// + [VariableMonitor("初始化完成", "M100.0", "1120")] + public bool InitComplete { get; set; } + + /// + /// 取碗机构空闲,True:忙碌,false:空闲 + /// PLC -> M100.1 + /// ModbusTcp -> 1121 + /// + [VariableMonitor("取碗机构空闲", "M100.1", "1121")] + public bool TakeBowlIdle { get; set; } + + /// + /// 温度到达,True:表示到达,false:未到达 + /// PLC -> M100.2 + /// ModbusTcp -> 1122 + /// + [VariableMonitor("温度到达", "M100.2", "1122")] + public bool TemperatureReached { get; set; } + + /// + /// 允许到面,配料完成 + /// PLC -> M100.3 + /// ModbusTcp -> 1123 + /// + [VariableMonitor("允许到面", "M100.3", "1123")] + public bool AllowFallNoodle { get; set; } + + /// + /// 机器人取面完成 + /// PLC -> M100.4 + /// ModbusTcp -> 1124 + /// + [VariableMonitor("机器人取面完成", "M100.4", "1124")] + public bool RbTakeNoodleComplete { get; set; } + + /// + /// 机器人倒面完成 + /// PLC -> M100.5 + /// ModbusTcp -> 1125 + /// + [VariableMonitor("机器人倒面完成", "M100.5", "1125")] + public bool RbFallNoodleComplete { get; set; } + + /// + /// 机器人出餐完成,上报取餐完成 + /// PLC -> M100.6 + /// ModbusTcp -> 1126 + /// + [VariableMonitor("机器人出餐完成", "M100.6", "1126")] + public bool RbOutMealComplete { get; set; } + + /// + /// 机器人空闲 + /// PLC -> M100.7 + /// ModbusTcp -> 1127 + /// + [VariableMonitor("机器人空闲", "M100.7", "1127")] + public bool RobotIdle { get; set; } + + /// + /// 取餐口检测 + /// PLC -> M101.0 + /// ModbusTcp -> 1128 + /// + [VariableMonitor("取餐口检测", "M101.0", "1128")] + public bool TakeMealDetect { get; set; } + + /// + /// 缺碗信号,false:缺碗,true:有碗 + /// PLC -> M101.1 + /// ModbusTcp -> 1129 + /// + [VariableMonitor("缺碗信号", "M101.1", "1129")] + public bool MissingBowl { get; set; } + + /// + /// 设备初始化中,执行中等于1,2秒后复位 + /// PLC -> M101.2 + /// ModbusTcp -> 1130 + /// + [VariableMonitor("设备初始化中", "M101.2", "1130")] + public bool DeviceIniting { get; set; } + + /// + /// 转台下限检测 + /// PLC -> M101.3 + /// ModbusTcp -> 1131 + /// + [VariableMonitor("转台下限检测", "M101.3", "1131")] + public bool TurntableLowerLimit { get; set; } + + /// + /// 缺碗信号 2 + /// PLC -> M101.4 + /// ModbusTcp -> 1132 + /// + [VariableMonitor("缺碗信号 2", "M101.4", "1132")] + public bool MissingBowlSignal2 { get; set; } + + /// + /// 转台上限检测 + /// PLC -> M101.5 + /// ModbusTcp -> 1133 + /// + [VariableMonitor("转台上限检测", "M101.5", "1133")] + public bool TurntableUpLimit { get; set; } + + /// + /// 补料完成 + /// PLC -> M101.6 + /// ModbusTcp -> 1134 + /// + [VariableMonitor("补料完成", "M101.6", "1134")] + public bool FeedComplete { get; set; } + + /// + /// 转台移动到位 + /// PLC -> M101.7 + /// ModbusTcp -> 1135 + /// + [VariableMonitor("转台移动到位", "M101.7", "1135")] + public bool TurntableMoveInPlace { get; set; } + + /// + /// 煮面炉状态,True:忙碌,false:空闲 + /// M102.0 - M102.5 + /// 1136 - 1141 + /// + [VariableMonitor("煮面炉状态", "M102.0", "1136")] + public bool[] NoodleCookerStatus { get; set; } = new bool[6] { false, false, false, false, false, false }; + + /// + /// 补料中 + /// M102.6 + /// 1142 + /// + [VariableMonitor("补料中", "M102.6", "1142")] + public bool Feeding { get; set; } + + /// + /// 煮面完成,上升后给信号 + /// M103.0 - M103.5 + /// 1144 - 1149 + /// + [VariableMonitor("煮面完成", "M103.0", "1144")] + public bool[] CookNoodlesComplete { get; set; } = new bool[6] { false, false, false, false, false, false }; + + /// + /// 硬件设备异常 + /// PLC -> M235.0 + /// True:设备正常,False:设备异常 + /// + [VariableMonitor("硬件设备异常", "M235.0", "")] + public bool Error { get; set; } = false; + + /// + /// 配方编号 + /// PLC -> VW0 + /// ModbusTcp -> 100 + /// + [VariableMonitor("配方编号", "VW0", "100")] + public ushort RecipeNumber { get; set; } + + /// + /// 转台设置位置 + /// PLC -> VW2 + /// ModbusTcp -> 101 + /// + [VariableMonitor("转台设置位置", "VW2", "101")] + public ushort TurntableLoc { get; set; } + + /// + /// 到面至煮面炉位置 + /// PLC -> VW4 + /// ModbusTcp -> 102 + /// + [VariableMonitor("到面至煮面炉位置", "VW4", "102")] + public ushort FallNoodleLoc { get; set; } + + /// + /// 取面位置 + /// PLC -> VW6 + /// ModbusTcp -> 103 + /// + [VariableMonitor("取面位置", "VW6", "103")] + public ushort TakeNoodleLoc { get; set; } + + /// + /// 转台反馈位置 + /// PLC -> VW372 + /// ModbusTcp -> 286 + /// + [VariableMonitor("转台反馈位置", "VW372", "286")] + public ushort TurntableFeedbackloc { get; set; } + + /// + /// 机器人取面位置队列 + /// + public ConcurrentQueue RBTakeNoodleTask { get; set; } = new ConcurrentQueue(); + + /// + /// 出碗队列 + /// + public ConcurrentQueue TakeBowlTask { get; set; } = new ConcurrentQueue(); + + /// + /// 是否有面条 + /// + public bool IsNoodles { get; set; } = true; + + public Dictionary ListOrder { get; set; } = new Dictionary(); //存放当前订单已做好素菜 + + public Dictionary ListOrderMeat { get; set; } = new Dictionary(); //存放当前订单已做好荤菜 + + public int DishNumber { set; get; } = 0; //当前订单中配菜的数量 + + #region 订单ID记录 + /// + /// 取碗订单ID + /// + public string TakeBowlId = string.Empty; + + /// + /// 配料完成订单ID + /// + public string IngredientsCompleteId = string.Empty; + + /// + /// 煮面口对应的订单ID + /// + //public string[] CookNodelId = new string[6] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, }; + public List CookNodelId { get; set; } = new List(); + + + //public string[] CookNodelId = new string[6] { string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, }; + + public OrderLocInfo[] orderLocInfos = new OrderLocInfo[6] { null, null, null, null, null, null }; + /// + /// 出餐订单ID + /// + public string OutMealId = string.Empty; + + + /// + /// 冒菜制作方式,true:加汤,false:不加汤 + /// + public bool OutMealType { get; set; } = false; + + /// + /// 转台位置轮询 + /// + public List TurntableLocLists = new List(); + + /// + /// 转台当前启动位置 + /// + [VariableMonitor("转台当前启动位置")] + public ushort CurrentLoc { get; set; } = 0; + + public List doOrderEvents { get; set; } = new List(); + + + + public int Num { get; set; } //记录同一个订单是否所有配菜均已出锅 + + public int Count { get; set; } = 0; //用于素菜的计数 + + public int CountMeat { get; set; } = 0;//用于荤菜计数 + + public int Vnum { get; set; } = 0; //单次订单素菜的总数 + public int VegtabNum { get; set; } = 0;//记录一个订单中素菜的数量 + + public int TotalNum { get; set; } = 0; //单次订单的配菜总数 + + public ConcurrentQueue> Conqueue = new ConcurrentQueue>(); //记录订单的ID 以及素菜数量 + public bool relock { get; set; } = false; //单次订单互锁 + + public bool HasVeg { get; set; } //是否有素菜判断 + + + public bool VegNoodlesLock { get; set; } = false; //取面和取餐互锁 + + public int VegN { get; set; } = 0; //素菜出餐计数 + #endregion + } + + public class CookNodleLocAndId + { + public string CookNodelId { get; set; } + + public int Loc { get; set; } + } +} diff --git a/BPASmartClient.MorkM/HardwareStatus.cs b/BPASmartClient.MorkM/HardwareStatus.cs new file mode 100644 index 00000000..ac34e10a --- /dev/null +++ b/BPASmartClient.MorkM/HardwareStatus.cs @@ -0,0 +1,18 @@ +using BPASmartClient.Device; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.MorkM +{ + public class HardwareStatus : IHardwareStatus + { + [HardwareStatus("输入状态", "I0.0")] + public bool Input1 { get; set; } + + [HardwareStatus("输出状态", "Q0.0")] + public bool OutPut1 { get; set; } + } +} diff --git a/BPASmartClient.MorkM/Model/MorksPar.cs b/BPASmartClient.MorkM/Model/MorksPar.cs new file mode 100644 index 00000000..6f97207c --- /dev/null +++ b/BPASmartClient.MorkM/Model/MorksPar.cs @@ -0,0 +1,16 @@ +using BPASmartClient.Model; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Toolkit.Mvvm.ComponentModel; + +namespace BPASmartClient.MorkM.Model +{ + internal class MorksPar + { + public ObservableCollection parSets { get; set; } = new ObservableCollection(); + } +} diff --git a/BPASmartClient.MorkM/Model/ParSet.cs b/BPASmartClient.MorkM/Model/ParSet.cs new file mode 100644 index 00000000..39eb45a6 --- /dev/null +++ b/BPASmartClient.MorkM/Model/ParSet.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.MorkM.Model +{ + public class ParSet + { + public ushort Minute { get { return _mMinute; } set { _mMinute = value; } } + private ushort _mMinute; + + public ushort Second { get { return _mSecond; } set { _mSecond = value; } } + private ushort _mSecond; + + + public bool IsShield { get { return _mIsShield; } set { _mIsShield = value; } } + private bool _mIsShield; + + + public string TextBlockContext { get { return _mTextBlockContext; } set { _mTextBlockContext = value; } } + private string _mTextBlockContext; + + public string CheckBoxContext { get { return _mCheckBoxContext; } set { _mCheckBoxContext = value; } } + private string _mCheckBoxContext; + + } +} diff --git a/BPASmartClient.MorkM/Model/WritePar.cs b/BPASmartClient.MorkM/Model/WritePar.cs new file mode 100644 index 00000000..b3c769fd --- /dev/null +++ b/BPASmartClient.MorkM/Model/WritePar.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.MorkM.Model +{ + public class WritePar + { + public string Address { get; set; } + public object Value { get; set; } + } +} diff --git a/BPASmartClient.MorkM/OrderLocInfo.cs b/BPASmartClient.MorkM/OrderLocInfo.cs new file mode 100644 index 00000000..40eda077 --- /dev/null +++ b/BPASmartClient.MorkM/OrderLocInfo.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.MorkM +{ + public class OrderLocInfo + { + public string SuborderId { get; set; } + public ushort Loc { get; set; } + public ushort RecipeNumber { get; set; } + public int BatchingId { get; set; } + public string GoodName { get; set; } + } + + /// + /// 存储订单中素菜荤菜数量 + /// + public class OrderInformation + { + public int VegatableNumber { get; set; } + + public int DishNum { get; set; } + + // public GoodsMakeType MakeType { get; set; } + } +} diff --git a/BPASmartClient.MorkM/View/Debug.xaml b/BPASmartClient.MorkM/View/Debug.xaml new file mode 100644 index 00000000..456ec5dc --- /dev/null +++ b/BPASmartClient.MorkM/View/Debug.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + +