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