添加拦截器
This commit is contained in:
parent
cd5683dae9
commit
a25a4bc6ed
@ -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<DeviceConfigModel> deviceList)
|
||||
{
|
||||
@ -40,16 +44,17 @@ namespace BOB.Singleton
|
||||
{
|
||||
if (E36233ADevice_1 == null)
|
||||
{
|
||||
E36233ADevice_1 = _proxyGen.CreateClassProxy<E36233A>(
|
||||
new object[] { tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout },
|
||||
// 通过接口代理
|
||||
E36233ADevice_1 = _proxyGen.CreateInterfaceProxyWithTarget<ITcp>(
|
||||
new E36233A(tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["E36233A_1"] = E36233ADevice_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
E36233ADevice_2 = _proxyGen.CreateClassProxy<E36233A>(
|
||||
new object[] { tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout },
|
||||
E36233ADevice_2 = _proxyGen.CreateInterfaceProxyWithTarget<ITcp>(
|
||||
new E36233A(tcp1.IPAddress, tcp1.Port, tcp1.ReadTimeout, tcp1.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["E36233A_2"] = E36233ADevice_2;
|
||||
@ -63,16 +68,16 @@ namespace BOB.Singleton
|
||||
{
|
||||
if (IT6724CDevice_1 == null)
|
||||
{
|
||||
IT6724CDevice_1 = _proxyGen.CreateClassProxy<IT6724C>(
|
||||
new object[] { sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout },
|
||||
IT6724CDevice_1 = _proxyGen.CreateInterfaceProxyWithTarget<ISerialPort>(
|
||||
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<IT6724C>(
|
||||
new object[] { sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout },
|
||||
IT6724CDevice_2 = _proxyGen.CreateInterfaceProxyWithTarget<ISerialPort>(
|
||||
new IT6724C(sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["IT6724C_2"] = IT6724CDevice_2;
|
||||
@ -84,8 +89,8 @@ namespace BOB.Singleton
|
||||
case "DeviceCommand.Device.LQ7500_D":
|
||||
if (device.CommunicationConfig is SerialPortConfig sp2)
|
||||
{
|
||||
LQ7500_DDevice = _proxyGen.CreateClassProxy<LQ7500_D>(
|
||||
new object[] { sp2.COMPort, sp2.BaudRate, sp2.DataBit, sp2.StopBit, sp2.ParityBit, sp2.ReadTimeout, sp2.WriteTimeout },
|
||||
LQ7500_DDevice = _proxyGen.CreateInterfaceProxyWithTarget<IModbusDevice>(
|
||||
new LQ7500_D(sp2.COMPort, sp2.BaudRate, sp2.DataBit, sp2.StopBit, sp2.ParityBit, sp2.ReadTimeout, sp2.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["LQ7500_D"] = LQ7500_DDevice;
|
||||
@ -96,8 +101,8 @@ namespace BOB.Singleton
|
||||
case "DeviceCommand.Device.EAEL9080":
|
||||
if (device.CommunicationConfig is TcpConfig tcp2)
|
||||
{
|
||||
EAEL9080Device = _proxyGen.CreateClassProxy<EAEL9080>(
|
||||
new object[] { tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout },
|
||||
EAEL9080Device = _proxyGen.CreateInterfaceProxyWithTarget<IModbusDevice>(
|
||||
new EAEL9080(tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["EAEL9080"] = EAEL9080Device;
|
||||
@ -108,8 +113,8 @@ namespace BOB.Singleton
|
||||
case "DeviceCommand.Device.IOBoard":
|
||||
if (device.CommunicationConfig is TcpConfig tcp3)
|
||||
{
|
||||
IOBoardevice = _proxyGen.CreateClassProxy<IOBoard>(
|
||||
new object[] { tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout },
|
||||
IOBoardevice = _proxyGen.CreateInterfaceProxyWithTarget<IModbusDevice>(
|
||||
new IOBoard(tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["IOBoard"] = IOBoardevice;
|
||||
@ -120,8 +125,8 @@ namespace BOB.Singleton
|
||||
case "DeviceCommand.Device.PSB11000":
|
||||
if (device.CommunicationConfig is TcpConfig tcp4)
|
||||
{
|
||||
PSB11000Device = _proxyGen.CreateClassProxy<PSB11000>(
|
||||
new object[] { tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout },
|
||||
PSB11000Device = _proxyGen.CreateInterfaceProxyWithTarget<IModbusDevice>(
|
||||
new PSB11000(tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["PSB11000"] = PSB11000Device;
|
||||
@ -132,8 +137,8 @@ namespace BOB.Singleton
|
||||
case "DeviceCommand.Device.WS_68030_380T":
|
||||
if (device.CommunicationConfig is TcpConfig tcp5)
|
||||
{
|
||||
WS_68030_380TDevice = _proxyGen.CreateClassProxy<WS_68030_380T>(
|
||||
new object[] { tcp5.IPAddress, tcp5.Port, tcp5.ReadTimeout, tcp5.WriteTimeout },
|
||||
WS_68030_380TDevice = _proxyGen.CreateInterfaceProxyWithTarget<IModbusDevice>(
|
||||
new WS_68030_380T(tcp5.IPAddress, tcp5.Port, tcp5.ReadTimeout, tcp5.WriteTimeout),
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["WS_68030_380T"] = WS_68030_380TDevice;
|
||||
@ -144,8 +149,8 @@ namespace BOB.Singleton
|
||||
case "DeviceCommand.Device.SQ0030G1D":
|
||||
if (device.CommunicationConfig is TcpConfig tcp7)
|
||||
{
|
||||
SQ0030G1DTDevice = _proxyGen.CreateClassProxy<SQ0030G1D>(
|
||||
new object[] { tcp7.IPAddress, tcp7.Port, tcp7.ReadTimeout, tcp7.WriteTimeout },
|
||||
SQ0030G1DTDevice = _proxyGen.CreateInterfaceProxyWithTarget<ITcp>(
|
||||
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<ZXKS>(
|
||||
|
||||
new object[] { tcp6.IPAddress, tcp6.Port, tcp6.ReadTimeout, tcp6.WriteTimeout },
|
||||
ZXKSTDevice = _proxyGen.CreateInterfaceProxyWithTarget<IModbusDevice>(
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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<Devices>();
|
||||
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<WaitingEvent>().Publish(false);
|
||||
}
|
||||
}
|
||||
#region 导航
|
||||
public void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
|
||||
_eventAggregator.GetEvent<WaitingEvent>().Publish(true);
|
||||
_=InitializeDevicesAsync();
|
||||
}
|
||||
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext)
|
||||
|
||||
24
DeviceCommand/Base/IModbusDevice.cs
Normal file
24
DeviceCommand/Base/IModbusDevice.cs
Normal file
@ -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<bool> 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<ushort[]> ReadHoldingRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default);
|
||||
|
||||
Task WriteSingleCoilAsync(byte slaveAddress, ushort coilAddress, bool value, CancellationToken ct = default);
|
||||
Task<bool[]> ReadCoilsAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default);
|
||||
|
||||
Task<ushort[]> ReadInputRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints, CancellationToken ct = default);
|
||||
}
|
||||
|
||||
}
|
||||
18
DeviceCommand/Base/ISerialPort.cs
Normal file
18
DeviceCommand/Base/ISerialPort.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Base
|
||||
{
|
||||
public interface ISerialPort
|
||||
{
|
||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||
|
||||
void Close();
|
||||
|
||||
Task SendAsync(string data, CancellationToken ct = default);
|
||||
|
||||
Task<string> ReadAsync(string delimiter = "\n", CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
23
DeviceCommand/Base/ITCP.cs
Normal file
23
DeviceCommand/Base/ITCP.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceCommand.Base
|
||||
{
|
||||
public interface ITcp
|
||||
{
|
||||
Task<bool> ConnectAsync(CancellationToken ct = default);
|
||||
|
||||
void Close();
|
||||
|
||||
Task SendAsync(byte[] buffer, CancellationToken ct = default);
|
||||
|
||||
Task SendAsync(string str, CancellationToken ct = default);
|
||||
|
||||
Task<byte[]> ReadAsync(int length, CancellationToken ct = default);
|
||||
|
||||
Task<string> ReadAsync(string delimiter = "\n", CancellationToken ct = default);
|
||||
|
||||
Task<string> WriteReadAsync(string command, string delimiter = "\n", CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 常用命令方法
|
||||
|
||||
/// <summary>
|
||||
/// 查询仪器标识,返回制造商、型号、序列号、固件版本
|
||||
/// </summary>
|
||||
#region 基础系统命令(必须保留)
|
||||
|
||||
/// <summary>查询设备身份</summary>
|
||||
public Task<string> QueryIDAsync(CancellationToken ct = default)
|
||||
=> SendCommandReadAsync("*IDN?", ct);
|
||||
|
||||
/// <summary>清除错误与状态</summary>
|
||||
public Task ClearStatusAsync(CancellationToken ct = default)
|
||||
=> SendAsync("*CLS\r\n", ct);
|
||||
|
||||
/// <summary>系统复位</summary>
|
||||
public Task ResetAsync(CancellationToken ct = default)
|
||||
=> SendAsync("*RST\r\n", ct);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 通道与输出控制
|
||||
|
||||
/// <summary>选择通道 CH1 或 CH2</summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 恢复出厂设置,不清除错误队列
|
||||
/// </summary>
|
||||
public Task SendResetAsync(CancellationToken ct = default)
|
||||
/// <summary>开关输出</summary>
|
||||
public Task SetOutputAsync(bool on, string channels = "1", CancellationToken ct = default)
|
||||
=> SendAsync($"OUTP {(on ? "ON" : "OFF")},(@{channels})\r\n", ct);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 电压/电流设置
|
||||
|
||||
/// <summary>设置电压 (0~30.9V)</summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 存储当前仪器状态到指定位置(0~9)
|
||||
/// </summary>
|
||||
public Task SaveStateAsync(int slot, CancellationToken ct = default)
|
||||
/// <summary>设置电流限值 (0~20.6A)</summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调用指定位置的仪器状态(0~9)
|
||||
/// </summary>
|
||||
public Task RecallStateAsync(int slot, CancellationToken ct = default)
|
||||
/// <summary>设置过压保护</summary>
|
||||
public Task SetOVPAsync(double ovp, string channels = "1", CancellationToken ct = default)
|
||||
=> SendAsync($"SOUR:VOLT:PROT {ovp},(@{channels})\r\n", ct);
|
||||
|
||||
/// <summary>设置过流保护</summary>
|
||||
public Task SetOCPAsync(double ocp, string channels = "1", CancellationToken ct = default)
|
||||
=> SendAsync($"SOUR:CURR:PROT {ocp},(@{channels})\r\n", ct);
|
||||
|
||||
/// <summary>清除 OVP/OCP 错误</summary>
|
||||
public Task ClearProtectionAsync(string channels = "1", CancellationToken ct = default)
|
||||
=> SendAsync($"SOUR:VOLT:PROT:CLE (@{channels})\r\n", ct);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 斜率设置(用于启动测试)
|
||||
|
||||
/// <summary>设置电压上升斜率</summary>
|
||||
public Task SetRiseSlewAsync(double slew, string channels = "1", CancellationToken ct = default)
|
||||
=> SendAsync($"SOUR:VOLT:SLEW:RIS {slew},(@{channels})\r\n", ct);
|
||||
|
||||
/// <summary>设置电压下降斜率</summary>
|
||||
public Task SetFallSlewAsync(double slew, string channels = "1", CancellationToken ct = default)
|
||||
=> SendAsync($"SOUR:VOLT:SLEW:FALL {slew},(@{channels})\r\n", ct);
|
||||
|
||||
#endregion
|
||||
|
||||
#region 测量
|
||||
|
||||
/// <summary>测量电压(V)</summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 操作完成标记,发送命令等待操作完成
|
||||
/// </summary>
|
||||
public Task SendOPCAsync(CancellationToken ct = default)
|
||||
/// <summary>测量电流(A)</summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询操作完成标记,返回 "1" 表示完成
|
||||
/// </summary>
|
||||
public async Task<bool> QueryOPCAsync(CancellationToken ct = default)
|
||||
#endregion
|
||||
|
||||
#region 保护状态查询
|
||||
|
||||
public async Task<bool> 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";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除状态寄存器与错误队列
|
||||
/// </summary>
|
||||
public Task ClearStatusAsync(CancellationToken ct = default)
|
||||
public async Task<bool> QueryOCPTrippedAsync(string channels = "1", CancellationToken ct = default)
|
||||
{
|
||||
return SendAsync("*CLS", ct);
|
||||
string result = await SendCommandReadAsync($"SOUR:CURR:PROT:TRIP? (@{channels})", ct);
|
||||
return result == "1";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询状态字节(STB),返回状态值
|
||||
/// </summary>
|
||||
public async Task<int> QueryStatusByteAsync(CancellationToken ct = default)
|
||||
{
|
||||
var result = await SendCommandAndReadAsync("*STB?", ct);
|
||||
return int.TryParse(result, out var value) ? value : 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 通用方法:发送命令并读取响应
|
||||
/// </summary>
|
||||
private async Task<string> 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<string> 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 通道与输出控制命令
|
||||
|
||||
/// <summary>
|
||||
/// 选择操作通道
|
||||
/// </summary>
|
||||
/// <param name="channel">通道号 1 或 2</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开启/关闭输出
|
||||
/// </summary>
|
||||
/// <param name="state">true 表示开,false 表示关</param>
|
||||
/// <param name="channels">通道列表,如 "1", "1:2"</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出上升延迟设置
|
||||
/// </summary>
|
||||
/// <param name="delay">延迟时间 0~3600 秒</param>
|
||||
/// <param name="channels">通道列表,如 "1", "1:2"</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出下降延迟设置
|
||||
/// </summary>
|
||||
/// <param name="delay">延迟时间 0~3600 秒</param>
|
||||
/// <param name="channels">通道列表,如 "1", "1:2"</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置串/并联模式
|
||||
/// </summary>
|
||||
/// <param name="mode">OFF(独立)、SER(串联)、PAR(并联)</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通道耦合控制
|
||||
/// </summary>
|
||||
/// <param name="channelList">ALL(全耦合)、NONE(无耦合)、或指定通道,如 @1:2</param>
|
||||
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 电压 / 电流参数设置命令
|
||||
|
||||
/// <summary>
|
||||
/// 设置立即电压(单通道或多通道)
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置立即电流(单通道或多通道)
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置触发电压(步进/序列模式使用)
|
||||
/// </summary>
|
||||
public Task SetTriggeredVoltageAsync(double voltage, string channels = "1", CancellationToken ct = default)
|
||||
{
|
||||
string cmd = $"SOUR:VOLT:TRIG {voltage}, (@{channels})\r\n";
|
||||
return SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置触发电流(步进/序列模式使用)
|
||||
/// </summary>
|
||||
public Task SetTriggeredCurrentAsync(double current, string channels = "1", CancellationToken ct = default)
|
||||
{
|
||||
string cmd = $"SOUR:CURR:TRIG {current}, (@{channels})\r\n";
|
||||
return SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置电压模式(FIX/STEP/LIST)
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置电流模式(FIX/STEP/LIST)
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置过压保护 OVP(110% 最大电压内)
|
||||
/// </summary>
|
||||
public Task SetOVPAsync(double voltage, string channels = "1", CancellationToken ct = default)
|
||||
{
|
||||
string cmd = $"SOUR:VOLT:PROT {voltage}, (@{channels})\r\n";
|
||||
return SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置过流保护 OCP(110% 最大电流内)
|
||||
/// </summary>
|
||||
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 测量与状态查询命令
|
||||
|
||||
/// <summary>
|
||||
/// 测量指定通道的实际电压
|
||||
/// </summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测量指定通道的实际电流
|
||||
/// </summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询错误队列(FIFO 返回下一个错误)
|
||||
/// </summary>
|
||||
public async Task<string> QueryNextErrorAsync(CancellationToken ct = default)
|
||||
{
|
||||
string cmd = "SYST:ERR? \r\n";
|
||||
return await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询 OVP(过压保护)状态,返回 true 表示触发
|
||||
/// </summary>
|
||||
public async Task<bool> 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";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询 OCP(过流保护)状态,返回 true 表示触发
|
||||
/// </summary>
|
||||
public async Task<bool> 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";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询远程 / 本地模式,返回 LOC / REM / RWL
|
||||
/// </summary>
|
||||
public async Task<string> QueryRemoteLocalStateAsync(CancellationToken ct = default)
|
||||
{
|
||||
string cmd = "SYST:COMM:RLST?\r\n";
|
||||
return await SendAsync(cmd, ct).ContinueWith(_ => ReadAsync(ct: ct)).Unwrap();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 电压/电流序列设置与触发
|
||||
|
||||
/// <summary>
|
||||
/// 设置通道的电压序列
|
||||
/// </summary>
|
||||
/// <param name="voltages">电压序列,逗号分隔</param>
|
||||
/// <param name="channels">通道列表,如 "1" 或 "1:2"</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置通道的电流序列
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置每步的 dwell 时间序列
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置序列循环次数
|
||||
/// </summary>
|
||||
/// <param name="count">循环次数,1~9999 或 "INF"</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动序列触发
|
||||
/// </summary>
|
||||
public async Task StartSequenceAsync(string channels = "1", CancellationToken ct = default)
|
||||
{
|
||||
string cmd = $"INIT (@{channels})\r\n";
|
||||
await SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置序列触发源
|
||||
/// </summary>
|
||||
/// <param name="source">IMMediate、BUS、PIN1、PIN2、PIN3</param>
|
||||
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 特殊功能命令
|
||||
|
||||
/// <summary>
|
||||
/// 设置远端 sensing 模式
|
||||
/// </summary>
|
||||
/// <param name="mode">INTernal(本地2线)、EXTernal(远端4线)</param>
|
||||
/// <param name="channels">通道列表,如 "1" 或 "1:2"</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置电压上升斜率
|
||||
/// </summary>
|
||||
/// <param name="slewRate">单位 V/s</param>
|
||||
/// <param name="channels">通道列表</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置电压下降斜率
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动数据日志
|
||||
/// </summary>
|
||||
/// <param name="filename">日志文件路径,如 Internal:/log1.dlog</param>
|
||||
public async Task StartDataLogAsync(string filename, CancellationToken ct = default)
|
||||
{
|
||||
string cmd = $"INIT:DLOG \"{filename}\"\r\n";
|
||||
await SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除保护状态(OVP/OCP)
|
||||
/// </summary>
|
||||
/// <param name="channels">通道列表</param>
|
||||
public async Task ClearProtectionAsync(string channels = "1", CancellationToken ct = default)
|
||||
{
|
||||
string cmd = $"SOUR:VOLT:PROT:CLE (@{channels})\r\n";
|
||||
await SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<uint> 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<bool> 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<bool> 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<bool> QueryOutputAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
public async Task<bool> 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<bool> QueryWorkModeAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
public async Task<bool> 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<ushort[]> 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<double> 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 四、实时测量
|
||||
|
||||
/// <summary>
|
||||
/// 读取设备状态寄存器(32 位)
|
||||
/// Bit 7:DC 输出/输入开启
|
||||
/// Bit 10:远程控制激活
|
||||
/// Bit 12:sink 模式
|
||||
/// </summary>
|
||||
public async Task<uint> 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<bool> IsDcOnAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
uint status = await ReadDeviceStatusAsync(slaveAddress, ct);
|
||||
return (status & (1 << 7)) != 0;
|
||||
}
|
||||
|
||||
public async Task<bool> IsRemoteActiveAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
uint status = await ReadDeviceStatusAsync(slaveAddress, ct);
|
||||
return (status & (1 << 10)) != 0;
|
||||
}
|
||||
|
||||
public async Task<bool> IsSinkModeActiveAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
uint status = await ReadDeviceStatusAsync(slaveAddress, ct);
|
||||
return (status & (1 << 12)) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取实际电压值(单位 V)
|
||||
/// 公式: 实际值 = 寄存器值 / 0xCCCC * 额定电压
|
||||
/// </summary>
|
||||
public async Task<double> ReadActualVoltageAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 507, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedVoltage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取实际电流值(单位 A)
|
||||
/// sink 模式下可能为负值,需要根据 Bit 12 判断
|
||||
/// </summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取实际功率值(单位 W)
|
||||
/// sink 模式下可能为负值
|
||||
/// </summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取额定电压(IEEE 754 float)
|
||||
/// </summary>
|
||||
public async Task<float> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取额定电流(IEEE 754 float)
|
||||
/// </summary>
|
||||
public async Task<float> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取额定功率(IEEE 754 float)
|
||||
/// </summary>
|
||||
public async Task<float> 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 五、保护阈值
|
||||
|
||||
/// <summary>
|
||||
/// 设置过压保护(OVP)阈值
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过压保护(OVP)阈值
|
||||
/// </summary>
|
||||
public async Task<double> ReadOverVoltageLimitAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 510, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedVoltage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置过流保护(OCP)阈值
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过流保护(OCP)阈值
|
||||
/// </summary>
|
||||
public async Task<double> ReadOverCurrentLimitAsync(double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 511, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedCurrent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置过功率保护(OPP)阈值
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过功率保护(OPP)阈值
|
||||
/// </summary>
|
||||
public async Task<double> ReadOverPowerLimitAsync(double ratedPower, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 512, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedPower;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取 OVP 报警计数器,读取后复位
|
||||
/// </summary>
|
||||
public async Task<ushort> ReadOVPCountAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 520, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取 OCP 报警计数器
|
||||
/// </summary>
|
||||
public async Task<ushort> ReadOCPCountAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 521, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取 OPP 报警计数器
|
||||
/// </summary>
|
||||
public async Task<ushort> ReadOPPCountAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 522, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过温(OT)报警计数器
|
||||
/// </summary>
|
||||
public async Task<ushort> 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<bool> 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<bool> 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<bool> 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<ushort> 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<ushort> 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<ushort> 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<ushort> ReadMPPModeAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 11000, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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 设置命令
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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<bool> 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<bool> 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<ushort[]> 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<double> 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<double> 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<double> 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<double> 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 四、实时测量与设备状态
|
||||
|
||||
/// <summary>
|
||||
/// 读取设备状态寄存器(32 位)
|
||||
/// Bit 7:DC 输出/输入开启
|
||||
/// Bit 10:远程控制激活
|
||||
/// Bit 12:sink 模式
|
||||
/// </summary>
|
||||
public async Task<uint> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取实际电压值(单位 V)
|
||||
/// 公式: 实际值 = 寄存器值 / 0xCCCC * 额定电压
|
||||
/// </summary>
|
||||
public async Task<double> ReadActualVoltageAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 507, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedVoltage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取实际电流值(单位 A)
|
||||
/// sink 模式下可能为负值,需要根据 Bit 12 判断
|
||||
/// </summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取实际功率值(单位 W)
|
||||
/// sink 模式下可能为负值
|
||||
/// </summary>
|
||||
public async Task<double> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取额定电压(IEEE 754 float)
|
||||
/// </summary>
|
||||
public async Task<float> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取额定电流(IEEE 754 float)
|
||||
/// </summary>
|
||||
public async Task<float> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取额定功率(IEEE 754 float)
|
||||
/// </summary>
|
||||
public async Task<float> 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 五、保护阈值
|
||||
|
||||
/// <summary>
|
||||
/// 设置过压保护(OVP)阈值
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过压保护(OVP)阈值
|
||||
/// </summary>
|
||||
public async Task<double> ReadOverVoltageLimitAsync(double ratedVoltage, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 510, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedVoltage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置过流保护(OCP)阈值
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过流保护(OCP)阈值
|
||||
/// </summary>
|
||||
public async Task<double> ReadOverCurrentLimitAsync(double ratedCurrent, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 511, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedCurrent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置过功率保护(OPP)阈值
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过功率保护(OPP)阈值
|
||||
/// </summary>
|
||||
public async Task<double> ReadOverPowerLimitAsync(double ratedPower, byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 512, 1, ct);
|
||||
return reg[0] / (double)0xCCCC * ratedPower;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取 OVP 报警计数器,读取后复位
|
||||
/// </summary>
|
||||
public async Task<ushort> ReadOVPCountAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 520, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取 OCP 报警计数器
|
||||
/// </summary>
|
||||
public async Task<ushort> ReadOCPCountAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 521, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取 OPP 报警计数器
|
||||
/// </summary>
|
||||
public async Task<ushort> ReadOPPCountAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 522, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取过温(OT)报警计数器
|
||||
/// </summary>
|
||||
public async Task<ushort> 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<bool> 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<bool> 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<bool> 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<ushort> 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<ushort> 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<ushort> 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<ushort> ReadMPPModeAsync(byte slaveAddress = 1, CancellationToken ct = default)
|
||||
{
|
||||
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 11000, 1, ct);
|
||||
return reg[0];
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Sequoia SQ0030G1D 控制类(SCPI 指令封装)
|
||||
/// </summary>
|
||||
|
||||
[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 封装 ==========
|
||||
|
||||
/// <summary>
|
||||
/// 发送 SCPI 指令(无返回)
|
||||
/// </summary>
|
||||
protected async Task WriteAsync(string cmd, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync(cmd + "\n", ct);
|
||||
ConfigureDevice(ip, port, sendTimeout, receiveTimeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送 SCPI 指令并读取返回
|
||||
/// </summary>
|
||||
protected async Task<string> QueryAsync(string cmd, CancellationToken ct = default)
|
||||
public SQ0030G1D() { }
|
||||
|
||||
// ===================== 基础封装 =====================
|
||||
|
||||
private Task WriteAsync(string cmd, CancellationToken ct = default)
|
||||
=> SendAsync(cmd + "\n", ct);
|
||||
|
||||
private async Task<string> QueryAsync(string cmd, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync(cmd + "\n", ct);
|
||||
return await ReadAsync(ct: ct);
|
||||
}
|
||||
|
||||
#endregion
|
||||
// ===================== 1. 基础控制 =====================
|
||||
|
||||
#region ========== 一、设备基础控制 ==========
|
||||
public Task<string> GetIdAsync(CancellationToken ct = default)
|
||||
=> QueryAsync("*IDN?", ct);
|
||||
|
||||
/// <summary>
|
||||
/// 查询设备标识 (*IDN?)
|
||||
/// </summary>
|
||||
public async Task<string> GetIdAsync(CancellationToken ct = default)
|
||||
=> await QueryAsync("*IDN?", ct);
|
||||
public Task ResetAsync(CancellationToken ct = default)
|
||||
=> WriteAsync("*RST", ct);
|
||||
|
||||
/// <summary>
|
||||
/// 恢复出厂设置(*RST)
|
||||
/// </summary>
|
||||
public async Task ResetAsync(CancellationToken ct = default)
|
||||
=> await WriteAsync("*RST", ct);
|
||||
public Task SetRemoteAsync(CancellationToken ct = default)
|
||||
=> WriteAsync("SYST:REM", ct);
|
||||
|
||||
/// <summary>
|
||||
/// 保存参数到内存 (*SAV n)
|
||||
/// </summary>
|
||||
public async Task SavePresetAsync(int index, CancellationToken ct = default)
|
||||
=> await WriteAsync($"*SAV {index}", ct);
|
||||
public Task SetLocalAsync(CancellationToken ct = default)
|
||||
=> WriteAsync("SYST:LOC", ct);
|
||||
|
||||
/// <summary>
|
||||
/// 从内存调用参数 (*RCL n)
|
||||
/// </summary>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// 切换到本地模式(SYST:LOC)
|
||||
/// </summary>
|
||||
public async Task SetLocalAsync(CancellationToken ct = default)
|
||||
=> await WriteAsync("SYST:LOC", ct);
|
||||
|
||||
/// <summary>
|
||||
/// 切换到远程模式(SYST:REM)
|
||||
/// </summary>
|
||||
public async Task SetRemoteAsync(CancellationToken ct = default)
|
||||
=> await WriteAsync("SYST:REM", ct);
|
||||
|
||||
/// <summary>
|
||||
/// 控制输出开关(ON/OFF)
|
||||
/// </summary>
|
||||
public async Task SetOutputAsync(bool on, CancellationToken ct = default)
|
||||
=> await WriteAsync($"OUTP:STAT {(on ? "ON" : "OFF")}", ct);
|
||||
|
||||
/// <summary>
|
||||
/// 查询输出状态(返回 true 表示 ON)
|
||||
/// </summary>
|
||||
public async Task<bool> 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<double> GetVoltageSettingAsync(CancellationToken ct = default)
|
||||
public async Task<double> 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<double> 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<double> 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<double> 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<double> 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<double> GetOVPAsync(CancellationToken ct = default)
|
||||
=> double.Parse((await QueryAsync("VOLT:PROT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);
|
||||
|
||||
public async Task<double> 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<double> 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<double> 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<double> MeasurePowerAsync(CancellationToken ct = default)
|
||||
=> double.Parse((await QueryAsync("MEAS:POW?", ct)).Replace("W", ""), CultureInfo.InvariantCulture);
|
||||
|
||||
/// <summary>
|
||||
/// 同时测量电压、电流、功率
|
||||
/// </summary>
|
||||
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<double> 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<double> 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<double> GetOCPAsync(CancellationToken ct = default)
|
||||
=> double.Parse((await QueryAsync("CURR:PROT?", ct)).Replace("A", ""), CultureInfo.InvariantCulture);
|
||||
|
||||
public async Task<bool> 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<string> GetSyncStatusAsync(CancellationToken ct = default)
|
||||
=> await QueryAsync("SYNC:STAT?", ct);
|
||||
|
||||
#endregion
|
||||
public Task RunTransientAsync(CancellationToken ct = default)
|
||||
=> WriteAsync("TRAN:RUN", ct);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,9 @@
|
||||
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)
|
||||
{
|
||||
string className = invocation.TargetType.Name;
|
||||
@ -21,7 +15,6 @@ namespace Logger
|
||||
|
||||
try
|
||||
{
|
||||
// 执行原方法
|
||||
invocation.Proceed();
|
||||
|
||||
// 如果是异步方法
|
||||
@ -29,12 +22,13 @@ namespace Logger
|
||||
(invocation.Method.ReturnType.IsGenericType &&
|
||||
invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)))
|
||||
{
|
||||
invocation.ReturnValue = InterceptAsync(invocation, sw);
|
||||
return;
|
||||
// 异步方法处理
|
||||
_= InterceptAsync(invocation, sw);
|
||||
}
|
||||
|
||||
|
||||
sw.Stop();
|
||||
LoggerHelper.SuccessWithNotify($"调用 {className}.{methodName}() 完成,耗时 {sw.ElapsedMilliseconds} ms");
|
||||
LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 完成,耗时 {sw.ElapsedMilliseconds} ms");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -46,18 +40,101 @@ namespace Logger
|
||||
|
||||
private async Task InterceptAsync(IInvocation invocation, Stopwatch sw)
|
||||
{
|
||||
// 创建一个默认返回值,用于捕获异常时返回
|
||||
object defaultReturnValue = null;
|
||||
|
||||
try
|
||||
{
|
||||
await (Task)invocation.ReturnValue;
|
||||
sw.Stop();
|
||||
// 获取返回类型
|
||||
Type returnType = invocation.Method.ReturnType;
|
||||
|
||||
// 如果返回类型是 Task<T>,我们需要处理泛型类型
|
||||
if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
{
|
||||
// 获取泛型参数类型(如 Task<bool> 中的 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);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user