From a25a4bc6ed8c0032ac0060c4cb9705d6ce7ee2b6 Mon Sep 17 00:00:00 2001 From: hsc Date: Wed, 19 Nov 2025 13:44:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8B=A6=E6=88=AA=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BOB/Singleton/Devices.cs | 149 +++++--- BOB/ViewModels/LogAreaViewModel.cs | 90 +++-- BOB/ViewModels/MainViewModel.cs | 26 +- DeviceCommand/Base/IModbusDevice.cs | 24 ++ DeviceCommand/Base/ISerialPort.cs | 18 + DeviceCommand/Base/ITCP.cs | 23 ++ DeviceCommand/Base/ModbusRtu.cs | 6 +- DeviceCommand/Base/ModbusTcp.cs | 2 +- DeviceCommand/Base/Serial_Port.cs | 6 +- DeviceCommand/Base/TCP.cs | 2 +- DeviceCommand/Device/E36233A.cs | 506 ++++++-------------------- DeviceCommand/Device/EAEL9080.cs | 342 ++--------------- DeviceCommand/Device/IOBoard.cs | 8 +- DeviceCommand/Device/IT6724C.cs | 4 +- DeviceCommand/Device/LQ7500-D.cs | 4 +- DeviceCommand/Device/PSB11000.cs | 307 ++-------------- DeviceCommand/Device/SQ0030G1D.cs | 230 +++--------- DeviceCommand/Device/WS-68030-380T.cs | 4 +- DeviceCommand/Device/ZXKS.cs | 4 +- Logger/LoggingInterceptor.cs | 175 ++++++--- ProcessManager/Setting.xaml | 2 +- 21 files changed, 600 insertions(+), 1332 deletions(-) create mode 100644 DeviceCommand/Base/IModbusDevice.cs create mode 100644 DeviceCommand/Base/ISerialPort.cs create mode 100644 DeviceCommand/Base/ITCP.cs diff --git a/BOB/Singleton/Devices.cs b/BOB/Singleton/Devices.cs index 8e8c4b4..e0c8b7f 100644 --- a/BOB/Singleton/Devices.cs +++ b/BOB/Singleton/Devices.cs @@ -1,9 +1,13 @@ -using DeviceCommand.Device; -using Model; -using Castle.DynamicProxy; +using Castle.DynamicProxy; +using DeviceCommand.Base; +using DeviceCommand.Device; using Logger; +using Model; using System; using System.Collections.Generic; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; namespace BOB.Singleton { @@ -15,17 +19,17 @@ namespace BOB.Singleton 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; } + private ITcp E36233ADevice_1 { get; set; } + private ITcp E36233ADevice_2 { get; set; } + private ISerialPort IT6724CDevice_1 { get; set; } + private ISerialPort IT6724CDevice_2 { get; set; } + private IModbusDevice EAEL9080Device { get; set; } + private IModbusDevice IOBoardevice { get; set; } + private IModbusDevice LQ7500_DDevice { get; set; } + private IModbusDevice PSB11000Device { get; set; } + private IModbusDevice WS_68030_380TDevice { get; set; } + private ITcp SQ0030G1DTDevice { get; set; } + private IModbusDevice ZXKSTDevice { get; set; } public Devices(List deviceList) { @@ -40,16 +44,17 @@ namespace BOB.Singleton { if (E36233ADevice_1 == null) { - E36233ADevice_1 = _proxyGen.CreateClassProxy( - new object[] { tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout }, + // 通过接口代理 + E36233ADevice_1 = _proxyGen.CreateInterfaceProxyWithTarget( + new E36233A(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 }, + E36233ADevice_2 = _proxyGen.CreateInterfaceProxyWithTarget( + new E36233A(tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout), _loggingInterceptor ); DeviceDic["E36233A_2"] = E36233ADevice_2; @@ -63,17 +68,17 @@ namespace BOB.Singleton { 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 + IT6724CDevice_1 = _proxyGen.CreateInterfaceProxyWithTarget( + new IT6724C(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 + IT6724CDevice_2 = _proxyGen.CreateInterfaceProxyWithTarget( + new IT6724C(sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout), + _loggingInterceptor ); DeviceDic["IT6724C_2"] = IT6724CDevice_2; } @@ -84,9 +89,9 @@ namespace BOB.Singleton 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 + LQ7500_DDevice = _proxyGen.CreateInterfaceProxyWithTarget( + new LQ7500_D(sp2.COMPort, sp2.BaudRate, sp2.DataBit, sp2.StopBit, sp2.ParityBit, sp2.ReadTimeout, sp2.WriteTimeout), + _loggingInterceptor ); DeviceDic["LQ7500_D"] = LQ7500_DDevice; } @@ -96,9 +101,9 @@ namespace BOB.Singleton case "DeviceCommand.Device.EAEL9080": if (device.CommunicationConfig is TcpConfig tcp2) { - EAEL9080Device = _proxyGen.CreateClassProxy( - new object[] { tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout }, - _loggingInterceptor + EAEL9080Device = _proxyGen.CreateInterfaceProxyWithTarget( + new EAEL9080(tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout), + _loggingInterceptor ); DeviceDic["EAEL9080"] = EAEL9080Device; } @@ -108,9 +113,9 @@ namespace BOB.Singleton case "DeviceCommand.Device.IOBoard": if (device.CommunicationConfig is TcpConfig tcp3) { - IOBoardevice = _proxyGen.CreateClassProxy( - new object[] { tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout }, - _loggingInterceptor + IOBoardevice = _proxyGen.CreateInterfaceProxyWithTarget( + new IOBoard(tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout), + _loggingInterceptor ); DeviceDic["IOBoard"] = IOBoardevice; } @@ -120,9 +125,9 @@ namespace BOB.Singleton case "DeviceCommand.Device.PSB11000": if (device.CommunicationConfig is TcpConfig tcp4) { - PSB11000Device = _proxyGen.CreateClassProxy( - new object[] { tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout }, - _loggingInterceptor + PSB11000Device = _proxyGen.CreateInterfaceProxyWithTarget( + new PSB11000(tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout), + _loggingInterceptor ); DeviceDic["PSB11000"] = PSB11000Device; } @@ -132,9 +137,9 @@ namespace BOB.Singleton 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 + WS_68030_380TDevice = _proxyGen.CreateInterfaceProxyWithTarget( + new WS_68030_380T(tcp5.IPAddress, tcp5.Port, tcp5.ReadTimeout, tcp5.WriteTimeout), + _loggingInterceptor ); DeviceDic["WS_68030_380T"] = WS_68030_380TDevice; } @@ -144,9 +149,9 @@ namespace BOB.Singleton case "DeviceCommand.Device.SQ0030G1D": if (device.CommunicationConfig is TcpConfig tcp7) { - SQ0030G1DTDevice = _proxyGen.CreateClassProxy( - new object[] { tcp7.IPAddress, tcp7.Port, tcp7.ReadTimeout, tcp7.WriteTimeout }, - _loggingInterceptor + SQ0030G1DTDevice = _proxyGen.CreateInterfaceProxyWithTarget( + new SQ0030G1D(tcp7.IPAddress, tcp7.Port, tcp7.ReadTimeout, tcp7.WriteTimeout), + _loggingInterceptor ); DeviceDic["SQ0030G1D"] = SQ0030G1DTDevice; } @@ -156,9 +161,8 @@ namespace BOB.Singleton case "DeviceCommand.Device.ZXKS": if (device.CommunicationConfig is TcpConfig tcp6) { - ZXKSTDevice = _proxyGen.CreateClassProxy( - - new object[] { tcp6.IPAddress, tcp6.Port, tcp6.ReadTimeout, tcp6.WriteTimeout }, + ZXKSTDevice = _proxyGen.CreateInterfaceProxyWithTarget( + new ZXKS(tcp6.IPAddress, tcp6.Port, tcp6.ReadTimeout, tcp6.WriteTimeout), _loggingInterceptor ); DeviceDic["ZXKS"] = ZXKSTDevice; @@ -171,5 +175,60 @@ namespace BOB.Singleton } } } + + public async Task ConnectAllDevicesAsync() + { + if (DeviceDic.Count == 0) + { + await Task.CompletedTask; + } + + foreach (var kvp in DeviceDic) + { + var name = kvp.Key; + var device = kvp.Value; + + if (device == null) + { + LoggerHelper.WarnWithNotify($"{name} 实例为空,跳过连接"); + continue; + } + await Task.Delay(10); + try + { + // 检查并处理 ITcp 接口 + if (device is ITcp itcpDevice) + { + bool result = await itcpDevice.ConnectAsync(CancellationToken.None); + LoggerHelper.SuccessWithNotify($"{name} 连接成功 (ITcp)"); + } + // 检查并处理 IModbusDevice 接口 + else if (device is IModbusDevice imodbusDevice) + { + bool result = await imodbusDevice.ConnectAsync(CancellationToken.None); + LoggerHelper.SuccessWithNotify($"{name} 连接成功 (IModbusDevice)"); + } + // 检查并处理 ISerialPort 接口 + else if (device is ISerialPort iserialPortDevice) + { + bool result = await iserialPortDevice.ConnectAsync(CancellationToken.None); + LoggerHelper.SuccessWithNotify($"{name} 连接成功 (ISerialPort)"); + } + else + { + LoggerHelper.WarnWithNotify($"{name} 不是有效的设备类型"); + } + } + catch(InvalidCastException ex) + { + + } + catch (Exception ex) + { + LoggerHelper.ErrorWithNotify($"{name} 连接失败: {ex.Message}", ex.StackTrace); + } + + } + } } } diff --git a/BOB/ViewModels/LogAreaViewModel.cs b/BOB/ViewModels/LogAreaViewModel.cs index 8230807..b5ddc0a 100644 --- a/BOB/ViewModels/LogAreaViewModel.cs +++ b/BOB/ViewModels/LogAreaViewModel.cs @@ -32,61 +32,59 @@ namespace BOB.ViewModels var brush = (Brush)new BrushConverter().ConvertFromString(log.color); Logs.Add(new LogItem(log.message, brush, log.depth)); }); - ShowDeviesInfo(); + //ShowDeviesInfo(); } - private void ShowDeviesInfo() - { - foreach (var kv in devices.DeviceDic) - { - string name = kv.Key; - object dev = kv.Value; + //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; - } + // if (dev == null) + // { + // LoggerHelper.InfoWithNotify($"{name} 实例为空", 0); + // continue; + // } - string typeName = dev.GetType().Name; - string status = GetDeviceConnectionStatus(dev); + // 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); + // 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 "串口未初始化"; + // if (serialField != null) + // { + // var serial = serialField.GetValue(device) as System.IO.Ports.SerialPort; + // if (serial == null) + // return "串口未初始化"; + // return serial.IsOpen ? "串口已连接" : "串口未连接"; + // } - return serial.IsOpen ? "串口已连接" : "串口未连接"; - } + // // TCP 设备 + // var tcpProperty = device.GetType().GetProperty( + // "TcpClient", + // BindingFlags.Public | BindingFlags.Instance + // ); - // 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 未连接"; + // } - if (tcpProperty != null) - { - var client = tcpProperty.GetValue(device) as System.Net.Sockets.TcpClient; - if (client == null) - return "TCP 未初始化"; - - return client.Connected ? "TCP 已连接" : "TCP 未连接"; - } - - return "无法识别设备类型"; - } + // return "无法识别设备类型"; + //} private void ClearLog() diff --git a/BOB/ViewModels/MainViewModel.cs b/BOB/ViewModels/MainViewModel.cs index 5712048..1f3b4fe 100644 --- a/BOB/ViewModels/MainViewModel.cs +++ b/BOB/ViewModels/MainViewModel.cs @@ -1,5 +1,7 @@ -using Common.PubEvent; +using BOB.Singleton; +using Common.PubEvent; using Common.PubEvents; +using Logger; using NLog; using Prism.Dialogs; using Prism.Events; @@ -27,10 +29,12 @@ namespace BOB.ViewModels public DialogCloseListener RequestClose { get; set; } private IEventAggregator _eventAggregator; private IDialogService _dialogService; - public MainViewModel(IEventAggregator eventAggregator, IDialogService dialogService) + private Devices _devices{ get; set; } + public MainViewModel(IEventAggregator eventAggregator, IDialogService dialogService,IContainerProvider containerProvider) { _dialogService = dialogService; _eventAggregator = eventAggregator; + _devices=containerProvider.Resolve(); testcommand = new DelegateCommand(test); } @@ -47,10 +51,26 @@ namespace BOB.ViewModels //_dialogService.ShowDialog("MessageBox",parameters); } + private async Task InitializeDevicesAsync() + { + try + { + await _devices.ConnectAllDevicesAsync(); + } + catch (Exception ex) + { + LoggerHelper.ErrorWithNotify($"设备连接异常: {ex.Message}", ex.StackTrace); + } + finally + { + _eventAggregator.GetEvent().Publish(false); + } + } #region 导航 public void OnNavigatedTo(NavigationContext navigationContext) { - + _eventAggregator.GetEvent().Publish(true); + _=InitializeDevicesAsync(); } public bool IsNavigationTarget(NavigationContext navigationContext) diff --git a/DeviceCommand/Base/IModbusDevice.cs b/DeviceCommand/Base/IModbusDevice.cs new file mode 100644 index 0000000..135e0da --- /dev/null +++ b/DeviceCommand/Base/IModbusDevice.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DeviceCommand.Base +{ + public interface IModbusDevice + { + Task ConnectAsync(CancellationToken ct = default); + void Close(); + + Task WriteSingleRegisterAsync(byte slaveAddress, ushort registerAddress, ushort value, CancellationToken ct = default); + Task WriteMultipleRegistersAsync(byte slaveAddress, ushort startAddress, ushort[] values, CancellationToken ct = default); + Task ReadHoldingRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default); + + Task WriteSingleCoilAsync(byte slaveAddress, ushort coilAddress, bool value, CancellationToken ct = default); + Task ReadCoilsAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default); + + Task ReadInputRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default); + } + +} diff --git a/DeviceCommand/Base/ISerialPort.cs b/DeviceCommand/Base/ISerialPort.cs new file mode 100644 index 0000000..887fc6e --- /dev/null +++ b/DeviceCommand/Base/ISerialPort.cs @@ -0,0 +1,18 @@ +using System; +using System.IO.Ports; +using System.Threading; +using System.Threading.Tasks; + +namespace DeviceCommand.Base +{ + public interface ISerialPort + { + Task ConnectAsync(CancellationToken ct = default); + + void Close(); + + Task SendAsync(string data, CancellationToken ct = default); + + Task ReadAsync(string delimiter = "\n", CancellationToken ct = default); + } +} diff --git a/DeviceCommand/Base/ITCP.cs b/DeviceCommand/Base/ITCP.cs new file mode 100644 index 0000000..f5fd9d5 --- /dev/null +++ b/DeviceCommand/Base/ITCP.cs @@ -0,0 +1,23 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace DeviceCommand.Base +{ + public interface ITcp + { + Task ConnectAsync(CancellationToken ct = default); + + void Close(); + + Task SendAsync(byte[] buffer, CancellationToken ct = default); + + Task SendAsync(string str, CancellationToken ct = default); + + Task ReadAsync(int length, CancellationToken ct = default); + + Task ReadAsync(string delimiter = "\n", CancellationToken ct = default); + + Task WriteReadAsync(string command, string delimiter = "\n", CancellationToken ct = default); + } +} diff --git a/DeviceCommand/Base/ModbusRtu.cs b/DeviceCommand/Base/ModbusRtu.cs index 59744d7..5768c56 100644 --- a/DeviceCommand/Base/ModbusRtu.cs +++ b/DeviceCommand/Base/ModbusRtu.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace DeviceCommand.Base { - public class ModbusRtu + public class ModbusRtu:IModbusDevice { public string PortName { get; private set; } = "COM1"; public int BaudRate { get; private set; } = 9600; @@ -22,9 +22,7 @@ namespace DeviceCommand.Base private readonly SemaphoreSlim _commLock = new(1, 1); - public void ConfigureDevice(string portName, int baudRate, int dataBits = 8, - StopBits stopBits = StopBits.One, Parity parity = Parity.None, - int readTimeout = 3000, int writeTimeout = 3000) + public void ConfigureDevice(string portName, int baudRate, int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None, int readTimeout = 3000, int writeTimeout = 3000) { PortName = portName; BaudRate = baudRate; diff --git a/DeviceCommand/Base/ModbusTcp.cs b/DeviceCommand/Base/ModbusTcp.cs index 79217a9..a0eb82d 100644 --- a/DeviceCommand/Base/ModbusTcp.cs +++ b/DeviceCommand/Base/ModbusTcp.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace DeviceCommand.Base { - public class ModbusTcp + public class ModbusTcp : IModbusDevice { public string IPAddress { get; private set; } = "127.0.0.1"; public int Port { get; private set; } = 502; diff --git a/DeviceCommand/Base/Serial_Port.cs b/DeviceCommand/Base/Serial_Port.cs index 7dfcabb..b852c7d 100644 --- a/DeviceCommand/Base/Serial_Port.cs +++ b/DeviceCommand/Base/Serial_Port.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace DeviceCommand.Base { - public class Serial_Port + public class Serial_Port: ISerialPort { public string PortName { get; set; } = "COM1"; public int BaudRate { get; set; } = 9600; @@ -18,9 +18,7 @@ namespace DeviceCommand.Base public SerialPort _SerialPort { get; private set; } = new SerialPort(); private readonly SemaphoreSlim _commLock = new(1, 1); - public void ConfigureDevice(string portName, int baudRate, int dataBits = 8, - StopBits stopBits = StopBits.One, Parity parity = Parity.None, - int readTimeout = 3000, int writeTimeout = 3000) + public void ConfigureDevice(string portName, int baudRate, int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None, int readTimeout = 3000, int writeTimeout = 3000) { PortName = portName; BaudRate = baudRate; diff --git a/DeviceCommand/Base/TCP.cs b/DeviceCommand/Base/TCP.cs index 9aa4fdf..56f7714 100644 --- a/DeviceCommand/Base/TCP.cs +++ b/DeviceCommand/Base/TCP.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace DeviceCommand.Base { - public class Tcp + public class Tcp: ITcp { public string IPAddress { get; private set; } = "127.0.0.1"; public int Port { get; private set; } = 502; diff --git a/DeviceCommand/Device/E36233A.cs b/DeviceCommand/Device/E36233A.cs index 05d141f..ef4b4ba 100644 --- a/DeviceCommand/Device/E36233A.cs +++ b/DeviceCommand/Device/E36233A.cs @@ -1,440 +1,160 @@ using Common.Attributes; using DeviceCommand.Base; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; +using System.Threading; using System.Threading.Tasks; namespace DeviceCommand.Device { - //是德 [BOBCommand] - public class E36233A:Tcp + public class E36233A : Tcp { - public E36233A(string IpAddress,int port,int SendTimeout,int ReceiveTimeout) + public E36233A(string ipAddress, int port, int sendTimeout, int receiveTimeout) { - ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); - ConnectAsync(); + ConfigureDevice(ipAddress, port, sendTimeout, receiveTimeout); } + public E36233A() { - ConnectAsync(); } - #region SCPI 常用命令方法 - /// - /// 查询仪器标识,返回制造商、型号、序列号、固件版本 - /// + #region 基础系统命令(必须保留) + + /// 查询设备身份 public Task QueryIDAsync(CancellationToken ct = default) + => SendCommandReadAsync("*IDN?", ct); + + /// 清除错误与状态 + public Task ClearStatusAsync(CancellationToken ct = default) + => SendAsync("*CLS\r\n", ct); + + /// 系统复位 + public Task ResetAsync(CancellationToken ct = default) + => SendAsync("*RST\r\n", ct); + + #endregion + + #region 通道与输出控制 + + /// 选择通道 CH1 或 CH2 + public Task SelectChannelAsync(int channel, CancellationToken ct = default) { - return SendCommandAndReadAsync("*IDN?", ct); + if (channel < 1 || channel > 2) + throw new ArgumentOutOfRangeException(nameof(channel)); + + return SendAsync($"INST:SEL CH{channel}\r\n", ct); } - /// - /// 恢复出厂设置,不清除错误队列 - /// - public Task SendResetAsync(CancellationToken ct = default) + /// 开关输出 + public Task SetOutputAsync(bool on, string channels = "1", CancellationToken ct = default) + => SendAsync($"OUTP {(on ? "ON" : "OFF")},(@{channels})\r\n", ct); + + #endregion + + #region 电压/电流设置 + + /// 设置电压 (0~30.9V) + public Task SetVoltageAsync(double volt, string channels = "1", CancellationToken ct = default) { - return SendAsync("*RST", ct); + if (volt < 0 || volt > 30.9) throw new ArgumentOutOfRangeException(nameof(volt)); + return SendAsync($"SOUR:VOLT {volt},(@{channels})\r\n", ct); } - /// - /// 存储当前仪器状态到指定位置(0~9) - /// - public Task SaveStateAsync(int slot, CancellationToken ct = default) + /// 设置电流限值 (0~20.6A) + public Task SetCurrentAsync(double curr, string channels = "1", CancellationToken ct = default) { - if (slot < 0 || slot > 9) throw new ArgumentOutOfRangeException(nameof(slot)); - return SendAsync($"*SAV {slot}", ct); + if (curr < 0 || curr > 20.6) throw new ArgumentOutOfRangeException(nameof(curr)); + return SendAsync($"SOUR:CURR {curr},(@{channels})\r\n", ct); } - /// - /// 调用指定位置的仪器状态(0~9) - /// - public Task RecallStateAsync(int slot, CancellationToken ct = default) + /// 设置过压保护 + public Task SetOVPAsync(double ovp, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:VOLT:PROT {ovp},(@{channels})\r\n", ct); + + /// 设置过流保护 + public Task SetOCPAsync(double ocp, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:CURR:PROT {ocp},(@{channels})\r\n", ct); + + /// 清除 OVP/OCP 错误 + public Task ClearProtectionAsync(string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:VOLT:PROT:CLE (@{channels})\r\n", ct); + + #endregion + + #region 斜率设置(用于启动测试) + + /// 设置电压上升斜率 + public Task SetRiseSlewAsync(double slew, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:VOLT:SLEW:RIS {slew},(@{channels})\r\n", ct); + + /// 设置电压下降斜率 + public Task SetFallSlewAsync(double slew, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:VOLT:SLEW:FALL {slew},(@{channels})\r\n", ct); + + #endregion + + #region 测量 + + /// 测量电压(V) + public async Task MeasureVoltageAsync(string channels = "1", CancellationToken ct = default) { - if (slot < 0 || slot > 9) throw new ArgumentOutOfRangeException(nameof(slot)); - return SendAsync($"*RCL {slot}", ct); + string result = await SendCommandReadAsync($"MEAS:VOLT? (@{channels})", ct); + return double.TryParse(result, out var value) ? value : 0; } - /// - /// 操作完成标记,发送命令等待操作完成 - /// - public Task SendOPCAsync(CancellationToken ct = default) + /// 测量电流(A) + public async Task MeasureCurrentAsync(string channels = "1", CancellationToken ct = default) { - return SendAsync("*OPC", ct); + string result = await SendCommandReadAsync($"MEAS:CURR? (@{channels})", ct); + return double.TryParse(result, out var value) ? value : 0; } - /// - /// 查询操作完成标记,返回 "1" 表示完成 - /// - public async Task QueryOPCAsync(CancellationToken ct = default) + #endregion + + #region 保护状态查询 + + public async Task QueryOVPTrippedAsync(string channels = "1", CancellationToken ct = default) { - var result = await SendCommandAndReadAsync("*OPC?", ct); + string result = await SendCommandReadAsync($"SOUR:VOLT:PROT:TRIP? (@{channels})", ct); return result == "1"; } - /// - /// 清除状态寄存器与错误队列 - /// - public Task ClearStatusAsync(CancellationToken ct = default) + public async Task QueryOCPTrippedAsync(string channels = "1", CancellationToken ct = default) { - return SendAsync("*CLS", ct); + string result = await SendCommandReadAsync($"SOUR:CURR:PROT:TRIP? (@{channels})", ct); + return result == "1"; } - /// - /// 查询状态字节(STB),返回状态值 - /// - public async Task QueryStatusByteAsync(CancellationToken ct = default) - { - var result = await SendCommandAndReadAsync("*STB?", ct); - return int.TryParse(result, out var value) ? value : 0; - } + #endregion - /// - /// 通用方法:发送命令并读取响应 - /// - private async Task SendCommandAndReadAsync(string command, CancellationToken ct = default) + #region 序列(用于阶梯电压/耐久测试) + + public Task SetVoltageListAsync(double[] voltages, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:LIST:VOLT {string.Join(",", voltages)},(@{channels})\r\n", ct); + + public Task SetCurrentListAsync(double[] currents, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:LIST:CURR {string.Join(",", currents)},(@{channels})\r\n", ct); + + public Task SetDwellListAsync(double[] times, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:LIST:DWEL {string.Join(",", times)},(@{channels})\r\n", ct); + + public Task SetSequenceRepeatAsync(string count, string channels = "1", CancellationToken ct = default) + => SendAsync($"SOUR:LIST:COUN {count},(@{channels})\r\n", ct); + + public Task StartSequenceAsync(string channels = "1", CancellationToken ct = default) + => SendAsync($"INIT (@{channels})\r\n", ct); + + #endregion + + #region 辅助方法 + + private async Task SendCommandReadAsync(string cmd, CancellationToken ct = default) { - await SendAsync($"{command}\r\n", ct); + await SendAsync(cmd + "\r\n", ct); return await ReadAsync("\n", ct); } #endregion - - #region 通道与输出控制命令 - - /// - /// 选择操作通道 - /// - /// 通道号 1 或 2 - public Task SelectChannelAsync(int channel, CancellationToken ct = default) - { - if (channel < 1 || channel > 2) throw new ArgumentOutOfRangeException(nameof(channel)); - return SendAsync($"INST:SEL CH{channel}\r\n", ct); - } - - /// - /// 开启/关闭输出 - /// - /// true 表示开,false 表示关 - /// 通道列表,如 "1", "1:2" - public Task SetOutputStateAsync(bool state, string channels = "1", CancellationToken ct = default) - { - if (string.IsNullOrWhiteSpace(channels)) throw new ArgumentNullException(nameof(channels)); - string cmd = $"OUTP {(state ? "ON" : "OFF")}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 输出上升延迟设置 - /// - /// 延迟时间 0~3600 秒 - /// 通道列表,如 "1", "1:2" - public Task SetOutputRiseDelayAsync(double delay, string channels = "1", CancellationToken ct = default) - { - if (delay < 0 || delay > 3600) throw new ArgumentOutOfRangeException(nameof(delay)); - string cmd = $"OUTP:DEL:RISE {delay}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 输出下降延迟设置 - /// - /// 延迟时间 0~3600 秒 - /// 通道列表,如 "1", "1:2" - public Task SetOutputFallDelayAsync(double delay, string channels = "1", CancellationToken ct = default) - { - if (delay < 0 || delay > 3600) throw new ArgumentOutOfRangeException(nameof(delay)); - string cmd = $"OUTP:DEL:FALL {delay}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置串/并联模式 - /// - /// OFF(独立)、SER(串联)、PAR(并联) - public Task SetOutputPairModeAsync(string mode, CancellationToken ct = default) - { - if (mode != "OFF" && mode != "SER" && mode != "PAR") - throw new ArgumentException("模式必须为 OFF, SER, PAR", nameof(mode)); - return SendAsync($"OUTP:PAIR {mode}\r\n", ct); - } - - /// - /// 通道耦合控制 - /// - /// ALL(全耦合)、NONE(无耦合)、或指定通道,如 @1:2 - public Task SetChannelCoupleAsync(string channelList, CancellationToken ct = default) - { - if (string.IsNullOrWhiteSpace(channelList)) throw new ArgumentNullException(nameof(channelList)); - return SendAsync($"OUTP:COUP:CHAN {channelList}\r\n", ct); - } - - #endregion - - #region 电压 / 电流参数设置命令 - - /// - /// 设置立即电压(单通道或多通道) - /// - public Task SetVoltageAsync(double voltage, string channels = "1", CancellationToken ct = default) - { - if (voltage < 0 || voltage > 30.9) throw new ArgumentOutOfRangeException(nameof(voltage)); - string cmd = $"SOUR:VOLT {voltage}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置立即电流(单通道或多通道) - /// - public Task SetCurrentAsync(double current, string channels = "1", CancellationToken ct = default) - { - if (current < 0 || current > 20.6) throw new ArgumentOutOfRangeException(nameof(current)); - string cmd = $"SOUR:CURR {current}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置触发电压(步进/序列模式使用) - /// - public Task SetTriggeredVoltageAsync(double voltage, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:VOLT:TRIG {voltage}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置触发电流(步进/序列模式使用) - /// - public Task SetTriggeredCurrentAsync(double current, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:CURR:TRIG {current}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置电压模式(FIX/STEP/LIST) - /// - public Task SetVoltageModeAsync(string mode, string channels = "1", CancellationToken ct = default) - { - if (mode != "FIX" && mode != "STEP" && mode != "LIST") throw new ArgumentException("模式必须为 FIX, STEP, LIST", nameof(mode)); - string cmd = $"SOUR:VOLT:MODE {mode}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置电流模式(FIX/STEP/LIST) - /// - public Task SetCurrentModeAsync(string mode, string channels = "1", CancellationToken ct = default) - { - if (mode != "FIX" && mode != "STEP" && mode != "LIST") throw new ArgumentException("模式必须为 FIX, STEP, LIST", nameof(mode)); - string cmd = $"SOUR:CURR:MODE {mode}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置过压保护 OVP(110% 最大电压内) - /// - public Task SetOVPAsync(double voltage, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:VOLT:PROT {voltage}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - /// - /// 设置过流保护 OCP(110% 最大电流内) - /// - public Task SetOCPAsync(double current, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:CURR:PROT {current}, (@{channels})\r\n"; - return SendAsync(cmd, ct); - } - - #endregion - - #region 测量与状态查询命令 - - /// - /// 测量指定通道的实际电压 - /// - public async Task MeasureVoltageAsync(string channels = "1", CancellationToken ct = default) - { - string cmd = $"MEAS:VOLT? (@{channels})\r\n"; - string result = await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap(); - return double.TryParse(result, out var voltage) ? voltage : 0; - } - - /// - /// 测量指定通道的实际电流 - /// - public async Task MeasureCurrentAsync(string channels = "1", CancellationToken ct = default) - { - string cmd = $"MEAS:CURR? (@{channels})\r\n"; - string result = await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap(); - return double.TryParse(result, out var current) ? current : 0; - } - - /// - /// 查询错误队列(FIFO 返回下一个错误) - /// - public async Task QueryNextErrorAsync(CancellationToken ct = default) - { - string cmd = "SYST:ERR? \r\n"; - return await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap(); - } - - /// - /// 查询 OVP(过压保护)状态,返回 true 表示触发 - /// - public async Task QueryOVPTrippedAsync(string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:VOLT:PROT:TRIP? (@{channels})\r\n"; - string result = await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap(); - return result == "1"; - } - - /// - /// 查询 OCP(过流保护)状态,返回 true 表示触发 - /// - public async Task QueryOCPTrippedAsync(string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:CURR:PROT:TRIP? (@{channels})\r\n"; - string result = await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap(); - return result == "1"; - } - - /// - /// 查询远程 / 本地模式,返回 LOC / REM / RWL - /// - public async Task QueryRemoteLocalStateAsync(CancellationToken ct = default) - { - string cmd = "SYST:COMM:RLST?\r\n"; - return await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap(); - } - - #endregion - - #region 电压/电流序列设置与触发 - - /// - /// 设置通道的电压序列 - /// - /// 电压序列,逗号分隔 - /// 通道列表,如 "1" 或 "1:2" - public async Task SetVoltageListAsync(double[] voltages, string channels = "1", CancellationToken ct = default) - { - string values = string.Join(",", voltages); - string cmd = $"SOUR:LIST:VOLT {values}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 设置通道的电流序列 - /// - public async Task SetCurrentListAsync(double[] currents, string channels = "1", CancellationToken ct = default) - { - string values = string.Join(",", currents); - string cmd = $"SOUR:LIST:CURR {values}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 设置每步的 dwell 时间序列 - /// - public async Task SetDwellListAsync(double[] dwellTimes, string channels = "1", CancellationToken ct = default) - { - string values = string.Join(",", dwellTimes); - string cmd = $"SOUR:LIST:DWEL {values}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 设置序列循环次数 - /// - /// 循环次数,1~9999 或 "INF" - public async Task SetSequenceCountAsync(string count, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:LIST:COUN {count}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 启动序列触发 - /// - public async Task StartSequenceAsync(string channels = "1", CancellationToken ct = default) - { - string cmd = $"INIT (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 设置序列触发源 - /// - /// IMMediate、BUS、PIN1、PIN2、PIN3 - public async Task SetTriggerSourceAsync(string source, string channels = "1", CancellationToken ct = default) - { - string cmd = $"TRIG:SOUR {source}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - #endregion - - #region 特殊功能命令 - - /// - /// 设置远端 sensing 模式 - /// - /// INTernal(本地2线)、EXTernal(远端4线) - /// 通道列表,如 "1" 或 "1:2" - public async Task SetRemoteSensingAsync(string mode, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:VOLT:SENS {mode}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 设置电压上升斜率 - /// - /// 单位 V/s - /// 通道列表 - public async Task SetVoltageRiseSlewAsync(double slewRate, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:VOLT:SLEW:RIS {slewRate}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 设置电压下降斜率 - /// - public async Task SetVoltageFallSlewAsync(double slewRate, string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:VOLT:SLEW:FALL {slewRate}, (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 启动数据日志 - /// - /// 日志文件路径,如 Internal:/log1.dlog - public async Task StartDataLogAsync(string filename, CancellationToken ct = default) - { - string cmd = $"INIT:DLOG \"{filename}\"\r\n"; - await SendAsync(cmd, ct); - } - - /// - /// 清除保护状态(OVP/OCP) - /// - /// 通道列表 - public async Task ClearProtectionAsync(string channels = "1", CancellationToken ct = default) - { - string cmd = $"SOUR:VOLT:PROT:CLE (@{channels})\r\n"; - await SendAsync(cmd, ct); - } - - #endregion - - } } diff --git a/DeviceCommand/Device/EAEL9080.cs b/DeviceCommand/Device/EAEL9080.cs index 6421dc2..6bbb10b 100644 --- a/DeviceCommand/Device/EAEL9080.cs +++ b/DeviceCommand/Device/EAEL9080.cs @@ -1,26 +1,24 @@ using Common.Attributes; using DeviceCommand.Base; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Threading; using System.Threading.Tasks; namespace DeviceCommand.Device { [BOBCommand] - public class EAEL9080:ModbusTcp + public class EAEL9080 : ModbusTcp { public EAEL9080(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) { ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); - ConnectAsync(); + } public EAEL9080() { - ConnectAsync(); + } - #region 一、基础控制与远程模式寄存器 + #region 一、基础控制 + public async Task SetRemoteControlAsync(bool activate, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(activate ? 0xFF00 : 0x0000); @@ -39,66 +37,33 @@ namespace DeviceCommand.Device await WriteSingleRegisterAsync(slaveAddress, 409, value, ct); } - public async Task ResetAlarmAsync(byte slaveAddress = 1, CancellationToken ct = default) + public async Task ReadDeviceStatusAsync(byte slaveAddress = 1, CancellationToken ct = default) { - await WriteSingleRegisterAsync(slaveAddress, 411, 0xFF00, ct); + ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 505, 2, ct); + return (uint)(reg[0] << 16 | reg[1]); } - public async Task WriteUserTextAsync(string text, byte slaveAddress = 1, CancellationToken ct = default) + public async Task IsDcOnAsync(byte slaveAddress = 1, CancellationToken ct = default) { - if (string.IsNullOrEmpty(text)) return; - - text = text.Length > 40 ? text[..40] : text; - int frameCount = (int)Math.Ceiling(text.Length / 4.0); - - for (int i = 0; i < frameCount; i++) - { - string frame = text.Substring(i * 4, Math.Min(4, text.Length - i * 4)); - ushort[] values = new ushort[frame.Length]; - for (int j = 0; j < frame.Length; j++) - { - values[j] = frame[j]; - } - await WriteMultipleRegistersAsync(slaveAddress, (ushort)(171 + i), values, ct); - } - } - public async Task QueryRemoteControlAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 402, 1, ct); - return result[0] == 0xFF00; + uint status = await ReadDeviceStatusAsync(slaveAddress, ct); + return (status & (1 << 7)) != 0; } - public async Task QueryOutputAsync(byte slaveAddress = 1, CancellationToken ct = default) + public async Task IsRemoteActiveAsync(byte slaveAddress = 1, CancellationToken ct = default) { - ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 405, 1, ct); - return result[0] == 0xFF00; + uint status = await ReadDeviceStatusAsync(slaveAddress, ct); + return (status & (1 << 10)) != 0; } - public async Task QueryWorkModeAsync(byte slaveAddress = 1, CancellationToken ct = default) + public async Task IsSinkModeActiveAsync(byte slaveAddress = 1, CancellationToken ct = default) { - ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 409, 1, ct); - return result[0] == 0xFF00; // true 表示 UIR(电阻模式),false 表示 UIP + uint status = await ReadDeviceStatusAsync(slaveAddress, ct); + return (status & (1 << 12)) != 0; } - public async Task ReadUserTextAsync(byte slaveAddress = 1, int length = 40, CancellationToken ct = default) - { - int frameCount = (int)Math.Ceiling(length / 4.0); - ushort[] textValues = new ushort[length]; - - for (int i = 0; i < frameCount; i++) - { - ushort[] frame = await ReadHoldingRegistersAsync(slaveAddress, (ushort)(171 + i), 4, ct); - for (int j = 0; j < frame.Length && (i * 4 + j) < length; j++) - { - textValues[i * 4 + j] = frame[j]; - } - } - - return textValues; - } #endregion - #region 二、电压 / 电流 / 功率 / 电阻设定值寄存器 + #region 二、电压 / 电流 / 功率 / 电阻设定值 public async Task SetVoltageAsync(double voltage, double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) { @@ -148,7 +113,10 @@ namespace DeviceCommand.Device return reg[0] / (double)0xCCCC * maxResistance; } - // sink 模式示例写方法 + #endregion + + #region 三、Sink 模式 + public async Task SetSinkPowerAsync(double power, double sinkRatedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(power / sinkRatedPower * 0xCCCC); @@ -167,7 +135,6 @@ namespace DeviceCommand.Device await WriteSingleRegisterAsync(slaveAddress, 504, value, ct); } - // 读方法 public async Task GetSinkPowerAsync(double sinkRatedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 498, 1, ct); @@ -186,309 +153,54 @@ namespace DeviceCommand.Device return reg[0] / (double)0xCCCC * sinkMaxResistance; } - #endregion - #region 三、设备状态与实际值查询寄存器 + #region 四、实时测量 - /// - /// 读取设备状态寄存器(32 位) - /// Bit 7:DC 输出/输入开启 - /// Bit 10:远程控制激活 - /// Bit 12:sink 模式 - /// - public async Task ReadDeviceStatusAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 505, 2, ct); // 32位寄存器 = 2 x 16位 - return (uint)(reg[0] << 16 | reg[1]); - } - - public async Task IsDcOnAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - uint status = await ReadDeviceStatusAsync(slaveAddress, ct); - return (status & (1 << 7)) != 0; - } - - public async Task IsRemoteActiveAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - uint status = await ReadDeviceStatusAsync(slaveAddress, ct); - return (status & (1 << 10)) != 0; - } - - public async Task IsSinkModeActiveAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - uint status = await ReadDeviceStatusAsync(slaveAddress, ct); - return (status & (1 << 12)) != 0; - } - - /// - /// 读取实际电压值(单位 V) - /// 公式: 实际值 = 寄存器值 / 0xCCCC * 额定电压 - /// public async Task ReadActualVoltageAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 507, 1, ct); return reg[0] / (double)0xCCCC * ratedVoltage; } - /// - /// 读取实际电流值(单位 A) - /// sink 模式下可能为负值,需要根据 Bit 12 判断 - /// public async Task ReadActualCurrentAsync(double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 508, 1, ct); double current = reg[0] / (double)0xCCCC * ratedCurrent; - - if (await IsSinkModeActiveAsync(slaveAddress, ct)) - current = -current; // sink 模式电流为负 - + if (await IsSinkModeActiveAsync(slaveAddress, ct)) current = -current; return current; } - /// - /// 读取实际功率值(单位 W) - /// sink 模式下可能为负值 - /// public async Task ReadActualPowerAsync(double ratedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 509, 1, ct); double power = reg[0] / (double)0xCCCC * ratedPower; - - if (await IsSinkModeActiveAsync(slaveAddress, ct)) - power = -power; - + if (await IsSinkModeActiveAsync(slaveAddress, ct)) power = -power; return power; } - /// - /// 读取额定电压(IEEE 754 float) - /// - public async Task ReadRatedVoltageAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 121, 2, ct); - byte[] bytes = new byte[4]; - bytes[0] = (byte)(reg[1] & 0xFF); - bytes[1] = (byte)(reg[1] >> 8); - bytes[2] = (byte)(reg[0] & 0xFF); - bytes[3] = (byte)(reg[0] >> 8); - return BitConverter.ToSingle(bytes, 0); - } - - /// - /// 读取额定电流(IEEE 754 float) - /// - public async Task ReadRatedCurrentAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 122, 2, ct); - byte[] bytes = new byte[4]; - bytes[0] = (byte)(reg[1] & 0xFF); - bytes[1] = (byte)(reg[1] >> 8); - bytes[2] = (byte)(reg[0] & 0xFF); - bytes[3] = (byte)(reg[0] >> 8); - return BitConverter.ToSingle(bytes, 0); - } - - /// - /// 读取额定功率(IEEE 754 float) - /// - public async Task ReadRatedPowerAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 123, 2, ct); - byte[] bytes = new byte[4]; - bytes[0] = (byte)(reg[1] & 0xFF); - bytes[1] = (byte)(reg[1] >> 8); - bytes[2] = (byte)(reg[0] & 0xFF); - bytes[3] = (byte)(reg[0] >> 8); - return BitConverter.ToSingle(bytes, 0); - } - #endregion - #region 四、保护与报警相关寄存器 + #region 五、保护阈值 - /// - /// 设置过压保护(OVP)阈值 - /// public async Task SetOverVoltageLimitAsync(double voltage, double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(voltage / ratedVoltage * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 510, value, ct); } - /// - /// 读取过压保护(OVP)阈值 - /// - public async Task ReadOverVoltageLimitAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 510, 1, ct); - return reg[0] / (double)0xCCCC * ratedVoltage; - } - - /// - /// 设置过流保护(OCP)阈值 - /// public async Task SetOverCurrentLimitAsync(double current, double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(current / ratedCurrent * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 511, value, ct); } - /// - /// 读取过流保护(OCP)阈值 - /// - public async Task ReadOverCurrentLimitAsync(double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 511, 1, ct); - return reg[0] / (double)0xCCCC * ratedCurrent; - } - - /// - /// 设置过功率保护(OPP)阈值 - /// public async Task SetOverPowerLimitAsync(double power, double ratedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(power / ratedPower * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 512, value, ct); } - /// - /// 读取过功率保护(OPP)阈值 - /// - public async Task ReadOverPowerLimitAsync(double ratedPower, byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 512, 1, ct); - return reg[0] / (double)0xCCCC * ratedPower; - } - - /// - /// 读取 OVP 报警计数器,读取后复位 - /// - public async Task ReadOVPCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 520, 1, ct); - return reg[0]; - } - - /// - /// 读取 OCP 报警计数器 - /// - public async Task ReadOCPCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 521, 1, ct); - return reg[0]; - } - - /// - /// 读取 OPP 报警计数器 - /// - public async Task ReadOPPCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 522, 1, ct); - return reg[0]; - } - - /// - /// 读取过温(OT)报警计数器 - /// - public async Task ReadOTCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 523, 1, ct); - return reg[0]; - } - #endregion - - #region 五、函数发生器与特殊功能寄存器 - - // 寄存器 850:函数发生器启动/停止 - public async Task SetFunctionGeneratorAsync(bool start, byte slaveAddress = 1, CancellationToken ct = default) - { - ushort value = start ? (ushort)0xFF00 : (ushort)0x0000; - await WriteSingleRegisterAsync(slaveAddress, 850, value, ct); - } - - public async Task ReadFunctionGeneratorAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 850, 1, ct); - return reg[0] == 0xFF00; - } - - // 寄存器 851:函数发生器作用于电压 - public async Task SetFunctionVoltageParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - await WriteSingleRegisterAsync(slaveAddress, 851, 0xFF00, ct); - } - - public async Task ReadFunctionVoltageParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 851, 1, ct); - return reg[0] == 0xFF00; - } - - // 寄存器 852:函数发生器作用于电流 - public async Task SetFunctionCurrentParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - await WriteSingleRegisterAsync(slaveAddress, 852, 0xFF00, ct); - } - - public async Task ReadFunctionCurrentParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 852, 1, ct); - return reg[0] == 0xFF00; - } - - // 寄存器 859~861:序列控制 - public async Task SetSequenceStartPointAsync(ushort startPoint, byte slaveAddress = 1, CancellationToken ct = default) - { - if (startPoint < 1 || startPoint > 99) throw new ArgumentOutOfRangeException(nameof(startPoint)); - await WriteSingleRegisterAsync(slaveAddress, 859, startPoint, ct); - } - - public async Task ReadSequenceStartPointAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 859, 1, ct); - return reg[0]; - } - - public async Task SetSequenceEndPointAsync(ushort endPoint, byte slaveAddress = 1, CancellationToken ct = default) - { - if (endPoint < 1 || endPoint > 99) throw new ArgumentOutOfRangeException(nameof(endPoint)); - await WriteSingleRegisterAsync(slaveAddress, 860, endPoint, ct); - } - - public async Task ReadSequenceEndPointAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 860, 1, ct); - return reg[0]; - } - - public async Task SetSequenceLoopCountAsync(ushort loopCount, byte slaveAddress = 1, CancellationToken ct = default) - { - if (loopCount > 999) throw new ArgumentOutOfRangeException(nameof(loopCount)); - await WriteSingleRegisterAsync(slaveAddress, 861, loopCount, ct); - } - - public async Task ReadSequenceLoopCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 861, 1, ct); - return reg[0]; - } - - // 寄存器 11000:MPP 跟踪模式 - public async Task SetMPPModeAsync(ushort mode, byte slaveAddress = 1, CancellationToken ct = default) - { - if (mode != 0x0001 && mode != 0x0002 && mode != 0x0004) throw new ArgumentOutOfRangeException(nameof(mode)); - await WriteSingleRegisterAsync(slaveAddress, 11000, mode, ct); - } - - public async Task ReadMPPModeAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 11000, 1, ct); - return reg[0]; - } - - #endregion - } } diff --git a/DeviceCommand/Device/IOBoard.cs b/DeviceCommand/Device/IOBoard.cs index e824b7d..f6d1097 100644 --- a/DeviceCommand/Device/IOBoard.cs +++ b/DeviceCommand/Device/IOBoard.cs @@ -1,4 +1,5 @@ -using DeviceCommand.Base; +using Common.Attributes; +using DeviceCommand.Base; using System; using System.Collections.Generic; using System.Linq; @@ -7,16 +8,17 @@ using System.Threading.Tasks; namespace DeviceCommand.Device { + [BOBCommand] 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) { diff --git a/DeviceCommand/Device/IT6724C.cs b/DeviceCommand/Device/IT6724C.cs index 1309602..b517cac 100644 --- a/DeviceCommand/Device/IT6724C.cs +++ b/DeviceCommand/Device/IT6724C.cs @@ -13,11 +13,11 @@ namespace DeviceCommand.Device 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() { - ConnectAsync(); + } #region 设置命令 diff --git a/DeviceCommand/Device/LQ7500-D.cs b/DeviceCommand/Device/LQ7500-D.cs index 59a66c1..d841c2f 100644 --- a/DeviceCommand/Device/LQ7500-D.cs +++ b/DeviceCommand/Device/LQ7500-D.cs @@ -14,11 +14,11 @@ namespace DeviceCommand.Device 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() { - ConnectAsync(); + } public byte SlaveAddress { get; set; } = 1; // default slave address diff --git a/DeviceCommand/Device/PSB11000.cs b/DeviceCommand/Device/PSB11000.cs index 30faafd..692b020 100644 --- a/DeviceCommand/Device/PSB11000.cs +++ b/DeviceCommand/Device/PSB11000.cs @@ -1,26 +1,23 @@ using Common.Attributes; using DeviceCommand.Base; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Threading; using System.Threading.Tasks; namespace DeviceCommand.Device { [BOBCommand] - public class PSB11000: ModbusTcp + public class PSB11000 : ModbusTcp { public PSB11000(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) { ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); - ConnectAsync(); } - public PSB11000() - { - ConnectAsync(); - } - #region 一、基础控制与远程模式寄存器 + + public PSB11000() { } + + #region 一、基础控制寄存器 + public async Task SetRemoteControlAsync(bool activate, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(activate ? 0xFF00 : 0x0000); @@ -44,24 +41,6 @@ namespace DeviceCommand.Device await WriteSingleRegisterAsync(slaveAddress, 411, 0xFF00, ct); } - public async Task WriteUserTextAsync(string text, byte slaveAddress = 1, CancellationToken ct = default) - { - if (string.IsNullOrEmpty(text)) return; - - text = text.Length > 40 ? text[..40] : text; - int frameCount = (int)Math.Ceiling(text.Length / 4.0); - - for (int i = 0; i < frameCount; i++) - { - string frame = text.Substring(i * 4, Math.Min(4, text.Length - i * 4)); - ushort[] values = new ushort[frame.Length]; - for (int j = 0; j < frame.Length; j++) - { - values[j] = frame[j]; - } - await WriteMultipleRegistersAsync(slaveAddress, (ushort)(171 + i), values, ct); - } - } public async Task QueryRemoteControlAsync(byte slaveAddress = 1, CancellationToken ct = default) { ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 402, 1, ct); @@ -77,28 +56,12 @@ namespace DeviceCommand.Device public async Task QueryWorkModeAsync(byte slaveAddress = 1, CancellationToken ct = default) { ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 409, 1, ct); - return result[0] == 0xFF00; // true 表示 UIR(电阻模式),false 表示 UIP + return result[0] == 0xFF00; // true 表示阻抗模式 } - public async Task ReadUserTextAsync(byte slaveAddress = 1, int length = 40, CancellationToken ct = default) - { - int frameCount = (int)Math.Ceiling(length / 4.0); - ushort[] textValues = new ushort[length]; - - for (int i = 0; i < frameCount; i++) - { - ushort[] frame = await ReadHoldingRegistersAsync(slaveAddress, (ushort)(171 + i), 4, ct); - for (int j = 0; j < frame.Length && (i * 4 + j) < length; j++) - { - textValues[i * 4 + j] = frame[j]; - } - } - - return textValues; - } #endregion - #region 二、电压 / 电流 / 功率 / 电阻设定值寄存器 + #region 二、电压/电流/功率/电阻设定值 public async Task SetVoltageAsync(double voltage, double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) { @@ -148,58 +111,53 @@ namespace DeviceCommand.Device return reg[0] / (double)0xCCCC * maxResistance; } - // sink 模式示例写方法 + #endregion + + #region 三、Sink 双向模式设定值 + public async Task SetSinkPowerAsync(double power, double sinkRatedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(power / sinkRatedPower * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 498, value, ct); } + public async Task GetSinkPowerAsync(double sinkRatedPower, byte slaveAddress = 1, CancellationToken ct = default) + { + ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 498, 1, ct); + return reg[0] / (double)0xCCCC * sinkRatedPower; + } + public async Task SetSinkCurrentAsync(double current, double sinkRatedCurrent, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(current / sinkRatedCurrent * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 499, value, ct); } - public async Task SetSinkResistanceAsync(double resistance, double sinkMaxResistance, byte slaveAddress = 1, CancellationToken ct = default) - { - ushort value = (ushort)(resistance / sinkMaxResistance * 0xCCCC); - await WriteSingleRegisterAsync(slaveAddress, 504, value, ct); - } - - // 读方法 - public async Task GetSinkPowerAsync(double sinkRatedPower, byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 498, 1, ct); - return reg[0] / (double)0xCCCC * sinkRatedPower; - } - public async Task GetSinkCurrentAsync(double sinkRatedCurrent, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 499, 1, ct); return reg[0] / (double)0xCCCC * sinkRatedCurrent; } + public async Task SetSinkResistanceAsync(double resistance, double sinkMaxResistance, byte slaveAddress = 1, CancellationToken ct = default) + { + ushort value = (ushort)(resistance / sinkMaxResistance * 0xCCCC); + await WriteSingleRegisterAsync(slaveAddress, 504, value, ct); + } + public async Task GetSinkResistanceAsync(double sinkMaxResistance, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 504, 1, ct); return reg[0] / (double)0xCCCC * sinkMaxResistance; } - #endregion - #region 三、设备状态与实际值查询寄存器 + #region 四、实时测量与设备状态 - /// - /// 读取设备状态寄存器(32 位) - /// Bit 7:DC 输出/输入开启 - /// Bit 10:远程控制激活 - /// Bit 12:sink 模式 - /// public async Task ReadDeviceStatusAsync(byte slaveAddress = 1, CancellationToken ct = default) { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 505, 2, ct); // 32位寄存器 = 2 x 16位 + ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 505, 2, ct); return (uint)(reg[0] << 16 | reg[1]); } @@ -221,273 +179,68 @@ namespace DeviceCommand.Device return (status & (1 << 12)) != 0; } - /// - /// 读取实际电压值(单位 V) - /// 公式: 实际值 = 寄存器值 / 0xCCCC * 额定电压 - /// public async Task ReadActualVoltageAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 507, 1, ct); return reg[0] / (double)0xCCCC * ratedVoltage; } - /// - /// 读取实际电流值(单位 A) - /// sink 模式下可能为负值,需要根据 Bit 12 判断 - /// public async Task ReadActualCurrentAsync(double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 508, 1, ct); double current = reg[0] / (double)0xCCCC * ratedCurrent; - - if (await IsSinkModeActiveAsync(slaveAddress, ct)) - current = -current; // sink 模式电流为负 - + if (await IsSinkModeActiveAsync(slaveAddress, ct)) current = -current; return current; } - /// - /// 读取实际功率值(单位 W) - /// sink 模式下可能为负值 - /// public async Task ReadActualPowerAsync(double ratedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 509, 1, ct); double power = reg[0] / (double)0xCCCC * ratedPower; - - if (await IsSinkModeActiveAsync(slaveAddress, ct)) - power = -power; - + if (await IsSinkModeActiveAsync(slaveAddress, ct)) power = -power; return power; } - /// - /// 读取额定电压(IEEE 754 float) - /// - public async Task ReadRatedVoltageAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 121, 2, ct); - byte[] bytes = new byte[4]; - bytes[0] = (byte)(reg[1] & 0xFF); - bytes[1] = (byte)(reg[1] >> 8); - bytes[2] = (byte)(reg[0] & 0xFF); - bytes[3] = (byte)(reg[0] >> 8); - return BitConverter.ToSingle(bytes, 0); - } - - /// - /// 读取额定电流(IEEE 754 float) - /// - public async Task ReadRatedCurrentAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 122, 2, ct); - byte[] bytes = new byte[4]; - bytes[0] = (byte)(reg[1] & 0xFF); - bytes[1] = (byte)(reg[1] >> 8); - bytes[2] = (byte)(reg[0] & 0xFF); - bytes[3] = (byte)(reg[0] >> 8); - return BitConverter.ToSingle(bytes, 0); - } - - /// - /// 读取额定功率(IEEE 754 float) - /// - public async Task ReadRatedPowerAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 123, 2, ct); - byte[] bytes = new byte[4]; - bytes[0] = (byte)(reg[1] & 0xFF); - bytes[1] = (byte)(reg[1] >> 8); - bytes[2] = (byte)(reg[0] & 0xFF); - bytes[3] = (byte)(reg[0] >> 8); - return BitConverter.ToSingle(bytes, 0); - } - #endregion - #region 四、保护与报警相关寄存器 + #region 五、保护阈值 - /// - /// 设置过压保护(OVP)阈值 - /// public async Task SetOverVoltageLimitAsync(double voltage, double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(voltage / ratedVoltage * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 510, value, ct); } - /// - /// 读取过压保护(OVP)阈值 - /// public async Task ReadOverVoltageLimitAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 510, 1, ct); return reg[0] / (double)0xCCCC * ratedVoltage; } - /// - /// 设置过流保护(OCP)阈值 - /// public async Task SetOverCurrentLimitAsync(double current, double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(current / ratedCurrent * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 511, value, ct); } - /// - /// 读取过流保护(OCP)阈值 - /// public async Task ReadOverCurrentLimitAsync(double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 511, 1, ct); return reg[0] / (double)0xCCCC * ratedCurrent; } - /// - /// 设置过功率保护(OPP)阈值 - /// public async Task SetOverPowerLimitAsync(double power, double ratedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort value = (ushort)(power / ratedPower * 0xCCCC); await WriteSingleRegisterAsync(slaveAddress, 512, value, ct); } - /// - /// 读取过功率保护(OPP)阈值 - /// public async Task ReadOverPowerLimitAsync(double ratedPower, byte slaveAddress = 1, CancellationToken ct = default) { ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 512, 1, ct); return reg[0] / (double)0xCCCC * ratedPower; } - /// - /// 读取 OVP 报警计数器,读取后复位 - /// - public async Task ReadOVPCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 520, 1, ct); - return reg[0]; - } - - /// - /// 读取 OCP 报警计数器 - /// - public async Task ReadOCPCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 521, 1, ct); - return reg[0]; - } - - /// - /// 读取 OPP 报警计数器 - /// - public async Task ReadOPPCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 522, 1, ct); - return reg[0]; - } - - /// - /// 读取过温(OT)报警计数器 - /// - public async Task ReadOTCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 523, 1, ct); - return reg[0]; - } - - #endregion - - #region 五、函数发生器与特殊功能寄存器 - - // 寄存器 850:函数发生器启动/停止 - public async Task SetFunctionGeneratorAsync(bool start, byte slaveAddress = 1, CancellationToken ct = default) - { - ushort value = start ? (ushort)0xFF00 : (ushort)0x0000; - await WriteSingleRegisterAsync(slaveAddress, 850, value, ct); - } - - public async Task ReadFunctionGeneratorAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 850, 1, ct); - return reg[0] == 0xFF00; - } - - // 寄存器 851:函数发生器作用于电压 - public async Task SetFunctionVoltageParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - await WriteSingleRegisterAsync(slaveAddress, 851, 0xFF00, ct); - } - - public async Task ReadFunctionVoltageParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 851, 1, ct); - return reg[0] == 0xFF00; - } - - // 寄存器 852:函数发生器作用于电流 - public async Task SetFunctionCurrentParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - await WriteSingleRegisterAsync(slaveAddress, 852, 0xFF00, ct); - } - - public async Task ReadFunctionCurrentParamAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 852, 1, ct); - return reg[0] == 0xFF00; - } - - // 寄存器 859~861:序列控制 - public async Task SetSequenceStartPointAsync(ushort startPoint, byte slaveAddress = 1, CancellationToken ct = default) - { - if (startPoint < 1 || startPoint > 99) throw new ArgumentOutOfRangeException(nameof(startPoint)); - await WriteSingleRegisterAsync(slaveAddress, 859, startPoint, ct); - } - - public async Task ReadSequenceStartPointAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 859, 1, ct); - return reg[0]; - } - - public async Task SetSequenceEndPointAsync(ushort endPoint, byte slaveAddress = 1, CancellationToken ct = default) - { - if (endPoint < 1 || endPoint > 99) throw new ArgumentOutOfRangeException(nameof(endPoint)); - await WriteSingleRegisterAsync(slaveAddress, 860, endPoint, ct); - } - - public async Task ReadSequenceEndPointAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 860, 1, ct); - return reg[0]; - } - - public async Task SetSequenceLoopCountAsync(ushort loopCount, byte slaveAddress = 1, CancellationToken ct = default) - { - if (loopCount > 999) throw new ArgumentOutOfRangeException(nameof(loopCount)); - await WriteSingleRegisterAsync(slaveAddress, 861, loopCount, ct); - } - - public async Task ReadSequenceLoopCountAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 861, 1, ct); - return reg[0]; - } - - // 寄存器 11000:MPP 跟踪模式 - public async Task SetMPPModeAsync(ushort mode, byte slaveAddress = 1, CancellationToken ct = default) - { - if (mode != 0x0001 && mode != 0x0002 && mode != 0x0004) throw new ArgumentOutOfRangeException(nameof(mode)); - await WriteSingleRegisterAsync(slaveAddress, 11000, mode, ct); - } - - public async Task ReadMPPModeAsync(byte slaveAddress = 1, CancellationToken ct = default) - { - ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 11000, 1, ct); - return reg[0]; - } - #endregion } } diff --git a/DeviceCommand/Device/SQ0030G1D.cs b/DeviceCommand/Device/SQ0030G1D.cs index 56d26a0..648642e 100644 --- a/DeviceCommand/Device/SQ0030G1D.cs +++ b/DeviceCommand/Device/SQ0030G1D.cs @@ -1,159 +1,85 @@ using Common.Attributes; using DeviceCommand.Base; -using System; using System.Globalization; using System.Threading; using System.Threading.Tasks; namespace DeviceCommand.Device { - /// - /// Sequoia SQ0030G1D 控制类(SCPI 指令封装) - /// + [BOBCommand] public class SQ0030G1D : Tcp { - public SQ0030G1D(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) + public SQ0030G1D(string ip, int port, int sendTimeout, int receiveTimeout) { - ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); - ConnectAsync(); - } - public SQ0030G1D() - { - ConnectAsync(); - } - #region ========== 通用 SCPI 封装 ========== - - /// - /// 发送 SCPI 指令(无返回) - /// - protected async Task WriteAsync(string cmd, CancellationToken ct = default) - { - await SendAsync(cmd + "\n", ct); + ConfigureDevice(ip, port, sendTimeout, receiveTimeout); } - /// - /// 发送 SCPI 指令并读取返回 - /// - protected async Task QueryAsync(string cmd, CancellationToken ct = default) + public SQ0030G1D() { } + + // ===================== 基础封装 ===================== + + private Task WriteAsync(string cmd, CancellationToken ct = default) + => SendAsync(cmd + "\n", ct); + + private async Task QueryAsync(string cmd, CancellationToken ct = default) { await SendAsync(cmd + "\n", ct); return await ReadAsync(ct: ct); } - #endregion + // ===================== 1. 基础控制 ===================== - #region ========== 一、设备基础控制 ========== + public Task GetIdAsync(CancellationToken ct = default) + => QueryAsync("*IDN?", ct); - /// - /// 查询设备标识 (*IDN?) - /// - public async Task GetIdAsync(CancellationToken ct = default) - => await QueryAsync("*IDN?", ct); + public Task ResetAsync(CancellationToken ct = default) + => WriteAsync("*RST", ct); - /// - /// 恢复出厂设置(*RST) - /// - public async Task ResetAsync(CancellationToken ct = default) - => await WriteAsync("*RST", ct); + public Task SetRemoteAsync(CancellationToken ct = default) + => WriteAsync("SYST:REM", ct); - /// - /// 保存参数到内存 (*SAV n) - /// - public async Task SavePresetAsync(int index, CancellationToken ct = default) - => await WriteAsync($"*SAV {index}", ct); + public Task SetLocalAsync(CancellationToken ct = default) + => WriteAsync("SYST:LOC", ct); - /// - /// 从内存调用参数 (*RCL n) - /// - public async Task RecallPresetAsync(int index, CancellationToken ct = default) - => await WriteAsync($"*RCL {index}", ct); + public Task SetOutputAsync(bool on, CancellationToken ct = default) + => WriteAsync($"OUTP:STAT {(on ? "ON" : "OFF")}", ct); - /// - /// 切换到本地模式(SYST:LOC) - /// - public async Task SetLocalAsync(CancellationToken ct = default) - => await WriteAsync("SYST:LOC", ct); - - /// - /// 切换到远程模式(SYST:REM) - /// - public async Task SetRemoteAsync(CancellationToken ct = default) - => await WriteAsync("SYST:REM", ct); - - /// - /// 控制输出开关(ON/OFF) - /// - public async Task SetOutputAsync(bool on, CancellationToken ct = default) - => await WriteAsync($"OUTP:STAT {(on ? "ON" : "OFF")}", ct); - - /// - /// 查询输出状态(返回 true 表示 ON) - /// public async Task GetOutputAsync(CancellationToken ct = default) => (await QueryAsync("OUTP:STAT?", ct)).Trim().ToUpper() == "ON"; - #endregion + // ===================== 2. 电压/频率控制 ===================== - #region ========== 二、电压控制 ========== + public Task SetVoltageAsync(double value, CancellationToken ct = default) + => WriteAsync($"VOLT {value}", ct); - public async Task SetVoltageAsync(double voltage, CancellationToken ct = default) - => await WriteAsync($"VOLT {voltage}", ct); - - public async Task GetVoltageSettingAsync(CancellationToken ct = default) + public async Task GetVoltageAsync(CancellationToken ct = default) => double.Parse((await QueryAsync("VOLT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture); - public async Task SetVoltageOffsetAsync(double value, CancellationToken ct = default) - => await WriteAsync($"VOLT:OFFS {value}", ct); - - public async Task GetVoltageOffsetAsync(CancellationToken ct = default) - => double.Parse((await QueryAsync("VOLT:OFFS?", ct)).Replace("V", ""), CultureInfo.InvariantCulture); - - public async Task SetVoltageMaxAsync(double value, CancellationToken ct = default) - => await WriteAsync($"VOLT:MAX {value}", ct); - - #endregion - - #region ========== 三、电流控制 ========== - - public async Task SetCurrentAsync(double current, CancellationToken ct = default) - => await WriteAsync($"CURR {current}", ct); - - public async Task GetCurrentSettingAsync(CancellationToken ct = default) - => double.Parse((await QueryAsync("CURR?", ct)).Replace("A", ""), CultureInfo.InvariantCulture); - - public async Task SetRegenerativeLimitAsync(double value, CancellationToken ct = default) - => await WriteAsync($"CURR:REG {value}", ct); - - public async Task GetRegenerativeLimitAsync(CancellationToken ct = default) - => double.Parse((await QueryAsync("CURR:REG?", ct)).Replace("A", ""), CultureInfo.InvariantCulture); - - #endregion - - #region ========== 四、频率控制 ========== - - public async Task SetFrequencyAsync(double freq, CancellationToken ct = default) - => await WriteAsync($"FREQ {freq}", ct); + public Task SetFrequencyAsync(double freq, CancellationToken ct = default) + => WriteAsync($"FREQ {freq}", ct); public async Task GetFrequencyAsync(CancellationToken ct = default) => double.Parse((await QueryAsync("FREQ?", ct)).Replace("Hz", ""), CultureInfo.InvariantCulture); - #endregion + // ===================== 3. 保护 ===================== - #region ========== 五、功率控制 ========== + public Task SetOVPAsync(double v, CancellationToken ct = default) + => WriteAsync($"VOLT:PROT {v}", ct); - public async Task SetPowerAsync(double power, CancellationToken ct = default) - => await WriteAsync($"POW {power}", ct); + public async Task GetOVPAsync(CancellationToken ct = default) + => double.Parse((await QueryAsync("VOLT:PROT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture); - public async Task GetPowerSettingAsync(CancellationToken ct = default) - => double.Parse((await QueryAsync("POW?", ct)).Replace("W", ""), CultureInfo.InvariantCulture); + public Task SetOCPAsync(double a, CancellationToken ct = default) + => WriteAsync($"CURR:PROT {a}", ct); - public async Task SetReactivePowerAsync(double var, CancellationToken ct = default) - => await WriteAsync($"POW:REAC {var}", ct); + public async Task GetOCPAsync(CancellationToken ct = default) + => double.Parse((await QueryAsync("CURR:PROT?", ct)).Replace("A", ""), CultureInfo.InvariantCulture); - #endregion + public Task ClearProtectionAsync(CancellationToken ct = default) + => WriteAsync("SYST:PROT:CLE", ct); - #region ========== 六、测量查询 ========== + // ===================== 4. 测量 ===================== public async Task MeasureVoltageAsync(CancellationToken ct = default) => double.Parse((await QueryAsync("MEAS:VOLT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture); @@ -164,14 +90,9 @@ namespace DeviceCommand.Device public async Task MeasurePowerAsync(CancellationToken ct = default) => double.Parse((await QueryAsync("MEAS:POW?", ct)).Replace("W", ""), CultureInfo.InvariantCulture); - /// - /// 同时测量电压、电流、功率 - /// public async Task<(double volt, double curr, double pow)> MeasureArrayAsync(CancellationToken ct = default) { - string result = await QueryAsync("MEAS:ARR?", ct); - var parts = result.Split(','); - + var parts = (await QueryAsync("MEAS:ARR?", ct)).Split(','); return ( double.Parse(parts[0].Replace("V", ""), CultureInfo.InvariantCulture), double.Parse(parts[1].Replace("A", ""), CultureInfo.InvariantCulture), @@ -179,70 +100,15 @@ namespace DeviceCommand.Device ); } - public async Task MeasureHarmonicAsync(int n, CancellationToken ct = default) - => double.Parse((await QueryAsync($"MEAS:HARM? {n}", ct)).Replace("%", ""), CultureInfo.InvariantCulture); + // ===================== 5.(可选)瞬态 ===================== - #endregion + public Task SetTransientOnAsync(bool on, CancellationToken ct = default) + => WriteAsync($"TRAN:STAT {(on ? "ON" : "OFF")}", ct); - #region ========== 七、保护设定 ========== + public Task SetTransientStepVoltageAsync(int step, double volt, CancellationToken ct = default) + => WriteAsync($"TRAN:STEP {step}:VOLT {volt}", ct); - public async Task SetOVPAsync(double v, CancellationToken ct = default) - => await WriteAsync($"VOLT:PROT {v}", ct); - - public async Task GetOVPAsync(CancellationToken ct = default) - => double.Parse((await QueryAsync("VOLT:PROT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture); - - public async Task SetOCPAsync(double a, CancellationToken ct = default) - => await WriteAsync($"CURR:PROT {a}", ct); - - public async Task GetOCPAsync(CancellationToken ct = default) - => double.Parse((await QueryAsync("CURR:PROT?", ct)).Replace("A", ""), CultureInfo.InvariantCulture); - - public async Task GetOTPStatusAsync(CancellationToken ct = default) - => (await QueryAsync("SYST:PROT:OTP?", ct)).Trim().ToUpper() == "ON"; - - public async Task ClearProtectionAsync(CancellationToken ct = default) - => await WriteAsync("SYST:PROT:CLE", ct); - - #endregion - - #region ========== 八、电子负载 ========== - - public async Task SetLoadModeCurrentAsync(CancellationToken ct = default) - => await WriteAsync("LOAD:MODE CURR", ct); - - public async Task SetLoadModePowerAsync(CancellationToken ct = default) - => await WriteAsync("LOAD:MODE POW", ct); - - public async Task SetLoadModeRLCAsync(CancellationToken ct = default) - => await WriteAsync("LOAD:MODE RLC", ct); - - public async Task SetLoadRLCResistanceAsync(double res, CancellationToken ct = default) - => await WriteAsync($"LOAD:RLC:RES {res}", ct); - - #endregion - - #region ========== 九、瞬态编程 ========== - - public async Task SetTransientStateAsync(bool on, CancellationToken ct = default) - => await WriteAsync($"TRAN:STAT {(on ? "ON" : "OFF")}", ct); - - public async Task SetTransientStepVoltageAsync(int step, double volt, CancellationToken ct = default) - => await WriteAsync($"TRAN:STEP {step}:VOLT {volt}", ct); - - public async Task RunTransientAsync(CancellationToken ct = default) - => await WriteAsync("TRAN:RUN", ct); - - #endregion - - #region ========== 十、多设备同步 ========== - - public async Task SetSyncSourceExternalAsync(CancellationToken ct = default) - => await WriteAsync("SYNC:SOUR EXT", ct); - - public async Task GetSyncStatusAsync(CancellationToken ct = default) - => await QueryAsync("SYNC:STAT?", ct); - - #endregion + public Task RunTransientAsync(CancellationToken ct = default) + => WriteAsync("TRAN:RUN", ct); } } diff --git a/DeviceCommand/Device/WS-68030-380T.cs b/DeviceCommand/Device/WS-68030-380T.cs index 6ad8aa3..83aa9ac 100644 --- a/DeviceCommand/Device/WS-68030-380T.cs +++ b/DeviceCommand/Device/WS-68030-380T.cs @@ -12,11 +12,11 @@ namespace DeviceCommand.Device public WS_68030_380T(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) { ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); - ConnectAsync(); + } public WS_68030_380T() { - ConnectAsync(); + } private const byte SlaveAddress = 1; diff --git a/DeviceCommand/Device/ZXKS.cs b/DeviceCommand/Device/ZXKS.cs index f75a6b3..4b57d40 100644 --- a/DeviceCommand/Device/ZXKS.cs +++ b/DeviceCommand/Device/ZXKS.cs @@ -14,11 +14,11 @@ namespace DeviceCommand.Device public ZXKS(string IpAddress, int port, int SendTimeout, int ReceiveTimeout) { ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout); - ConnectAsync(); + } public ZXKS() { - ConnectAsync(); + } } } diff --git a/Logger/LoggingInterceptor.cs b/Logger/LoggingInterceptor.cs index fc65a35..f7a2e33 100644 --- a/Logger/LoggingInterceptor.cs +++ b/Logger/LoggingInterceptor.cs @@ -1,63 +1,140 @@ using Castle.DynamicProxy; -using System; -using System.Collections.Generic; +using Logger; using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace Logger +public class LoggingInterceptor : IInterceptor { - public class LoggingInterceptor : IInterceptor + public void Intercept(IInvocation invocation) { - public void Intercept(IInvocation invocation) + string className = invocation.TargetType.Name; + string methodName = invocation.Method.Name; + + LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 开始"); + + var sw = Stopwatch.StartNew(); + + try { - string className = invocation.TargetType.Name; - string methodName = invocation.Method.Name; + invocation.Proceed(); - LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 开始"); - - var sw = Stopwatch.StartNew(); - - try + // 如果是异步方法 + if (invocation.Method.ReturnType == typeof(Task) || + (invocation.Method.ReturnType.IsGenericType && + invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))) { - // 执行原方法 - 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; + // 异步方法处理 + _= InterceptAsync(invocation, sw); } + + + sw.Stop(); + LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 完成,耗时 {sw.ElapsedMilliseconds} ms"); } - - private async Task InterceptAsync(IInvocation invocation, Stopwatch sw) + catch (Exception ex) { - 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; - } + sw.Stop(); + LoggerHelper.ErrorWithNotify($"调用 {className}.{methodName}() 异常:{ex.Message}", ex.StackTrace); + throw; } } + + private async Task InterceptAsync(IInvocation invocation, Stopwatch sw) + { + // 创建一个默认返回值,用于捕获异常时返回 + object defaultReturnValue = null; + + try + { + // 获取返回类型 + Type returnType = invocation.Method.ReturnType; + + // 如果返回类型是 Task,我们需要处理泛型类型 + if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>)) + { + // 获取泛型参数类型(如 Task 中的 bool) + Type resultType = returnType.GetGenericArguments()[0]; + + // 获取原始方法返回的任务 + var task = (Task)invocation.ReturnValue; + + try + { + // 异步等待并获取结果 + await task; + + // 执行完任务后,获取结果类型并记录日志 + if (resultType == typeof(bool)) + { + bool result = (bool)((dynamic)task).Result; + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms,结果: {result}"); + } + else if (resultType == typeof(bool[])) + { + bool[] result = (bool[])((dynamic)task).Result; + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms,结果: [{string.Join(",", result)}]"); + } + else if (resultType == typeof(ushort[])) + { + ushort[] result = (ushort[])((dynamic)task).Result; + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms,结果: [{string.Join(",", result)}]"); + } + else if (resultType == typeof(string[])) + { + string[] result = (string[])((dynamic)task).Result; + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms,结果: [{string.Join(",", result)}]"); + } + else if (resultType == typeof(byte[])) + { + byte[] result = (byte[])((dynamic)task).Result; + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms,结果: [{BitConverter.ToString(result)}]"); + } + else if (resultType == typeof(void)) + { + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms"); + } + else + { + LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms,结果: {((dynamic)task).Result}"); + } + } + catch (Exception ex) + { + // 如果出现异常,记录异常并设置默认返回值 + sw.Stop(); + LoggerHelper.ErrorWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 异常:{ex.Message}", ex.StackTrace); + + // 根据返回类型设置默认值 + if (resultType == typeof(bool)) + defaultReturnValue = false; // 默认为 false + else if (resultType == typeof(bool[])) + defaultReturnValue = new bool[0]; // 默认为空数组 + else if (resultType == typeof(ushort[])) + defaultReturnValue = new ushort[0]; // 默认为空数组 + else if (resultType == typeof(string[])) + defaultReturnValue = new string[0]; // 默认为空数组 + else if (resultType == typeof(byte[])) + defaultReturnValue = new byte[0]; // 默认为空字节数组 + else if (resultType == typeof(void)) + defaultReturnValue = null; // 无返回值,设置为 null + + // 返回默认值 + invocation.ReturnValue = Task.FromResult(defaultReturnValue); + return; + } + } + else + { + // 如果是普通的 Task,无需处理泛型返回值 + await (Task)invocation.ReturnValue; + 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); + } + } + + } diff --git a/ProcessManager/Setting.xaml b/ProcessManager/Setting.xaml index 4801599..01831d6 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" - + MinHeight="250" Width="800">