diff --git a/BPASmartClient.JXJFoodBigStation/App.xaml.cs b/BPASmartClient.JXJFoodBigStation/App.xaml.cs index 02b20491..0ccdee1c 100644 --- a/BPASmartClient.JXJFoodBigStation/App.xaml.cs +++ b/BPASmartClient.JXJFoodBigStation/App.xaml.cs @@ -13,7 +13,6 @@ using BPASmartClient.CustomResource.Pages.View; using BPASmartClient.CustomResource.Pages.ViewModel; using BPASmartClient.Helper; using BPASmartClient.JXJFoodBigStation.Model; -using BPASmartClient.Nfc; namespace BPASmartClient.JXJFoodBigStation { @@ -52,7 +51,6 @@ namespace BPASmartClient.JXJFoodBigStation private void MenuInit() { - NfcServer.GetInstance.Init(); #region 配方管理菜单 ObservableCollection RecipeManage = new ObservableCollection(); @@ -117,19 +115,11 @@ namespace BPASmartClient.JXJFoodBigStation #region 硬件设备监控 ObservableCollection DeviceMonitor = new ObservableCollection(); - DeviceMonitor.Add(new SubMenumodel() - { - SubMenuName = "原料设备列表", - SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.技术员 }, - AssemblyName = "BPASmartClient.DosingSystem", - ToggleWindowPath = "View.DeviceListView" - }); - DeviceMonitor.Add(new SubMenumodel() { SubMenuName = "设备状态", SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.技术员 }, - AssemblyName = "BPASmartClient.DosingSystem", + AssemblyName = "BPASmartClient.JXJFoodBigStation", ToggleWindowPath = "View.HardwareStatusView" }); diff --git a/BPASmartClient.JXJFoodBigStation/BPASmartClient.JXJFoodBigStation.csproj b/BPASmartClient.JXJFoodBigStation/BPASmartClient.JXJFoodBigStation.csproj index 18cc382e..965d4327 100644 --- a/BPASmartClient.JXJFoodBigStation/BPASmartClient.JXJFoodBigStation.csproj +++ b/BPASmartClient.JXJFoodBigStation/BPASmartClient.JXJFoodBigStation.csproj @@ -10,6 +10,7 @@ + @@ -19,11 +20,9 @@ $(DefaultXamlRuntime) - Designer $(DefaultXamlRuntime) - Designer diff --git a/BPASmartClient.JXJFoodBigStation/Model/GVL_BigStation.cs b/BPASmartClient.JXJFoodBigStation/Model/GVL_BigStation.cs new file mode 100644 index 00000000..c256f74e --- /dev/null +++ b/BPASmartClient.JXJFoodBigStation/Model/GVL_BigStation.cs @@ -0,0 +1,43 @@ +using BPASmartClient.JXJFoodBigStation.Model.Siemens; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.JXJFoodBigStation.Model +{ + public class GVL_BigStation + { + /// + /// 配方数据 + /// + public ObservableCollection RemoteRecipes = new ObservableCollection(); + /// + /// 配方队列 + /// + public ConcurrentQueue RecipeQueue = new ConcurrentQueue(); + /// + /// 往输送带下发配方完成 + /// + public bool IssueRecipeFinish { get; set; } = false; + /// + /// 当前料仓的位置 + /// + public int StockInIsWork { get; set; } = 0; + /// + /// 单个配方执行完成标志 + /// + public bool RecipeFinish { get; set; } = false; + /// + /// 记录AGV进站送货的指令顺序 + /// + public int AgvDeliveryPosition { get; set; }= 0; + /// + /// 记录AGV进站取货的指令顺序 + /// + public int AgvPickUpPosition { get; set; } = 0; + } +} diff --git a/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKDeviceStatus.cs b/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKDeviceStatus.cs index 7b5fbaa2..5eb14640 100644 --- a/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKDeviceStatus.cs +++ b/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKDeviceStatus.cs @@ -5,15 +5,14 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using BPASmartClient.S7Net; namespace BPASmartClient.JXJFoodBigStation.Model.HK_PLC { public class HKDeviceStatus { - public ModbusTcp ModBusHK = new ModbusTcp(); - public string IpAddress => ModBusHK.IPAdress; - public bool IsConnected => ModBusHK.Connected; - + public SiemensHelper HK_PLC_S7 = new SiemensHelper(); + public bool IsConnected => HK_PLC_S7.IsConnected; public void Init() { if (IsConnected) @@ -32,8 +31,8 @@ namespace BPASmartClient.JXJFoodBigStation.Model.HK_PLC { if (IsConnected) { - ModBusHK.SetUint(HKPlcCommAddress.SingleStockBinLocationToPLC, value); - ModBusHK.Write(HKPlcCommAddress.SingleDosingFinishToPLC, (ushort)1); + HK_PLC_S7.Write(HKPlcCommAddress.SingleStockBinLocationToPLC, value); + HK_PLC_S7.Write(HKPlcCommAddress.SingleDosingFinishToPLC, (ushort)1); } } /// @@ -41,21 +40,21 @@ namespace BPASmartClient.JXJFoodBigStation.Model.HK_PLC /// public void AllowDosingSignReset() { - ModBusHK.Write(HKPlcCommAddress.IsAllowDosing,(ushort)0); + HK_PLC_S7.Write(HKPlcCommAddress.IsAllowDosing,(ushort)0); } /// /// 复位plc到达某料仓信号 /// public void StockStateSignReset() { - ModBusHK.Write(HKPlcCommAddress.StockState, (ushort)0); + HK_PLC_S7.Write(HKPlcCommAddress.StockState, (ushort)0); } /// /// 复位一个配方配料完成信号 /// public void RecipeDosingFinishReset() { - ModBusHK.Write(HKPlcCommAddress.RecipeDosingFinish, (ushort)0); + HK_PLC_S7.Write(HKPlcCommAddress.RecipeDosingFinish, (ushort)0); } /// /// 下发配方数据 @@ -66,8 +65,8 @@ namespace BPASmartClient.JXJFoodBigStation.Model.HK_PLC { if (IsConnected) { - ModBusHK.SetUint(HKPlcCommAddress.BarrelNumToPLC, BarrelNum); - ModBusHK.Write(HKPlcCommAddress.StockBinLocationToPLC, StockBinLocation); + HK_PLC_S7.Write(HKPlcCommAddress.BarrelNumToPLC, BarrelNum); + HK_PLC_S7.Write(HKPlcCommAddress.StockBinLocationToPLC, StockBinLocation); } } } diff --git a/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKPlcCommAddress.cs b/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKPlcCommAddress.cs index 4cb3917d..e7cadc07 100644 --- a/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKPlcCommAddress.cs +++ b/BPASmartClient.JXJFoodBigStation/Model/HK_PLC/HKPlcCommAddress.cs @@ -9,6 +9,7 @@ namespace BPASmartClient.JXJFoodBigStation.Model.HK_PLC public class HKPlcCommAddress { #region 海科PLC ==> 上位机 + public static string HeartHealth { get; set; } = "M5000.0"; /// /// 是否允许配料 /// @@ -40,8 +41,57 @@ namespace BPASmartClient.JXJFoodBigStation.Model.HK_PLC /// 当前配料料仓的位置 /// public static string SingleStockBinLocationToPLC { get; set; } = ""; - + /// + /// 配方配料完成 + /// public static string RecipeDosingFinish { get; set; } = ""; #endregion + + #region AGV进出站 + /// + /// Agv送货 进站申请 + /// + public static string DeliveryAGVApply { get; set; } = "M4002"; + /// + /// Agv送货 进站申请 + /// + public static string DeliveryAGVIsApply { get; set; } = "M5002"; + /// + /// Agv送货 进站顶升申请 + /// + public static string DeliveryAGVApplyJack { get; set; } = "M4004"; + /// + /// Agv送货 进站顶升申请 + /// + public static string DeliveryAGVIsApplyJack { get; set; } = "M5004"; + /// + /// Agv送货 送货完成 + /// + public static string DeliveryAGVFinsih { get; set; } = "M4005"; + /// + /// Agv送货 工位上有货架 + /// + public static string StationHaveCargo { get; set; } = "M5005"; + /// + /// Agv送货 进站申请 + /// + public static string PickAGVApply { get; set; } = "M4003"; + /// + /// Agv送货 进站申请 + /// + public static string PickAGVIsApply { get; set; } = "M5003"; + /// + /// Agv送货 取货架完成 + /// + public static string PickCargoAGVFinish { get; set; } = "M4006"; + /// + /// Agv送货 取料完成 + /// + public static string PickAGVFinish { get; set; } = "M5006"; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar { get; set; } = "M4007"; + #endregion } } diff --git a/BPASmartClient.JXJFoodBigStation/Model/ProcessControl.cs b/BPASmartClient.JXJFoodBigStation/Model/ProcessControl.cs index e3008fd8..462e53f7 100644 --- a/BPASmartClient.JXJFoodBigStation/Model/ProcessControl.cs +++ b/BPASmartClient.JXJFoodBigStation/Model/ProcessControl.cs @@ -1,4 +1,5 @@ -using BPASmartClient.Helper; +using BPASmartClient.CustomResource.Pages.Model; +using BPASmartClient.Helper; using BPASmartClient.JXJFoodBigStation.Model.HK_PLC; using BPASmartClient.JXJFoodBigStation.Model.Siemens; using BPASmartClient.Modbus; @@ -9,78 +10,71 @@ using System.Collections.ObjectModel; using System.Configuration; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace BPASmartClient.JXJFoodBigStation.Model { public class ProcessControl - { + { private volatile static ProcessControl _Instance; public static ProcessControl GetInstance => _Instance ?? (_Instance = new ProcessControl()); private ProcessControl() { } - public ObservableCollection RemoteRecipes; - ConcurrentQueue RecipeQueue = new ConcurrentQueue(); - ConcurrentQueue DeviceQueue = new ConcurrentQueue(); public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); public SiemensDeviceStatus SiemensDevice = new SiemensDeviceStatus(); public HKDeviceStatus HKDevice = new HKDeviceStatus(); + GVL_BigStation BigStation = new GVL_BigStation(); + /// + /// 接收原料数据 + /// + public RecipeRawMaterial RawMaterial; public void Init() { - string HK_PLC_IP = ConfigurationManager.AppSettings["HKPlc_IP"]; - string HK_PLC_Port = ConfigurationManager.AppSettings["HKPlc_Port"]; - string Siemens_PLC_IP = ConfigurationManager.AppSettings["Siemens_IP"]; - string Siemens_PLC_Port = ConfigurationManager.AppSettings["Siemens_Port"]; - Task.Run(new Action(() => - { - HKDevice.ModBusHK.ModbusTcpConnect(HK_PLC_IP, int.Parse(HK_PLC_Port)); - SiemensDevice.SiemensTcp.ModbusTcpConnect(Siemens_PLC_IP, int.Parse(Siemens_PLC_Port)); - if (HKDevice.IsConnected) - { - HKDevice.Init(); - } - if (SiemensDevice.IsConnected) - { - SiemensDevice.Init(); - } - })); - ActionManage.GetInstance.Register(new Action(()=> - { - - }), "给流水线下发配方数据", true); ActionManage.GetInstance.Register(new Action(() => { - if (SiemensDevice.IsConnected) + if (SiemensDevice.IsConnected) { - var res = SiemensDevice.SiemensTcp.GetString(SiemensCommAddress.RecipeName, (ushort)20); - var res1 = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.RecipeID); - var res2 = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.RawMaterial); + var res = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeName); + var res1 = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeID); + int res2 = SiemensDevice.Siemens_PLC_S7.ReadClass(RawMaterial, 0, 0); if ((res != null && res is string recipeName) && (res1 != null && res1 is uint recipeID) && - (res2 != null && res2 is ushort[] rawMaterial)) + (res2 > 0)) { - RawMaterials.Clear(); - RawMaterials.Add(new RemoteRecipeRawMaterial() + int index = Array.FindIndex(Json.Data.Recipes.ToArray(), p => p.RecipeCode == recipeID); + if (!(index >= 0)) { - RawMaterialBarrelNum = rawMaterial[0], - RawMaterialLocation= rawMaterial[1], - RawMaterialWeight= rawMaterial[2] - }); - Json.Data.Recipes.Add(new RemoteRecipeData() + RawMaterials.Clear(); + for (int i = 0; i < 15; i++) + { + RawMaterials.Add(new RemoteRecipeRawMaterial() + { + RawMaterialBarrelNum = RawMaterial.RawMaterialBarrelNum[i], + RawMaterialLocation = RawMaterial.RawMaterialLocation[i], + RawMaterialWeight = RawMaterial.RawMaterialWeight[i] + }); + } + Json.Data.Recipes.Add(new RemoteRecipeData() + { + RecipeName = recipeName, + RecipeCode = recipeID, + RawMaterial = RawMaterials + }); + } + else { - RecipeName = recipeName, - RecipeCode = recipeID, - RawMaterial = RawMaterials - }); + MessageLog.GetInstance.AlarmLog("配方列表中存在该配方ID"); + } } } }), "西门子下发配方", true); ActionManage.GetInstance.Register(new Action(() => { - if (SiemensDevice.IsConnected) + if (SiemensDevice.IsConnected) { - var res = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.TrayLocationNum); - var res1 = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.RecipeID); + var res = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.TrayLocationNum); + var res1 = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeID); if (res != null && res is int TrayLocation && res1 != null && res1 is int recipeId) { int index = Array.FindIndex(Json.Data.Recipes.ToArray(), p => p.RecipeCode == recipeId); @@ -91,64 +85,175 @@ namespace BPASmartClient.JXJFoodBigStation.Model } } }), "AGV到位信号", true);//根据下发的配方ID将 托盘的位置信息添加到配方中 - - RecipeQueue.Clear(); - ReceviceData(); + string HK_PLC_IP = ConfigurationManager.AppSettings["HKPlc_IP"]; + string Siemens_PLC_IP = ConfigurationManager.AppSettings["Siemens_IP"]; + try + { + //HKDevice.HK_PLC_S7.Connect(S7.Net.CpuType.S7200Smart, HK_PLC_IP); + //SiemensDevice.Siemens_PLC_S7.Connect(S7.Net.CpuType.S71500, Siemens_PLC_IP); + if (HKDevice.IsConnected) + { + HKDevice.Init(); + } + if (SiemensDevice.IsConnected) + { + SiemensDevice.Init(); + } + } + catch(Exception ex) + { + + } + BigStation.RecipeQueue.Clear(); + Json.Data.Recipes = TestData.GetInstance.Recipes;//添加测试数据 ThreadManage.GetInstance().StartLong(new Action(() => { + ReceviceData(); RecipeInfoToHKPLC(); + Thread.Sleep(10); }), "流程处理", true); + ThreadManage.GetInstance().StartLong(new Action(() => { + if (HKDevice.IsConnected && SiemensDevice.IsConnected) + { + AgvGetInDelivery(); + AgvGetInPickUp(); + } + Thread.Sleep(10); + }), "AGV进站送取货", true); + } + /// + /// AGV进站送货 + /// + private void AgvGetInDelivery() + { + + switch (BigStation.AgvDeliveryPosition) + { + case 0: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.DeliveryAGVApply) is bool)) + { + BigStation.AgvDeliveryPosition = 1; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.DeliveryAGVApply, true); + } + break; + case 1: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.DeliveryAGVIsApply) is bool)) + { + BigStation.AgvDeliveryPosition = 2; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.DeliveryAGVIsApply, true); + } + break; + case 2: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.DeliveryAGVApplyJack) is bool)) + { + BigStation.AgvDeliveryPosition = 3; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.DeliveryAGVApplyJack, true); + } + break; + case 3: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.DeliveryAGVIsApplyJack) is bool)) + { + BigStation.AgvDeliveryPosition = 4; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.DeliveryAGVIsApplyJack, true); + } + break; + case 4: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.DeliveryAGVFinsih) is bool)) + { + BigStation.AgvDeliveryPosition = 5; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.DeliveryAGVFinsih, true); + } + break; + case 5: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.StationHaveCargo) is bool)) + { + BigStation.AgvDeliveryPosition = 0; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.StationHaveCargo, true); + } + break; + default: + break; + } + //获取工位上是否有小车 + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.StationIsExistCar, (bool) + HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.StationIsExistCar)); + } + /// + /// AGV进站取货 + /// + private void AgvGetInPickUp() + { + switch (BigStation.AgvPickUpPosition) + { + case 0: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.PickAGVApply) is bool)) + { + BigStation.AgvPickUpPosition = 1; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.PickAGVApply, true); + } + break; + case 1: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.PickAGVIsApply) is bool)) + { + BigStation.AgvPickUpPosition = 2; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.PickAGVIsApply, true); + } + break; + case 2: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.PickCargoAGVFinish) is bool)) + { + BigStation.AgvPickUpPosition = 3; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.PickCargoAGVFinish, true); + } + break; + case 3: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.PickAGVFinish) is bool)) + { + BigStation.AgvPickUpPosition = 0; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.PickAGVFinish, true); + } + break; + default: + break; + } } - private void ReceviceData() { - RemoteRecipes = Json.Data.Recipes; - RawMaterials = TestData.GetInstance.RawMaterials;//添加测试数据 + BigStation.RemoteRecipes = Json.Data.Recipes; if (Json.Data.Recipes.Count > 0) { foreach (var data in Json.Data.Recipes) { - if(!(RecipeQueue.Contains(data.RecipeCode))) - RecipeQueue.Enqueue(data.RecipeCode); + if(!(BigStation.RecipeQueue.Contains(data.RecipeCode))) + BigStation.RecipeQueue.Enqueue(data.RecipeCode); } } } - /// - /// 当前料仓的位置 - /// - private int StockInIsWork; - /// - /// 单个配方执行完成标志 - /// - private bool RecipeFinfish; - private void RecipeInfoToHKPLC() + private void RecipeInfoToHKPLC() { - if (RecipeQueue.Count > 0) + if (BigStation.RecipeQueue.Count > 0) { - int index = Array.FindIndex(RemoteRecipes.ToArray(), p => p.RecipeCode == RecipeQueue.ElementAt(0)); - if (index >= 0 && index <= RemoteRecipes.Count) + int index = Array.FindIndex(BigStation.RemoteRecipes.ToArray(), p => p.RecipeCode == BigStation.RecipeQueue.ElementAt(0)); + if (index >= 0 && index <= BigStation.RemoteRecipes.Count) { - long code = RemoteRecipes.ElementAt(index).RecipeCode; - if (RTrig.GetInstance("IsAllowDosing").Start(HKDevice.ModBusHK.Read(HKPlcCommAddress.IsAllowDosing) is bool a)) + long code = BigStation.RemoteRecipes.ElementAt(index).RecipeCode; + if (RTrig.GetInstance("IsAllowDosing").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.IsAllowDosing) is bool a)) { - foreach (var item in RemoteRecipes.ElementAt(index).RawMaterial) + foreach (var item in BigStation.RemoteRecipes.ElementAt(index).RawMaterial) { HKDevice.StockBinPar((uint)item.RawMaterialBarrelNum, (ushort)item.RawMaterialLocation); } HKDevice.AllowDosingSignReset(); - + BigStation.IssueRecipeFinish = true; } - - if (RTrig.GetInstance("StockState").Start(HKDevice.ModBusHK.Read(HKPlcCommAddress.RecipeDosingFinish) is bool)) + if (RTrig.GetInstance("StockState").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.RecipeDosingFinish) is bool)) { HKDevice.RecipeDosingFinishReset(); - RecipeQueue.TryDequeue(out code); + BigStation.RecipeQueue.TryDequeue(out code); + Json.Data.Recipes.RemoveAt(index);//制作完成,移除当前配方 } } } } - private void HKPLCIsWork() - { - } } } diff --git a/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/DeviceAddress.cs b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/DeviceAddress.cs new file mode 100644 index 00000000..12eff44a --- /dev/null +++ b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/DeviceAddress.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.JXJFoodBigStation.Model +{ + public class DeviceAddress + { + #region 源地址 + ///// + ///// 设备名称起始地址 + ///// + //public static string DeviceName { get; set; } = "LW0"; + + ///// + ///// 料仓重量反馈起始地址 + ///// + //public static string WeightFeedback { get; set; } = "LW52";//LW204 + + ///// + ///// 重量设置地址 + ///// + //public static string WeightSet { get; set; } = "LW21";//LW200 + + ///// + ///// 启动信号地址 + ///// + //public static string Start { get; set; } = "LW20";//LW210 + + ///// + ///// 下料重量反馈地址 + ///// + //public static string CutWeightFeedback { get; set; } = "LW54";//LW202 + + ///// + ///// 设备运行状态地址 + ///// + //public static string RunStatus { get; set; } = "LW55";//LW206 + + ///// + ///// 料仓的位置 + ///// + //public static string Location { get; set; } = "LW53"; + #endregion + #region 上位机下发 + /// + /// 原料出料重量 + /// + public static string WeightSet { get; set; } = "LW11"; + /// + /// 启动开始配料 + /// + public static string Start { get; set; } = "LW12"; + #endregion + #region 上位机读取 + /// + /// 设备运行状态地址 + /// + public static string RunStatus { get; set; } = "LW50"; + /// + /// 报警字 + /// + public static string AlarmInfo { get; set; } = "LW51"; + /// + /// 原料名称 + /// + public static string DeviceName { get; set; } = "LW52"; + /// + /// 料仓的位置 + /// + public static string Location { get; set; } = "LW53"; + /// + /// 原料类型 + /// + public static string RawMaterialType { get; set; } = "LW54"; + /// + /// 出料完成信号 + /// + public static string OutRawMaterialFinish { get; set; } = "LW55"; + /// + /// 料仓重量反馈起始地址 + /// + public static string WeightFeedback { get; set; } = "LW56"; + /// + /// 下料重量反馈地址 + /// + public static string CutWeightFeedback { get; set; } = "LW57"; + #endregion + } +} diff --git a/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/LocaPar.cs b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/LocaPar.cs new file mode 100644 index 00000000..9736b46d --- /dev/null +++ b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/LocaPar.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections.ObjectModel; +using BPASmartClient.JXJFoodBigStation.ViewModel; + +namespace BPASmartClient.JXJFoodBigStation.Model +{ + public class LocaPar + { + public ObservableCollection Recipes { get; set; } = new ObservableCollection(); + } +} diff --git a/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RawMaterialDeviceStatus.cs b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RawMaterialDeviceStatus.cs new file mode 100644 index 00000000..5aa423ab --- /dev/null +++ b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RawMaterialDeviceStatus.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.JXJFoodBigStation.Model +{ + public class RawMaterialDeviceStatus + { + /// + /// 原料类型 + /// 1:液体 + /// 2:膏体 + /// 3:粉体 + /// + public ushort RawMaterialType { get; set; } + + /// + /// 料仓重量反馈 + /// + public float WeightFeedback { get; set; } + + /// + /// 上限反馈 + /// + public bool UpLimitFeedback { get; set; } + + /// + /// 下限反馈 + /// + public bool DownLimitFeedback { get; set; } + + /// + /// 下料重量反馈 + /// + public float CutWeightFeedback { get; set; } + + /// + /// 设备运行状态 + /// + public ushort RunStatus { get; set; } + } +} diff --git a/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RawMaterialModel.cs b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RawMaterialModel.cs new file mode 100644 index 00000000..be213b12 --- /dev/null +++ b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RawMaterialModel.cs @@ -0,0 +1,93 @@ +using Microsoft.Toolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.JXJFoodBigStation.Model +{ + /// + /// 原料模块 + /// + public class RawMaterialModel : ObservableObject + { + /// + /// 原料名称 + /// + public string RawMaterialName { get { return _mRawMaterialName; } set { _mRawMaterialName = value; OnPropertyChanged(); } } + private string _mRawMaterialName; + + /// + /// 原料编号 + /// + public int RawMateriaLocation { get { return _mRawMaterialLocation; } set { _mRawMaterialLocation = value; OnPropertyChanged(); } } + private int _mRawMaterialLocation; + + /// + /// 原料设备IP + /// + public string DeviceIp { get; set; } + + /// + /// 原料重量设置 + /// + public uint RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; OnPropertyChanged(); } } + private uint _mRawMaterialWeight; + + /// + /// 原料类型 MW18 + /// 1:液体 + /// 2:膏体 + /// 3:粉体 + /// + [Newtonsoft.Json.JsonIgnore] + public ushort RawMaterialType { get { return _mRawMaterialType; } set { _mRawMaterialType = value; OnPropertyChanged(); } } + private ushort _mRawMaterialType; + + /// + /// 料仓重量反馈 MD40 + /// + [Newtonsoft.Json.JsonIgnore] + public float WeightFeedback { get { return _mWeightFeedback; } set { _mWeightFeedback = value; OnPropertyChanged(); } } + private float _mWeightFeedback; + + /// + /// 上限反馈 + /// + [Newtonsoft.Json.JsonIgnore] + public bool UpLimtFeedback { get { return _mUpLimtFeedback; } set { _mUpLimtFeedback = value; OnPropertyChanged(); } } + private bool _mUpLimtFeedback; + + /// + /// 下限反馈 + /// + [Newtonsoft.Json.JsonIgnore] + public bool DownLimtFeedback { get { return _mDownLimtFeedback; } set { _mDownLimtFeedback = value; OnPropertyChanged(); } } + private bool _mDownLimtFeedback; + + /// + /// 下料重量反馈 MD52 + /// + [Newtonsoft.Json.JsonIgnore] + public float UpLimtWeightFeedback { get { return _mUpLimtWeightFeedback; } set { _mUpLimtWeightFeedback = value; OnPropertyChanged(); } } + private float _mUpLimtWeightFeedback; + + + /// + /// 原料ID + /// + public string RawMaterialId { get { return _mRawMaterialId; } set { _mRawMaterialId = value; OnPropertyChanged(); } } + private string _mRawMaterialId; + + /// + /// 原料设备执行状态 + /// 1:空闲状态 + /// 2:下料中 + /// 3:下料完成 + /// + [Newtonsoft.Json.JsonIgnore] + public ushort RecipeStatus { get { return _mRecipeStatus; } set { _mRecipeStatus = value; OnPropertyChanged(); } } + private ushort _mRecipeStatus = 1; + } +} diff --git a/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RecipeModel.cs b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RecipeModel.cs new file mode 100644 index 00000000..a0ff670c --- /dev/null +++ b/BPASmartClient.JXJFoodBigStation/Model/RawMaterial/RecipeModel.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using BPASmartClient.JXJFoodBigStation.ViewModel; +using Microsoft.Toolkit.Mvvm.ComponentModel; + +namespace BPASmartClient.JXJFoodBigStation.Model +{ + /// + /// 配方模块 + /// + public class RecipeModel : ObservableObject + { + [Newtonsoft.Json.JsonIgnore] + public bool IsEnable { get { return _mIsEnable; } set { _mIsEnable = value; OnPropertyChanged(); } } + private bool _mIsEnable = true; + + /// + /// 序号 + /// + public int SerialNum { get { return _mSerialNum; } set { _mSerialNum = value; OnPropertyChanged(); } } + private int _mSerialNum; + + /// + /// 配方名称 + /// + public string RecipeName { get { return _mRecipeName; } set { _mRecipeName = value; OnPropertyChanged(); } } + private string _mRecipeName; + + /// + /// 配方编码 + /// + public string RecipCode { get { return _mRecipCode; } set { _mRecipCode = value; OnPropertyChanged(); } } + private string _mRecipCode; + + [Newtonsoft.Json.JsonIgnore] + public AutoResetEvent Are { get; set; } = new AutoResetEvent(false); + + /// + /// 原料集合 + /// + public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); + + } +} diff --git a/BPASmartClient.JXJFoodBigStation/Model/Siemens/RemoteRecipeRawMaterial.cs b/BPASmartClient.JXJFoodBigStation/Model/Siemens/RemoteRecipeRawMaterial.cs index 47112da9..9a69a2c9 100644 --- a/BPASmartClient.JXJFoodBigStation/Model/Siemens/RemoteRecipeRawMaterial.cs +++ b/BPASmartClient.JXJFoodBigStation/Model/Siemens/RemoteRecipeRawMaterial.cs @@ -6,28 +6,27 @@ using System.Threading.Tasks; namespace BPASmartClient.JXJFoodBigStation.Model { - public class RemoteRecipeRawMaterial + public class RemoteRecipeRawMaterial { private int _mIp; - public int DeviceIp { get { return _mIp; } set { _mIp = value; } } + public int DeviceIp { get { return _mIp; } set { _mIp = value; }} - private int _mRawMaterialBarrelNum; /// /// 原料对应的桶号 /// public int RawMaterialBarrelNum { get { return _mRawMaterialBarrelNum; } set { _mRawMaterialBarrelNum = value; } } + private int _mRawMaterialBarrelNum; - private double _mRawMaterialWeight; /// /// 需要原料重量 /// - public double RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value;} } - + public double RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; } } + private double _mRawMaterialWeight; - private int _mRawMaterialLocation; /// /// 原料对应料仓的位置 /// - public int RawMaterialLocation { get { return _mRawMaterialLocation; } set { _mRawMaterialLocation = value;} } + public int RawMaterialLocation { get { return _mRawMaterialLocation; } set { _mRawMaterialLocation = value; } } + private int _mRawMaterialLocation; } } diff --git a/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensCommAddress.cs b/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensCommAddress.cs index 8288bc9b..3265a831 100644 --- a/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensCommAddress.cs +++ b/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensCommAddress.cs @@ -26,19 +26,316 @@ namespace BPASmartClient.JXJFoodBigStation.Model.Siemens /// public static string RawMaterial { get; set; } = ""; #endregion - #region AGV到位(与西门子PLC交互)西门子PLC ==> 上位机 + /// + /// 托盘的位置编号 + /// public static string TrayLocationNum { get; set; } = ""; + /// + /// 配方ID + /// public static string TrayRecipeID { get; set; } = ""; - public static string TrayState { get; set; } = ""; + /// + /// 状态信号 + /// + public static string StateSign { get; set; } = ""; #endregion - #region Tray配料完成(与西门子PLC交互)上位机 ==> 西门子PLC - public static string TrayLocationNumToPLC { get; set; } = ""; - public static string TrayRecipeIDToPLC { get; set; } = ""; - public static string TrayStateToPLC { get; set; } = ""; + public static string TrayLocationNumToSiemens { get; set; } = ""; + public static string TrayRecipeIDToSiemens { get; set; } = ""; + public static string TrayStateToSiemens { get; set; } = ""; + #endregion + #region AGV小车进出工站1 + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string DeliveryAGVApply1 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string DeliveryAGVIsApply1 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 从西门子读取 + /// + public static string DeliveryAGVApplyJack1 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 写给西门子 + /// + public static string DeliveryAGVIsApplyJack1 { get; set; } = ""; + /// + /// Agv送货 送货完成 从西门子读取 + /// + public static string DeliveryAGVFinsih1{ get; set; } = ""; + /// + /// Agv送货 工位上有货架 写给西门子 + /// + public static string StationHaveCargo1 { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string PickAGVApply1 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string PickAGVIsApply1 { get; set; } = ""; + /// + /// Agv送货 取货架完成 从西门子读取 + /// + public static string PickCargoAGVFinish1 { get; set; } = ""; + /// + /// Agv送货 取料完成 写给西门子 + /// + public static string PickAGVFinish1 { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar1 { get; set; } = ""; + #endregion + #region AGV小车进出工站2 + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string DeliveryAGVApply2 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string DeliveryAGVIsApply2 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 从西门子读取 + /// + public static string DeliveryAGVApplyJack2 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 写给西门子 + /// + public static string DeliveryAGVIsApplyJack2 { get; set; } = ""; + /// + /// Agv送货 送货完成 从西门子读取 + /// + public static string DeliveryAGVFinsih2 { get; set; } = ""; + /// + /// Agv送货 工位上有货架 写给西门子 + /// + public static string StationHaveCargo2 { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string PickAGVApply2 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string PickAGVIsApply2 { get; set; } = ""; + /// + /// Agv送货 取货架完成 从西门子读取 + /// + public static string PickCargoAGVFinish2 { get; set; } = ""; + /// + /// Agv送货 取料完成 写给西门子 + /// + public static string PickAGVFinish2 { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar2 { get; set; } = ""; + #endregion + #region AGV小车进出工站3 + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string DeliveryAGVApply3 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string DeliveryAGVIsApply3 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 从西门子读取 + /// + public static string DeliveryAGVApplyJack3 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 写给西门子 + /// + public static string DeliveryAGVIsApplyJack3 { get; set; } = ""; + /// + /// Agv送货 送货完成 从西门子读取 + /// + public static string DeliveryAGVFinsih3 { get; set; } = ""; + /// + /// Agv送货 工位上有货架 写给西门子 + /// + public static string StationHaveCargo3 { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string PickAGVApply3 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string PickAGVIsApply3 { get; set; } = ""; + /// + /// Agv送货 取货架完成 从西门子读取 + /// + public static string PickCargoAGVFinish3 { get; set; } = ""; + /// + /// Agv送货 取料完成 写给西门子 + /// + public static string PickAGVFinish3 { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar3 { get; set; } = ""; + #endregion + #region AGV小车进出工站4 + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string DeliveryAGVApply4 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string DeliveryAGVIsApply4 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 从西门子读取 + /// + public static string DeliveryAGVApplyJack4 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 写给西门子 + /// + public static string DeliveryAGVIsApplyJack4 { get; set; } = ""; + /// + /// Agv送货 送货完成 从西门子读取 + /// + public static string DeliveryAGVFinsih4 { get; set; } = ""; + /// + /// Agv送货 工位上有货架 写给西门子 + /// + public static string StationHaveCargo4 { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string PickAGVApply4 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string PickAGVIsApply4 { get; set; } = ""; + /// + /// Agv送货 取货架完成 从西门子读取 + /// + public static string PickCargoAGVFinish4 { get; set; } = ""; + /// + /// Agv送货 取料完成 写给西门子 + /// + public static string PickAGVFinish4 { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar4 { get; set; } = ""; + #endregion + #region AGV小车进出工站5 + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string DeliveryAGVApply5 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string DeliveryAGVIsApply5 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 从西门子读取 + /// + public static string DeliveryAGVApplyJack5 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 写给西门子 + /// + public static string DeliveryAGVIsApplyJack5 { get; set; } = ""; + /// + /// Agv送货 送货完成 从西门子读取 + /// + public static string DeliveryAGVFinsih5 { get; set; } = ""; + /// + /// Agv送货 工位上有货架 写给西门子 + /// + public static string StationHaveCargo5 { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string PickAGVApply5 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string PickAGVIsApply5 { get; set; } = ""; + /// + /// Agv送货 取货架完成 从西门子读取 + /// + public static string PickCargoAGVFinish5 { get; set; } = ""; + /// + /// Agv送货 取料完成 写给西门子 + /// + public static string PickAGVFinish5 { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar5 { get; set; } = ""; + #endregion + #region AGV小车进出工站6 + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string DeliveryAGVApply6 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string DeliveryAGVIsApply6 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 从西门子读取 + /// + public static string DeliveryAGVApplyJack6 { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 写给西门子 + /// + public static string DeliveryAGVIsApplyJack6 { get; set; } = ""; + /// + /// Agv送货 送货完成 从西门子读取 + /// + public static string DeliveryAGVFinsih6 { get; set; } = ""; + /// + /// Agv送货 工位上有货架 写给西门子 + /// + public static string StationHaveCargo6 { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string PickAGVApply6 { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string PickAGVIsApply6 { get; set; } = ""; + /// + /// Agv送货 取货架完成 从西门子读取 + /// + public static string PickCargoAGVFinish6 { get; set; } = ""; + /// + /// Agv送货 取料完成 写给西门子 + /// + public static string PickAGVFinish6 { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar6 { get; set; } = ""; #endregion } - + public class RecipeRawMaterial + { + /// + /// 原料对应的桶号 + /// + public int[] RawMaterialBarrelNum = new int[15]; + /// + /// 需要原料重量 + /// + public double[] RawMaterialWeight = new double[15]; + /// + /// 原料对应料仓的位置 + /// + public int[] RawMaterialLocation = new int[15]; + } } diff --git a/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensDeviceStatus.cs b/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensDeviceStatus.cs index ac0106bf..b74e35af 100644 --- a/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensDeviceStatus.cs +++ b/BPASmartClient.JXJFoodBigStation/Model/Siemens/SiemensDeviceStatus.cs @@ -5,28 +5,28 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using BPASmartClient.S7Net; namespace BPASmartClient.JXJFoodBigStation.Model.Siemens { public class SiemensDeviceStatus { - public ModbusTcp SiemensTcp = new ModbusTcp(); - public bool IsConnected => SiemensTcp.Connected; - public string IpAddress => SiemensTcp.IPAdress; + public SiemensHelper Siemens_PLC_S7 = new SiemensHelper(); + public bool IsConnected => Siemens_PLC_S7.IsConnected; /// /// 配方接收信号复位 /// public void RecipeSignReset() { - this.SiemensTcp.Write(SiemensCommAddress.RecipeState, (ushort)0); + this.Siemens_PLC_S7.Write(SiemensCommAddress.RecipeState, (ushort)0); } /// /// AGV到位信号复位 /// public void AgvSignReset() { - this.SiemensTcp.Write(SiemensCommAddress.TrayState, (ushort)0); + this.Siemens_PLC_S7.Write(SiemensCommAddress.StateSign, (ushort)0); } public void Init() { @@ -34,13 +34,13 @@ namespace BPASmartClient.JXJFoodBigStation.Model.Siemens { ThreadManage.GetInstance().StartLong(new Action(() => { - var res = this.SiemensTcp.Read(SiemensCommAddress.RecipeState); + var res = this.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeState); if (res != null && RTrig.GetInstance("RecipeTrig").Start(res is bool SignTrig)) { ActionManage.GetInstance.Send("西门子下发配方"); RecipeSignReset(); } - var AgvState = this.SiemensTcp.Read(SiemensCommAddress.TrayState); + var AgvState = this.Siemens_PLC_S7.Read(SiemensCommAddress.StateSign); if (AgvState != null && RTrig.GetInstance("AgvTrig").Start(res is bool AgvSignTrig)) { ActionManage.GetInstance.Send("AGV到位信号"); @@ -56,9 +56,9 @@ namespace BPASmartClient.JXJFoodBigStation.Model.Siemens /// private void DosingFinsih(int TrayLocation,int recipeID) { - this.SiemensTcp.Write(SiemensCommAddress.TrayLocationNumToPLC, TrayLocation); - this.SiemensTcp.Write(SiemensCommAddress.TrayStateToPLC, 1); - this.SiemensTcp.Write(SiemensCommAddress.TrayRecipeIDToPLC, recipeID); + this.Siemens_PLC_S7.Write(SiemensCommAddress.TrayLocationNumToSiemens, TrayLocation); + this.Siemens_PLC_S7.Write(SiemensCommAddress.TrayStateToSiemens, 1); + this.Siemens_PLC_S7.Write(SiemensCommAddress.TrayRecipeIDToSiemens, recipeID); } } } diff --git a/BPASmartClient.JXJFoodBigStation/Model/TestData.cs b/BPASmartClient.JXJFoodBigStation/Model/TestData.cs index d28bf9d5..b7b7c45e 100644 --- a/BPASmartClient.JXJFoodBigStation/Model/TestData.cs +++ b/BPASmartClient.JXJFoodBigStation/Model/TestData.cs @@ -13,6 +13,7 @@ namespace BPASmartClient.JXJFoodBigStation.Model { public volatile static TestData Instance; public static TestData GetInstance => Instance ?? (Instance = new TestData()); + public ObservableCollection Recipes { get; set; } = new ObservableCollection(); public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); public TestData() { @@ -53,7 +54,7 @@ namespace BPASmartClient.JXJFoodBigStation.Model RawMaterialLocation = RawMaterialLocation2 }); - Json.Data.Recipes.Add(new Model.RemoteRecipeData() + Recipes.Add(new Model.RemoteRecipeData() { RecipeName = recipeName, RecipeCode = recipeCode, @@ -99,7 +100,7 @@ namespace BPASmartClient.JXJFoodBigStation.Model RawMaterialLocation = RawMaterialLocation2_2 }); - Json.Data.Recipes.Add(new Model.RemoteRecipeData() + Recipes.Add(new Model.RemoteRecipeData() { RecipeName = recipeName_2, RecipeCode = recipeCode_2, diff --git a/BPASmartClient.JXJFoodBigStation/View/RecipeInfosView.xaml b/BPASmartClient.JXJFoodBigStation/View/RecipeInfosView.xaml index 4256a586..1ce7f330 100644 --- a/BPASmartClient.JXJFoodBigStation/View/RecipeInfosView.xaml +++ b/BPASmartClient.JXJFoodBigStation/View/RecipeInfosView.xaml @@ -28,7 +28,7 @@ - + --> @@ -58,14 +58,13 @@ - - - - + + + @@ -77,8 +76,11 @@ - - + + + + + @@ -86,10 +88,10 @@ - 小料 + 大料站 - + @@ -102,52 +104,32 @@ 原料位置 原料重量 - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeInfosViewModel.cs b/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeInfosViewModel.cs index 65ad9e20..ad4390da 100644 --- a/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeInfosViewModel.cs +++ b/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeInfosViewModel.cs @@ -22,10 +22,18 @@ namespace BPASmartClient.JXJFoodBigStation.ViewModel { RecipeName = rm.RecipeName; RecipeCode = rm.RecipeCode; - RawMaterials = rm.RawMaterial; + TrayCode = rm.TrayCode; + //RawMaterialsInfo = rm.RawMaterial; + //var rest = RawMaterialsInfo.GetHashCode(); + + foreach (var item in rm.RawMaterial) + { + RawMaterialsInfo.Add(item); + } } }), "RecipeInfo"); - ReturnPage = new RelayCommand(() => + + ReturnPage = new RelayCommand(() => { ActionManage.GetInstance.Send("CloseRecipeInfosView"); }); @@ -37,7 +45,11 @@ namespace BPASmartClient.JXJFoodBigStation.ViewModel public long RecipeCode { get { return _mRecipeCode; } set { _mRecipeCode = value; OnPropertyChanged(); } } private long _mRecipeCode; + public int TrayCode { get { return _mTrayCode; } set { _mTrayCode = value; OnPropertyChanged(); } } + private int _mTrayCode; + public RelayCommand ReturnPage { get; set; } - public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); + + public ObservableCollection RawMaterialsInfo { get; set; } = new ObservableCollection(); } } diff --git a/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeReceiveViewModel.cs b/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeReceiveViewModel.cs index deb0d14f..c463d75b 100644 --- a/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeReceiveViewModel.cs +++ b/BPASmartClient.JXJFoodBigStation/ViewModel/RecipeReceiveViewModel.cs @@ -23,6 +23,7 @@ namespace BPASmartClient.JXJFoodBigStation.ViewModel { public class RecipeReceiveViewModel : ObservableObject { + ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); public RecipeReceiveViewModel() { //Json.Read(); @@ -35,14 +36,53 @@ namespace BPASmartClient.JXJFoodBigStation.ViewModel RecipeInfosView nrv = new RecipeInfosView(); var res = Json.Data.Recipes.FirstOrDefault(p => p.RecipeCode == num); ActionManage.GetInstance.Send("RecipeInfo", res); - nrv.ShowDialog(); + nrv.Show(); MessageLog.GetInstance.ShowUserLog($"查看配方——{res.RecipeName}"); } }); + NewSimulateRecipe = new RelayCommand(() => + { + RawMaterials.Clear(); + string recipeName = "配方" + (Json.Data.Recipes.Count + 1) + ""; + go: + long recipeCode = new Random().Next(1000, 9999); + foreach (var item in Recipes) + { + if (item.RecipeCode == recipeCode) + { + goto go; + } + } + int trayCode = new Random().Next(1, 3); + for (int i = 1; i < 16; i++) + { + RawMaterials.Add(new RemoteRecipeRawMaterial() + { + RawMaterialWeight = new Random().Next(10, 1000), + RawMaterialBarrelNum = new Random().Next(1, 3), + RawMaterialLocation = i, + }); + } + Json.Data.Recipes.Add(new RemoteRecipeData() + { + RecipeName = recipeName, + RecipeCode = recipeCode, + TrayCode = trayCode, + RawMaterial = RawMaterials, + }); + + }); + ClearAllRecipe = new RelayCommand(() => + { + Json.Data.Recipes.Clear(); + }); } public RelayCommand DetailsCommand { get; set; } + public RelayCommand NewSimulateRecipe { get; set; } + public RelayCommand ClearAllRecipe { get; set; } + public ObservableCollection Recipes { get; set; } } } diff --git a/BPASmartClient.JXJFoodSmallStation/App.config b/BPASmartClient.JXJFoodSmallStation/App.config index 5ff78b1a..5b550290 100644 --- a/BPASmartClient.JXJFoodSmallStation/App.config +++ b/BPASmartClient.JXJFoodSmallStation/App.config @@ -2,8 +2,6 @@ - - \ No newline at end of file diff --git a/BPASmartClient.JXJFoodSmallStation/App.xaml.cs b/BPASmartClient.JXJFoodSmallStation/App.xaml.cs index ee7287db..92abc22f 100644 --- a/BPASmartClient.JXJFoodSmallStation/App.xaml.cs +++ b/BPASmartClient.JXJFoodSmallStation/App.xaml.cs @@ -30,7 +30,6 @@ namespace BPASmartClient.JXJFoodSmallStation DeviceInquire.GetInstance.Init();//配料机设备上线监听,设备列表初始化 ProcessControl.GetInstance.Init(); MainView mv = new MainView(); - //mv.Show(); LoginView lv = new LoginView(); var res = lv.ShowDialog(); if (res != null && res == true) @@ -53,25 +52,25 @@ namespace BPASmartClient.JXJFoodSmallStation private void MenuInit() { - NfcServer.GetInstance.Init(); + //NfcServer.GetInstance.Init(); #region 配方管理菜单 ObservableCollection RecipeManage = new ObservableCollection(); - RecipeManage.Add(new SubMenumodel() + /*RecipeManage.Add(new SubMenumodel() { SubMenuName = "本地配方管理", SubMenuPermission = new Permission[] { Permission.管理员 }, AssemblyName = "BPASmartClient.JXJFoodSmallStation", ToggleWindowPath = "View.RecipeSettingsView" - }); + });*/ - RecipeManage.Add(new SubMenumodel() + /*RecipeManage.Add(new SubMenumodel() { SubMenuName = "本地配方下发", SubMenuPermission = new Permission[] { Permission.操作员, Permission.管理员 }, AssemblyName = "BPASmartClient.JXJFoodSmallStation", ToggleWindowPath = "View.RecipeControlView" - }); + });*/ RecipeManage.Add(new SubMenumodel() { SubMenuName = "服务配方管理", @@ -176,13 +175,13 @@ namespace BPASmartClient.JXJFoodSmallStation ToggleWindowPath = "Pages.View.PasswordChangeView" }); - UserManager.Add(new SubMenumodel() + /* UserManager.Add(new SubMenumodel() { SubMenuName = "NFC登录设置", SubMenuPermission = new Permission[] { Permission.管理员 }, AssemblyName = "BPASmartClient.CustomResource", ToggleWindowPath = "Pages.View.NfcSetView" - }); + });*/ MenuManage.GetInstance.menuModels.Add(new MenuModel() { diff --git a/BPASmartClient.JXJFoodSmallStation/BPASmartClient.JXJFoodSmallStation.csproj b/BPASmartClient.JXJFoodSmallStation/BPASmartClient.JXJFoodSmallStation.csproj index 1305e32f..b6e0a466 100644 --- a/BPASmartClient.JXJFoodSmallStation/BPASmartClient.JXJFoodSmallStation.csproj +++ b/BPASmartClient.JXJFoodSmallStation/BPASmartClient.JXJFoodSmallStation.csproj @@ -16,35 +16,7 @@ + - - diff --git a/BPASmartClient.JXJFoodSmallStation/Model/DeviceInquire.cs b/BPASmartClient.JXJFoodSmallStation/Model/DeviceInquire.cs index 1f24e6bb..9a7fce73 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/DeviceInquire.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/DeviceInquire.cs @@ -207,7 +207,7 @@ namespace BPASmartClient.JXJFoodSmallStation.Model } public void StatusReset() { - this.modbusTcp.Write(DeviceAddress.RunStatus, (ushort)0); + this.modbusTcp.Write(DeviceAddress.RunStatus, (ushort)0);//OutRawMaterialFinish复位出料完成信号 } public void OutRawMaterialReset() { diff --git a/BPASmartClient.JXJFoodSmallStation/Model/GVL_SmallStation.cs b/BPASmartClient.JXJFoodSmallStation/Model/GVL_SmallStation.cs new file mode 100644 index 00000000..7f26f5d4 --- /dev/null +++ b/BPASmartClient.JXJFoodSmallStation/Model/GVL_SmallStation.cs @@ -0,0 +1,49 @@ +using BPASmartClient.JXJFoodSmallStation.Model.Siemens; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.JXJFoodSmallStation.Model +{ + public class GVL_SmallStation + { + /// + /// 配方数据 + /// + public ObservableCollection RemoteRecipes = new ObservableCollection(); + /// + /// 配方队列 + /// + public ConcurrentQueue RecipeQueue = new ConcurrentQueue(); + + /// + /// 往输送带下发配方完成 + /// + public bool IssueRecipeFinish { get; set; } = false; + + public bool IsAllow { get; set; } = false; + + public bool IsAllowOut { set; get; } = false; + /// + /// 当前料仓的位置 + /// + public int StockInIsWork { get; set; } = 0; + /// + /// 单个配方执行完成标志 + /// + public bool RecipeFinish { get; set; } = false; + + /// + /// 记录AGV进站送货的指令顺序 + /// + public int AgvDeliveryPosition { get; set; }= 0; + /// + /// 记录AGV进站取货的指令顺序 + /// + public int AgvPickUpPosition { get; set; } = 0; + } +} diff --git a/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKDeviceStatus.cs b/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKDeviceStatus.cs index 29b9411c..14c9e29d 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKDeviceStatus.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKDeviceStatus.cs @@ -5,15 +5,14 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using BPASmartClient.S7Net; namespace BPASmartClient.JXJFoodSmallStation.Model.HK_PLC { public class HKDeviceStatus { - public ModbusTcp ModBusHK = new ModbusTcp(); - public string IpAddress => ModBusHK.IPAdress; - public bool IsConnected => ModBusHK.Connected; - + public SiemensHelper HK_PLC_S7 = new SiemensHelper(); + public bool IsConnected => HK_PLC_S7.IsConnected; public void Init() { if (IsConnected) @@ -32,8 +31,8 @@ namespace BPASmartClient.JXJFoodSmallStation.Model.HK_PLC { if (IsConnected) { - ModBusHK.SetUint(HKPlcCommAddress.SingleStockBinLocationToPLC, value); - ModBusHK.Write(HKPlcCommAddress.SingleDosingFinishToPLC, (ushort)1); + HK_PLC_S7.Write(HKPlcCommAddress.SingleStockBinLocationToPLC, value); + HK_PLC_S7.Write(HKPlcCommAddress.SingleDosingFinishToPLC, (ushort)1); } } /// @@ -41,21 +40,21 @@ namespace BPASmartClient.JXJFoodSmallStation.Model.HK_PLC /// public void AllowDosingSignReset() { - ModBusHK.Write(HKPlcCommAddress.IsAllowDosing,(ushort)0); + HK_PLC_S7.Write(HKPlcCommAddress.IsAllowDosing,(ushort)0); } /// /// 复位plc到达某料仓信号 /// public void StockStateSignReset() { - ModBusHK.Write(HKPlcCommAddress.StockState, (ushort)0); + HK_PLC_S7.Write(HKPlcCommAddress.StockState, (ushort)0); } /// /// 复位一个配方配料完成信号 /// public void RecipeDosingFinishReset() { - ModBusHK.Write(HKPlcCommAddress.RecipeDosingFinish, (ushort)0); + HK_PLC_S7.Write(HKPlcCommAddress.RecipeDosingFinish, (ushort)0); } /// /// 下发配方数据 @@ -66,8 +65,8 @@ namespace BPASmartClient.JXJFoodSmallStation.Model.HK_PLC { if (IsConnected) { - ModBusHK.SetUint(HKPlcCommAddress.BarrelNumToPLC, BarrelNum); - ModBusHK.Write(HKPlcCommAddress.StockBinLocationToPLC, StockBinLocation); + HK_PLC_S7.Write(HKPlcCommAddress.BarrelNumToPLC, BarrelNum); + HK_PLC_S7.Write(HKPlcCommAddress.StockBinLocationToPLC, StockBinLocation); } } } diff --git a/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKPlcCommAddress.cs b/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKPlcCommAddress.cs index 0445b1db..80a9398b 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKPlcCommAddress.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/HK_PLC/HKPlcCommAddress.cs @@ -43,5 +43,52 @@ namespace BPASmartClient.JXJFoodSmallStation.Model.HK_PLC public static string RecipeDosingFinish { get; set; } = ""; #endregion + + #region AGV进出站 + /// + /// Agv送货 进站申请 + /// + public static string DeliveryAGVApply { get; set; } = ""; + /// + /// Agv送货 进站申请 + /// + public static string DeliveryAGVIsApply { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 + /// + public static string DeliveryAGVApplyJack { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 + /// + public static string DeliveryAGVIsApplyJack { get; set; } = ""; + /// + /// Agv送货 送货完成 + /// + public static string DeliveryAGVFinsih { get; set; } = ""; + /// + /// Agv送货 工位上有货架 + /// + public static string StationHaveCargo { get; set; } = ""; + /// + /// Agv送货 进站申请 + /// + public static string PickAGVApply { get; set; } = ""; + /// + /// Agv送货 进站申请 + /// + public static string PickAGVIsApply { get; set; } = ""; + /// + /// Agv送货 取货架完成 + /// + public static string PickCargoAGVFinish { get; set; } = ""; + /// + /// Agv送货 取料完成 + /// + public static string PickAGVFinish { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar { get; set; } = ""; + #endregion } } diff --git a/BPASmartClient.JXJFoodSmallStation/Model/ProcessControl.cs b/BPASmartClient.JXJFoodSmallStation/Model/ProcessControl.cs index ba8fedc5..292e5ce2 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/ProcessControl.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/ProcessControl.cs @@ -15,37 +15,43 @@ using System.Threading.Tasks; namespace BPASmartClient.JXJFoodSmallStation.Model { public class ProcessControl - { + { private volatile static ProcessControl _Instance; public static ProcessControl GetInstance => _Instance ?? (_Instance = new ProcessControl()); private ProcessControl() { } - public ObservableCollection RemoteRecipes = new ObservableCollection(); - ConcurrentQueue RecipeQueue = new ConcurrentQueue(); public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); public SiemensDeviceStatus SiemensDevice = new SiemensDeviceStatus(); public HKDeviceStatus HKDevice = new HKDeviceStatus(); + GVL_SmallStation SmallStation = new GVL_SmallStation(); + /// + /// 接收原料数据 + /// + public RecipeRawMaterial RawMaterial; public void Init() { ActionManage.GetInstance.Register(new Action(() => { if (SiemensDevice.IsConnected) { - var res = SiemensDevice.SiemensTcp.GetString(SiemensCommAddress.RecipeName, (ushort)20); - var res1 = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.RecipeID); - var res2 = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.RawMaterial); + var res = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeName); + var res1 = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeID); + int res2 = SiemensDevice.Siemens_PLC_S7.ReadClass(RawMaterial, 0, 0); if ((res != null && res is string recipeName) && (res1 != null && res1 is uint recipeID) && - (res2 != null && res2 is ushort[] rawMaterial)) + (res2 > 0)) { RawMaterials.Clear(); - RawMaterials.Add(new RemoteRecipeRawMaterial() + for (int i = 0; i < 15; i++) { - RawMaterialBarrelNum = rawMaterial[0], - RawMaterialLocation = rawMaterial[1], - RawMaterialWeight = rawMaterial[2] - }); + RawMaterials.Add(new RemoteRecipeRawMaterial() + { + RawMaterialBarrelNum = RawMaterial.RawMaterialBarrelNum[i], + RawMaterialLocation = RawMaterial.RawMaterialLocation[i], + RawMaterialWeight = RawMaterial.RawMaterialWeight[i] + }); + } Json.Data.Recipes.Add(new RemoteRecipeData() { RecipeName = recipeName, @@ -59,8 +65,8 @@ namespace BPASmartClient.JXJFoodSmallStation.Model { if (SiemensDevice.IsConnected) { - var res = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.TrayLocationNum); - var res1 = SiemensDevice.SiemensTcp.Read(SiemensCommAddress.RecipeID); + var res = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.TrayLocationNum); + var res1 = SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeID); if (res != null && res is int TrayLocation && res1 != null && res1 is int recipeId) { int index = Array.FindIndex(Json.Data.Recipes.ToArray(), p => p.RecipeCode == recipeId); @@ -72,14 +78,12 @@ namespace BPASmartClient.JXJFoodSmallStation.Model } }), "AGV到位信号", true);//根据下发的配方ID将 托盘的位置信息添加到配方中 string HK_PLC_IP = ConfigurationManager.AppSettings["HKPlc_IP"]; - string HK_PLC_Port = ConfigurationManager.AppSettings["HKPlc_Port"]; string Siemens_PLC_IP = ConfigurationManager.AppSettings["Siemens_IP"]; - string Siemens_PLC_Port = ConfigurationManager.AppSettings["Siemens_Port"]; - Task.Run(new Action(() => + try { - HKDevice.ModBusHK.ModbusTcpConnect(HK_PLC_IP, int.Parse(HK_PLC_Port)); - SiemensDevice.SiemensTcp.ModbusTcpConnect(Siemens_PLC_IP, int.Parse(Siemens_PLC_Port)); - if (HKDevice.IsConnected) + //HKDevice.HK_PLC_S7.Connect(S7.Net.CpuType.S7200Smart, HK_PLC_IP); + //SiemensDevice.Siemens_PLC_S7.Connect(S7.Net.CpuType.S71500, Siemens_PLC_IP); + if (HKDevice.IsConnected) { HKDevice.Init(); } @@ -87,85 +91,180 @@ namespace BPASmartClient.JXJFoodSmallStation.Model { SiemensDevice.Init(); } - })); - RecipeQueue.Clear(); - RawMaterials = TestData.GetInstance.RawMaterials;//添加测试数据 + } + catch(Exception ex) + { + + } + SmallStation.RecipeQueue.Clear(); + Json.Data.Recipes = TestData.GetInstance.Recipes;//添加测试数据 ThreadManage.GetInstance().StartLong(new Action(() => { - RemoteRecipes = Json.Data.Recipes; ReceviceData(); RecipeInfoToHKPLC(); Thread.Sleep(10); }), "流程处理", true); + ThreadManage.GetInstance().StartLong(new Action(() => { + if (SiemensDevice.IsConnected && HKDevice.IsConnected) + { + AgvGetInDelivery(); + AgvGetInPickUp(); + } + Thread.Sleep(10); + }), "AGV进站送取货", true); + } + /// + /// AGV进站送货 + /// + private void AgvGetInDelivery() + { + switch (SmallStation.AgvDeliveryPosition) + { + case 0: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.DeliveryAGVApply) is bool)) + { + SmallStation.AgvDeliveryPosition = 1; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.DeliveryAGVApply, true); + } + break; + case 1: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.DeliveryAGVIsApply) is bool)) + { + SmallStation.AgvDeliveryPosition = 2; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.DeliveryAGVIsApply, true); + } + break; + case 2: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.DeliveryAGVApplyJack) is bool)) + { + SmallStation.AgvDeliveryPosition = 3; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.DeliveryAGVApplyJack, true); + } + break; + case 3: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.DeliveryAGVIsApplyJack) is bool)) + { + SmallStation.AgvDeliveryPosition = 4; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.DeliveryAGVIsApplyJack, true); + } + break; + case 4: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.DeliveryAGVFinsih) is bool)) + { + SmallStation.AgvDeliveryPosition = 5; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.DeliveryAGVFinsih, true); + } + break; + case 5: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.StationHaveCargo) is bool)) + { + SmallStation.AgvDeliveryPosition = 0; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.StationHaveCargo, true); + } + break; + default: + break; + } + //获取工位上是否有小车 + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.StationIsExistCar, (bool) + HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.StationIsExistCar)); + } + /// + /// AGV进站取货 + /// + private void AgvGetInPickUp() + { + switch (SmallStation.AgvPickUpPosition) + { + case 0: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.PickAGVApply) is bool)) + { + SmallStation.AgvPickUpPosition = 1; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.PickAGVApply, true); + } + break; + case 1: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.PickAGVIsApply) is bool)) + { + SmallStation.AgvPickUpPosition = 2; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.PickAGVIsApply, true); + } + break; + case 2: + if (RTrig.GetInstance("").Start(SiemensDevice.Siemens_PLC_S7.Read(SiemensCommAddress.PickCargoAGVFinish) is bool)) + { + SmallStation.AgvPickUpPosition = 3; + HKDevice.HK_PLC_S7.Write(HKPlcCommAddress.PickCargoAGVFinish, true); + } + break; + case 3: + if (RTrig.GetInstance("").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.PickAGVFinish) is bool)) + { + SmallStation.AgvPickUpPosition = 0; + SiemensDevice.Siemens_PLC_S7.Write(SiemensCommAddress.PickAGVFinish, true); + } + break; + default: + break; + } } - private void ReceviceData() { + SmallStation.RemoteRecipes = Json.Data.Recipes; if (Json.Data.Recipes.Count > 0) { foreach (var data in Json.Data.Recipes) { - if(!(RecipeQueue.Contains(data.RecipeCode))) - RecipeQueue.Enqueue(data.RecipeCode); + if(!(SmallStation.RecipeQueue.Contains(data.RecipeCode))) + SmallStation.RecipeQueue.Enqueue(data.RecipeCode); } } } - /// - /// 当前料仓的位置 - /// - private int StockInIsWork; - /// - /// 单个配方执行完成标志 - /// - private bool RecipeFinfish; - private void RecipeInfoToHKPLC() + private void RecipeInfoToHKPLC() { - if (RecipeQueue.Count > 0) + if (SmallStation.RecipeQueue.Count > 0) { - int index = Array.FindIndex(RemoteRecipes.ToArray(), p => p.RecipeCode == RecipeQueue.ElementAt(0)); - if (index >= 0 && index <= RemoteRecipes.Count) + int index = Array.FindIndex(SmallStation.RemoteRecipes.ToArray(), p => p.RecipeCode == SmallStation.RecipeQueue.ElementAt(0)); + if (index >= 0 && index <= SmallStation.RemoteRecipes.Count) { - long code = RemoteRecipes.ElementAt(index).RecipeCode; - if (RTrig.GetInstance("IsAllowDosing").Start(HKDevice.ModBusHK.Read(HKPlcCommAddress.IsAllowDosing) is bool a)) + long code = SmallStation.RemoteRecipes.ElementAt(index).RecipeCode; + if (RTrig.GetInstance("IsAllowDosing").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.IsAllowDosing) is bool a)) { - foreach (var item in RemoteRecipes.ElementAt(index).RawMaterial) + foreach (var item in SmallStation.RemoteRecipes.ElementAt(index).RawMaterial) { HKDevice.StockBinPar((uint)item.RawMaterialBarrelNum, (ushort)item.RawMaterialLocation); } HKDevice.AllowDosingSignReset(); - + SmallStation.IssueRecipeFinish = true; } - if (RTrig.GetInstance("StockState").Start(HKDevice.ModBusHK.Read(HKPlcCommAddress.StockState) is bool)) + if (RTrig.GetInstance("StockState").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.StockState) is bool) && SmallStation.IssueRecipeFinish) { - var res = HKDevice.ModBusHK.Read(HKPlcCommAddress.StockBinLocation); + var res = HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.StockBinLocation); if (res != null && res is int loc) { - - int loc_index = Array.FindIndex(RemoteRecipes.ElementAt(index).RawMaterial.ToArray(), p => p.RawMaterialLocation == loc); - double weight = RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(loc_index).RawMaterialWeight; + int loc_index = Array.FindIndex(SmallStation.RemoteRecipes.ElementAt(index).RawMaterial.ToArray(), p => p.RawMaterialLocation == loc); + double weight = SmallStation.RemoteRecipes.ElementAt(index).RawMaterial.ElementAt(loc_index).RawMaterialWeight; if (loc_index >= 1 && loc_index <= 15) { DeviceInquire.GetInstance.GetDeviceObject(loc_index)?.Start((uint)weight);//启动并写入每个原料重量 - StockInIsWork = loc_index; + SmallStation.StockInIsWork = loc_index; HKDevice.StockStateSignReset(); } } } - if (RTrig.GetInstance("OutRawMaterialFinish").Start(DeviceInquire.GetInstance.GetDeviceObject(StockInIsWork).modbusTcp.Read(DeviceAddress.OutRawMaterialFinish) is bool)) + if (RTrig.GetInstance("OutRawMaterialFinish").Start(DeviceInquire.GetInstance.GetDeviceObject(SmallStation.StockInIsWork).modbusTcp.Read(DeviceAddress.OutRawMaterialFinish) is bool)) { - HKDevice.SingleDosing((uint)StockInIsWork); - DeviceInquire.GetInstance.GetDeviceObject(StockInIsWork).OutRawMaterialReset(); + HKDevice.SingleDosing((uint)SmallStation.StockInIsWork); + DeviceInquire.GetInstance.GetDeviceObject(SmallStation.StockInIsWork).OutRawMaterialReset(); } - if (RTrig.GetInstance("StockState").Start(HKDevice.ModBusHK.Read(HKPlcCommAddress.RecipeDosingFinish) is bool)) + if (RTrig.GetInstance("StockState").Start(HKDevice.HK_PLC_S7.Read(HKPlcCommAddress.RecipeDosingFinish) is bool)) { HKDevice.RecipeDosingFinishReset(); - RecipeQueue.TryDequeue(out code); + SmallStation.RecipeQueue.TryDequeue(out code); + Json.Data.Recipes.RemoveAt(index);//制作完成,移除当前配方 } } } } - private void HKPLCIsWork() - { - } } } diff --git a/BPASmartClient.JXJFoodSmallStation/Model/Siemens/RemoteRecipeRawMaterial.cs b/BPASmartClient.JXJFoodSmallStation/Model/Siemens/RemoteRecipeRawMaterial.cs index dd524cfa..b012fc71 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/Siemens/RemoteRecipeRawMaterial.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/Siemens/RemoteRecipeRawMaterial.cs @@ -6,28 +6,27 @@ using System.Threading.Tasks; namespace BPASmartClient.JXJFoodSmallStation.Model { - public class RemoteRecipeRawMaterial + public class RemoteRecipeRawMaterial { private int _mIp; - public int DeviceIp { get { return _mIp; } set { _mIp = value; } } + public int DeviceIp { get { return _mIp; } set { _mIp = value; }} - private int _mRawMaterialBarrelNum; /// /// 原料对应的桶号 /// public int RawMaterialBarrelNum { get { return _mRawMaterialBarrelNum; } set { _mRawMaterialBarrelNum = value; } } + private int _mRawMaterialBarrelNum; - private double _mRawMaterialWeight; /// /// 需要原料重量 /// - public double RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value;} } - + public double RawMaterialWeight { get { return _mRawMaterialWeight; } set { _mRawMaterialWeight = value; } } + private double _mRawMaterialWeight; - private int _mRawMaterialLocation; /// /// 原料对应料仓的位置 /// - public int RawMaterialLocation { get { return _mRawMaterialLocation; } set { _mRawMaterialLocation = value;} } + public int RawMaterialLocation { get { return _mRawMaterialLocation; } set { _mRawMaterialLocation = value; } } + private int _mRawMaterialLocation; } } diff --git a/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensCommAddress.cs b/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensCommAddress.cs index 341c2f44..b05bab8a 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensCommAddress.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensCommAddress.cs @@ -28,17 +28,84 @@ namespace BPASmartClient.JXJFoodSmallStation.Model.Siemens #endregion #region AGV到位(与西门子PLC交互)西门子PLC ==> 上位机 + /// + /// 托盘的位置编号 + /// public static string TrayLocationNum { get; set; } = ""; + /// + /// 配方ID + /// public static string TrayRecipeID { get; set; } = ""; - public static string TrayState { get; set; } = ""; + /// + /// 状态信号 + /// + public static string StateSign { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string DeliveryAGVApply { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string DeliveryAGVIsApply { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 从西门子读取 + /// + public static string DeliveryAGVApplyJack { get; set; } = ""; + /// + /// Agv送货 进站顶升申请 写给西门子 + /// + public static string DeliveryAGVIsApplyJack { get; set; } = ""; + /// + /// Agv送货 送货完成 从西门子读取 + /// + public static string DeliveryAGVFinsih { get; set; } = ""; + /// + /// Agv送货 工位上有货架 写给西门子 + /// + public static string StationHaveCargo { get; set; } = ""; + /// + /// Agv送货 进站申请 从西门子读取 + /// + public static string PickAGVApply { get; set; } = ""; + /// + /// Agv送货 进站申请 写给西门子 + /// + public static string PickAGVIsApply { get; set; } = ""; + /// + /// Agv送货 取货架完成 从西门子读取 + /// + public static string PickCargoAGVFinish { get; set; } = ""; + /// + /// Agv送货 取料完成 写给西门子 + /// + public static string PickAGVFinish { get; set; } = ""; + /// + /// 工位上是否有小车 + /// + public static string StationIsExistCar { get; set; } = ""; #endregion #region Tray配料完成(与西门子PLC交互)上位机 ==> 西门子PLC - public static string TrayLocationNumToPLC { get; set; } = ""; - public static string TrayRecipeIDToPLC { get; set; } = ""; - public static string TrayStateToPLC { get; set; } = ""; + public static string TrayLocationNumToSiemens { get; set; } = ""; + public static string TrayRecipeIDToSiemens { get; set; } = ""; + public static string TrayStateToSiemens { get; set; } = ""; #endregion } - + public class RecipeRawMaterial + { + /// + /// 原料对应的桶号 + /// + public int[] RawMaterialBarrelNum = new int[15]; + /// + /// 需要原料重量 + /// + public double[] RawMaterialWeight = new double[15]; + /// + /// 原料对应料仓的位置 + /// + public int[] RawMaterialLocation = new int[15]; + } } diff --git a/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensDeviceStatus.cs b/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensDeviceStatus.cs index 69d4788e..6d9944a9 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensDeviceStatus.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/Siemens/SiemensDeviceStatus.cs @@ -5,28 +5,28 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using BPASmartClient.S7Net; namespace BPASmartClient.JXJFoodSmallStation.Model.Siemens { public class SiemensDeviceStatus { - public ModbusTcp SiemensTcp = new ModbusTcp(); - public bool IsConnected => SiemensTcp.Connected; - public string IpAddress => SiemensTcp.IPAdress; + public SiemensHelper Siemens_PLC_S7 = new SiemensHelper(); + public bool IsConnected => Siemens_PLC_S7.IsConnected; /// /// 配方接收信号复位 /// public void RecipeSignReset() { - this.SiemensTcp.Write(SiemensCommAddress.RecipeState, (ushort)0); + this.Siemens_PLC_S7.Write(SiemensCommAddress.RecipeState, (ushort)0); } /// /// AGV到位信号复位 /// public void AgvSignReset() { - this.SiemensTcp.Write(SiemensCommAddress.TrayState, (ushort)0); + this.Siemens_PLC_S7.Write(SiemensCommAddress.StateSign, (ushort)0); } public void Init() { @@ -34,13 +34,13 @@ namespace BPASmartClient.JXJFoodSmallStation.Model.Siemens { ThreadManage.GetInstance().StartLong(new Action(() => { - var res = this.SiemensTcp.Read(SiemensCommAddress.RecipeState); + var res = this.Siemens_PLC_S7.Read(SiemensCommAddress.RecipeState); if (res != null && RTrig.GetInstance("RecipeTrig").Start(res is bool SignTrig)) { ActionManage.GetInstance.Send("西门子下发配方"); RecipeSignReset(); } - var AgvState = this.SiemensTcp.Read(SiemensCommAddress.TrayState); + var AgvState = this.Siemens_PLC_S7.Read(SiemensCommAddress.StateSign); if (AgvState != null && RTrig.GetInstance("AgvTrig").Start(res is bool AgvSignTrig)) { ActionManage.GetInstance.Send("AGV到位信号"); @@ -56,9 +56,9 @@ namespace BPASmartClient.JXJFoodSmallStation.Model.Siemens /// private void DosingFinsih(int TrayLocation,int recipeID) { - this.SiemensTcp.Write(SiemensCommAddress.TrayLocationNumToPLC, TrayLocation); - this.SiemensTcp.Write(SiemensCommAddress.TrayStateToPLC, 1); - this.SiemensTcp.Write(SiemensCommAddress.TrayRecipeIDToPLC, recipeID); + this.Siemens_PLC_S7.Write(SiemensCommAddress.TrayLocationNumToSiemens, TrayLocation); + this.Siemens_PLC_S7.Write(SiemensCommAddress.TrayStateToSiemens, 1); + this.Siemens_PLC_S7.Write(SiemensCommAddress.TrayRecipeIDToSiemens, recipeID); } } } diff --git a/BPASmartClient.JXJFoodSmallStation/Model/TestData.cs b/BPASmartClient.JXJFoodSmallStation/Model/TestData.cs index ae9576f8..6503b448 100644 --- a/BPASmartClient.JXJFoodSmallStation/Model/TestData.cs +++ b/BPASmartClient.JXJFoodSmallStation/Model/TestData.cs @@ -13,6 +13,7 @@ namespace BPASmartClient.JXJFoodSmallStation.Model { public volatile static TestData Instance; public static TestData GetInstance => Instance ?? (Instance = new TestData()); + public ObservableCollection Recipes { get; set; } = new ObservableCollection(); public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); public TestData() { @@ -53,7 +54,7 @@ namespace BPASmartClient.JXJFoodSmallStation.Model RawMaterialLocation = RawMaterialLocation2 }); - Json.Data.Recipes.Add(new Model.RemoteRecipeData() + Recipes.Add(new Model.RemoteRecipeData() { RecipeName = recipeName, RecipeCode = recipeCode, @@ -99,7 +100,7 @@ namespace BPASmartClient.JXJFoodSmallStation.Model RawMaterialLocation = RawMaterialLocation2_2 }); - Json.Data.Recipes.Add(new Model.RemoteRecipeData() + Recipes.Add(new Model.RemoteRecipeData() { RecipeName = recipeName_2, RecipeCode = recipeCode_2, diff --git a/BPASmartClient.JXJFoodSmallStation/View/RecipeInfosView.xaml b/BPASmartClient.JXJFoodSmallStation/View/RecipeInfosView.xaml index bd034126..edf21224 100644 --- a/BPASmartClient.JXJFoodSmallStation/View/RecipeInfosView.xaml +++ b/BPASmartClient.JXJFoodSmallStation/View/RecipeInfosView.xaml @@ -28,7 +28,7 @@ - + --> @@ -58,14 +58,13 @@ - - - - + + + @@ -77,8 +76,11 @@ - - + + + + + @@ -86,10 +88,10 @@ - 小料 + 小料站 - + @@ -102,52 +104,32 @@ 原料位置 原料重量 - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeInfosViewModel.cs b/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeInfosViewModel.cs index eb01cd0f..5cee9780 100644 --- a/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeInfosViewModel.cs +++ b/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeInfosViewModel.cs @@ -22,10 +22,18 @@ namespace BPASmartClient.JXJFoodSmallStation.ViewModel { RecipeName = rm.RecipeName; RecipeCode = rm.RecipeCode; - RawMaterials = rm.RawMaterial; + TrayCode = rm.TrayCode; + //RawMaterialsInfo = rm.RawMaterial; + //var rest = RawMaterialsInfo.GetHashCode(); + + foreach (var item in rm.RawMaterial) + { + RawMaterialsInfo.Add(item); + } } }), "RecipeInfo"); - ReturnPage = new RelayCommand(() => + + ReturnPage = new RelayCommand(() => { ActionManage.GetInstance.Send("CloseRecipeInfosView"); }); @@ -37,7 +45,11 @@ namespace BPASmartClient.JXJFoodSmallStation.ViewModel public long RecipeCode { get { return _mRecipeCode; } set { _mRecipeCode = value; OnPropertyChanged(); } } private long _mRecipeCode; + public int TrayCode { get { return _mTrayCode; } set { _mTrayCode = value; OnPropertyChanged(); } } + private int _mTrayCode; + public RelayCommand ReturnPage { get; set; } - public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); + + public ObservableCollection RawMaterialsInfo { get; set; } = new ObservableCollection(); } } diff --git a/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeReceiveViewModel.cs b/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeReceiveViewModel.cs index 501f4b8c..36857a1e 100644 --- a/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeReceiveViewModel.cs +++ b/BPASmartClient.JXJFoodSmallStation/ViewModel/RecipeReceiveViewModel.cs @@ -23,6 +23,7 @@ namespace BPASmartClient.JXJFoodSmallStation.ViewModel { public class RecipeReceiveViewModel : ObservableObject { + ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); public RecipeReceiveViewModel() { //Json.Read(); @@ -35,14 +36,53 @@ namespace BPASmartClient.JXJFoodSmallStation.ViewModel RecipeInfosView nrv = new RecipeInfosView(); var res = Json.Data.Recipes.FirstOrDefault(p => p.RecipeCode == num); ActionManage.GetInstance.Send("RecipeInfo", res); - nrv.ShowDialog(); + nrv.Show(); MessageLog.GetInstance.ShowUserLog($"查看配方——{res.RecipeName}"); } }); + NewSimulateRecipe = new RelayCommand(() => + { + RawMaterials.Clear(); + string recipeName = "配方" + (Json.Data.Recipes.Count + 1) + ""; + go: + long recipeCode = new Random().Next(1000, 9999); + foreach (var item in Recipes) + { + if (item.RecipeCode == recipeCode) + { + goto go; + } + } + int trayCode = new Random().Next(1, 3); + for (int i = 1; i < 16; i++) + { + RawMaterials.Add(new RemoteRecipeRawMaterial() + { + RawMaterialWeight = new Random().Next(10, 1000), + RawMaterialBarrelNum = new Random().Next(1, 3), + RawMaterialLocation = i, + }); + } + Json.Data.Recipes.Add(new RemoteRecipeData() + { + RecipeName = recipeName, + RecipeCode = recipeCode, + TrayCode = trayCode, + RawMaterial = RawMaterials, + }); + + }); + ClearAllRecipe = new RelayCommand(() => + { + Json.Data.Recipes.Clear(); + }); } public RelayCommand DetailsCommand { get; set; } + public RelayCommand NewSimulateRecipe { get; set; } + public RelayCommand ClearAllRecipe { get; set; } + public ObservableCollection Recipes { get; set; } } } diff --git a/SmartClient.sln b/SmartClient.sln index 408ebd9b..f2ae20db 100644 --- a/SmartClient.sln +++ b/SmartClient.sln @@ -121,17 +121,16 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.KHKJ", "BPASmartClient.KHKJ\BPASmartClient.KHKJ.csproj", "{C0060FB3-7AEA-4D14-ADCE-DB78D3665D5B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.MorkTM", "BPASmartClient.MorkTM\BPASmartClient.MorkTM.csproj", "{1612F583-D328-45C6-8BB1-5D41B8F1D216}" -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.KHKJ", "BPASmartClient.KHKJ\BPASmartClient.KHKJ.csproj", "{C0060FB3-7AEA-4D14-ADCE-DB78D3665D5B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.Nfc", "BPASmartClient.Nfc\BPASmartClient.Nfc.csproj", "{42D35B7C-764C-4692-AA85-9B343A0F5B7F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.Argox", "BPASmartClient.Argox\BPASmartClient.Argox.csproj", "{B8D499BA-A18A-4FD6-B036-44F02B4D164B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BPASmartClient.S7Net", "BPASmartClient.S7Net\BPASmartClient.S7Net.csproj", "{D1F2379E-1755-4B50-9D67-15C960C33FFA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.S7Net", "BPASmartClient.S7Net\BPASmartClient.S7Net.csproj", "{D1F2379E-1755-4B50-9D67-15C960C33FFA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BPASmartClient.JXJFoodBigStation", "BPASmartClient.JXJFoodBigStation\BPASmartClient.JXJFoodBigStation.csproj", "{FA695D7E-6F12-4483-A16D-8494609FAE68}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.JXJFoodBigStation", "BPASmartClient.JXJFoodBigStation\BPASmartClient.JXJFoodBigStation.csproj", "{FA695D7E-6F12-4483-A16D-8494609FAE68}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BPASmartClient.JXJFoodSmallStation", "BPASmartClient.JXJFoodSmallStation\BPASmartClient.JXJFoodSmallStation.csproj", "{D609C4CF-FA5C-4D39-B12F-07A60FFE5E40}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPASmartClient.JXJFoodSmallStation", "BPASmartClient.JXJFoodSmallStation\BPASmartClient.JXJFoodSmallStation.csproj", "{D609C4CF-FA5C-4D39-B12F-07A60FFE5E40}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution