From cd5683dae9f7b01d4c5a3b792a05dd6fa48f8172 Mon Sep 17 00:00:00 2001 From: hsc Date: Tue, 18 Nov 2025 10:22:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=A4=9A=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BOB/App.xaml.cs | 18 ++ BOB/Singleton/Devices.cs | 175 +++++++++++++ BOB/SystemConfig.cs | 11 +- BOB/ViewModels/LogAreaViewModel.cs | 64 ++++- BOB/ViewModels/ShellViewModel.cs | 20 +- BOB/Views/ShellView.xaml | 2 +- DeviceCommand/Base/ModbusTcp.cs | 1 - DeviceCommand/Device/E36233A.cs | 6 +- DeviceCommand/Device/EAEL9080.cs | 6 +- DeviceCommand/Device/IOBoard.cs | 32 +++ DeviceCommand/Device/IT6724C.cs | 6 +- DeviceCommand/Device/LQ7500-D.cs | 7 +- DeviceCommand/Device/PSB11000.cs | 6 +- DeviceCommand/Device/SQ0030G1D.cs | 6 +- DeviceCommand/Device/WS-68030-380T.cs | 6 +- DeviceCommand/Device/ZXKS.cs | 6 +- Logger/Logger.csproj | 1 + Logger/LoggingInterceptor.cs | 63 +++++ ProcessManager/JsonHelper.cs | 7 +- ProcessManager/MainWindow.xaml | 243 +++++------------- ProcessManager/Setting.xaml | 141 +++++----- ProcessManager/ViewModels/PMainViewModel.cs | 44 +++- ProcessManager/ViewModels/SettingViewModel.cs | 37 ++- 23 files changed, 648 insertions(+), 260 deletions(-) create mode 100644 BOB/Singleton/Devices.cs create mode 100644 DeviceCommand/Device/IOBoard.cs create mode 100644 Logger/LoggingInterceptor.cs diff --git a/BOB/App.xaml.cs b/BOB/App.xaml.cs index 89a7314..7455af9 100644 --- a/BOB/App.xaml.cs +++ b/BOB/App.xaml.cs @@ -1,5 +1,6 @@ using BOB.Converters; using BOB.Models; +using BOB.Singleton; using BOB.ViewModels; using BOB.ViewModels.Dialogs; using BOB.Views; @@ -7,6 +8,7 @@ using BOB.Views.Dialogs; using Castle.DynamicProxy; using System.Configuration; using System.Data; +using System.Diagnostics; using System.Reflection; using System.Windows; using static System.Runtime.InteropServices.JavaScript.JSType; @@ -22,6 +24,21 @@ namespace BOB { return Container.Resolve(); } + protected override void OnStartup(StartupEventArgs e) + { + if (e.Args.Length > 0) + { + string deviceName = e.Args[0]; + SystemConfig.Instance.Title = deviceName; + //Debugger.Launch(); + } + else + { + SystemConfig.Instance.Title = "设备2";//模拟打开的设备 + } + base.OnStartup(e); + } + protected override void OnInitialized() { base.OnInitialized(); @@ -40,6 +57,7 @@ namespace BOB //注册全局变量 containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); } } diff --git a/BOB/Singleton/Devices.cs b/BOB/Singleton/Devices.cs new file mode 100644 index 0000000..8e8c4b4 --- /dev/null +++ b/BOB/Singleton/Devices.cs @@ -0,0 +1,175 @@ +using DeviceCommand.Device; +using Model; +using Castle.DynamicProxy; +using Logger; +using System; +using System.Collections.Generic; + +namespace BOB.Singleton +{ + public class Devices + { + public Dictionary DeviceDic { get; private set; } = new Dictionary(); + + private readonly ProxyGenerator _proxyGen = new ProxyGenerator(); + private readonly IInterceptor _loggingInterceptor = new LoggingInterceptor(); + + // 保留对单个实例引用(可选) + private E36233A E36233ADevice_1 { get; set; } + private E36233A E36233ADevice_2 { get; set; } + private IT6724C IT6724CDevice_1 { get; set; } + private IT6724C IT6724CDevice_2 { get; set; } + private EAEL9080 EAEL9080Device { get; set; } + private IOBoard IOBoardevice { get; set; } + private LQ7500_D LQ7500_DDevice { get; set; } + private PSB11000 PSB11000Device { get; set; } + private WS_68030_380T WS_68030_380TDevice { get; set; } + private SQ0030G1D SQ0030G1DTDevice { get; set; } + private ZXKS ZXKSTDevice { get; set; } + + public Devices(List deviceList) + { + foreach (var device in deviceList) + { + if (!device.IsEnabled) continue; + + switch (device.DeviceType) + { + case "DeviceCommand.Device.E36233A": + if (device.CommunicationConfig is TcpConfig tcp1) + { + if (E36233ADevice_1 == null) + { + E36233ADevice_1 = _proxyGen.CreateClassProxy( + new object[] { tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["E36233A_1"] = E36233ADevice_1; + } + else + { + E36233ADevice_2 = _proxyGen.CreateClassProxy( + new object[] { tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["E36233A_2"] = E36233ADevice_2; + } + } + else throw new InvalidOperationException("E36233A 必须使用 TcpConfig"); + break; + + case "DeviceCommand.Device.IT6724C": + if (device.CommunicationConfig is SerialPortConfig sp1) + { + if (IT6724CDevice_1 == null) + { + IT6724CDevice_1 = _proxyGen.CreateClassProxy( + new object[] { sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["IT6724C_1"] = IT6724CDevice_1; + } + else + { + IT6724CDevice_2 = _proxyGen.CreateClassProxy( + new object[] { sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["IT6724C_2"] = IT6724CDevice_2; + } + } + else throw new InvalidOperationException("IT6724C 必须使用 SerialPortConfig"); + break; + + case "DeviceCommand.Device.LQ7500_D": + if (device.CommunicationConfig is SerialPortConfig sp2) + { + LQ7500_DDevice = _proxyGen.CreateClassProxy( + new object[] { sp2.COMPort, sp2.BaudRate, sp2.DataBit, sp2.StopBit, sp2.ParityBit, sp2.ReadTimeout, sp2.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["LQ7500_D"] = LQ7500_DDevice; + } + else throw new InvalidOperationException("LQ7500D 必须使用 SerialPortConfig"); + break; + + case "DeviceCommand.Device.EAEL9080": + if (device.CommunicationConfig is TcpConfig tcp2) + { + EAEL9080Device = _proxyGen.CreateClassProxy( + new object[] { tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["EAEL9080"] = EAEL9080Device; + } + else throw new InvalidOperationException("EAEL9080 必须使用 TcpConfig"); + break; + + case "DeviceCommand.Device.IOBoard": + if (device.CommunicationConfig is TcpConfig tcp3) + { + IOBoardevice = _proxyGen.CreateClassProxy( + new object[] { tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["IOBoard"] = IOBoardevice; + } + else throw new InvalidOperationException("IOBoard 必须使用 TcpConfig"); + break; + + case "DeviceCommand.Device.PSB11000": + if (device.CommunicationConfig is TcpConfig tcp4) + { + PSB11000Device = _proxyGen.CreateClassProxy( + new object[] { tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["PSB11000"] = PSB11000Device; + } + else throw new InvalidOperationException("PSB11000 必须使用 TcpConfig"); + break; + + case "DeviceCommand.Device.WS_68030_380T": + if (device.CommunicationConfig is TcpConfig tcp5) + { + WS_68030_380TDevice = _proxyGen.CreateClassProxy( + new object[] { tcp5.IPAddress, tcp5.Port, tcp5.ReadTimeout, tcp5.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["WS_68030_380T"] = WS_68030_380TDevice; + } + else throw new InvalidOperationException("WS_68030_380T 必须使用 TcpConfig"); + break; + + case "DeviceCommand.Device.SQ0030G1D": + if (device.CommunicationConfig is TcpConfig tcp7) + { + SQ0030G1DTDevice = _proxyGen.CreateClassProxy( + new object[] { tcp7.IPAddress, tcp7.Port, tcp7.ReadTimeout, tcp7.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["SQ0030G1D"] = SQ0030G1DTDevice; + } + else throw new InvalidOperationException("SQ0030G1D 必须使用 TcpConfig"); + break; + + case "DeviceCommand.Device.ZXKS": + if (device.CommunicationConfig is TcpConfig tcp6) + { + ZXKSTDevice = _proxyGen.CreateClassProxy( + + new object[] { tcp6.IPAddress, tcp6.Port, tcp6.ReadTimeout, tcp6.WriteTimeout }, + _loggingInterceptor + ); + DeviceDic["ZXKS"] = ZXKSTDevice; + } + else throw new InvalidOperationException("ZXKS 必须使用 TcpConfig"); + break; + + default: + throw new NotSupportedException($"未知设备类型:{device.DeviceType}"); + } + } + } + } +} diff --git a/BOB/SystemConfig.cs b/BOB/SystemConfig.cs index adafe9d..39947f3 100644 --- a/BOB/SystemConfig.cs +++ b/BOB/SystemConfig.cs @@ -31,6 +31,7 @@ namespace BOB [JsonIgnore] public string SystemPath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "BOB"); + public string Title { get; set; } = ""; public int PerformanceLevel { get; set; } = 50; @@ -51,7 +52,7 @@ namespace BOB if (!Directory.Exists(SystemPath)) Directory.CreateDirectory(SystemPath); - string configPath = Path.Combine(SystemPath, "system.json"); + string configPath = Path.Combine(SystemPath, $"{Title}.json"); // 支持接口多态序列化 string json = JsonConvert.SerializeObject(this, Formatting.Indented, @@ -73,11 +74,13 @@ namespace BOB public void LoadFromFile() { - string configPath = Path.Combine(SystemPath, "system.json"); - + string configPath = Path.Combine(SystemPath, $"{Title}.json"); + if(Title == "") + { + return; + } if (!File.Exists(configPath)) { - // 文件不存在则保存当前配置 SaveToFile(); return; } diff --git a/BOB/ViewModels/LogAreaViewModel.cs b/BOB/ViewModels/LogAreaViewModel.cs index 835d258..8230807 100644 --- a/BOB/ViewModels/LogAreaViewModel.cs +++ b/BOB/ViewModels/LogAreaViewModel.cs @@ -1,6 +1,9 @@ -using Logger; +using BOB.Singleton; +using DeviceCommand.Device; +using Logger; using Prism.Mvvm; using System.Collections.ObjectModel; +using System.Reflection; using System.Windows; using System.Windows.Input; using System.Windows.Media; @@ -18,8 +21,10 @@ namespace BOB.ViewModels set => SetProperty(ref _logs, value); } public ICommand ClearLogCommand { get; set; } - public LogAreaViewModel() + public Devices devices { get; set; } + public LogAreaViewModel(IContainerProvider containerProvider) { + devices=containerProvider.Resolve(); ClearLogCommand = new DelegateCommand(ClearLog); LoggerHelper.Progress = new System.Progress<(string message, string color,int depth)>( log => @@ -27,8 +32,63 @@ namespace BOB.ViewModels var brush = (Brush)new BrushConverter().ConvertFromString(log.color); Logs.Add(new LogItem(log.message, brush, log.depth)); }); + ShowDeviesInfo(); } + private void ShowDeviesInfo() + { + foreach (var kv in devices.DeviceDic) + { + string name = kv.Key; + object dev = kv.Value; + + if (dev == null) + { + LoggerHelper.InfoWithNotify($"{name} 实例为空", 0); + continue; + } + + string typeName = dev.GetType().Name; + string status = GetDeviceConnectionStatus(dev); + + LoggerHelper.InfoWithNotify( + $"设备:{name} | 类型:{typeName} | {status}", 0); + } + } + private string GetDeviceConnectionStatus(object device) + { + // 串口设备 + var serialField = device.GetType().GetProperty("_SerialPort", + BindingFlags.Public | BindingFlags.Instance); + + if (serialField != null) + { + var serial = serialField.GetValue(device) as System.IO.Ports.SerialPort; + if (serial == null) + return "串口未初始化"; + + return serial.IsOpen ? "串口已连接" : "串口未连接"; + } + + // TCP 设备 + var tcpProperty = device.GetType().GetProperty( + "TcpClient", + BindingFlags.Public | BindingFlags.Instance + ); + + if (tcpProperty != null) + { + var client = tcpProperty.GetValue(device) as System.Net.Sockets.TcpClient; + if (client == null) + return "TCP 未初始化"; + + return client.Connected ? "TCP 已连接" : "TCP 未连接"; + } + + return "无法识别设备类型"; + } + + private void ClearLog() { Logs.Clear(); diff --git a/BOB/ViewModels/ShellViewModel.cs b/BOB/ViewModels/ShellViewModel.cs index 5319b5c..46e47f7 100644 --- a/BOB/ViewModels/ShellViewModel.cs +++ b/BOB/ViewModels/ShellViewModel.cs @@ -1,9 +1,11 @@ using BOB.Models; +using BOB.Singleton; using BOB.Views; using Common.PubEvent; using Logger; using MaterialDesignThemes.Wpf; using Microsoft.Win32; +using Model; using Newtonsoft.Json; using System.IO; using System.Windows; @@ -15,6 +17,13 @@ namespace BOB.ViewModels public class ShellViewModel : BindableBase { #region 属性 + private string _Title=""; + + public string Title + { + get => _Title; + set => SetProperty(ref _Title, value); + } private bool _IsLeftDrawerOpen; public bool IsLeftDrawerOpen @@ -90,11 +99,14 @@ namespace BOB.ViewModels private IEventAggregator _eventAggregator; private GlobalVariables _globalVariables; + private IContainerProvider _containerProvider; private StepRunning _stepRunning; + private Devices _devices; private Task? currentExecutionTask; public ShellViewModel(IEventAggregator eventAggregator, IContainerProvider containerProvider,GlobalVariables globalVariables, StepRunning stepRunning) { _eventAggregator = eventAggregator; + _containerProvider = containerProvider; _globalVariables = globalVariables; _stepRunning =stepRunning; LeftDrawerOpenCommand = new DelegateCommand(LeftDrawerOpen); @@ -124,9 +136,10 @@ namespace BOB.ViewModels _ => RunIcon }; } - #region ToolBar命令 private void Load() { + SystemConfig.Instance.LoadFromFile(); + _containerProvider.Resolve((typeof(List), SystemConfig.Instance.DeviceList)); if (SystemConfig.Instance.DefaultSubProgramFilePath != null) { if (File.Exists(SystemConfig.Instance.DefaultSubProgramFilePath)) @@ -134,7 +147,10 @@ namespace BOB.ViewModels Open(SystemConfig.Instance.DefaultSubProgramFilePath); } } - } + Title = SystemConfig.Instance.Title; + } + #region ToolBar命令 + private void SetDefault() { if(_globalVariables.CurrentFilePath!=null) diff --git a/BOB/Views/ShellView.xaml b/BOB/Views/ShellView.xaml index 9f128ab..6d8e0a5 100644 --- a/BOB/Views/ShellView.xaml +++ b/BOB/Views/ShellView.xaml @@ -11,7 +11,7 @@ mc:Ignorable="d" prism:ViewModelLocator.AutoWireViewModel="True" WindowStyle="None" - Title="ShellView" + Title="{Binding Title}" d:DesignHeight="1080" d:DesignWidth="1920"> diff --git a/DeviceCommand/Base/ModbusTcp.cs b/DeviceCommand/Base/ModbusTcp.cs index 9d6ef31..79217a9 100644 --- a/DeviceCommand/Base/ModbusTcp.cs +++ b/DeviceCommand/Base/ModbusTcp.cs @@ -41,7 +41,6 @@ namespace DeviceCommand.Base TcpClient.Dispose(); TcpClient = new TcpClient(); } - await TcpClient.ConnectAsync(IPAddress, Port, ct); Modbus = new ModbusFactory().CreateMaster(TcpClient); return true; diff --git a/DeviceCommand/Device/E36233A.cs b/DeviceCommand/Device/E36233A.cs index 420ddd7..05d141f 100644 --- a/DeviceCommand/Device/E36233A.cs +++ b/DeviceCommand/Device/E36233A.cs @@ -12,9 +12,13 @@ namespace DeviceCommand.Device [BOBCommand] public class E36233A:Tcp { + public E36233A(string IpAddress,int port,int SendTimeout,int ReceiveTimeout) + { + ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); + ConnectAsync(); + } public E36233A() { - ConfigureDevice("127.0.0.1", 502, 3000, 3000); ConnectAsync(); } #region SCPI 常用命令方法 diff --git a/DeviceCommand/Device/EAEL9080.cs b/DeviceCommand/Device/EAEL9080.cs index a23bdd6..6421dc2 100644 --- a/DeviceCommand/Device/EAEL9080.cs +++ b/DeviceCommand/Device/EAEL9080.cs @@ -11,9 +11,13 @@ namespace DeviceCommand.Device [BOBCommand] public class EAEL9080:ModbusTcp { + public EAEL9080(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) + { + ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); + ConnectAsync(); + } public EAEL9080() { - ConfigureDevice("127.0.0.1", 502, 3000, 3000); ConnectAsync(); } #region 一、基础控制与远程模式寄存器 diff --git a/DeviceCommand/Device/IOBoard.cs b/DeviceCommand/Device/IOBoard.cs new file mode 100644 index 0000000..e824b7d --- /dev/null +++ b/DeviceCommand/Device/IOBoard.cs @@ -0,0 +1,32 @@ +using DeviceCommand.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DeviceCommand.Device +{ + public class IOBoard:ModbusTcp + { + public IOBoard(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) + { + ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); + ConnectAsync(); + } + public IOBoard() + { + ConnectAsync(); + } + public async Task WriteOutput(byte slaveId, ushort startAddress, ushort value) + { + await WriteSingleRegisterAsync(slaveId, startAddress, value); + } + + public async Task WriteOutputsBatch(byte slaveId, ushort startAddress, ushort[] values) + { + await WriteMultipleRegistersAsync(slaveId, startAddress, values); + } + + } +} diff --git a/DeviceCommand/Device/IT6724C.cs b/DeviceCommand/Device/IT6724C.cs index b84689f..1309602 100644 --- a/DeviceCommand/Device/IT6724C.cs +++ b/DeviceCommand/Device/IT6724C.cs @@ -10,9 +10,13 @@ namespace DeviceCommand.Device [BOBCommand] public class IT6724C : Serial_Port { + public IT6724C(string COMPort,int BaudRate,int DataBits, StopBits stopBits, Parity parity,int ReadTimeout,int ReceiveTimeout) + { + ConfigureDevice(COMPort,BaudRate,DataBits,stopBits,parity, ReadTimeout, ReceiveTimeout); + ConnectAsync(); + } public IT6724C() { - ConfigureDevice("COM1", 9600, 8, StopBits.One, Parity.None, 3000, 3000); ConnectAsync(); } diff --git a/DeviceCommand/Device/LQ7500-D.cs b/DeviceCommand/Device/LQ7500-D.cs index 8422d1f..59a66c1 100644 --- a/DeviceCommand/Device/LQ7500-D.cs +++ b/DeviceCommand/Device/LQ7500-D.cs @@ -1,6 +1,7 @@ using Common.Attributes; using DeviceCommand.Base; using System; +using System.IO.Ports; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; @@ -10,9 +11,13 @@ namespace DeviceCommand.Device [BOBCommand] public class LQ7500_D : ModbusRtu { + public LQ7500_D(string COMPort, int BaudRate, int DataBits, StopBits stopBits, Parity parity, int ReadTimeout, int ReceiveTimeout) + { + ConfigureDevice(COMPort, BaudRate, DataBits, stopBits, parity, ReadTimeout, ReceiveTimeout); + ConnectAsync(); + } public LQ7500_D() { - ConfigureDevice("COM1", 9600); ConnectAsync(); } public byte SlaveAddress { get; set; } = 1; // default slave address diff --git a/DeviceCommand/Device/PSB11000.cs b/DeviceCommand/Device/PSB11000.cs index 55ffa12..30faafd 100644 --- a/DeviceCommand/Device/PSB11000.cs +++ b/DeviceCommand/Device/PSB11000.cs @@ -11,9 +11,13 @@ namespace DeviceCommand.Device [BOBCommand] public class PSB11000: ModbusTcp { + public PSB11000(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) + { + ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); + ConnectAsync(); + } public PSB11000() { - ConfigureDevice("127.0.0.1", 502, 3000, 3000); ConnectAsync(); } #region 一、基础控制与远程模式寄存器 diff --git a/DeviceCommand/Device/SQ0030G1D.cs b/DeviceCommand/Device/SQ0030G1D.cs index 7357509..56d26a0 100644 --- a/DeviceCommand/Device/SQ0030G1D.cs +++ b/DeviceCommand/Device/SQ0030G1D.cs @@ -13,9 +13,13 @@ namespace DeviceCommand.Device [BOBCommand] public class SQ0030G1D : Tcp { + public SQ0030G1D(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) + { + ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); + ConnectAsync(); + } public SQ0030G1D() { - ConfigureDevice("127.0.0.1", 502, 3000, 3000); ConnectAsync(); } #region ========== 通用 SCPI 封装 ========== diff --git a/DeviceCommand/Device/WS-68030-380T.cs b/DeviceCommand/Device/WS-68030-380T.cs index 8c8a372..6ad8aa3 100644 --- a/DeviceCommand/Device/WS-68030-380T.cs +++ b/DeviceCommand/Device/WS-68030-380T.cs @@ -9,9 +9,13 @@ namespace DeviceCommand.Device [BOBCommand] public class WS_68030_380T : ModbusTcp { + public WS_68030_380T(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) + { + ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); + ConnectAsync(); + } public WS_68030_380T() { - ConfigureDevice("127.0.0.1", 502, 3000, 3000); ConnectAsync(); } private const byte SlaveAddress = 1; diff --git a/DeviceCommand/Device/ZXKS.cs b/DeviceCommand/Device/ZXKS.cs index 1e9b2c7..f75a6b3 100644 --- a/DeviceCommand/Device/ZXKS.cs +++ b/DeviceCommand/Device/ZXKS.cs @@ -11,9 +11,13 @@ namespace DeviceCommand.Device [BOBCommand] public class ZXKS:ModbusTcp { + public ZXKS(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) + { + ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); + ConnectAsync(); + } public ZXKS() { - ConfigureDevice("127.0.0.1", 502, 3000, 3000); ConnectAsync(); } } diff --git a/Logger/Logger.csproj b/Logger/Logger.csproj index 6b0ee50..a7b514b 100644 --- a/Logger/Logger.csproj +++ b/Logger/Logger.csproj @@ -7,6 +7,7 @@ + diff --git a/Logger/LoggingInterceptor.cs b/Logger/LoggingInterceptor.cs new file mode 100644 index 0000000..fc65a35 --- /dev/null +++ b/Logger/LoggingInterceptor.cs @@ -0,0 +1,63 @@ +using Castle.DynamicProxy; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Logger +{ + public class LoggingInterceptor : IInterceptor + { + public void Intercept(IInvocation invocation) + { + string className = invocation.TargetType.Name; + string methodName = invocation.Method.Name; + + LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 开始"); + + var sw = Stopwatch.StartNew(); + + try + { + // 执行原方法 + invocation.Proceed(); + + // 如果是异步方法 + if (invocation.Method.ReturnType == typeof(Task) || + (invocation.Method.ReturnType.IsGenericType && + invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))) + { + invocation.ReturnValue = InterceptAsync(invocation, sw); + return; + } + + sw.Stop(); + LoggerHelper.SuccessWithNotify($"调用 {className}.{methodName}() 完成,耗时 {sw.ElapsedMilliseconds} ms"); + } + catch (Exception ex) + { + sw.Stop(); + LoggerHelper.ErrorWithNotify($"调用 {className}.{methodName}() 异常:{ex.Message}", ex.StackTrace); + throw; + } + } + + private async Task InterceptAsync(IInvocation invocation, Stopwatch sw) + { + try + { + await (Task)invocation.ReturnValue; + sw.Stop(); + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms"); + } + catch (Exception ex) + { + sw.Stop(); + LoggerHelper.ErrorWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 异常:{ex.Message}", ex.StackTrace); + throw; + } + } + } +} diff --git a/ProcessManager/JsonHelper.cs b/ProcessManager/JsonHelper.cs index 19adeab..df2601d 100644 --- a/ProcessManager/JsonHelper.cs +++ b/ProcessManager/JsonHelper.cs @@ -11,7 +11,7 @@ namespace ProcessManager public static string SystemPath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "BOB"); - private static string ConfigFile => Path.Combine(SystemPath, "system.json"); + public static string ConfigFile; private static readonly JsonSerializerSettings jsonSettings = new() { @@ -41,10 +41,7 @@ namespace ProcessManager { if (!File.Exists(ConfigFile)) { - // 如果不存在自动创建一个默认的 SystemConfig - var defaultConfig = new SystemConfig(); - SaveToFile(defaultConfig); - return defaultConfig; + throw new Exception("没找到系统配置文件"); } try diff --git a/ProcessManager/MainWindow.xaml b/ProcessManager/MainWindow.xaml index aa16972..bc49d4c 100644 --- a/ProcessManager/MainWindow.xaml +++ b/ProcessManager/MainWindow.xaml @@ -1,188 +1,79 @@  + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ProcessManager/Setting.xaml b/ProcessManager/Setting.xaml index 8c7e2d8..4801599 100644 --- a/ProcessManager/Setting.xaml +++ b/ProcessManager/Setting.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:local="clr-namespace:ProcessManager" - Height="500" + Width="800"> @@ -64,65 +64,91 @@ Width="200" /> - - - - + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + - - _configList; + + public ObservableCollection ConfigList + { + get => _configList; + set => SetProperty(ref _configList, value); + } + private readonly IDialogService _dialogService; private Dictionary ProcessDic { get; set; } = new Dictionary(); public ICommand StartCommand { get; set; } public ICommand EditCommand { get; set; } + public ICommand WindowLoadedCommand { get; set; } public PMainViewModel(IDialogService dialogService) { _dialogService = dialogService; EditCommand=new DelegateCommand(OnEdit); StartCommand = new DelegateCommand(OnStart); + WindowLoadedCommand = new DelegateCommand(OnWindowLoaded); + } + + private void OnWindowLoaded() + { + if (ConfigList != null) ConfigList.Clear(); + var JSONFiles = Directory.GetFiles(JsonHelper.SystemPath, "*.json"); + foreach(var file in JSONFiles) + { + JsonHelper.ConfigFile = file; + var config = JsonHelper.LoadFromFile(); + if(ConfigList==null) + { + ConfigList = new ObservableCollection(); + } + ConfigList.Add(config); + } } private void OnStart(string deviceName) @@ -41,13 +71,24 @@ namespace ProcessManager.ViewModels ProcessStartInfo startInfo = new ProcessStartInfo { FileName = exePath, + Arguments = deviceName, UseShellExecute = true }; + var configToSave = ConfigList.FirstOrDefault(x => x.Title == deviceName); + if (configToSave != null) + { + JsonHelper.ConfigFile = Path.Combine(JsonHelper.SystemPath, $"{deviceName}.json"); + JsonHelper.SaveToFile(configToSave); + } var process = Process.Start(startInfo); process.EnableRaisingEvents = true; process.Exited += (s, args) => { ProcessDic.Remove(deviceName); + Application.Current.Dispatcher.Invoke(() => + { + OnWindowLoaded(); + }); }; ProcessDic.Add(deviceName, process); } @@ -64,6 +105,7 @@ namespace ProcessManager.ViewModels MessageBox.Show("请先关闭进程再进行编辑"); return; } + JsonHelper.ConfigFile = Path.Combine(JsonHelper.SystemPath, $"{deviceName}.json"); var ConfigSystem = JsonHelper.LoadFromFile(); var parameters = new DialogParameters { diff --git a/ProcessManager/ViewModels/SettingViewModel.cs b/ProcessManager/ViewModels/SettingViewModel.cs index 8e49564..b6b594d 100644 --- a/ProcessManager/ViewModels/SettingViewModel.cs +++ b/ProcessManager/ViewModels/SettingViewModel.cs @@ -3,6 +3,7 @@ using BOB.Models; using Model; using Prism.Mvvm; using System.Collections.ObjectModel; +using System.IO; using System.Windows.Input; namespace ProcessManager.ViewModels @@ -16,12 +17,32 @@ namespace ProcessManager.ViewModels get => _Title; set => SetProperty(ref _Title, value); } + private bool _SelectedDeviceType; + //true为serialport ,false为tcp + public bool SelectedDeviceType + { + get => _SelectedDeviceType; + set => SetProperty(ref _SelectedDeviceType, value); + } private DeviceConfigModel _SelectedDevice; public DeviceConfigModel SelectedDevice { get => _SelectedDevice; - set => SetProperty(ref _SelectedDevice, value); + set + { + if(SetProperty(ref _SelectedDevice, value)) + { + if(value.CommunicationConfig is SerialPortConfig) + { + SelectedDeviceType = true; + } + else + { + SelectedDeviceType = false; + } + } + } } private SystemConfig _config; @@ -44,7 +65,19 @@ namespace ProcessManager.ViewModels private void Save() { - RequestClose.Invoke(); + try + { + //foreach(var d in Config.DeviceList) + //{ + // d.Id=Guid.NewGuid(); + //} + JsonHelper.SaveToFile(Config); + RequestClose.Invoke(); + } + catch (Exception) + { + throw; + } } private void Cancel()