diff --git a/BPASmartClient.Device/BaseDevice.cs b/BPASmartClient.Device/BaseDevice.cs index f2c02831..1fba0596 100644 --- a/BPASmartClient.Device/BaseDevice.cs +++ b/BPASmartClient.Device/BaseDevice.cs @@ -532,7 +532,6 @@ namespace BPASmartClient.Device variableMonitors.ElementAt(index).CurrentValue = item.GetValue(status)?.ToString(); } } - } } } diff --git a/BPASmartClient.DosingSystemSingle/App.xaml b/BPASmartClient.DosingSystemSingle/App.xaml new file mode 100644 index 00000000..7fb508f6 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/App.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BPASmartClient.DosingSystemSingle/App.xaml.cs b/BPASmartClient.DosingSystemSingle/App.xaml.cs new file mode 100644 index 00000000..ff378cf2 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/App.xaml.cs @@ -0,0 +1,300 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using BPASmartClient.CustomResource.Pages.Enums; +using BPASmartClient.CustomResource.Pages.Model; +using BPASmartClient.CustomResource.Pages.View; +using BPASmartClient.CustomResource.Pages.ViewModel; +using BPASmartClient.DosingSystemSingle.View; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + public static Window MainWindow; + + public EventWaitHandle ProgramStarted { get; set; } + protected override void OnStartup(StartupEventArgs e) + { + bool createNew; + ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, "DosingSystemSingleApp", out createNew); + if (!createNew) + { + MessageBox.Show("程序已启动"); + App.Current.Shutdown(); + Environment.Exit(0); + } + base.OnStartup(e); + BPASmartClient.Helper.SystemHelper.GetInstance.CreateDesktopShortcut(); + MenuInit(); + DataInit(); + ThreadManage.GetInstance().Start(new Action(() => + { + DeviceInquire.GetInstance.Init();//配料机设备上线监听,设备列表初始化 + }), "设备初始化"); + MainView mv = new MainView(); + mv.TitleName = "味魔方管理系统软件[简称:味魔方] 1.0.1"; + LoginView lv = new LoginView(); + var res = lv.ShowDialog(); + if (res != null && res == true) + { + BPASmartClient.CustomResource.Pages.Model.MessageNotify.GetInstance.ShowUserLog("用户登录"); + mv.Show(); + } + else + mv.Close(); + MainWindow = mv; + } + + protected override void OnExit(ExitEventArgs e) + { + base.OnExit(e); + Json.Save(); + Json.Save(); + BPASmartClient.CustomResource.Pages.Model.MessageNotify.GetInstance.LogSave(); + ThreadManage.GetInstance().Dispose(); + } + + private void MenuInit() + { + #region 配方管理菜单 + ObservableCollection RecipeManage = new ObservableCollection(); + RecipeManage.Add(new SubMenumodel() + { + SubMenuName = "配方管理", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.RecipeSettingsView" + }); + + RecipeManage.Add(new SubMenumodel() + { + SubMenuName = "配方下发", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.RecipeControlView" + }); + + MenuManage.GetInstance.menuModels.Add(new MenuModel() + { + MainMenuIcon = "", + MainMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + MainMenuName = "配方管理", + Alias = "Recipe Management", + subMenumodels = RecipeManage, + }); + #endregion + + #region 参数设置 + ObservableCollection ParSet = new ObservableCollection(); + ParSet.Add(new SubMenumodel() + { + SubMenuName = "原料参数设置", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.DeviceMaterialParView" + }); + + ParSet.Add(new SubMenumodel() + { + SubMenuName = "设备参数设置", + SubMenuPermission = new Permission[] { Permission.管理员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.CommParSetView" + }); + + //ParSet.Add(new SubMenumodel() + //{ + // SubMenuName = "出料口管理设置", + // SubMenuPermission = new Permission[] { Permission.管理员 }, + // AssemblyName = "BPASmartClient.DosingSystemSingle", + // ToggleWindowPath = "View.OutletManagementView" + //}); + + MenuManage.GetInstance.menuModels.Add(new MenuModel() + { + MainMenuIcon = "", + MainMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + MainMenuName = "参数设置", + Alias = "Parameter Set", + subMenumodels = ParSet, + }); + #endregion + + #region 手动控制 + /*ObservableCollection ManualControl = new ObservableCollection(); + ManualControl.Add(new SubMenumodel() + { + SubMenuName = "气缸手动控制", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.ManualControlView" + }); + + ManualControl.Add(new SubMenumodel() + { + SubMenuName = "输送带手动控制", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.ConveyerBeltManualView" + }); + //ManualControl.Add(new SubMenumodel() + //{ + // SubMenuName = "料仓控制", + // SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.技术员 }, + // AssemblyName = "BPASmartClient.DosingSystemSingle", + // ToggleWindowPath = "View.StockControlView" + //}); + MenuManage.GetInstance.menuModels.Add(new MenuModel() + { + MainMenuIcon = "", + MainMenuName = "手动控制", + MainMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + Alias = "Parameter Set", + subMenumodels = ManualControl, + });*/ + #endregion + + #region 消息日志 + ObservableCollection InfoLog = new ObservableCollection(); + InfoLog.Add(new SubMenumodel() + { + SubMenuName = "操作日志", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.CustomResource", + ToggleWindowPath = "Pages.View.UserLogView" + }); + + InfoLog.Add(new SubMenumodel() + { + SubMenuName = "运行日志", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.CustomResource", + ToggleWindowPath = "Pages.View.RunLogView" + }); + + InfoLog.Add(new SubMenumodel() + { + SubMenuName = "报警记录", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.CustomResource", + ToggleWindowPath = "Pages.View.AlarmView" + }); + + InfoLog.Add(new SubMenumodel() + { + SubMenuName = "调试日志", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.CustomResource", + ToggleWindowPath = "Pages.View.DebugLogView" + }); + + //InfoLog.Add(new SubMenumodel() + //{ + // SubMenuName = "报表数据", + // SubMenuPermission = new Permission[] { Permission.操作员, Permission.管理员, Permission.技术员, Permission.技术员 }, + // AssemblyName = "BPASmartClient.CustomResource", + // ToggleWindowPath = "Pages.View.ReportView" + //}); + + MenuManage.GetInstance.menuModels.Add(new MenuModel() + { + MainMenuIcon = "", + MainMenuName = "消息日志", + MainMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + Alias = "Message Log", + subMenumodels = InfoLog, + }); + #endregion + + #region 硬件设备监控 + ObservableCollection DeviceMonitor = new ObservableCollection(); + DeviceMonitor.Add(new SubMenumodel() + { + SubMenuName = "原料设备列表", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.DeviceListView" + }); + + DeviceMonitor.Add(new SubMenumodel() + { + SubMenuName = "设备状态", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.DosingSystemSingle", + ToggleWindowPath = "View.HardwareStatusView" + }); + + MenuManage.GetInstance.menuModels.Add(new MenuModel() + { + MainMenuIcon = "", + MainMenuName = "设备监控", + MainMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + Alias = "Device Monitor", + subMenumodels = DeviceMonitor, + }); + #endregion + + #region 用户管理 + ObservableCollection UserManager = new ObservableCollection(); + UserManager.Add(new SubMenumodel() + { + SubMenuName = "用户登录", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.CustomResource", + ToggleWindowPath = "Pages.View.SubPagLoginView" + }); + + UserManager.Add(new SubMenumodel() + { + SubMenuName = "密码修改", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.CustomResource", + ToggleWindowPath = "Pages.View.PasswordChangeView" + }); + UserManager.Add(new SubMenumodel() + { + SubMenuName = "用户管理", + SubMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + AssemblyName = "BPASmartClient.CustomResource", + ToggleWindowPath = "Pages.View.UserManagerView" + }); + + //UserManager.Add(new SubMenumodel() + //{ + // SubMenuName = "NFC登录管理", + // SubMenuPermission = new Permission[] { Permission.管理员 }, + // AssemblyName = "BPASmartClient.CustomResource", + // ToggleWindowPath = "Pages.View.NfcSetView" + //}); + + MenuManage.GetInstance.menuModels.Add(new MenuModel() + { + MainMenuIcon = "", + MainMenuName = "用户管理", + MainMenuPermission = new Permission[] { Permission.管理员, Permission.操作员, Permission.观察员, Permission.技术员 }, + Alias = "User Management", + subMenumodels = UserManager, + }); + #endregion + } + + private void DataInit() + { + //Config.GetInstance.Init(); + Json.Read(); + Json.Read(); + Json.Read(); + } + } +} diff --git a/BPASmartClient.DosingSystemSingle/AssemblyInfo.cs b/BPASmartClient.DosingSystemSingle/AssemblyInfo.cs new file mode 100644 index 00000000..8b5504ec --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/BPASmartClient.DosingSystemSingle/BPASmartClient.DosingSystemSingle.csproj b/BPASmartClient.DosingSystemSingle/BPASmartClient.DosingSystemSingle.csproj new file mode 100644 index 00000000..86b5d8c8 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/BPASmartClient.DosingSystemSingle.csproj @@ -0,0 +1,86 @@ + + + + WinExe + net6.0-windows + enable + true + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + Code + + + + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + Designer + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + $(DefaultXamlRuntime) + + + + diff --git a/BPASmartClient.DosingSystemSingle/Converter/DataTableRedundantConverter.cs b/BPASmartClient.DosingSystemSingle/Converter/DataTableRedundantConverter.cs new file mode 100644 index 00000000..277e5bb8 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Converter/DataTableRedundantConverter.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using System.Windows.Media; + +namespace BPASmartClient.DosingSystemSingle.Converter +{ + public class DataTableRedundantConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value != null && value is bool bit) + { + if (bit) + return new SolidColorBrush(Color.FromArgb(255, 245, 63, 98)); + else + return new SolidColorBrush(Color.FromArgb(255, 42, 178, 231)); + } + return default; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/BPASmartClient.DosingSystemSingle/Converter/RunStatusConvert.cs b/BPASmartClient.DosingSystemSingle/Converter/RunStatusConvert.cs new file mode 100644 index 00000000..9858a799 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Converter/RunStatusConvert.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace BPASmartClient.DosingSystemSingle.Converter +{ + public class RunStatusConvert : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is ushort tempValue) + { + if (tempValue == 1) return "等待配料"; + if (tempValue == 2) return "配料中"; + if (tempValue == 3) return "配料完成"; + } + return "等待配料"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class EnbleConvert : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is ushort tempValue) + { + if (tempValue == 0) return true; + if (tempValue == 1) return false; + + } + return true; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class IntToSourceConvert : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is ushort tempValue) + { + if (tempValue == 0) return "本地原料"; + if (tempValue == 1) return "设备原料"; + + } + return "未知"; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + +} diff --git a/BPASmartClient.DosingSystemSingle/Model/AlarmInfo.cs b/BPASmartClient.DosingSystemSingle/Model/AlarmInfo.cs new file mode 100644 index 00000000..07469019 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/AlarmInfo.cs @@ -0,0 +1,48 @@ +using BPASmartClient.CustomResource.Pages.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle +{ + public class AlarmInfo + { + /// + /// 1#急停 + /// + [Alarm("1#急停")] + public bool EStop1 { get; set; } + + /// + /// 伺服故障 + /// + [Alarm("伺服故障")] + public bool Servo { get; set; } + + /// + /// 变频器故障 + /// + [Alarm("变频器故障")] + public bool Inverter { get; set; } + + /// + /// 2#急停 + /// + [Alarm("2#急停")] + public bool EStop2 { get; set; } + + /// + /// 料仓上限 + /// + [Alarm("料仓上限")] + public bool SiloUpperLimit { get; set; } + + /// + /// 料仓下限 + /// + [Alarm("料仓下限")] + public bool SiloLowerLimit { get; set; } + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/ConveyerBeltModel.cs b/BPASmartClient.DosingSystemSingle/Model/ConveyerBeltModel.cs new file mode 100644 index 00000000..e83c1e17 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/ConveyerBeltModel.cs @@ -0,0 +1,54 @@ +using BPA.Helper; +using BPASmartClient.CustomResource.Pages.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle +{ + public class ConveyerBeltModel : NotifyBase + { + public string Name { get { return _mName; } set { _mName = value; OnPropertyChanged(); } } + private string _mName; + + public int Num { get { return _mNum; } set { _mNum = value; OnPropertyChanged(); } } + private int _mNum; + + public int Speed + { + get { return _mSpeed; } + set + { + _mSpeed = value; + + SiemensDevice.GetInstance.MySiemens.Write($"DB4.DBW{Num * 2 + 132}", (short)value); + //SiemensDevice.GetInstance.MySiemens.WriteInt16(4, (short)value, (Num * 2 + 132)); + MessageNotify.GetInstance.ShowRunLog($"DB4.DBW{Num * 2 + 132},{value}"); + OnPropertyChanged(); + } + } + private int _mSpeed; + + public bool ConveyerBeltWork + { + get { return _mConveyerBeltWork; } + set + { + _mConveyerBeltWork = value; + if (Num >= 1 && Num <= 32) + { + var add = SiemensDevice.GetInstance.GetSiemensBitSingleAdd("DB5.DBX", Num, 6); + SiemensDevice.GetInstance.MySiemens.Write(add, value); + MessageNotify.GetInstance.ShowRunLog($"{add},{value}"); + } + OnPropertyChanged(); + } + } + private bool _mConveyerBeltWork; + + public bool Control { get; set; } + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/CylinderStatusModel.cs b/BPASmartClient.DosingSystemSingle/Model/CylinderStatusModel.cs new file mode 100644 index 00000000..da14ce46 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/CylinderStatusModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + public class CylinderStatusModel : NotifyBase + { + /// + /// 气缸原点信号 + /// + public bool HomeStatus { get { return _mHomeStatus; } set { _mHomeStatus = value; OnPropertyChanged(); } } + private bool _mHomeStatus; + + /// + /// 气缸到位信号 + /// + public bool InPlace { get { return _mInPlace; } set { _mInPlace = value; OnPropertyChanged(); } } + private bool _mInPlace; + + + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/DeviceAddress.cs b/BPASmartClient.DosingSystemSingle/Model/DeviceAddress.cs new file mode 100644 index 00000000..eaafef7b --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/DeviceAddress.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle +{ + public class DeviceAddress + { + /// + /// 设备名称起始地址 + /// + public static string DeviceName { get; set; } = "LW0"; + + /// + /// 料仓重量反馈起始地址 + /// + public static string WeightFeedback { get; set; } = "LW52"; + + /// + /// 重量设置地址 + /// + public static string WeightSet { get; set; } = "LW21"; + + /// + /// 启动信号地址 + /// + public static string Start { get; set; } = "LW20"; + + /// + /// 下料重量反馈地址 + /// + public static string CutWeightFeedback { get; set; } = "LW54"; + + /// + /// 设备编号 + /// + public static string DeviceNum { get; set; } = "LW57"; + + /// + /// 设备故障编码 + /// + public static string DeviceAlarmCode { get; set; } = "LW51"; + + /// + /// 原料设备类型 + /// 1:膏体,2:液体,3:粉体 + /// + public static string MaterialDeviceType { get; set; } = "LW56"; + + /// + /// 设备运行状态地址 + /// + public static string RunStatus { get; set; } = "LW60"; + + /// + /// 出料完成,置位该信号,plc复位运行状态 + /// + public static string FinfishStatus { get; set; } = "LW40"; + + /// + /// 慢加重量 + /// + public static string SlowlyAddWeight { get; set; } = "LW23"; + + /// + /// 提前关阀重量 + /// + public static string PreCloseValveWeight { get; set; } = "LW25"; + + /// + /// 快加速度 + /// + public static string RapidAcceleration { get; set; } = "LW27"; + + /// + /// 慢加速度 + /// + public static string SlowAcceleration { get; set; } = "LW29"; + + /// + /// 伺服手动速度 + /// + public static string ServoManualSpeed { get; set; } = "LW31"; + + /// + /// 料仓上限重量 + /// + public static string SiloUpperLimitWeight { get; set; } = "LW33"; + + /// + /// 料仓下限重量 + /// + public static string LowerLimitWeightOfSilo { get; set; } = "LW35"; + + /// + /// 搅拌速度 + /// + public static string StirringSpeed { get; set; } = "LW37"; + } + + + +} diff --git a/BPASmartClient.DosingSystemSingle/Model/DeviceCurrentStatus.cs b/BPASmartClient.DosingSystemSingle/Model/DeviceCurrentStatus.cs new file mode 100644 index 00000000..3680c5ae --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/DeviceCurrentStatus.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + public class DeviceCurrentStatus : NotifyBase + { + /// + /// 当前料仓重量反馈 + /// + public double Weight { get { return _mWeight; } set { _mWeight = value; OnPropertyChanged(); } } + private double _mWeight; + + /// + /// 重量设置 + /// + public float SetWeight { get { return _mSetWeight; } set { _mSetWeight = value; OnPropertyChanged(); } } + private float _mSetWeight; + + ///// + ///// 下料控制 + ///// + //public bool IsLayOff { get { return _mIsLayOff; } set { _mIsLayOff = value; OnPropertyChanged(); } } + //private bool _mIsLayOff; + + /// + /// 下料控制 + /// + public bool BaitingControl { get { return _mBaitingControl; } set { _mBaitingControl = value; OnPropertyChanged(); } } + private bool _mBaitingControl; + + + /// + /// 设备运行状态 + /// + public bool RunStatus { get { return _mRunStatus; } set { _mRunStatus = value; OnPropertyChanged(); } } + private bool _mRunStatus; + + /// + /// 设备编号 + /// + public int DeviceNum { get { return _mDeviceNum; } set { _mDeviceNum = value; OnPropertyChanged(); } } + private int _mDeviceNum; + + /// + /// 设备名称 + /// + public string DeviceName { get { return _mDeviceName; } set { _mDeviceName = value; OnPropertyChanged(); } } + private string _mDeviceName; + + /// + /// 仓盖是否被打开 + /// + public bool IsOpen { get { return _mIsOpen; } set { _mIsOpen = value; OnPropertyChanged(); } } + private bool _mIsOpen; + + /// + /// 料仓时候有报警 + /// + public bool IsFault { get { return _mIsFault; } set { _mIsFault = value; OnPropertyChanged(); } } + private bool _mIsFault; + + /// + /// 桶到位检测 + /// + public bool BucketFlagbit { get { return _mBucketFlagbit; } set { _mBucketFlagbit = value; OnPropertyChanged(); } } + private bool _mBucketFlagbit; + + + + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/DeviceInquire.cs b/BPASmartClient.DosingSystemSingle/Model/DeviceInquire.cs new file mode 100644 index 00000000..7a052229 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/DeviceInquire.cs @@ -0,0 +1,403 @@ +using BPASmartClient.CustomResource.Pages.Model; +using BPASmartClient.DosingSystemSingle.ViewModel; +using BPASmartClient.Modbus; +using BPASmartClient.Model; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net.NetworkInformation; +using System.Threading; +using System.Threading.Tasks; +using BPA.Helper; +using System.Text.RegularExpressions; + +namespace BPASmartClient.DosingSystemSingle +{ + public class DeviceInquire + { + private volatile static DeviceInquire _Instance; + public static DeviceInquire GetInstance => _Instance ?? (_Instance = new DeviceInquire()); + private DeviceInquire() { } + + string IPSegment = "192.168.0."; + ConcurrentDictionary DeviceLists = new ConcurrentDictionary(); + List InvalidIP = new List();//无效 IP 集合 + List IPLists = new List();//启动 Ping 任务IP集合 + ConcurrentQueue IPQueues = new ConcurrentQueue();//pincomplete 完成队列 + + public ObservableCollection TopDeviceCurrentStatuses { get; set; } = new ObservableCollection(); + public ObservableCollection BottomDeviceCurrentStatuses { get; set; } = new ObservableCollection(); + public ObservableCollection devices { get; set; } = new ObservableCollection(); + private void DeviceDataInit() + { + ThreadManage.GetInstance().StartLong(new Action(() => + { + for (int i = 0; i < DeviceLists.Count; i++) + { + string deviceName = DeviceLists.ElementAt(i).Value.DeviceName; + int TopIndex = Array.FindIndex(TopDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName); + int BottomIndex = Array.FindIndex(BottomDeviceCurrentStatuses.ToArray(), p => p.DeviceName == deviceName); + if (TopIndex >= 0 && TopIndex < TopDeviceCurrentStatuses.Count) + { + TopDeviceCurrentStatuses.ElementAt(TopIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback; + TopDeviceCurrentStatuses.ElementAt(TopIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum; + } + + if (BottomIndex >= 0 && BottomIndex < BottomDeviceCurrentStatuses.Count) + { + BottomDeviceCurrentStatuses.ElementAt(BottomIndex).Weight = DeviceLists.ElementAt(i).Value.deviceStatus.WeightFeedback; + BottomDeviceCurrentStatuses.ElementAt(BottomIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum; + } + + int deviceIndex = Array.FindIndex(devices.ToArray(), p => p.IpAddress == DeviceLists.ElementAt(i).Key/* && p.DeviceName != DeviceLists.ElementAt(i).Value.DeviceName && p.DeviceNum != DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum*/); + if (deviceIndex >= 0 && deviceIndex < devices.Count) + { + devices.ElementAt(deviceIndex).DeviceName = DeviceLists.ElementAt(i).Value.DeviceName; + devices.ElementAt(deviceIndex).DeviceNum = DeviceLists.ElementAt(i).Value.deviceStatus.DeviceNum; + } + } + Thread.Sleep(200); + }), "设备状态监听"); + } + + private void TestData() + { + for (int i = 0; i < 8; i++) + { + DeviceLists.TryAdd($"192.168.1.{i + 1}", new DeviceStatus() { DeviceName = $"测试设备{i + 1}" }); + TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() + { + DeviceName = $"测试设备{i + 1}", + DeviceNum = i + 1, + Weight = new Random().Next(100, 10000) / 100.0 + }); + Global.DeviceRawMaterials.Add(new RawMaterialModel() + { + DeviceIp = $"192.168.1.{i + 1}", + RawMaterialName = $"测试设备{i + 1}", + }); + devices.Add(new Devices() + { + DeviceName = $"测试设备{i + 1}", + DeviceNum = i + 1, + IpAddress = $"192.168.1.{i + 1}", + }); + } + + for (int i = 8; i < 16; i++) + { + DeviceLists.TryAdd($"192.168.1.{i + 1}", new DeviceStatus() { DeviceName = $"测试设备{i + 1}" }); + BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus() + { + DeviceName = $"测试设备{i + 1}", + DeviceNum = i + 1, + Weight = new Random().Next(100, 10000) / 100.0 + }); + Global.DeviceRawMaterials.Add(new RawMaterialModel() + { + DeviceIp = $"192.168.1.{i + 1}", + RawMaterialName = $"测试设备{i + 1}", + }); + devices.Add(new Devices() + { + DeviceName = $"测试设备{i + 1}", + DeviceNum = i + 1, + IpAddress = $"192.168.1.{i + 1}", + }); + } + } + + public void Init() + { + if (!string.IsNullOrEmpty(Json.Data.BaseParModel.NetworkSegAddress)) IPSegment = Json.Data.BaseParModel.NetworkSegAddress; + else Json.Data.BaseParModel.NetworkSegAddress = IPSegment; + //TestData(); + IpAddressLines(); + //SiemensDevice.GetInstance.Connect(Json.Data.BaseParModel.DeviceAddress); + DeviceDataInit(); + ThreadManage.GetInstance().StartLong(new Action(() => + { + if (IPQueues.Count >= IPLists.Count) + IpAddressLines(); + Thread.Sleep(5000); + }), "配料机设备上线监听", true); + } + + public void Rescan() + { + InvalidIP.Clear(); + } + + public DeviceStatus GetDevice(string ip) + { + if (ip != null) + { + if (DeviceLists.ContainsKey(ip)) return DeviceLists[ip]; + else return new DeviceStatus(); + //var res = DeviceLists.Values.FirstOrDefault(p => p.IpAddress == ip); + //if (res != null) return res; + } + return new DeviceStatus(); + } + + public List GetDevice() + { + List deviceStatuses = new List(); + foreach (var device in DeviceLists) + { + deviceStatuses.Add(device.Value); + } + return deviceStatuses; + } + + private void IpAddressLines() + { + IPLists.Clear(); + IPQueues.Clear(); + /*for (int i = 1; i <= 255; i++) + { + if (!InvalidIP.Contains($"{IPSegment}{i}") && !DeviceLists.ContainsKey($"{IPSegment}{i}")) + { + string pattern = @"^(([1-9]\d?)|(1\d{2})|(2[01]\d)|(22[0-3]))(\.((1?\d\d?)|(2[04]/d)|(25[0-5]))){3}$"; + if (Regex.IsMatch($"{IPSegment}{i}", pattern)) + { + IPLists.Add($"{IPSegment}{i}"); + } + } + }*/ + IPLists.Add($"{IPSegment}10"); + IPLists.Add($"{IPSegment}20"); + IPLists.Add($"{IPSegment}30"); + + IPLists.ForEach((item) => + { + Ping myPing = new Ping(); + myPing.PingCompleted += new PingCompletedEventHandler(_myPing_PingCompleted); + myPing.SendAsync(item, 1000, null); + }); + } + + private void _myPing_PingCompleted(object sender, PingCompletedEventArgs e) + { + if (e.Reply.Status == IPStatus.Success) + { + string ip = e.Reply.Address.ToString(); + if (!DeviceLists.ContainsKey(ip)) + { + DeviceStatus DS = new DeviceStatus(); + DS.modbusTcp.IsReconnect = false; + + DS.modbusTcp.ConnectOk = new Action(() => + { + string DeviceName = DS.modbusTcp.GetString(DeviceAddress.DeviceName, 20).Trim()?.Replace(" ", "");//读取设备名称 + if (DeviceName.Length > 0) + { + DeviceLists.TryAdd(ip, DS); + DeviceLists[ip].Init(DeviceName); + DeviceLists[ip].modbusTcp.IsReconnect = false; + App.Current.Dispatcher.Invoke(new Action(() => + { + devices.Add(new Devices() { DeviceName = DeviceName, IpAddress = ip }); + + if (TopDeviceCurrentStatuses.Count <= 7) + TopDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName }); + else + BottomDeviceCurrentStatuses.Add(new DeviceCurrentStatus() { DeviceName = DeviceName }); + for (int i = 0; i < Json.Data.Recipes.Count; i++) + { + for (int m = 0; m < Json.Data.Recipes.ElementAt(i).RawMaterials.Count; m++) + { + if (Json.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).DeviceIp == ip) + { + Json.Data.Recipes.ElementAt(i).RawMaterials.ElementAt(m).RawMaterialName = DeviceName; + } + } + } + if (Global.DeviceRawMaterials.Count > 0) + { + if (Global.DeviceRawMaterials.FirstOrDefault(p => p.RawMaterialName == DeviceName) == null) + { + Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 }); + } + } + else + { + Global.DeviceRawMaterials.Add(new RawMaterialModel() { RawMaterialName = DeviceName, DeviceIp = ip, RawMaterialSource = 1 }); + } + + })); + } + else + { + if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); + } + }); + + DS.modbusTcp.ConnectFail = new Action(() => + { + if (!InvalidIP.Contains(ip)) InvalidIP.Add(ip); + }); + + DS.modbusTcp.Disconnect = new Action(() => + { + if (InvalidIP.Contains(ip)) InvalidIP.Remove(ip); + var res = devices.FirstOrDefault(P => P.IpAddress == ip); + if (res != null && devices.Contains(res)) + { + App.Current.Dispatcher.Invoke(new Action(() => + { + devices.Remove(res); + var item = Global.DeviceRawMaterials.FirstOrDefault(P => P.RawMaterialName == res.DeviceName); + if (item != null) Global.DeviceRawMaterials.Remove(item); + + var topRes = TopDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName); + var bottomRes = BottomDeviceCurrentStatuses.FirstOrDefault(p => p.DeviceName == res.DeviceName); + if (topRes != null) TopDeviceCurrentStatuses.Remove(topRes); + if (bottomRes != null) BottomDeviceCurrentStatuses.Remove(bottomRes); + })); + } + if (DeviceLists.ContainsKey(ip)) + { + DeviceLists[ip].Dispose(); + var res11 = DeviceLists[ip]; + DeviceLists.TryRemove(ip, out res11); + } + }); + + Task.Run(new Action(() => + { + DS.modbusTcp.ModbusTcpConnect(ip, 502);//PLC连接 + IPQueues.Enqueue(e.Reply.Address.ToString()); + })); + } + else IPQueues.Enqueue(e.Reply.Address.ToString()); + } + else IPQueues.Enqueue(e.Reply.Address.ToString()); + } + } + + public class DeviceStatus + { + + #region 对象属性声明 + public string DeviceName = String.Empty; + public string IpAddress => modbusTcp.IPAdress; + + /// + /// 设备状态 + /// + public RawMaterialDeviceStatus deviceStatus { get; set; } = new RawMaterialDeviceStatus(); + + public ModbusTcp modbusTcp = new ModbusTcp(); + + public bool IsConnected => modbusTcp.Connected; + #endregion + + public void Init(string DeviceName) + { + modbusTcp.Show = new Action((s) => { MessageNotify.GetInstance.ShowRunLog(s); }); + modbusTcp.ShowEx = new Action((s) => { MessageNotify.GetInstance.ShowRunLog(s); }); + this.DeviceName = DeviceName; + AlarmHelper.Init(); + if (modbusTcp.Connected) + { + ThreadManage.GetInstance().StartLong(new Action(() => + { + this.DeviceName = modbusTcp.GetString(DeviceAddress.DeviceName, 20)?.Trim()?.Replace(" ", ""); + deviceStatus.RunStatus = (ushort)this.modbusTcp.ReadShort(DeviceAddress.RunStatus); //获取设备运行状态 + deviceStatus.WeightFeedback = this.modbusTcp.ReadShort(DeviceAddress.WeightFeedback);//获取设备料仓剩余重量 + deviceStatus.NowWeightFeedback = this.modbusTcp.GetReal(DeviceAddress.CutWeightFeedback);//获取下料重量 + deviceStatus.DeviceNum = (ushort)this.modbusTcp.ReadShort(DeviceAddress.DeviceNum);//获取设备编号 + deviceStatus.DeviceAlarmCode = (ushort)this.modbusTcp.ReadShort(DeviceAddress.DeviceAlarmCode);//获取设备故障编码 + + AlarmHelper.GetInstance(DeviceName).EStop1 = deviceStatus.DeviceAlarmCode.GetBitValue(1); + AlarmHelper.GetInstance(DeviceName).Servo = deviceStatus.DeviceAlarmCode.GetBitValue(2); + AlarmHelper.GetInstance(DeviceName).Inverter = deviceStatus.DeviceAlarmCode.GetBitValue(3); + AlarmHelper.GetInstance(DeviceName).EStop2 = deviceStatus.DeviceAlarmCode.GetBitValue(7); + AlarmHelper.GetInstance(DeviceName).SiloUpperLimit = deviceStatus.DeviceAlarmCode.GetBitValue(8); + AlarmHelper.GetInstance(DeviceName).SiloLowerLimit = deviceStatus.DeviceAlarmCode.GetBitValue(9); + + if (DeviceName=="A20") { + //MessageNotify.GetInstance.ShowRunLog($"{this.modbusTcp.GetReal(DeviceAddress.WeightSet)}"); + } + Thread.Sleep(10); + }), $"{DeviceName} 开始监听", true); + } + } + + public void SetDeviceName(string name) + { + this.modbusTcp.Write(DeviceAddress.DeviceName, new ushort[20]); + this.modbusTcp.SetString(DeviceAddress.DeviceName, name); + } + + public void StatusReset() + { + this.modbusTcp.Write(DeviceAddress.FinfishStatus, (ushort)1); + //var res = modbusTcp.Read(DeviceAddress.RunStatus); + } + + public void Dispose() + { + ThreadManage.GetInstance().StopTask($"{DeviceName} 开始监听"); + } + + public void Start(float Value) + { + if (modbusTcp.Connected) + { + var res = Json.Data.deviceParModels.FirstOrDefault(p => p.MaterialName == DeviceName); + if (res != null) + { + prop1: + modbusTcp.SetReal(DeviceAddress.SlowlyAddWeight, res.SlowlyAddWeight); + var Value1 = (float)this.modbusTcp.GetReal(DeviceAddress.SlowlyAddWeight); + if (Value1 != null && Value1.ToString() != res.SlowlyAddWeight.ToString()) goto prop1; + prop2: + modbusTcp.SetReal(DeviceAddress.PreCloseValveWeight, res.PreCloseValveWeight); + var Value2 = (float)this.modbusTcp.GetReal(DeviceAddress.PreCloseValveWeight); + if (Value2 != null && Value2.ToString() != res.PreCloseValveWeight.ToString()) goto prop2; + prop3: + modbusTcp.SetUint(DeviceAddress.RapidAcceleration, (uint)res.RapidAcceleration); + var Value3 = this.modbusTcp.GetUint(DeviceAddress.RapidAcceleration); + if (Value3 != null && Value3.ToString() != res.RapidAcceleration.ToString()) goto prop3; + prop4: + modbusTcp.SetUint(DeviceAddress.SlowAcceleration, (uint)res.SlowAcceleration); + var Value4 = this.modbusTcp.GetUint(DeviceAddress.SlowAcceleration); + if (Value4 != null && Value4.ToString() != res.SlowAcceleration.ToString()) goto prop4; + prop5: + modbusTcp.SetUint(DeviceAddress.ServoManualSpeed, (uint)res.ServoManualSpeed); + var Value5 = this.modbusTcp.GetUint(DeviceAddress.ServoManualSpeed); + if (Value5 != null && Value5.ToString() != res.ServoManualSpeed.ToString()) goto prop5; + prop6: + modbusTcp.SetUint(DeviceAddress.SiloUpperLimitWeight, (uint)res.SiloUpperLimitWeight); + var Value6 = this.modbusTcp.GetUint(DeviceAddress.SiloUpperLimitWeight); + if (Value6 != null && Value6.ToString() != res.SiloUpperLimitWeight.ToString()) goto prop6; + prop7: + modbusTcp.SetUint(DeviceAddress.LowerLimitWeightOfSilo, (uint)res.LowerLimitWeightOfSilo); + var Value7 = this.modbusTcp.GetUint(DeviceAddress.LowerLimitWeightOfSilo); + if (Value7 != null && Value7.ToString() != res.LowerLimitWeightOfSilo.ToString()) goto prop7; + prop8: + modbusTcp.SetUint(DeviceAddress.StirringSpeed, (uint)res.StirringSpeed); + var Value8 = this.modbusTcp.GetUint(DeviceAddress.StirringSpeed); + if (Value8 != null && Value8.ToString() != res.StirringSpeed.ToString()) goto prop8; + MessageNotify.GetInstance.ShowRunLog($"{res.MaterialName},参数下发完成"); + } + prop9: + modbusTcp.SetReal(DeviceAddress.WeightSet, Value);//写入配方量 + var Value9 = this.modbusTcp.GetReal(DeviceAddress.WeightSet); + if (Value9 != null && Value9.ToString() != Value.ToString()) goto prop9; + /* + prop10: + modbusTcp.Write(DeviceAddress.Start, (ushort)1);//设备启动写入 + var Value10 = (short[])this.modbusTcp.Read(DeviceAddress.Start); + if (Value10 != null && Value10[0] != 1) goto prop10;*/ + //modbusTcp.Write(DeviceAddress.Start, (ushort)1);//设备启动写入 + MessageNotify.GetInstance.ShowRunLog($"{DeviceName},设置重量:{Value},味魔方启动"); + Thread.Sleep(100); + } + } + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/GlobalDevice.cs b/BPASmartClient.DosingSystemSingle/Model/GlobalDevice.cs new file mode 100644 index 00000000..d257bb48 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/GlobalDevice.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle +{ + public class GlobalDevice + { + /// + /// PLC 设备数据 + /// + public static PlcToComputer PlcData { get; set; } = new PlcToComputer(); + + /// + /// 电机速度 + /// + public static ushort[] MotorSpeed { get; set; } = new ushort[32]; + + /// + /// 输送带控制 + /// + public static uint MotorControl { get; set; } + + /// + /// 输送带控制反馈 + /// + public static uint MotorControlFeedback { get; set; } + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/OutletInfoModel.cs b/BPASmartClient.DosingSystemSingle/Model/OutletInfoModel.cs new file mode 100644 index 00000000..26bd5ec3 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/OutletInfoModel.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BPA.Helper; +using System.Collections.ObjectModel; + +namespace BPASmartClient.DosingSystemSingle +{ + /// + /// 出料口信息 + /// + public class OutletInfoModel : NotifyBase + { + /// + /// 出料口名称 + /// + public string OutletName { get { return _mOutletName; } set { _mOutletName = value; OnPropertyChanged(); } } + private string _mOutletName; + + /// + /// 出料口位置 + /// + public int OutletLoc { get { return _mOutletLoc; } set { _mOutletLoc = value; OnPropertyChanged(); } } + private int _mOutletLoc; + + /// + /// 出料口对应的料仓信息 + /// + public ObservableCollection SiloInfos { get; set; } = new ObservableCollection(); + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/RawMaterialDeviceStatus.cs b/BPASmartClient.DosingSystemSingle/Model/RawMaterialDeviceStatus.cs new file mode 100644 index 00000000..242db770 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/RawMaterialDeviceStatus.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle +{ + public class RawMaterialDeviceStatus + { + + /// + /// 原料类型 + /// 1:膏体 + /// 2:液体 + /// 3:粉体 + /// + public ushort RawMaterialType { get; set; } + + /// + /// 料仓重量反馈 + /// + public float WeightFeedback { get; set; } + + /// + /// 当前出料重量反馈 + /// + public float NowWeightFeedback { get; set; } + + /// + /// 上限反馈 + /// + public bool UpLimitFeedback { get; set; } + + /// + /// 下限反馈 + /// + public bool DownLimitFeedback { get; set; } + + /// + /// 下料重量反馈 + /// + public float CutWeightFeedback { get; set; } + + /// + /// 设备运行状态 + /// 0:未知 + /// 1:等待配料 + /// 2:配料中 + /// 3:配料完成 + /// + public ushort RunStatus { get; set; } + + /// + /// 设备故障编码 + /// + public ushort DeviceAlarmCode { get; set; } + + /// + /// 设备料仓编号 + /// + public ushort DeviceNum { get; set; } + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/RecipeModel.cs b/BPASmartClient.DosingSystemSingle/Model/RecipeModel.cs new file mode 100644 index 00000000..c5689cfb --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/RecipeModel.cs @@ -0,0 +1,54 @@ +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.Model; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + /// + /// 配方模块 + /// + public class RecipeModel : NotifyBase + { + [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); + + [Newtonsoft.Json.JsonIgnore] + public string RecipStatus { get { return _mRecipStatus; } set { _mRecipStatus = value; OnPropertyChanged(); } } + private string _mRecipStatus; + + + /// + /// 原料集合 + /// + public ObservableCollection RawMaterials { get; set; } = new ObservableCollection(); + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/RecipeProcess.cs b/BPASmartClient.DosingSystemSingle/Model/RecipeProcess.cs new file mode 100644 index 00000000..3fbee8d9 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/RecipeProcess.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + public class RecipeProcess : NotifyBase + { + public string RawMaterialName { get { return _mRawMaterialName; } set { _mRawMaterialName = value; OnPropertyChanged(); } } + private string _mRawMaterialName; + + + public int RawMaterialStatus { get { return _mRawMaterialStatus; } set { _mRawMaterialStatus = value; OnPropertyChanged(); } } + private int _mRawMaterialStatus; + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/SiemensPlc/ComputerToPlc.cs b/BPASmartClient.DosingSystemSingle/Model/SiemensPlc/ComputerToPlc.cs new file mode 100644 index 00000000..5f817652 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/SiemensPlc/ComputerToPlc.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle.Model +{ + + public class ComputerToPlc + { + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/SiemensPlc/PlcToComputer.cs b/BPASmartClient.DosingSystemSingle/Model/SiemensPlc/PlcToComputer.cs new file mode 100644 index 00000000..5bb74b62 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/SiemensPlc/PlcToComputer.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle +{ + /// + /// PLC 到上位机数据 + /// + public class PlcToComputer + { + public PlcToComputer() + { + for (int i = 0; i < cylinderFlagBitStatus.Length; i++) + { + cylinderFlagBitStatus[i] = new CylinderFlagBitStatus(); + } + } + + /// + /// 心跳 + /// + public bool Heartbeat { get; set; } + + /// + /// 接收配方完成 + /// + public bool ResComplete { get; set; } + + /// + /// 系统启动或停止状态 + /// + public bool SystemStartOrStop { get; set; } + + /// + /// 手自动状态 + /// + public bool HandOrAuto { get; set; } + + /// + /// 桶位置反馈 + /// + public short[] LocationFeedback { get; set; } = new short[32]; + + /// + /// 桶是否允许配料 + /// + public bool[] IsAllowIngredients { get; set; } = new bool[32]; + + /// + /// 报警信息 + /// + public bool[] ArrayInfo { get; set; } = new bool[32]; + + /// + /// 本地急停 + /// + public bool LocalEStop { get; set; } + + /// + /// 远程急停 + /// + public bool RemoteEStop { get; set; } + + /// + /// 上桶工位检测 + /// + public bool OnDetection { get; set; } + + /// + /// 下桶工位检测 + /// + public bool UnderDetection { get; set; } + + /// + /// 上桶工位气缸检测 + /// + public CylinderFlagBitStatus OnCylinderDetection { get; set; } = new CylinderFlagBitStatus(); + + /// + /// 下桶工位气缸检测 + /// + public CylinderFlagBitStatus UnderCylinderDetection { get; set; } = new CylinderFlagBitStatus(); + + /// + /// 工位光电检测 + /// + public bool[] StationDetection { get; set; } = new bool[32]; + + /// + /// 气缸状态信号 + /// + public CylinderFlagBitStatus[] cylinderFlagBitStatus { get; set; } = new CylinderFlagBitStatus[32]; + } + + /// + /// 气缸到位检测类 + /// + public class CylinderFlagBitStatus + { + /// + /// 气缸原点信号 + /// + public bool HomeSignal { get; set; } + + /// + /// 气缸到位信号 + /// + public bool InPlaceSignal { get; set; } + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/StockStatusModel.cs b/BPASmartClient.DosingSystemSingle/Model/StockStatusModel.cs new file mode 100644 index 00000000..88430838 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/StockStatusModel.cs @@ -0,0 +1,61 @@ +using BPA.Helper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BPASmartClient.DosingSystemSingle +{ + public class StockStatusModel : NotifyBase + { + /// + /// 料仓物料重量 + /// + public double MaterialWeight { get { return _materialWeight; } set { _materialWeight = value; OnPropertyChanged(); } } + private double _materialWeight; + + /// + /// 料仓物料名称 + /// + public string MaterialName { get { return _materialName; } set { _materialName = value; OnPropertyChanged(); } } + private string _materialName; + + /// + /// 是否真在运行 + /// + public bool IsRunning { get { return _isRunning; } set { _isRunning = value; OnPropertyChanged(); } } + private bool _isRunning; + + /// + /// 是否正在下料 + /// + public bool IsLayOff { get { return _isLayOff; } set { _isLayOff = value; OnPropertyChanged(); } } + private bool _isLayOff; + + /// + /// 是否开盖 + /// + public bool IsOpen { get { return _mIsOpen; } set { _mIsOpen = value; OnPropertyChanged(); } } + private bool _mIsOpen; + + /// + /// 是否故障报警 + /// + public bool IsFault { get { return _isFault; } set { _isFault = value; OnPropertyChanged(); } } + private bool _isFault; + + /// + /// 下料状态 0:未出料 1:出料指令下发 2:出料完成 + /// + public int IssueStatus { get { return _isIssueStatus; } set { _isIssueStatus = value; OnPropertyChanged(); } } + private int _isIssueStatus; + + /// + /// 下料重量 + /// + public double IssueWeight { get { return _IssueWeight; } set { _IssueWeight = value; OnPropertyChanged(); } } + private double _IssueWeight; + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/ViewModelBase.cs b/BPASmartClient.DosingSystemSingle/Model/ViewModelBase.cs new file mode 100644 index 00000000..797a183a --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/ViewModelBase.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BPA.Helper; + +using System.Collections.ObjectModel; + +namespace BPASmartClient.DosingSystemSingle +{ + public class ViewModelBase : NotifyBase + { + public int Index { get; set; } = -1; + public BPARelayCommand AddCommand { get; set; }//添加 + public BPARelayCommand CancelCommand { get; set; }//取消 + public BPARelayCommand SaveCommand { get; set; }//保存 + public BPARelayCommand RemoveCommand { get; set; }//移除 + public BPARelayCommand DetailsCommand { get; set; }//编辑 + + /// + /// 错误信息 + /// + public string ErrorInfo { get { return _mErrorInfo; } set { _mErrorInfo = value; OnPropertyChanged(); } } + private string _mErrorInfo = string.Empty; + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/par/BasePar.cs b/BPASmartClient.DosingSystemSingle/Model/par/BasePar.cs new file mode 100644 index 00000000..0b9ede1d --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/par/BasePar.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + /// + /// 基础参数 + /// + public class BasePar : NotifyBase + { + /// + /// 设备扫描网段 + /// + public string NetworkSegAddress { get { return _mNetworkSegAddress; } set { _mNetworkSegAddress = value; OnPropertyChanged(); } } + private string _mNetworkSegAddress = "192.168.0."; + + /// + /// 输送带设备 PLC IP 地址 + /// + public string DeviceAddress { get { return _mDeviceAddress; } set { _mDeviceAddress = value; OnPropertyChanged(); } } + private string _mDeviceAddress = "192.168.0.15"; + + /// + /// 输送带数量 + /// + public int ConveyerBeltCount + { + get { return _mConveyerBeltCount; } + set + { + _mConveyerBeltCount = value; + //var temp = ConveyerBeltModels; + //App.Current.Dispatcher.Invoke(() => { ConveyerBeltModels.Clear(); }); + //for (int i = 0; i < value; i++) + //{ + // App.Current.Dispatcher.Invoke(() => + // { + // ConveyerBeltModels.Add(new ConveyerBeltModel() + // { + // Name = $"输送带{i + 1}速度", + // Num = i + 1, + // Speed = (i >= 0 && i < temp.Count) ? temp.ElementAt(i).Speed : 0 + // }); + // }); + //} + OnPropertyChanged(); + } + } + private int _mConveyerBeltCount = 0; + + /// + /// 升降气缸数量 + /// + public int LiftCylinderCount { get { return _mLiftCylinderCount; } set { _mLiftCylinderCount = value; OnPropertyChanged(); } } + private int _mLiftCylinderCount = 0; + + /// + /// 阻挡气缸数量 + /// + public int BlockCylinderCount { get { return _mBlockCylinderCount; } set { _mBlockCylinderCount = value; OnPropertyChanged(); } } + private int _mBlockCylinderCount = 0; + + /// + /// 托盘气缸数量 + /// + public int PalletCylinderCount { get { return _mPalletCylinderCount; } set { _mPalletCylinderCount = value; OnPropertyChanged(); } } + private int _mPalletCylinderCount = 0; + + //public ObservableCollection ConveyerBeltModels { get; set; } = new ObservableCollection(); + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/par/DevicePar.cs b/BPASmartClient.DosingSystemSingle/Model/par/DevicePar.cs new file mode 100644 index 00000000..51e00327 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/par/DevicePar.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections.ObjectModel; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + public class DevicePar : NotifyBase + { + /// + /// 配料设备参数 + /// + public ObservableCollection deviceParModels { get; set; } = new ObservableCollection(); + + public ObservableCollection OutletInfoModels { get; set; } = new ObservableCollection(); + + public BasePar BaseParModel { get { return _mBaseParModel; } set { _mBaseParModel = value; OnPropertyChanged(); } } + private BasePar _mBaseParModel = new BasePar(); + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/par/DeviceParModel.cs b/BPASmartClient.DosingSystemSingle/Model/par/DeviceParModel.cs new file mode 100644 index 00000000..fdfb1faf --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/par/DeviceParModel.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BPA.Helper; + +namespace BPASmartClient.DosingSystemSingle +{ + public class DeviceParModel : NotifyBase + { + /// + /// 原料名称 + /// + public string MaterialName { get { return _mMaterialName; } set { _mMaterialName = value; OnPropertyChanged(); } } + private string _mMaterialName = string.Empty; + + /// + /// 慢加重量 + /// + public float SlowlyAddWeight { get { return _mSlowlyAddWeight; } set { _mSlowlyAddWeight = value; OnPropertyChanged(); } } + private float _mSlowlyAddWeight; + + /// + /// 提前关阀重量 + /// + public float PreCloseValveWeight { get { return _mPreCloseValveWeight; } set { _mPreCloseValveWeight = value; OnPropertyChanged(); } } + private float _mPreCloseValveWeight; + + /// + /// 快加速度 + /// + public int RapidAcceleration { get { return _mRapidAcceleration; } set { _mRapidAcceleration = value; OnPropertyChanged(); } } + private int _mRapidAcceleration; + + /// + /// 慢加速度 + /// + public int SlowAcceleration { get { return _mSlowAcceleration; } set { _mSlowAcceleration = value; OnPropertyChanged(); } } + private int _mSlowAcceleration; + + /// + /// 伺服手动速度 + /// + public int ServoManualSpeed { get { return _mServoManualSpeed; } set { _mServoManualSpeed = value; OnPropertyChanged(); } } + private int _mServoManualSpeed; + + /// + /// 料仓上限重量 + /// + public int SiloUpperLimitWeight { get { return _mSiloUpperLimitWeight; } set { _mSiloUpperLimitWeight = value; OnPropertyChanged(); } } + private int _mSiloUpperLimitWeight; + + /// + /// 料仓下限重量 + /// + public int LowerLimitWeightOfSilo { get { return _mLowerLimitWeightOfSilo; } set { _mLowerLimitWeightOfSilo = value; OnPropertyChanged(); } } + private int _mLowerLimitWeightOfSilo; + + /// + /// 搅拌速度 + /// + public int StirringSpeed { get { return _mStirringSpeed; } set { _mStirringSpeed = value; OnPropertyChanged(); } } + private int _mStirringSpeed; + + /// + /// 是否重复 + /// + [Newtonsoft.Json.JsonIgnore] + public bool IsRedundant { get { return _mIsRedundant; } set { _mIsRedundant = value; OnPropertyChanged(); } } + private bool _mIsRedundant; + + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Model/par/LocaPar.cs b/BPASmartClient.DosingSystemSingle/Model/par/LocaPar.cs new file mode 100644 index 00000000..64323d62 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Model/par/LocaPar.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Collections.ObjectModel; +using BPASmartClient.DosingSystemSingle.ViewModel; +using BPASmartClient.Model; + +namespace BPASmartClient.DosingSystemSingle +{ + public class LocaPar + { + public ObservableCollection Recipes { get; set; } = new ObservableCollection(); + + + } +} diff --git a/BPASmartClient.DosingSystemSingle/Service/SiemensDevice.cs b/BPASmartClient.DosingSystemSingle/Service/SiemensDevice.cs new file mode 100644 index 00000000..a4c2c4a9 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/Service/SiemensDevice.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using BPASmartClient.S7Net; +using BPA.Helper; +using S7.Net; + +namespace BPASmartClient.DosingSystemSingle +{ + public class SiemensDevice + { + private volatile static SiemensDevice _Instance; + public static SiemensDevice GetInstance => _Instance ?? (_Instance = new SiemensDevice()); + private SiemensDevice() { } + + public SiemensHelper MySiemens { get; set; } = new SiemensHelper(); + + private bool IsConnect { get; set; } + bool tempValue = false; + public void Connect(string ip) + { + try + { + while (!MySiemens.IsConnected) + { + MySiemens.Connect(S7.Net.CpuType.S71200, ip); + Thread.Sleep(2000); + } + } + catch (Exception ex) + { + + } + IsConnect = MySiemens.IsConnected; + ThreadManage.GetInstance().StartLong(new Action(() => + { + if (IsConnect) MySiemens.Write("DB4.DBX0.0", tempValue);//设备心跳 + tempValue = !tempValue; + Thread.Sleep(100); + }), "设备心跳", true); + + ThreadManage.GetInstance().StartLong(new Action(() => + { + if (IsConnect) + { + GlobalDevice.PlcData = MySiemens.ReadClass(3);//获取PLC到上位机的数据 + var res = MySiemens.Read(DataType.DataBlock, 4, 134, VarType.Word, 32); + if (res != null && res is ushort[] ushorts && ushorts.Length == 32) + { + GlobalDevice.MotorSpeed = ushorts; + } + GlobalDevice.MotorControl = MySiemens.Read("DB5.DBD6");//获取输送带控制信号 + //GlobalDevice.MotorControlFeedback = MySiemens.Read("DB3.DBD0");//获取当前输送带运行状态 + GlobalDevice.MotorControl = (uint)(GlobalDevice.MotorControl.ToBytes(BPA.Helper.DataFormat.ABCD)).ToInt(); + Thread.Sleep(50); + } + }), "读取输送线设备数据", true); + + } + + /// + /// 通过顺序编号获取西门子数据地址 + /// + /// 地址标头 + /// 编号 + /// 起始地址 + /// + public string GetSiemensBitSingleAdd(string Prefix, int num, int StartAdd = 0) + { + if (num > 0) + { + string Add = string.Empty; + var FirstAdd = num / 8; + var EndAdd = (num % 8); + if (EndAdd == 0) + { + FirstAdd--; + EndAdd = 7; + } + else EndAdd--; + Add = $"{Prefix}{FirstAdd + StartAdd}.{EndAdd}"; + return Add; + } + return default; + } + + } +} diff --git a/BPASmartClient.DosingSystemSingle/View/ChangeDeviceNameView.xaml b/BPASmartClient.DosingSystemSingle/View/ChangeDeviceNameView.xaml new file mode 100644 index 00000000..fbc54b86 --- /dev/null +++ b/BPASmartClient.DosingSystemSingle/View/ChangeDeviceNameView.xaml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +