添加设备心跳添加设备控制界面

This commit is contained in:
hsc 2025-11-24 15:57:19 +08:00
parent 4640b47331
commit 9264596831
58 changed files with 4995 additions and 531 deletions

View File

@ -34,7 +34,7 @@ namespace BOB
}
else
{
SystemConfig.Instance.Title = "设备1";//模拟打开的设备
SystemConfig.Instance.Title = "设备2";//模拟打开的设备
}
base.OnStartup(e);
}
@ -42,7 +42,6 @@ namespace BOB
protected override void OnInitialized()
{
base.OnInitialized();
var regionManager = Container.Resolve<IRegionManager>();
regionManager.RequestNavigate("ShellViewManager", "MainView");
}
@ -55,7 +54,15 @@ namespace BOB
//注册弹窗
containerRegistry.RegisterDialog<MessageBoxView, MessageBoxViewModel>("MessageBox");
containerRegistry.RegisterDialog<ParameterSetting, ParameterSettingViewModel>("ParameterSetting");
containerRegistry.RegisterDialog<DeviceSetting, DeviceSettingViewModel>("DeviceSetting");
containerRegistry.RegisterDialog<BackfeedView, BackfeedViewModel>("Backfeed");
containerRegistry.RegisterDialog<EAEL9080View, EAEL9080ViewModel>("EAEL9080");
containerRegistry.RegisterDialog<IOBoardView, IOBoardViewModel>("IOBoard");
containerRegistry.RegisterDialog<IT6724CView, IT6724CViewModel>("IT6724C");
containerRegistry.RegisterDialog<LQ7500_DView, LQ7500_DViewModel>("LQ7500_D");
containerRegistry.RegisterDialog<PSB11000View, PSB11000ViewModel>("PSB11000");
containerRegistry.RegisterDialog<SQ0030G1DView, SQ0030G1DViewModel>("SQ0030G1D");
containerRegistry.RegisterDialog<WS_68030_380TView, WS_68030_380TViewModel>("WS_68030_380T");
containerRegistry.RegisterDialog<ZXKSView, ZXKSViewModel>("ZXKS");
//注册全局变量
containerRegistry.RegisterSingleton<GlobalVariables>();
containerRegistry.RegisterSingleton<Devices>();
@ -63,8 +70,8 @@ namespace BOB
}
protected override void OnExit(ExitEventArgs e)
{
var devices = Container.Resolve<Devices>();
devices.Dispose();
//var devices = Container.Resolve<Devices>();
//devices.Dispose();
base.OnExit(e);
}
}

View File

@ -0,0 +1,49 @@
using Model;
namespace BOB.Models
{
public class DeviceInfoModel : BindableBase
{
private string _deviceName;
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private string _deviceType;
public string DeviceType
{
get => _deviceType;
set => SetProperty(ref _deviceType, value);
}
private string _remark;
public string Remark
{
get => _remark;
set => SetProperty(ref _remark, value);
}
private bool _isEnabled;
public bool IsEnabled
{
get => _isEnabled;
set => SetProperty(ref _isEnabled, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private ICommunicationConfig _communicationConfig;
public ICommunicationConfig CommunicationConfig
{
get => _communicationConfig;
set => SetProperty(ref _communicationConfig, value);
}
}
}

View File

@ -21,13 +21,11 @@ namespace BOB.Singleton
private readonly ProxyGenerator _proxyGen = new ProxyGenerator();
private readonly IInterceptor _loggingInterceptor = new LoggingInterceptor();
//private ITcp E36233ADevice { get; set; }
private ISerialPort IT6724CDevice { get; set; }
//private ISerialPort IT6724CReverseDevice{ get; set; }
private IModbusDevice EAEL9080Device { get; set; }
private ITcp EAEL9080Device { get; set; }
private IModbusDevice IOBoardevice { get; set; }
private IModbusDevice LQ7500_DDevice { get; set; }
private IModbusDevice PSB11000Device { get; set; }
private ITcp PSB11000Device { get; set; }
private IModbusDevice WS_68030_380TDevice { get; set; }
private ITcp SQ0030G1DTDevice { get; set; }
private IModbusDevice ZXKSTDevice { get; set; }
@ -47,14 +45,21 @@ namespace BOB.Singleton
case "DeviceCommand.Device.E36233A":
if (device.CommunicationConfig is TcpConfig tcp1)
{
BackfeedDevice=new Backfeed(tcp1);
BackfeedDevice = _proxyGen.CreateClassProxy<Backfeed>(
new object[] { tcp1 },
_loggingInterceptor
);
DeviceDic["Backfeed"] = BackfeedDevice;
}
break;
case "DeviceCommand.Device.IT6724CReverse":
if (device.CommunicationConfig is SerialPortConfig sp3)
{
BackfeedDevice = new Backfeed(sp3);
BackfeedDevice = _proxyGen.CreateClassProxy<Backfeed>(
new object[] { sp3 },
_loggingInterceptor
);
DeviceDic["Backfeed"] = BackfeedDevice;
}
break;
@ -62,8 +67,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.IT6724C":
if (device.CommunicationConfig is SerialPortConfig sp1)
{
IT6724CDevice = _proxyGen.CreateClassProxyWithTarget(
new IT6724C(sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout),
var IT6724CDevice = _proxyGen.CreateClassProxy<IT6724C>(
new object[] { sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout },
_loggingInterceptor
);
DeviceDic["IT6724C"] = IT6724CDevice;
@ -74,8 +79,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.LQ7500_D":
if (device.CommunicationConfig is SerialPortConfig sp2)
{
LQ7500_DDevice = _proxyGen.CreateClassProxyWithTarget(
new LQ7500_D(sp2.COMPort, sp2.BaudRate, sp2.DataBit, sp2.StopBit, sp2.ParityBit, sp2.ReadTimeout, sp2.WriteTimeout),
var LQ7500_DDevice = _proxyGen.CreateClassProxy<LQ7500_D>(
new object[] { sp2.COMPort, sp2.BaudRate, sp2.DataBit, sp2.StopBit, sp2.ParityBit, sp2.ReadTimeout, sp2.WriteTimeout },
_loggingInterceptor
);
DeviceDic["LQ7500_D"] = LQ7500_DDevice;
@ -86,8 +91,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.EAEL9080":
if (device.CommunicationConfig is TcpConfig tcp2)
{
EAEL9080Device = _proxyGen.CreateClassProxyWithTarget(
new EAEL9080(tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout),
var EAEL9080Device = _proxyGen.CreateClassProxy<EAEL9080>(
new object[] { tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout },
_loggingInterceptor
);
DeviceDic["EAEL9080"] = EAEL9080Device;
@ -98,8 +103,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.IOBoard":
if (device.CommunicationConfig is TcpConfig tcp3)
{
IOBoardevice = _proxyGen.CreateClassProxyWithTarget(
new IOBoard(tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout),
var IOBoardevice = _proxyGen.CreateClassProxy<IOBoard>(
new object[] { tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout },
_loggingInterceptor
);
DeviceDic["IOBoard"] = IOBoardevice;
@ -110,8 +115,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.PSB11000":
if (device.CommunicationConfig is TcpConfig tcp4)
{
PSB11000Device = _proxyGen.CreateClassProxyWithTarget(
new PSB11000(tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout),
var PSB11000Device = _proxyGen.CreateClassProxy<PSB11000>(
new object[] { tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout },
_loggingInterceptor
);
DeviceDic["PSB11000"] = PSB11000Device;
@ -122,8 +127,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.WS_68030_380T":
if (device.CommunicationConfig is TcpConfig tcp5)
{
WS_68030_380TDevice = _proxyGen.CreateClassProxyWithTarget(
new WS_68030_380T(tcp5.IPAddress, tcp5.Port, tcp5.ReadTimeout, tcp5.WriteTimeout),
var WS_68030_380TDevice = _proxyGen.CreateClassProxy<WS_68030_380T>(
new object[] { tcp5.IPAddress, tcp5.Port, tcp5.ReadTimeout, tcp5.WriteTimeout },
_loggingInterceptor
);
DeviceDic["WS_68030_380T"] = WS_68030_380TDevice;
@ -134,8 +139,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.SQ0030G1D":
if (device.CommunicationConfig is TcpConfig tcp7)
{
SQ0030G1DTDevice = _proxyGen.CreateClassProxyWithTarget(
new SQ0030G1D(tcp7.IPAddress, tcp7.Port, tcp7.ReadTimeout, tcp7.WriteTimeout),
var SQ0030G1DTDevice = _proxyGen.CreateClassProxy<SQ0030G1D>(
new object[] { tcp7.IPAddress, tcp7.Port, tcp7.ReadTimeout, tcp7.WriteTimeout },
_loggingInterceptor
);
DeviceDic["SQ0030G1D"] = SQ0030G1DTDevice;
@ -146,8 +151,8 @@ namespace BOB.Singleton
case "DeviceCommand.Device.ZXKS":
if (device.CommunicationConfig is TcpConfig tcp6)
{
ZXKSTDevice = _proxyGen.CreateClassProxyWithTarget(
new ZXKS(tcp6.IPAddress, tcp6.Port, tcp6.ReadTimeout, tcp6.WriteTimeout),
var ZXKSTDevice = _proxyGen.CreateClassProxy<ZXKS>(
new object[] { tcp6.IPAddress, tcp6.Port, tcp6.ReadTimeout, tcp6.WriteTimeout },
_loggingInterceptor
);
DeviceDic["ZXKS"] = ZXKSTDevice;
@ -159,6 +164,7 @@ namespace BOB.Singleton
throw new NotSupportedException($"未知设备类型:{device.DeviceType}");
}
}
}

View File

@ -0,0 +1,159 @@
using DeviceCommand.Base;
using DeviceCommand.Device;
using Logger;
namespace BOB.Tasks
{
public class HeartbeatManager<T> where T : class
{
private readonly T _device;
private readonly CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
bool IsActive = false;
int ReConnectionAttempts = 0;
private const int MaxReconnectAttempts = 10;
public HeartbeatManager(T device)
{
_device = device ?? throw new ArgumentNullException(nameof(device));
_cancellationTokenSource = new CancellationTokenSource();
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
_heartbeatTask = Task.Run(() => HeartbeatLoop(_device, _cancellationTokenSource.Token));
}
// 停止设备的心跳
public void StopHeartbeat()
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask?.Wait();
_heartbeatTask = null;
}
private async Task HeartbeatLoop(T device, CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
switch (device)
{
case EAEL9080 eAEL9080:
await eAEL9080.SendAsync("SYSTem:REMote\r\n", ct);
IsActive = true;
break;
case IT6724C iT6724C:
await iT6724C.SendAsync("SYSTem:REMote\r\n", ct);
IsActive = true;
break;
case PSB11000 pSB11000:
await pSB11000.SendAsync("SYSTem:REMote\r\n", ct);
IsActive = true;
break;
case SQ0030G1D sQ0030G1D:
await sQ0030G1D.SendAsync("SYSTem:REMote\r\n", ct);
IsActive = true;
break;
case WS_68030_380T wS_68030_380T:
await wS_68030_380T.ReadCoilsAsync(1,0,1);
IsActive = true;
break;
case IOBoard iOBoard:
await iOBoard.ReadCoilsAsync(1, 0, 1);
IsActive = true;
break;
case LQ7500_D lQ7500_D:
await lQ7500_D.ReadCoilsAsync(1, 0, 1);
IsActive = true;
break;
case ZXKS zXKS:
await zXKS.ReadCoilsAsync(1, 0, 1);
IsActive = true;
break;
case Backfeed backfeed:
if (backfeed.CurrentInstance is E36233A e36233A)
{
await e36233A.SendAsync("SYSTem:REMote\r\n", ct);
IsActive = true;
}
else if (backfeed.CurrentInstance is IT6724CReverse iT6724CReverse)
{
await iT6724CReverse.SendAsync("SYSTem:REMote\r\n", ct);
IsActive = true;
}
break;
}
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
LoggerHelper.ErrorWithNotify($"重连次数超过上限,停止重连:{device.GetType().Name}");
StopHeartbeat();
return;
}
await ReconnectDevice(device, ct);
}
}
}
private async Task ReconnectDevice(T device, CancellationToken ct)
{
try
{
bool result = false;
if (device is ITcp itcpDevice)
{
result = await itcpDevice.ConnectAsync(CancellationToken.None);
}
else if (device is IModbusDevice imodbusDevice)
{
result = await imodbusDevice.ConnectAsync(CancellationToken.None);
}
else if (device is ISerialPort iserialPortDevice)
{
result = await iserialPortDevice.ConnectAsync(CancellationToken.None);
}
else if (device is Backfeed backfeedDevice)
{
if (backfeedDevice.CurrentInstance is ITcp itcpDevice1)
{
result = await itcpDevice1.ConnectAsync(CancellationToken.None);
}
else if (backfeedDevice.CurrentInstance is ISerialPort iserialPortDevice1)
{
result = await iserialPortDevice1.ConnectAsync(CancellationToken.None);
}
}
if (result == false) { LoggerHelper.ErrorWithNotify($"重连失败:{device.GetType().Name}"); }
else ReConnectionAttempts=0;
}
catch (Exception ex)
{
LoggerHelper.ErrorWithNotify($"重连异常:{device.GetType().Name}"+ex.Message);
}
}
}
}

View File

@ -0,0 +1,351 @@
using BOB.Singleton;
using DeviceCommand.Device;
using Logger;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using SqlSugar;
using System;
using System.Windows.Input;
namespace BOB.ViewModels.Dialogs
{
public class BackfeedViewModel : BindableBase, IDialogAware
{
#region
private string _Title = "反灌电压";
public string Title
{
get { return _Title; }
set { SetProperty(ref _Title, value); }
}
private string _设备标识字符串;
public string
{
get { return _设备标识字符串; }
set { SetProperty(ref _设备标识字符串, value); }
}
private string _输出电压;
public string
{
get { return _输出电压; }
set { SetProperty(ref _输出电压, value); }
}
private string _输出电流;
public string
{
get { return _输出电流; }
set { SetProperty(ref _输出电流, value); }
}
private string _OCP电流;
public string OCP电流
{
get { return _OCP电流; }
set { SetProperty(ref _OCP电流, value); }
}
private string _OVP电压;
public string OVP电压
{
get { return _OVP电压; }
set { SetProperty(ref _OVP电压, value); }
}
private string _OPP功率;
public string OPP功率
{
get { return _OPP功率; }
set { SetProperty(ref _OPP功率, value); }
}
#endregion
#region
public ICommand ConnectCommand { get; private set; }
public ICommand DisconnectCommand { get; private set; }
public ICommand QueryDeviceCommand { get; private set; }
public ICommand SetVoltageCommand { get; private set; }
public ICommand SetCurrentCommand { get; private set; }
public ICommand EnableOCPCommand { get; private set; }
public ICommand DisableOCPCommand { get; private set; }
public ICommand SetOCPCommand { get; private set; }
public ICommand EnableOVPCommand { get; private set; }
public ICommand DisableOVPCommand { get; private set; }
public ICommand SetOVPCommand { get; private set; }
public ICommand EnableOPPCommand { get; private set; }
public ICommand DisableOPPCommand { get; private set; }
public ICommand SetOPPCommand { get; private set; }
public ICommand CloseCommand { get; private set; }
#endregion
private IEventAggregator _eventAggregator { get;set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
private object device { get; set; }
public BackfeedViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
// Initialize commands
ConnectCommand = new AsyncDelegateCommand(OnConnect);
DisconnectCommand = new DelegateCommand(OnDisconnect);
QueryDeviceCommand = new AsyncDelegateCommand(OnQueryDevice);
SetVoltageCommand = new AsyncDelegateCommand(OnSetVoltage);
SetCurrentCommand = new AsyncDelegateCommand(OnSetCurrent);
EnableOCPCommand = new AsyncDelegateCommand(OnEnableOCP);
DisableOCPCommand = new AsyncDelegateCommand(OnDisableOCP);
SetOCPCommand = new AsyncDelegateCommand(OnSetOCP);
EnableOVPCommand = new AsyncDelegateCommand(OnEnableOVP);
DisableOVPCommand = new AsyncDelegateCommand(OnDisableOVP);
SetOVPCommand = new AsyncDelegateCommand(OnSetOVP);
EnableOPPCommand = new AsyncDelegateCommand(OnEnableOPP);
DisableOPPCommand = new AsyncDelegateCommand(OnDisableOPP);
SetOPPCommand = new AsyncDelegateCommand(OnSetOPP);
CloseCommand = new DelegateCommand(OnClose);
}
#region Command Handlers
private async Task OnConnect()
{
if (device is E36233A e36233A)
{
await e36233A.ConnectAsync();
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.ConnectAsync();
}
}
private void OnDisconnect()
{
if (device is E36233A e36233A)
{
e36233A.Close();
}
else if (device is IT6724CReverse it6724CReverse)
{
it6724CReverse.Close();
}
}
private async Task OnQueryDevice()
{
if (device is E36233A e36233A)
{
= await e36233A.();
}
else if (device is IT6724CReverse it6724CReverse)
{
= await it6724CReverse.();
}
}
private async Task OnSetVoltage()
{
if (device is E36233A e36233A)
{
await e36233A.(Convert.ToDouble());
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.(Convert.ToDouble());
}
}
private async Task OnSetCurrent()
{
if (device is E36233A e36233A)
{
await e36233A.(Convert.ToDouble());
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.(Convert.ToDouble());
}
}
private async Task OnEnableOCP()
{
if (device is E36233A e36233A)
{
await e36233A.OCP开关(true);
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OCP开关(true);
}
}
private async Task OnDisableOCP()
{
if (device is E36233A e36233A)
{
await e36233A.OCP开关(false);
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OCP开关(false);
}
}
private async Task OnSetOCP()
{
if (device is E36233A e36233A)
{
await e36233A.OCP电流(Convert.ToDouble(OCP电流));
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OCP电流(Convert.ToDouble(OCP电流));
}
}
private async Task OnEnableOVP()
{
if (device is E36233A e36233A)
{
await e36233A.OVP开关(true);
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OVP开关(true);
}
}
private async Task OnDisableOVP()
{
if (device is E36233A e36233A)
{
await e36233A.OVP开关(false);
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OVP开关(false);
}
}
private async Task OnSetOVP()
{
if (device is E36233A e36233A)
{
await e36233A.OVP电压(Convert.ToDouble(OVP电压));
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OVP电压(Convert.ToDouble(OVP电压));
}
}
private async Task OnEnableOPP()
{
if (device is E36233A e36233A)
{
await e36233A.OVP开关(true);
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OVP开关(true);
}
}
private async Task OnDisableOPP()
{
if (device is E36233A e36233A)
{
await e36233A.OVP开关(false);
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.OVP开关(false);
}
}
private async Task OnSetOPP()
{
if (device is E36233A e36233A)
{
await e36233A.(Convert.ToDouble(OPP功率));
}
else if (device is IT6724CReverse it6724CReverse)
{
await it6724CReverse.(Convert.ToDouble(OPP功率));
}
}
private void OnClose()
{
RequestClose.Invoke();
}
#endregion
#region Dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
// Implement cleanup logic here if needed
}
public void OnDialogOpened(IDialogParameters parameters)
{
try
{
if (_devices.DeviceDic.ContainsKey("E36233A"))
{
var a = _devices.DeviceDic["E36233A"] as E36233A;
if (a != null)
{
device = a;
}
else
{
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
RequestClose.Invoke();
}
}
else if (_devices.DeviceDic.ContainsKey("IT6724CReverse"))
{
var a = _devices.DeviceDic["IT6724CReverse"] as IT6724CReverse;
if (a != null)
{
device = a;
}
else
{
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
RequestClose.Invoke();
}
}
}
catch (Exception)
{
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
}
}
#endregion
}
}

View File

@ -1,74 +0,0 @@
using BOB.Models;
using Common.PubEvent;
using Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using static BOB.Models.ParameterModel;
namespace BOB.ViewModels.Dialogs
{
public class DeviceSettingViewModel : BindableBase, IDialogAware
{
#region
private string _title = "设备设置界面";
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
private DeviceInfoModel _Device;
public DeviceInfoModel Device
{
get => _Device;
set => SetProperty(ref _Device, value);
}
#endregion
public DialogCloseListener RequestClose { get; set; }
private GlobalVariables _globalVariables;
private IEventAggregator _eventAggregator;
public ICommand CancelCommand { get; set; }
public ICommand SaveCommand { get; set; }
public DeviceSettingViewModel(GlobalVariables globalVariables, IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_globalVariables = globalVariables;
CancelCommand = new DelegateCommand(Cancel);
SaveCommand = new DelegateCommand(Save);
}
private void Save()
{
RequestClose.Invoke(ButtonResult.OK);
}
private void Cancel()
{
RequestClose.Invoke(ButtonResult.No);
}
#region Prism Dialog
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
}
public void OnDialogOpened(IDialogParameters parameters)
{
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
}
#endregion
}
}

View File

@ -0,0 +1,181 @@
using BOB.Singleton;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Events;
using System;
using System.Threading.Tasks;
using System.Windows.Input;
using DeviceCommand.Device;
using Logger;
using BOB.ViewModels.UserControls;
namespace BOB.ViewModels.Dialogs
{
public class EAEL9080ViewModel : BindableBase, IDialogAware
{
#region
private string _Title = "低压直流负载";
private string _设备标识字符串;
private string _负载模式;
private string _电流LA;
private string _电流LB;
private NumericalDisplayViewModel _电压MV=new();
private NumericalDisplayViewModel _电流MV = new();
private NumericalDisplayViewModel _功率MV=new();
public string Title
{
get { return _Title; }
set { SetProperty(ref _Title, value); }
}
public string
{
get { return _设备标识字符串; }
set { SetProperty(ref _设备标识字符串, value); }
}
public string
{
get { return _负载模式; }
set { SetProperty(ref _负载模式, value); }
}
public string LA
{
get { return _电流LA; }
set { SetProperty(ref _电流LA, value); }
}
public string LB
{
get { return _电流LB; }
set { SetProperty(ref _电流LB, value); }
}
public NumericalDisplayViewModel MV
{
get { return _电压MV; }
set { SetProperty(ref _电压MV, value); }
}
public NumericalDisplayViewModel MV
{
get { return _电流MV; }
set { SetProperty(ref _电流MV, value); }
}
public NumericalDisplayViewModel MV
{
get { return _功率MV; }
set { SetProperty(ref _功率MV, value); }
}
#endregion
#region
public ICommand { get; private set; }
public ICommand { get; private set; }
public ICommand { get; private set; }
public ICommand { get; private set; }
public ICommand { get; private set; }
public ICommand { get; private set; }
public ICommand { get; private set; }
public ICommand { get; private set; }
#endregion
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
private EAEL9080 device { get; set; }
public EAEL9080ViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
= new AsyncDelegateCommand(OnConnect);
= new DelegateCommand(OnDisconnect);
= new AsyncDelegateCommand(OnSetRemoteMode);
= new AsyncDelegateCommand(OnSetLoadMode);
= new AsyncDelegateCommand(OnPowerOn);
= new AsyncDelegateCommand(OnPowerOff);
= new DelegateCommand(OnOff);
= new AsyncDelegateCommand(OnQueryDeviceInfo);
}
private async Task OnQueryDeviceInfo()
{
= await device.();
}
private void OnOff()
{
RequestClose.Invoke();
}
private async Task OnConnect()
{
await device.ConnectAsync();
}
private async void OnDisconnect()
{
device.Close();
}
private async Task OnSetRemoteMode()
{
await device.(true);
}
private async Task OnSetLoadMode()
{
}
private async Task OnPowerOn()
{
await device.();
}
private async Task OnPowerOff()
{
await device.();
}
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
try
{
var a = _devices.DeviceDic["EAEL9080"] as EAEL9080;
if (a != null)
{
device = a;
}
else
{
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
RequestClose.Invoke();
}
}
catch (Exception)
{
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
}
}
#endregion
}
}

View File

@ -0,0 +1,139 @@
using BOB.Singleton;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BOB.ViewModels.Dialogs
{
public class IOBoardViewModel : BindableBase, IDialogAware
{
#region
private string _title = "IO板卡";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private int _startAddress;
public int StartAddress
{
get { return _startAddress; }
set { SetProperty(ref _startAddress, value); }
}
public ObservableCollection<string> AddressNames { get; set; }
private string _offset;
public string Offset
{
get { return _offset; }
set { SetProperty(ref _offset, value); }
}
private string _batchWriteStatus;
public string BatchWriteStatus
{
get { return _batchWriteStatus; }
set { SetProperty(ref _batchWriteStatus, value); }
}
#endregion
#region
public ICommand ConnectCommand { get; private set; }
public ICommand DisconnectCommand { get; private set; }
public ICommand PowerOnCommand { get; private set; }
public ICommand PowerOffCommand { get; private set; }
public ICommand SetCommand { get; private set; }
public ICommand ReadCommand { get; private set; }
public ICommand CloseCommand { get; private set; }
#endregion
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
public IOBoardViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
ConnectCommand = new DelegateCommand(OnConnect);
DisconnectCommand = new DelegateCommand(OnDisconnect);
PowerOnCommand = new DelegateCommand(OnPowerOn);
PowerOffCommand = new DelegateCommand(OnPowerOff);
SetCommand = new DelegateCommand(OnSet);
ReadCommand = new DelegateCommand(OnRead);
CloseCommand = new DelegateCommand(OnClose);
}
private void OnConnect()
{
// 连接逻辑
Console.WriteLine("连接设备...");
}
private void OnDisconnect()
{
// 断开连接逻辑
Console.WriteLine("断开设备...");
}
private void OnPowerOn()
{
// 开启电源逻辑
Console.WriteLine("电源开启...");
}
private void OnPowerOff()
{
// 关闭电源逻辑
Console.WriteLine("电源关闭...");
}
private void OnSet()
{
// 设置逻辑
Console.WriteLine("设置...");
}
private void OnRead()
{
// 读取逻辑
Console.WriteLine("读取...");
}
private void OnClose()
{
RequestClose.Invoke();
}
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
#endregion
}
}

View File

@ -0,0 +1,230 @@
using BOB.Singleton;
using DeviceCommand.Device;
using Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BOB.ViewModels.Dialogs
{
public class IT6724CViewModel : BindableBase, IDialogAware
{
#region
private string _title = "低压直流电源";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private string _设备标识字符串;
public string
{
get { return _设备标识字符串; }
set { SetProperty(ref _设备标识字符串, value); }
}
private string _输出电压;
public string
{
get { return _输出电压; }
set { SetProperty(ref _输出电压, value); }
}
private string _输出电流;
public string
{
get { return _输出电流; }
set { SetProperty(ref _输出电流, value); }
}
private string _OCP电流;
public string OCP电流
{
get { return _OCP电流; }
set { SetProperty(ref _OCP电流, value); }
}
private string _OVP电压;
public string OVP电压
{
get { return _OVP电压; }
set { SetProperty(ref _OVP电压, value); }
}
#endregion
#region
public ICommand ConnectCommand { get; private set; }
public ICommand DisconnectCommand { get; private set; }
public ICommand PowerOnCommand { get; private set; }
public ICommand PowerOffCommand { get; private set; }
public ICommand SetOutputVoltageCommand { get; private set; }
public ICommand SetOutputCurrentCommand { get; private set; }
public ICommand SetRemoteModeCommand { get; private set; }
public ICommand QueryDeviceInfoCommand { get; private set; }
public ICommand EnableOCPCommand { get; private set; }
public ICommand DisableOCPCommand { get; private set; }
public ICommand ClearOCPAlarmCommand { get; private set; }
public ICommand SetOCPCommand { get; private set; }
public ICommand EnableOVPCommand { get; private set; }
public ICommand DisableOVPCommand { get; private set; }
public ICommand ClearOVPAlarmCommand { get; private set; }
public ICommand SetOVPCommand { get; private set; }
public ICommand CloseCommand { get; private set; }
#endregion
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
private IT6724C device { get; set; }
public IT6724CViewModel(IContainerProvider containerProvider)
{
ConnectCommand = new AsyncDelegateCommand(OnConnect);
DisconnectCommand = new DelegateCommand(OnDisconnect);
PowerOnCommand = new AsyncDelegateCommand(OnPowerOn);
PowerOffCommand = new AsyncDelegateCommand(OnPowerOff);
SetOutputVoltageCommand = new AsyncDelegateCommand(OnSetOutputVoltage);
SetOutputCurrentCommand = new AsyncDelegateCommand(OnSetOutputCurrent);
SetRemoteModeCommand = new AsyncDelegateCommand(OnSetRemoteMode);
QueryDeviceInfoCommand = new AsyncDelegateCommand(OnQueryDeviceInfo);
EnableOCPCommand = new AsyncDelegateCommand(OnEnableOCP);
DisableOCPCommand = new AsyncDelegateCommand(OnDisableOCP);
ClearOCPAlarmCommand = new AsyncDelegateCommand(OnClearOCPAlarm);
SetOCPCommand = new AsyncDelegateCommand(OnSetOCP);
EnableOVPCommand = new AsyncDelegateCommand(OnEnableOVP);
DisableOVPCommand = new AsyncDelegateCommand(OnDisableOVP);
ClearOVPAlarmCommand = new AsyncDelegateCommand(OnClearOVPAlarm);
SetOVPCommand = new AsyncDelegateCommand(OnSetOVP);
CloseCommand = new DelegateCommand(OnClose);
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
}
#region
private void OnClose()
{
RequestClose.Invoke();
}
private async Task OnConnect()
{
await device.ConnectAsync();
}
private void OnDisconnect()
{
device.Close();
}
private async Task OnPowerOn()
{
await device.(true);
}
private async Task OnPowerOff()
{
await device.(false);
}
private async Task OnSetOutputVoltage()
{
await device.(double.Parse());
}
private async Task OnSetOutputCurrent()
{
await device.(double.Parse());
}
private async Task OnSetRemoteMode()
{
await device.();
}
private async Task OnQueryDeviceInfo()
{
=await device.();
}
private async Task OnEnableOCP()
{
await device.OCP开关(true);
}
private async Task OnDisableOCP()
{
await device.OCP开关(false);
}
private async Task OnClearOCPAlarm()
{
await device.();
}
private async Task OnSetOCP()
{
await device.OCP电流(double.Parse(OCP电流));
}
private async Task OnEnableOVP()
{
await device.OVP开关(true);
}
private async Task OnDisableOVP()
{
await device.OVP开关(false);
}
private async Task OnClearOVPAlarm()
{
await device.();
}
private async Task OnSetOVP()
{
await device.OVP电压(double.Parse(OVP电压));
}
#endregion
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
try
{
var a = _devices.DeviceDic["IT6724C"] as IT6724C;
if (a != null)
{
device = a;
}
else
{
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
RequestClose.Invoke();
}
}
catch (Exception)
{
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
}
}
#endregion
}
}

View File

@ -0,0 +1,57 @@
using BOB.Singleton;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BOB.ViewModels.Dialogs
{
public class LQ7500_DViewModel : BindableBase, IDialogAware
{
#region
private string _Title = "水冷机";
public string Title
{
get { return _Title; }
set { SetProperty(ref _Title, value); }
}
#endregion
#region
#endregion
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
public LQ7500_DViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
}
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
#endregion
}
}

View File

@ -0,0 +1,196 @@
using BOB.Singleton;
using DeviceCommand.Device;
using Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BOB.ViewModels.Dialogs
{
public class PSB11000ViewModel : BindableBase, IDialogAware
{
#region
private string _Title = "反灌高压直流双向电源";
public string Title
{
get { return _Title; }
set { SetProperty(ref _Title, value); }
}
private string _设备标识字符串;
public string
{
get { return _设备标识字符串; }
set { SetProperty(ref _设备标识字符串, value); }
}
private string _输出电压;
public string
{
get { return _输出电压; }
set { SetProperty(ref _输出电压, value); }
}
private string _输出电流;
public string
{
get { return _输出电流; }
set { SetProperty(ref _输出电流, value); }
}
private string _OCP电流;
public string OCP电流
{
get { return _OCP电流; }
set { SetProperty(ref _OCP电流, value); }
}
#endregion
#region
public ICommand ConnectCommand { get; private set; }
public ICommand DisconnectCommand { get; private set; }
public ICommand PowerOnCommand { get; private set; }
public ICommand PowerOffCommand { get; private set; }
public ICommand SetRemoteModeCommand { get; private set; }
public ICommand QueryDeviceInfoCommand { get; private set; }
public ICommand SwitchWorkingModeCommand { get; private set; }
public ICommand SwitchDCSourceModeCommand { get; private set; }
public ICommand SwitchLoadModeCommand { get; private set; }
public ICommand SetCCVoltageCommand { get; private set; }
public ICommand SetCCCurrentCommand { get; private set; }
public ICommand SetOCPCurrentCommand { get; private set; }
public ICommand CloseCommand { get; private set; }
#endregion
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
private PSB11000 device;
public PSB11000ViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
ConnectCommand = new AsyncDelegateCommand(OnConnect);
DisconnectCommand = new DelegateCommand(OnDisconnect);
PowerOnCommand = new AsyncDelegateCommand(OnPowerOn);
PowerOffCommand = new AsyncDelegateCommand(OnPowerOff);
SetRemoteModeCommand = new AsyncDelegateCommand(OnSetRemoteMode);
QueryDeviceInfoCommand = new AsyncDelegateCommand(OnQueryDeviceInfo);
SwitchWorkingModeCommand = new AsyncDelegateCommand(OnSwitchWorkingMode);
SwitchDCSourceModeCommand = new AsyncDelegateCommand(OnSwitchDCSourceMode);
SwitchLoadModeCommand = new AsyncDelegateCommand(OnSwitchLoadMode);
SetCCVoltageCommand = new AsyncDelegateCommand(OnSetCCVoltage);
SetCCCurrentCommand = new AsyncDelegateCommand(OnSetCCCurrent);
SetOCPCurrentCommand = new AsyncDelegateCommand(OnSetOCPCurrent);
CloseCommand = new DelegateCommand(OnClose);
}
#region Command Handlers
private void OnClose()
{
RequestClose.Invoke();
}
private async Task OnConnect()
{
await device.ConnectAsync();
}
private void OnDisconnect()
{
device.Close();
}
private async Task OnPowerOn()
{
await device.();
}
private async Task OnPowerOff()
{
await device.();
}
private async Task OnSetRemoteMode()
{
await device.(true);
}
private async Task OnQueryDeviceInfo()
{
=await device.();
}
private async Task OnSwitchWorkingMode()
{
}
private async Task OnSwitchDCSourceMode()
{
// Logic for switching DC source mode
}
private async Task OnSwitchLoadMode()
{
// Logic for switching load mode
}
private async Task OnSetCCVoltage()
{
// Logic for setting CC voltage
}
private async Task OnSetCCCurrent()
{
// Logic for setting CC current
}
private async Task OnSetOCPCurrent()
{
}
#endregion
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
try
{
var a = _devices.DeviceDic["PSB11000"] as PSB11000;
if (a != null)
{
device = a;
}
else
{
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
RequestClose.Invoke();
}
}
catch (Exception)
{
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
}
}
#endregion
}
}

View File

@ -0,0 +1,227 @@
using BOB.Singleton;
using DeviceCommand.Device;
using Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BOB.ViewModels.Dialogs
{
public class SQ0030G1DViewModel : BindableBase, IDialogAware
{
#region
private string _Title = "交流电源";
public string Title
{
get { return _Title; }
set { SetProperty(ref _Title, value); }
}
private string _UPhaseVoltage;
public string UPhaseVoltage
{
get { return _UPhaseVoltage; }
set { SetProperty(ref _UPhaseVoltage, value); }
}
private string _VPhaseVoltage;
public string VPhaseVoltage
{
get { return _VPhaseVoltage; }
set { SetProperty(ref _VPhaseVoltage, value); }
}
private string _WPhaseVoltage;
public string WPhaseVoltage
{
get { return _WPhaseVoltage; }
set { SetProperty(ref _WPhaseVoltage, value); }
}
private string _CommonOutputVoltage;
public string CommonOutputVoltage
{
get { return _CommonOutputVoltage; }
set { SetProperty(ref _CommonOutputVoltage, value); }
}
private string _CommonOutputFrequency;
public string CommonOutputFrequency
{
get { return _CommonOutputFrequency; }
set { SetProperty(ref _CommonOutputFrequency, value); }
}
private string _StepOutputVoltage;
public string StepOutputVoltage
{
get { return _StepOutputVoltage; }
set { SetProperty(ref _StepOutputVoltage, value); }
}
private string _StepOutputFrequency;
public string StepOutputFrequency
{
get { return _StepOutputFrequency; }
set { SetProperty(ref _StepOutputFrequency, value); }
}
private string _StepOutputVoltageGroup;
public string StepOutputVoltageGroup
{
get { return _StepOutputVoltageGroup; }
set { SetProperty(ref _StepOutputVoltageGroup, value); }
}
private string _StepOutputFrequencyGroup;
public string StepOutputFrequencyGroup
{
get { return _StepOutputFrequencyGroup; }
set { SetProperty(ref _StepOutputFrequencyGroup, value); }
}
#endregion
#region
public ICommand ConnectCommand { get; private set; }
public ICommand DisconnectCommand { get; private set; }
public ICommand SetVoltageLevelLowCommand { get; private set; }
public ICommand SetVoltageLevelHighCommand { get; private set; }
public ICommand SetThreePhaseVoltageCommand { get; private set; }
public ICommand SetCommonOutputVoltageCommand { get; private set; }
public ICommand SetCommonOutputFrequencyCommand { get; private set; }
public ICommand SetStepOutputVoltageCommand { get; private set; }
public ICommand SetStepOutputFrequencyCommand { get; private set; }
public ICommand OpenPowerSupplyCommand { get; private set; }
public ICommand ClosePowerSupplyCommand { get; private set; }
public ICommand CloseCommand { get; private set; }
#endregion
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
private SQ0030G1D device { get; set; }
public SQ0030G1DViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
ConnectCommand = new AsyncDelegateCommand(OnConnect);
DisconnectCommand = new DelegateCommand(OnDisconnect);
CloseCommand = new DelegateCommand(OnClose);
SetVoltageLevelLowCommand = new AsyncDelegateCommand(OnSetVoltageLevelLow);
SetVoltageLevelHighCommand = new AsyncDelegateCommand(OnSetVoltageLevelHigh);
SetThreePhaseVoltageCommand = new AsyncDelegateCommand(OnSetThreePhaseVoltage);
SetCommonOutputVoltageCommand = new AsyncDelegateCommand(OnSetCommonOutputVoltage);
SetCommonOutputFrequencyCommand = new AsyncDelegateCommand(OnSetCommonOutputFrequency);
SetStepOutputVoltageCommand = new AsyncDelegateCommand(OnSetStepOutputVoltage);
SetStepOutputFrequencyCommand = new AsyncDelegateCommand(OnSetStepOutputFrequency);
ClosePowerSupplyCommand = new AsyncDelegateCommand(ClosePowerSupply);
OpenPowerSupplyCommand = new AsyncDelegateCommand(OpenPowerSupply);
}
#region Command Handlers
private void OnClose()
{
RequestClose.Invoke();
}
private async Task OnConnect()
{
await device.ConnectAsync();
}
private void OnDisconnect()
{
device.Close();
}
private async Task OpenPowerSupply()
{
await device.();
}
private async Task ClosePowerSupply()
{
await device.();
}
private async Task OnSetVoltageLevelLow()
{
}
private async Task OnSetVoltageLevelHigh()
{
}
private async Task OnSetThreePhaseVoltage()
{
}
private async Task OnSetCommonOutputVoltage()
{
}
private async Task OnSetCommonOutputFrequency()
{
}
private async Task OnSetStepOutputVoltage()
{
}
private async Task OnSetStepOutputFrequency()
{
}
#endregion
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
try
{
var a = _devices.DeviceDic["SQ0030G1D"] as SQ0030G1D;
if (a != null)
{
device = a;
}
else
{
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
RequestClose.Invoke();
}
}
catch (Exception)
{
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
}
}
#endregion
}
}

View File

@ -0,0 +1,149 @@
using BOB.Singleton;
using DeviceCommand.Device;
using Logger;
using NetTaste;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BOB.ViewModels.Dialogs
{
public class WS_68030_380TViewModel : BindableBase, IDialogAware
{
#region
private string _title = "交流负载";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private string _currentPowerDisplay;
public string CurrentPowerDisplay
{
get { return _currentPowerDisplay; }
set { SetProperty(ref _currentPowerDisplay, value); }
}
#endregion
#region
public ICommand ConnectCommand { get; private set; }
public ICommand DisconnectCommand { get; private set; }
public ICommand LoadCommand { get; private set; }
public ICommand UnloadCommand { get; private set; }
public ICommand ReadPowerCommand { get; private set; }
public ICommand SetPowerCommand { get; private set; }
public ICommand CloseCommand { get; private set; }
#endregion
#region
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
private WS_68030_380T device { get; set; }
public WS_68030_380TViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
// 初始化命令
ConnectCommand = new AsyncDelegateCommand(OnConnect);
DisconnectCommand = new DelegateCommand(OnDisconnect);
LoadCommand = new AsyncDelegateCommand(OnLoad);
UnloadCommand = new AsyncDelegateCommand(OnUnload);
ReadPowerCommand = new AsyncDelegateCommand(OnReadPower);
SetPowerCommand = new AsyncDelegateCommand(OnSetPower);
CloseCommand = new DelegateCommand(OnClose);
}
#endregion
#region
private async Task OnConnect()
{
await device.ConnectAsync();
}
private void OnDisconnect()
{
device.Close();
}
private async Task OnLoad()
{
await device.();
}
private async Task OnUnload()
{
await device.();
}
private async Task OnReadPower()
{
var result = await device._KW();
}
private async Task OnSetPower()
{
if (float.TryParse(CurrentPowerDisplay, out float a))
{
await device._KW(a);
}
}
#endregion
#region Dialog
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
try
{
var a = _devices.DeviceDic["WS_68030_380T"] as WS_68030_380T;
if (a != null)
{
device = a;
}
else
{
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
RequestClose.Invoke();
}
}
catch (Exception)
{
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
}
}
private void OnClose()
{
RequestClose.Invoke();
}
#endregion
}
}

View File

@ -0,0 +1,57 @@
using BOB.Singleton;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BOB.ViewModels.Dialogs
{
public class ZXKSViewModel : BindableBase, IDialogAware
{
#region
private string _Title = "环境箱";
public string Title
{
get { return _Title; }
set { SetProperty(ref _Title, value); }
}
#endregion
#region
#endregion
private IEventAggregator _eventAggregator { get; set; }
private Devices _devices { get; set; }
private GlobalVariables _globalVariables { get; set; }
public ZXKSViewModel(IContainerProvider containerProvider)
{
_devices = containerProvider.Resolve<Devices>();
_globalVariables = containerProvider.Resolve<GlobalVariables>();
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
}
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
#endregion
}
}

View File

@ -1,11 +1,14 @@
using BOB.Models;
using BOB.Singleton;
using BOB.Views.Dialogs;
using Common.PubEvent;
using DeviceCommand.Base;
using DeviceCommand.Device;
using Logger;
using MaterialDesignThemes.Wpf;
using Model;
using OxyPlot;
using Prism.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@ -13,6 +16,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Xml;
@ -69,6 +73,7 @@ namespace BOB.ViewModels
#endregion
private GlobalVariables _globalVariables { get; set; }
private IDialogService _dialogService { get; set; }
private IContainerProvider _containerProvider { get; set; }
private Devices _devices { get; set; }
private IEventAggregator _eventAggregator { get; set; }
public ICommand ParameterAddCommand { get; set; }
@ -76,11 +81,13 @@ namespace BOB.ViewModels
public ICommand ParameterDeleteCommand { get; set; }
public ICommand DeviceEditCommand { get; set; }
public ICommand ReconnnectCommand { get; set; }
public ICommand CloseCommand { get; set; }
public ParametersManagerViewModel(GlobalVariables GlobalVariables,IDialogService dialogService,IEventAggregator eventAggregator,IContainerProvider containerProvider)
{
_containerProvider= containerProvider;
_globalVariables = GlobalVariables;
_eventAggregator= eventAggregator;
_devices=containerProvider.Resolve<Devices>();
@ -91,36 +98,12 @@ namespace BOB.ViewModels
ParameterDeleteCommand = new DelegateCommand(ParameterDelete);
DeviceEditCommand = new DelegateCommand(DeviceEdit);
ReconnnectCommand = new DelegateCommand(Reconnnect);
CloseCommand = new DelegateCommand(Close);
DeviceList = new ObservableCollection<DeviceConfigModel>(SystemConfig.Instance.DeviceList);
InitData();
}
private void Reconnnect()
{
if(SelectedDevice!=null)
{
if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
{
Task.Run(async () =>
{
switch (device)
{
case ITcp tcpDevice:
await tcpDevice.ConnectAsync();
break;
case ISerialPort serialDevice:
await serialDevice.ConnectAsync();
break;
case IModbusDevice modbusDevice:
await modbusDevice.ConnectAsync();
break;
}
});
}
}
}
private void InitData()
{
@ -171,6 +154,27 @@ namespace BOB.ViewModels
case IModbusDevice modbusDevice:
isConnected = (modbusDevice.TcpClient?.Connected ?? false) || (modbusDevice.SerialPort?.IsOpen ?? false);
break;
default:
if (device is Backfeed backfeed)
{
if (backfeed.CurrentDevice == "E36233A")
{
var e36233A = backfeed.CurrentInstance as E36233A;
if (e36233A != null)
{
isConnected = e36233A.TcpClient?.Connected ?? false;
}
}
else if (backfeed.CurrentDevice == "IT6724CReverse")
{
var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
if (it6724CReverse != null)
{
isConnected = it6724CReverse.SerialPort?.IsOpen ?? false;
}
}
}
break;
}
}
@ -193,21 +197,15 @@ namespace BOB.ViewModels
{
return;
}
var param = new DialogParameters
var type = SelectedDevice.DeviceType.Split('.').Last();
if(type=="E36233A"|| type == "IT6724CReverse")
{
{ "Devices", SelectedDevice }
};
_dialogService.ShowDialog("DeviceSetting", param, (r) =>
_dialogService.Show("Backfeed");
}
else
{
if (r.Result == ButtonResult.OK)
{
}
else
{
}
});
_dialogService.Show(type);
}
}
private void ParameterDelete()
@ -254,7 +252,113 @@ namespace BOB.ViewModels
});
}
private void Close()
{
if (SelectedDevice != null)
{
if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
{
Task.Run(() =>
{
switch (device)
{
case ITcp tcpDevice:
tcpDevice.Close();
break;
case ISerialPort serialDevice:
serialDevice.Close();
break;
case IModbusDevice modbusDevice:
modbusDevice.Close();
break;
default:
if (device is Backfeed backfeed)
{
if (backfeed.CurrentDevice == "E36233A")
{
var e36233A = backfeed.CurrentInstance as E36233A;
if (e36233A != null)
{
e36233A.Close();
}
}
else if (backfeed.CurrentDevice == "IT6724CReverse")
{
var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
if (it6724CReverse != null)
{
it6724CReverse.Close();
}
}
}
break;
}
});
}
}
}
private void Reconnnect()
{
if (SelectedDevice != null)
{
if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
{
Task.Run(async () =>
{
try
{
switch (device)
{
case ITcp tcpDevice:
await tcpDevice.ConnectAsync();
break;
case ISerialPort serialDevice:
await serialDevice.ConnectAsync();
break;
case IModbusDevice modbusDevice:
await modbusDevice.ConnectAsync();
break;
default:
if (device is Backfeed backfeed)
{
if (backfeed.CurrentDevice == "E36233A")
{
var e36233A = backfeed.CurrentInstance as E36233A;
if (e36233A != null)
{
await e36233A.ConnectAsync();
}
}
else if (backfeed.CurrentDevice == "IT6724CReverse")
{
var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
if (it6724CReverse != null)
{
await it6724CReverse.ConnectAsync();
}
}
}
break;
}
}
catch (Exception ex)
{
LoggerHelper.ErrorWithNotify($"设备重连时发生错误: {SelectedDevice.Remark} - {ex.Message}", ex.StackTrace);
}
});
}
}
}
#endregion
}
}

View File

@ -0,0 +1,69 @@
using Prism.Mvvm;
using System.Windows;
using System.Windows.Media;
namespace BOB.ViewModels.UserControls
{
public class NumericalDisplayViewModel : BindableBase
{
public NumericalDisplayViewModel()
{
}
private string _channelNumber = string.Empty;
private double _MonitorValue = double.NaN;
private double _upperLimit = double.NaN;
private double _lowerLimit = double.NaN;
private SolidColorBrush _textColor = Brushes.Green;
private SolidColorBrush _backgroundColor = Brushes.White;
private Visibility _limitsVisibility = Visibility.Visible;
// 通道号
public string ChannelNumber
{
get => _channelNumber;
set => SetProperty(ref _channelNumber, value);
}
public double MonitorValue
{
get => _MonitorValue;
set => SetProperty(ref _MonitorValue, value);
}
// 上限
public double UpperLimit
{
get => _upperLimit;
set => SetProperty(ref _upperLimit, value);
}
// 下限
public double LowerLimit
{
get => _lowerLimit;
set => SetProperty(ref _lowerLimit, value);
}
// 文字颜色
public SolidColorBrush TextColor
{
get => _textColor;
set => SetProperty(ref _textColor, value);
}
// 背景颜色
public SolidColorBrush BackgroundColor
{
get => _backgroundColor;
set => SetProperty(ref _backgroundColor, value);
}
// 上下限可见度
public Visibility LimitsVisibility
{
get => _limitsVisibility;
set => SetProperty(ref _limitsVisibility, value);
}
}
}

View File

@ -0,0 +1,216 @@
<UserControl x:Class="BOB.Views.Dialogs.BackfeedView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition />
<RowDefinition Height="350" />
</Grid.RowDefinitions>
<!-- 实时监控 -->
<GroupBox x:Name="实时监控区"
Header="实时监控"
Grid.Column="1"
Padding="0,0,0,0">
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</GroupBox>
<!-- 实时曲线 -->
<GroupBox Header="实时曲线"
Grid.Row="1"
Padding="0,0,0,0">
<oxy:PlotView Model="{Binding 曲线Model}" />
</GroupBox>
<!-- 调试选项 -->
<GroupBox Header="调试选项"
Grid.Row="2">
<TreeView Margin="10">
<!-- 连接状态设置 -->
<TreeViewItem Header="连接状态设置">
<StackPanel Orientation="Horizontal">
<Button Content="连接"
Margin="5"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Margin="5"
Command="{Binding DisconnectCommand}" />
</StackPanel>
</TreeViewItem>
<!-- 查询 -->
<TreeViewItem Header="查询">
<TreeViewItem Header="查询设备标识">
<StackPanel Orientation="Horizontal">
<Button Content="查询设备标识"
Margin="5"
Command="{Binding QueryDeviceCommand}" />
<Label Content="结果"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding 设备标识字符串}"
MinWidth="100"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
<!-- 设置 -->
<TreeViewItem Header="设置">
<!-- 远程模式 -->
<TreeViewItem Header="远程">
<Button Content="设置为远程模式"
Command="{Binding SetRemoteModeCommand}"
Margin="5" />
</TreeViewItem>
<!-- 输出设置 -->
<TreeViewItem Header="输出">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding OutputOnCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding OutputOffCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电压(V)"
Command="{Binding SetVoltageCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding 输出电压}"
materialDesign:HintAssist.Hint=""
MinWidth="100"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电流(A)"
Command="{Binding SetCurrentCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding 输出电流}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
VerticalAlignment="Center" />
</StackPanel>
</TreeViewItem>
<!-- 电流保护 -->
<TreeViewItem Header="电流保护(OCP)">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding EnableOCPCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding DisableOCPCommand}"
Margin="5" />
<Button Content="清除报警"
Command="{Binding ClearOCPAlarmCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电流保护(A)"
Command="{Binding SetOCPCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding OCP电流}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
VerticalAlignment="Center" />
</StackPanel>
</TreeViewItem>
<!-- 电压保护 -->
<TreeViewItem Header="电压保护(OVP)">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding EnableOVPCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding DisableOVPCommand}"
Margin="5" />
<Button Content="清除报警"
Command="{Binding ClearOVPAlarmCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电压保护(V)"
Command="{Binding SetOVPCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding OVP电压}"
materialDesign:HintAssist.Hint=""
MinWidth="100"
VerticalAlignment="Center" />
</StackPanel>
</TreeViewItem>
<!-- 功率保护 -->
<TreeViewItem Header="功率保护(OPP)">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding EnableOPPCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding DisableOPPCommand}"
Margin="5" />
<Button Content="清除报警"
Command="{Binding ClearOPPAlarmCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置功率(W)"
Command="{Binding SetOPPCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding OPP功率}"
materialDesign:HintAssist.Hint=""
MinWidth="100"
VerticalAlignment="Center" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
</TreeView>
</GroupBox>
<StackPanel Grid.Row="2"
VerticalAlignment="Bottom">
<Button Content="关闭"
Width="70"
Margin="10"
HorizontalAlignment="Right"
Command="{Binding CloseCommand}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// BackfeedView.xaml 的交互逻辑
/// </summary>
public partial class BackfeedView : UserControl
{
public BackfeedView()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -1,113 +0,0 @@
<UserControl x:Class="BOB.Views.Dialogs.DeviceSetting"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:converters="clr-namespace:BOB.Converters"
xmlns:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:behavior="clr-namespace:Common.Behaviors;assembly=Common"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
prism:ViewModelLocator.AutoWireViewModel="True"
Background="White"
Panel.ZIndex="1000"
mc:Ignorable="d"
Height="290"
Width="450">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<UserControl.Resources>
<converters:DeviceNameConverter x:Key="DeviceNameConverter" />
<converters:StringToVisibilityConverter x:Key="StringToVisibilityConverter" />
</UserControl.Resources>
<Grid>
<GroupBox Header="{Binding Title}"
Padding="10,15,10,0"
behavior:WindowDragBehavior.EnableWindowDrag="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<ScrollViewer>
<StackPanel>
<StackPanel Height="30"
Visibility="{Binding Device.ErrorMessage, Converter={StaticResource StringToVisibilityConverter}}"
Orientation="Horizontal"
Margin="7,7,0,7">
<TextBlock Text="{Binding Device.ErrorMessage}"
Padding="0,11"
Height="30"
Foreground="Red" />
</StackPanel>
<StackPanel Height="30"
Orientation="Horizontal"
Margin="7">
<Label Content="设备名称"
VerticalAlignment="Bottom"
Width="85" />
<TextBox Text="{Binding Device.Name}"
VerticalAlignment="Bottom"
materialDesign:HintAssist.Hint="设备名称"
Width="120" />
</StackPanel>
<StackPanel Height="30"
Orientation="Horizontal"
Margin="7">
<Label Content="是否启用"
Width="85"
VerticalAlignment="Bottom" />
<CheckBox IsChecked="{Binding IsEnable}"
VerticalAlignment="Bottom"
materialDesign:HintAssist.Hint="是否启用"
Width="120" />
</StackPanel>
<Label Content="连接参数"
Height="30"
Margin="7"
VerticalContentAlignment="Bottom" />
<ItemsControl ItemsSource="{Binding DeviceConnectSettings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
Height="30"
Margin="0,7">
<Label Content="{Binding Name}"
Width="75"
Margin="40,0,4,0"
VerticalContentAlignment="Bottom" />
<TextBox VerticalAlignment="Bottom"
Visibility="{Binding Name, Converter={StaticResource DeviceNameConverter}}"
materialDesign:HintAssist.Hint=""
Text="{Binding Value}"
Width="120" />
<ComboBox VerticalAlignment="Bottom"
materialDesign:HintAssist.Hint=""
Visibility="{Binding Name, Converter={StaticResource DeviceNameConverter}, ConverterParameter=Inverse}"
ItemsSource="{Binding Name, Converter={StaticResource DeviceNameConverter}, ConverterParameter=Items}"
SelectedItem="{Binding Value}"
Width="120" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
FlowDirection="RightToLeft"
Margin="5,10,5,15">
<Button Content="取消"
Width="70"
Command="{Binding CancelCommand}" />
<Button Content="保存"
Width="70"
Margin="20,0"
Command="{Binding SaveCommand}" />
</StackPanel>
</Grid>
</GroupBox>
</Grid>
</UserControl>

View File

@ -0,0 +1,125 @@
<UserControl x:Class="BOB.Views.Dialogs.EAEL9080View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
xmlns:oxy1="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
prism:ViewModelLocator.AutoWireViewModel="True"
Background="White"
Height="850"
Width="900"
>
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition />
<RowDefinition Height="350" />
</Grid.RowDefinitions>
<!-- 实时监控 -->
<GroupBox x:Name="实时监控区"
Header="实时监控"
Padding="0,0,0,0">
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
Grid.Column="0" />
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
Grid.Column="1" />
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
Grid.Column="2" />
</Grid>
</GroupBox>
<!-- 实时曲线 -->
<GroupBox Header="实时曲线"
Grid.Row="1"
Padding="0,0,0,0">
<oxy:PlotView Model="{Binding 曲线Model}" />
</GroupBox>
<!-- 调试选项 -->
<GroupBox Header="调试选项"
Grid.Row="2">
<TreeView Margin="10">
<TreeViewItem Header="连接状态设置">
<StackPanel Orientation="Horizontal">
<Button Content="连接"
Margin="5"
Command="{Binding 连接命令}" />
<Button Content="断开"
Margin="5"
Command="{Binding 断开命令}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="查询">
<TreeViewItem Header="查询设备标识">
<StackPanel Orientation="Horizontal">
<Button Content="查询设备标识"
Margin="5"
Command="{Binding 查询设备信息命令}" />
<Label Content="结果"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding 设备标识字符串}"
MinWidth="100"
materialDesign:HintAssist.Hint="设备标识字符串"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="设置">
<TreeViewItem Header="远程">
<Button Content="设置为远程模式"
Command="{Binding 设置为远程模式命令}" />
</TreeViewItem>
<TreeViewItem Header="模式切换">
<StackPanel Orientation="Horizontal">
<Button Content="负载模式切换"
Command="{Binding 设置负载工作模式命令}"
Margin="5" />
<ComboBox MinWidth="200"
ItemsSource="{Binding 负载模式枚举}"
SelectedItem="{Binding 负载模式}"
materialDesign:HintAssist.Hint="负载模式"
Margin="5" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="输出">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding 电源输出开命令}"
Margin="5" />
<Button Content="关"
Command="{Binding 电源输出关命令}"
Margin="5" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
</TreeView>
</GroupBox>
<StackPanel Grid.Row="2" VerticalAlignment="Bottom">
<Button Content="关闭"
Width="70"
Margin="10"
HorizontalAlignment="Right"
Command="{Binding 关闭命令}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// EAEL9080View.xaml 的交互逻辑
/// </summary>
public partial class EAEL9080View : UserControl
{
public EAEL9080View()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -0,0 +1,86 @@
<UserControl x:Class="BOB.Views.Dialogs.IOBoardView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
<TreeView Margin="10">
<TreeViewItem Header="连接状态设置">
<StackPanel Orientation="Horizontal">
<Button Content="连接"
Margin="5"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Margin="5"
Command="{Binding DisconnectCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="输出">
<TreeViewItem Header="单通道设置">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Margin="5"
Command="{Binding PowerOnCommand}" />
<Button Content="关"
Margin="5"
Command="{Binding PowerOffCommand}" />
<Label Content="输出地址"
Margin="5"
VerticalContentAlignment="Center" />
<ComboBox SelectedIndex="{Binding StartAddress, Mode=TwoWay}"
ItemsSource="{Binding AddressNames}"
MinWidth="100"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="全通道设置">
<StackPanel>
<Label Content="偏移"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding Offset}"
MinWidth="100"
Margin="5"
VerticalContentAlignment="Center" />
<Label Content="状态"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding BatchWriteStatus}"
MinWidth="100"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置"
Margin="5"
Command="{Binding SetCommand}" />
<Button Content="读取"
Margin="5"
Command="{Binding ReadCommand}" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
</TreeView>
<StackPanel Grid.Row="2"
VerticalAlignment="Bottom">
<Button Content="关闭"
Width="70"
Margin="10"
HorizontalAlignment="Right"
Command="{Binding CloseCommand}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// IOBoardView.xaml 的交互逻辑
/// </summary>
public partial class IOBoardView : UserControl
{
public IOBoardView()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -0,0 +1,168 @@
<UserControl x:Class="BOB.Views.Dialogs.IT6724CView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:oxy="http://oxyplot.org/wpf"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtoDown">
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition />
<RowDefinition Height="350" />
</Grid.RowDefinitions>
<GroupBox x:Name="实时监控区"
Header="实时监控"
Grid.Row="0"
Padding="0,0,0,0">
</GroupBox>
<GroupBox Header="实时曲线"
Grid.Row="1"
Padding="0,0,0,0">
<oxy:PlotView Model="{Binding 曲线Model}" />
</GroupBox>
<GroupBox Header="调试选项"
Grid.Row="2">
<TreeView Margin="10">
<TreeViewItem Header="连接状态设置">
<StackPanel Orientation="Horizontal">
<Button Content="连接"
Margin="5"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Margin="5"
Command="{Binding DisconnectCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="查询">
<TreeViewItem Header="查询设备标识">
<StackPanel Orientation="Horizontal">
<Button Content="查询设备标识"
Margin="5"
Command="{Binding QueryDeviceInfoCommand}" />
<Label Content="结果"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding 设备标识字符串}"
MinWidth="100"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="设置">
<TreeViewItem Header="远程">
<Button Content="设置为远程模式"
Command="{Binding SetRemoteModeCommand}"
Margin="5" />
</TreeViewItem>
<TreeViewItem Header="输出">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding PowerOnCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding PowerOffCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电压(V)"
Command="{Binding SetOutputVoltageCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding 输出电压}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电流(A)"
Command="{Binding SetOutputCurrentCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding 输出电流}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
VerticalAlignment="Center" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="电流保护(OCP)">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding EnableOCPCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding DisableOCPCommand}"
Margin="5" />
<Button Content="清除报警"
Command="{Binding ClearOCPAlarmCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电流保护(A)"
Command="{Binding SetOCPCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding OCP电流}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
VerticalAlignment="Center" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="电压保护(OVP)">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding EnableOVPCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding DisableOVPCommand}"
Margin="5" />
<Button Content="清除报警"
Command="{Binding ClearOVPAlarmCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置电压保护(V)"
Command="{Binding SetOVPCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding OVP电压}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
VerticalAlignment="Center" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
</TreeView>
</GroupBox>
<StackPanel Grid.Row="2"
VerticalAlignment="Bottom">
<Button Content="关闭"
Width="70"
Margin="10"
HorizontalAlignment="Right"
Command="{Binding CloseCommand}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// IT6724CView.xaml 的交互逻辑
/// </summary>
public partial class IT6724CView : UserControl
{
public IT6724CView()
{
InitializeComponent();
}
private void MouseLeftButtoDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -0,0 +1,21 @@
<UserControl x:Class="BOB.Views.Dialogs.LQ7500_DView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// LQ7500_DView.xaml 的交互逻辑
/// </summary>
public partial class LQ7500_DView : UserControl
{
public LQ7500_DView()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -0,0 +1,170 @@
<UserControl x:Class="BOB.Views.Dialogs.PSB11000View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition />
<RowDefinition Height="350" />
</Grid.RowDefinitions>
<GroupBox x:Name="实时监控区"
Header="实时监控"
Grid.Column="1"
Padding="0,0,0,0">
</GroupBox>
<GroupBox Header="实时曲线"
Grid.Row="1"
Padding="0,0,0,0">
<oxy:PlotView Model="{Binding 曲线Model}" />
</GroupBox>
<GroupBox Header="调试选项"
Grid.Row="2">
<TreeView Margin="10">
<TreeViewItem Header="连接状态设置">
<StackPanel Orientation="Horizontal">
<Button Content="连接"
Margin="5"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Margin="5"
Command="{Binding DisconnectCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="查询">
<TreeViewItem Header="查询设备标识">
<StackPanel Orientation="Horizontal">
<Button Content="查询设备标识"
Margin="5"
Command="{Binding QueryDeviceInfoCommand}" />
<Label Content="结果"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding 设备标识字符串}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="设置">
<TreeViewItem Header="远程">
<Button Content="设置为远程模式"
Command="{Binding SetRemoteModeCommand}" />
</TreeViewItem>
<TreeViewItem Header="模式切换">
<StackPanel Orientation="Horizontal">
<Button Content="工作模式切换"
Command="{Binding SwitchWorkingModeCommand}"
Margin="5" />
<ComboBox MinWidth="200"
materialDesign:HintAssist.Hint=""
ItemsSource="{Binding 工作模式枚举}"
SelectedItem="{Binding 工作模式}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="直流源模式切换"
Command="{Binding SwitchDCSourceModeCommand}"
Margin="5" />
<ComboBox MinWidth="200"
materialDesign:HintAssist.Hint=""
ItemsSource="{Binding 直流源模式枚举}"
SelectedItem="{Binding 直流源模式}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="负载模式切换"
Command="{Binding SwitchLoadModeCommand}"
Margin="5" />
<ComboBox MinWidth="200"
materialDesign:HintAssist.Hint=""
ItemsSource="{Binding 负载模式枚举}"
SelectedItem="{Binding 负载模式}"
Margin="5" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="输出">
<StackPanel Orientation="Horizontal">
<Button Content="开"
Command="{Binding PowerOnCommand}"
Margin="5" />
<Button Content="关"
Command="{Binding PowerOffCommand}"
Margin="5" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置CC模式电压(V)"
Command="{Binding SetCCVoltageCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding 输出电压}"
materialDesign:HintAssist.Hint=""
MinWidth="100"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置CC模式电流(A)"
Command="{Binding SetCCCurrentCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding 输出电流}"
MinWidth="100"
materialDesign:HintAssist.Hint=""
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设置OCP电流(A)"
Command="{Binding SetOCPCurrentCommand}"
Margin="5" />
<Label Content="值:"
VerticalAlignment="Center" />
<TextBox Text="{Binding OCP电流}"
materialDesign:HintAssist.Hint=""
MinWidth="100"
VerticalAlignment="Center" />
</StackPanel>
<!-- Add similar blocks for other settings (OVP, OPP, etc.) -->
</TreeViewItem>
</TreeViewItem>
</TreeView>
</GroupBox>
<StackPanel Grid.Row="2"
VerticalAlignment="Bottom">
<Button Content="关闭"
Width="70"
Margin="10"
HorizontalAlignment="Right"
Command="{Binding CloseCommand}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// PSB11000View.xaml 的交互逻辑
/// </summary>
public partial class PSB11000View : UserControl
{
public PSB11000View()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -0,0 +1,204 @@
<UserControl x:Class="BOB.Views.Dialogs.SQ0030G1DView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
<TreeView Margin="10">
<TreeViewItem Header="连接状态设置">
<StackPanel Orientation="Horizontal">
<Button Content="连接"
Margin="5"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Margin="5"
Command="{Binding DisconnectCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="电压开关设置">
<StackPanel Orientation="Horizontal">
<Button Content="开启"
Margin="5"
Command="{Binding OpenPowerSupplyCommand}" />
<Button Content="关闭"
Margin="5"
Command="{Binding ClosePowerSupplyCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="设置">
<TreeViewItem Header="设定三相电压输出">
<TreeViewItem Header="设定三相电压档位">
<StackPanel Orientation="Horizontal">
<Button Content="低档"
Margin="5"
Command="{Binding SetVoltageLevelLowCommand}" />
<Button Content="高档"
Margin="5"
Command="{Binding SetVoltageLevelHighCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="输出">
<StackPanel Orientation="Vertical">
<Button Content="设定三相输出电压"
Margin="5"
Command="{Binding SetThreePhaseVoltageCommand}" />
<StackPanel Orientation="Horizontal">
<Label Content="U相输出电压"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding UPhaseVoltage}"
MinWidth="50"
materialDesign:HintAssist.Hint=""
Margin="5"
VerticalContentAlignment="Center" />
<Label Content="V"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="V相输出电压"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding VPhaseVoltage}"
MinWidth="50"
materialDesign:HintAssist.Hint=""
Margin="5"
VerticalContentAlignment="Center" />
<Label Content="V"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="W相输出电压"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding WPhaseVoltage}"
MinWidth="50"
materialDesign:HintAssist.Hint=""
Margin="5"
VerticalContentAlignment="Center" />
<Label Content="V"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
</StackPanel>
</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="设定通用功能输出">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Button Content="设定通用功能输出电压"
Margin="5"
Command="{Binding SetCommonOutputVoltageCommand}" />
<Label Content="输出电压"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding CommonOutputVoltage}"
MinWidth="50"
materialDesign:HintAssist.Hint=""
Margin="5"
VerticalContentAlignment="Center" />
<Label Content="V"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设定通用功能输出频率"
Margin="5"
Command="{Binding SetCommonOutputFrequencyCommand}" />
<Label Content="输出频率"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding CommonOutputFrequency}"
MinWidth="50"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
<Label Content="Hz"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="设定步阶功能输出">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Button Content="设定步阶功能输出电压"
Margin="5"
Command="{Binding SetStepOutputVoltageCommand}" />
<Label Content="组号"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding StepOutputVoltageGroup}"
MinWidth="50"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
<Label Content="输出电压"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding StepOutputVoltage}"
MinWidth="50"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
<Label Content="V"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="设定步阶功能输出频率"
Margin="5"
Command="{Binding SetStepOutputFrequencyCommand}" />
<Label Content="组号"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding StepOutputFrequencyGroup}"
MinWidth="50"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
<Label Content="输出频率"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding StepOutputFrequency}"
MinWidth="50"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
<Label Content="Hz"
Margin="5"
VerticalContentAlignment="Center" />
</StackPanel>
</StackPanel>
</TreeViewItem>
</TreeViewItem>
</TreeView>
<StackPanel Grid.Row="2"
VerticalAlignment="Bottom">
<Button Content="关闭"
Width="70"
Margin="10"
HorizontalAlignment="Right"
Command="{Binding CloseCommand}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// SQ0030G1DView.xaml 的交互逻辑
/// </summary>
public partial class SQ0030G1DView : UserControl
{
public SQ0030G1DView()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -0,0 +1,71 @@
<UserControl x:Class="BOB.Views.Dialogs.WS_68030_380TView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:prism="http://prismlibrary.com/"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
<TreeView Margin="10">
<TreeViewItem Header="连接状态设置">
<StackPanel Orientation="Horizontal">
<Button Content="连接"
Margin="5"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Margin="5"
Command="{Binding DisconnectCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="上下载设置">
<StackPanel Orientation="Horizontal">
<Button Content="加载"
Margin="5"
Command="{Binding LoadCommand}" />
<Button Content="卸载"
Margin="5"
Command="{Binding UnloadCommand}" />
</StackPanel>
</TreeViewItem>
<TreeViewItem Header="功率设置">
<StackPanel Orientation="Horizontal">
<Button Content="读取功率"
Margin="5"
Command="{Binding ReadPowerCommand}" />
<Button Content="设置功率"
Margin="5"
Command="{Binding SetPowerCommand}" />
<Label Content="功率"
Margin="5"
VerticalContentAlignment="Center" />
<TextBox Text="{Binding CurrentPowerDisplay}"
MinWidth="100"
Margin="5"
materialDesign:HintAssist.Hint=""
VerticalContentAlignment="Center" />
</StackPanel>
</TreeViewItem>
</TreeView>
<StackPanel Grid.Row="2"
VerticalAlignment="Bottom">
<Button Content="关闭"
Width="70"
Margin="10"
HorizontalAlignment="Right"
Command="{Binding CloseCommand}" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// WS_68030_380TView.xaml 的交互逻辑
/// </summary>
public partial class WS_68030_380TView : UserControl
{
public WS_68030_380TView()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -0,0 +1,21 @@
<UserControl x:Class="BOB.Views.Dialogs.ZXKSView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.Dialogs"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
Background="White"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="850"
Width="900">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
</Grid>
</UserControl>

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
{
/// <summary>
/// ZXKSView.xaml 的交互逻辑
/// </summary>
public partial class ZXKSView : UserControl
{
public ZXKSView()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}

View File

@ -121,10 +121,12 @@
</DataGrid.Columns>
<DataGrid.ContextMenu>
<ContextMenu>
<!--<MenuItem Header="编辑"
Command="{Binding DeviceEditCommand}" />-->
<MenuItem Header="编辑"
Command="{Binding DeviceEditCommand}" />
<MenuItem Header="重新连接"
Command="{Binding ReconnnectCommand}" />
<MenuItem Header="关闭"
Command="{Binding CloseCommand}" />
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>

View File

@ -0,0 +1,74 @@
<UserControl x:Class="BOB.Views.UserControls.NumericalDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BOB.Views.UserControls"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<Grid>
<Border Background="{Binding BackgroundColor}"
CornerRadius="16"
Padding="16"
Margin="5">
<Border.Effect>
<DropShadowEffect BlurRadius="8"
ShadowDepth="4"
Opacity="0.3" />
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1.3*" />
<RowDefinition Height="6.2*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<!-- 通道号 -->
<Viewbox>
<TextBlock HorizontalAlignment="Center"
FontSize="18"
FontWeight="Bold">
<Run Text="{Binding ChannelNumber}" />
</TextBlock>
</Viewbox>
<!-- 温度 -->
<Viewbox Grid.Row="1">
<TextBlock Text="{Binding Temperature, StringFormat='0.00'}"
FontSize="40"
FontWeight="SemiBold"
Foreground="{Binding TextColor}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Viewbox>
<!-- 上下限 -->
<Viewbox Grid.Row="2">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Visibility="{Binding LimitsVisibility}">
<TextBlock Text="下限: "
FontSize="12"
Foreground="Gray" />
<TextBlock Text="{Binding LowerLimit, StringFormat='0.00'}"
FontSize="12"
FontWeight="Bold"
Foreground="Gray"
Margin="0,0,10,0" />
<TextBlock Text="上限: "
FontSize="12"
Foreground="Gray" />
<TextBlock Text="{Binding UpperLimit, StringFormat='0.00'}"
FontSize="12"
FontWeight="Bold"
Foreground="Gray" />
</StackPanel>
</Viewbox>
</Grid>
</Border>
</Grid>
</UserControl>

View File

@ -13,18 +13,16 @@ using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace BOB.Views.Dialogs
namespace BOB.Views.UserControls
{
/// <summary>
/// DeviceSetting.xaml 的交互逻辑
/// 数值显示卡控件.xaml 的交互逻辑
/// </summary>
public partial class DeviceSetting : UserControl
public partial class NumericalDisplay : UserControl
{
public DeviceSetting()
public NumericalDisplay()
{
InitializeComponent();
}
}
}

View File

@ -14,6 +14,6 @@ namespace DeviceCommand.Base
Task SendAsync(string data, CancellationToken ct = default);
Task<string> ReadAsync(string delimiter = "\n", CancellationToken ct = default);
Task<string> myReadAsync(string delimiter = "\n", CancellationToken ct = default);
}
}

View File

@ -22,7 +22,7 @@ namespace DeviceCommand.Base
public TcpClient TcpClient { get; set; }
public IModbusMaster Modbus { get; set; }
private readonly SemaphoreSlim _commLock = new(1, 1);
protected 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)
{
@ -35,7 +35,7 @@ namespace DeviceCommand.Base
WriteTimeout = writeTimeout;
}
public async Task<bool> ConnectAsync(CancellationToken ct = default)
public virtual async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
@ -61,7 +61,7 @@ namespace DeviceCommand.Base
}
}
public void Close()
public virtual void Close()
{
if (SerialPort.IsOpen)
SerialPort.Close();

View File

@ -18,7 +18,7 @@ namespace DeviceCommand.Base
public TcpClient TcpClient { get; set; } = new TcpClient();
public IModbusMaster Modbus { get; set; }
private readonly SemaphoreSlim _commLock = new(1, 1);
protected readonly SemaphoreSlim _commLock = new(1, 1);
public void ConfigureDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
{
@ -28,7 +28,7 @@ namespace DeviceCommand.Base
ReceiveTimeout = receiveTimeout;
}
public async Task<bool> ConnectAsync(CancellationToken ct = default)
public virtual async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
@ -52,7 +52,7 @@ namespace DeviceCommand.Base
_commLock.Release();
}
}
public void Close()
public virtual void Close()
{
if (TcpClient.Connected) TcpClient.Close();
}

View File

@ -16,7 +16,7 @@ namespace DeviceCommand.Base
public int ReadTimeout { get; set; } = 3000;
public int WriteTimeout { get; set; } = 3000;
public SerialPort SerialPort { get; set; } = new SerialPort();
private readonly SemaphoreSlim commLock = new(1, 1);
protected 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)
{
@ -28,7 +28,7 @@ namespace DeviceCommand.Base
ReadTimeout = readTimeout;
WriteTimeout = writeTimeout;
}
public async Task<bool> ConnectAsync(CancellationToken ct = default)
public virtual async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await commLock.WaitAsync(ct);
try
@ -52,12 +52,12 @@ namespace DeviceCommand.Base
}
}
public void Close()
public virtual void Close()
{
if (SerialPort.IsOpen) SerialPort.Close();
}
public async Task SendAsync(string data, CancellationToken ct = default)
public virtual async Task SendAsync(string data, CancellationToken ct = default)
{
await commLock.WaitAsync(ct);
try
@ -80,8 +80,12 @@ namespace DeviceCommand.Base
commLock.Release();
}
}
public async Task<string> ReadAsync(CancellationToken ct = default)
{
return await myReadAsync(ct: ct).WaitAsync(TimeSpan.FromMilliseconds(ReadTimeout), ct);
}
public async Task<string> ReadAsync(string delimiter = "\n", CancellationToken ct = default)
public async Task<string> myReadAsync(string delimiter = "\n", CancellationToken ct = default)
{
await commLock.WaitAsync(ct);
try

View File

@ -10,12 +10,12 @@ namespace DeviceCommand.Base
{
public class Tcp: ITcp
{
public string IPAddress { get; private set; } = "127.0.0.1";
public int Port { get; private set; } = 502;
public int SendTimeout { get; private set; } = 3000;
public int ReceiveTimeout { get; private set; } = 3000;
public string IPAddress { get; set; }
public int Port { get; set; }
public int SendTimeout { get; set; }
public int ReceiveTimeout { get; set; }
public TcpClient TcpClient { get; set; } = new TcpClient();
private readonly SemaphoreSlim _commLock = new(1, 1);
protected readonly SemaphoreSlim _commLock = new(1, 1);
public void ConfigureDevice(string ipAddress, int port, int sendTimeout = 3000, int receiveTimeout = 3000)
{
@ -25,20 +25,14 @@ namespace DeviceCommand.Base
ReceiveTimeout = receiveTimeout;
}
public async Task<bool> ConnectAsync(CancellationToken ct = default)
public virtual async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
{
if (TcpClient.Connected)
{
var remoteEndPoint = (IPEndPoint)TcpClient.Client.RemoteEndPoint!;
if (remoteEndPoint.Address.MapToIPv4().ToString() == IPAddress && remoteEndPoint.Port == Port)
return true;
TcpClient.Close();
TcpClient.Dispose();
TcpClient = new TcpClient();
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
@ -50,7 +44,7 @@ namespace DeviceCommand.Base
}
}
public void Close()
public virtual void Close()
{
if (!TcpClient.Connected)
{

View File

@ -9,7 +9,7 @@ namespace DeviceCommand.Device
[BOBCommand]
public class Backfeed
{
private string CurrentDevice { get; set; }
public string CurrentDevice { get; set; }
private E36233A _E36233A { get; set; }
private IT6724CReverse _IT6724CReverse { get; set; }
public object CurrentInstance

View File

@ -1,5 +1,6 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.Linq;
using System.Threading;
@ -14,11 +15,106 @@ namespace DeviceCommand.Device
{
ConfigureDevice(ipAddress, port, sendTimeout, receiveTimeout);
}
public E36233A()
#region
private CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
{
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
if (TcpClient.Connected)
{
return true;
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
IsActive = true;
StartHeartbeat();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_commLock.Release();
}
}
public override void Close()
{
if (!TcpClient.Connected)
{
throw new InvalidOperationException("TCP 没有连接成功");
}
if (TcpClient.Connected)
{
TcpClient.Close();
StopHeartbeat();
}
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource = new();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
// 停止设备的心跳
public void StopHeartbeat()
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await ();
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool resultConnect = await ConnectAsync(ct);
if (resultConnect)
{
ReConnectionAttempts = 0;
}
}
catch (Exception ex)
{
}
}
#endregion
#region
public async Task (CancellationToken ct = default)
@ -95,7 +191,11 @@ namespace DeviceCommand.Device
{
await SendAsync($"{指令}\r\n", ct);
}
public virtual async Task<string> (CancellationToken ct = default)
{
await SendAsync("*IDN?\r\n", ct);
return await ReadAsync(ct: ct);
}
#endregion
}
}

View File

@ -1,204 +1,323 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System.Threading;
using System.Threading.Tasks;
namespace DeviceCommand.Device
{
[BOBCommand]
public class EAEL9080 : ModbusTcp
public class EAEL9080 : Tcp
{
public EAEL9080(string IpAddress, int port, int SendTimeout, int ReceiveTimeout)
{
ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout);
}
public EAEL9080() { }
#region
public virtual async Task (bool , byte slaveAddress = 1, CancellationToken ct = default)
#region
private CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
ushort value = (ushort)( ? 0xFF00 : 0x0000);
await WriteSingleRegisterAsync(slaveAddress, 402, value, ct);
await _commLock.WaitAsync(ct);
try
{
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
if (TcpClient.Connected)
{
return true;
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
IsActive = true;
StartHeartbeat();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_commLock.Release();
}
}
public override void Close()
{
if (!TcpClient.Connected)
{
throw new InvalidOperationException("TCP 没有连接成功");
}
if (TcpClient.Connected)
{
TcpClient.Close();
StopHeartbeat();
}
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
if (_cancellationTokenSource == null||_cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource = new();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
public virtual async Task (bool , byte slaveAddress = 1, CancellationToken ct = default)
// 停止设备的心跳
public void StopHeartbeat()
{
ushort value = (ushort)( ? 0xFF00 : 0x0000);
await WriteSingleRegisterAsync(slaveAddress, 405, value, ct);
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
public virtual async Task (bool 使, byte slaveAddress = 1, CancellationToken ct = default)
private async Task HeartbeatLoop(CancellationToken ct)
{
ushort value = (ushort)(使 ? 0xFF00 : 0x0000);
await WriteSingleRegisterAsync(slaveAddress, 409, value, ct);
}
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
public virtual async Task<uint> (byte slaveAddress = 1, CancellationToken ct = default)
try
{
await (true);
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 505, 2, ct);
return (uint)(reg[0] << 16 | reg[1]);
}
try
{
bool resultConnect = await ConnectAsync(ct);
if (resultConnect)
{
ReConnectionAttempts = 0;
}
}
catch (Exception ex)
{
public virtual async Task<bool> (byte slaveAddress = 1, CancellationToken ct = default)
{
uint status = await (slaveAddress, ct);
return (status & (1 << 7)) != 0;
}
}
public virtual async Task<bool> (byte slaveAddress = 1, CancellationToken ct = default)
{
uint status = await (slaveAddress, ct);
return (status & (1 << 10)) != 0;
}
public virtual async Task<bool> Sink模式状态(byte slaveAddress = 1, CancellationToken ct = default)
{
uint status = await (slaveAddress, ct);
return (status & (1 << 12)) != 0;
}
#endregion
#region / / /
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询设备信息
public virtual async Task<string> (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 500, value, ct);
return await WriteReadAsync($"*IDN?\r\n", "\n", ct: ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 重置设备
public virtual async Task (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 500, 1, ct);
return reg[0] / (double)0xCCCC * ;
await SendAsync($"*RST\r\n", ct);
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"OUTPut:PROTection:CLEar\r\n", ct);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 打开输出
public virtual async Task (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 501, value, ct);
await SendAsync($"OUTPut ON\r\n", ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 关闭输出
public virtual async Task (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 501, 1, ct);
return reg[0] / (double)0xCCCC * ;
await SendAsync($"OUTPut OFF\r\n", ct);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 设置远程控制
public virtual async Task (bool , CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 502, value, ct);
await SendAsync($"SYSTem:LOCK {(激活 ? "ON" : "OFF")}\r\n", ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询远程控制状态
public virtual async Task<string> (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 502, 1, ct);
return reg[0] / (double)0xCCCC * ;
return await WriteReadAsync($"SYSTem:LOCK:OWNer?\r\n", "\n", ct: ct);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 设置电压
public virtual async Task (double , CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 503, value, ct);
await SendAsync($"SOURce:VOLTage {电压}V\r\n", ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 设置电流
public virtual async Task (double , CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 503, 1, ct);
return reg[0] / (double)0xCCCC * ;
await SendAsync($"SOURce:CURRent {电流}A\r\n", ct);
}
#endregion
#region Sink
public virtual async Task Sink功率(double , double Sink额定功率, byte slaveAddress = 1, CancellationToken ct = default)
// 设置功率
public virtual async Task (double , CancellationToken ct = default)
{
ushort value = (ushort)( / Sink额定功率 * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 498, value, ct);
await SendAsync($"SOURce:POWer {功率}W\r\n", ct);
}
public virtual async Task Sink电流(double , double Sink额定电流, byte slaveAddress = 1, CancellationToken ct = default)
// 设置电阻
public virtual async Task (double , CancellationToken ct = default)
{
ushort value = (ushort)( / Sink额定电流 * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 499, value, ct);
await SendAsync($"SOURce:RESistance {电阻}Ω\r\n", ct);
}
public virtual async Task Sink电阻(double , double Sink最大电阻, byte slaveAddress = 1, CancellationToken ct = default)
// 设置过压保护
public virtual async Task (double , CancellationToken ct = default)
{
ushort value = (ushort)( / Sink最大电阻 * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 504, value, ct);
await SendAsync($"SOURce:VOLTage:PROTection {电压}V\r\n", ct);
}
public virtual async Task<double> Sink功率(double Sink额定功率, byte slaveAddress = 1, CancellationToken ct = default)
// 设置过流保护
public virtual async Task (double , CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 498, 1, ct);
return reg[0] / (double)0xCCCC * Sink额定功率;
await SendAsync($"SOURce:CURRent:PROTection {电流}A\r\n", ct);
}
public virtual async Task<double> Sink电流(double Sink额定电流, byte slaveAddress = 1, CancellationToken ct = default)
// 设置过功率保护
public virtual async Task (double , CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 499, 1, ct);
return reg[0] / (double)0xCCCC * Sink额定电流;
await SendAsync($"SOURce:POWer:PROTection {功率}W\r\n", ct);
}
public virtual async Task<double> Sink电阻(double Sink最大电阻, byte slaveAddress = 1, CancellationToken ct = default)
// 查询电压
public virtual async Task<double> (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 504, 1, ct);
return reg[0] / (double)0xCCCC * Sink最大电阻;
var str = await WriteReadAsync($"MEASure:VOLTage?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
#endregion
#region
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询电流
public virtual async Task<double> (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 507, 1, ct);
return reg[0] / (double)0xCCCC * ;
var str = await WriteReadAsync($"MEASure:CURRent?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询功率
public virtual async Task<double> (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 508, 1, ct);
double current = reg[0] / (double)0xCCCC * ;
if (await Sink模式状态(slaveAddress, ct)) current = -current;
return current;
var str = await WriteReadAsync($"MEASure:POWer?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 批量查询电压、电流、功率
public virtual async Task<(double , double , double )> (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 509, 1, ct);
double power = reg[0] / (double)0xCCCC * ;
if (await Sink模式状态(slaveAddress, ct)) power = -power;
return power;
var str = await WriteReadAsync($"MEASure:ARRay?\r\n", "\n", ct: ct);
var values = str.Split(',');
return (
Convert.ToDouble(values[0]),
Convert.ToDouble(values[1]),
Convert.ToDouble(values[2])
);
}
#endregion
#region
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询标称电压
public virtual async Task<double> (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 510, value, ct);
var str = await WriteReadAsync($"SYSTem:NOMinal:VOLTage?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询标称电流
public virtual async Task<double> (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 511, value, ct);
var str = await WriteReadAsync($"SYSTem:NOMinal:CURRent?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
#region
// 激活指定通道
public virtual async Task (int , CancellationToken ct = default)
{
await SendAsync($"INST:SEL CH{通道号}\r\n", ct);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询当前激活的通道
public virtual async Task<string> (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 512, value, ct);
return await WriteReadAsync($"INST:SEL?\r\n", "\n", ct);
}
// 激活所有通道
public virtual async Task (CancellationToken ct = default)
{
await SendAsync("INST:SEL ALL\r\n", ct);
}
// 设置指定通道电压
public virtual async Task (int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:VOLT {电压}V\r\n", ct);
}
// 设置指定通道电流
public virtual async Task (int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:CURR {电流}A\r\n", ct);
}
// 设置指定通道功率
public virtual async Task (int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:POW {功率}W\r\n", ct);
}
// 设置指定通道 Sink 模式电流
public virtual async Task Sink电流(int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:SINK:CURR {电流}A\r\n", ct);
}
// 启动指定通道输出
public virtual async Task (int , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:OUTP ON\r\n", ct);
}
// 关闭指定通道输出
public virtual async Task (int , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:OUTP OFF\r\n", ct);
}
// 同时启停所有通道输出
public virtual async Task (CancellationToken ct = default)
{
await SendAsync("INST:ALL:OUTP ON\r\n", ct);
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync("INST:ALL:OUTP OFF\r\n", ct);
}
// 查询指定通道的电压、电流和功率(批量)
public virtual async Task<(double , double , double )> (int , CancellationToken ct = default)
{
var str = await WriteReadAsync($"CH{通道号}:MEAS:ARR?\r\n", "\n", ct);
var values = str.Split(',');
return (
Convert.ToDouble(values[0]), // 电压
Convert.ToDouble(values[1]), // 电流
Convert.ToDouble(values[2]) // 功率
);
}
#endregion
}
}

View File

@ -1,5 +1,6 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.Collections.Generic;
using System.Linq;
@ -15,11 +16,107 @@ namespace DeviceCommand.Device
{
ConfigureDevice(Ip地址, , , );
}
public IOBoard()
#region
private CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
{
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
if (TcpClient.Connected)
{
return true;
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
IsActive = true;
StartHeartbeat();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_commLock.Release();
}
}
public override void Close()
{
if (!TcpClient.Connected)
{
throw new InvalidOperationException("TCP 没有连接成功");
}
if (TcpClient.Connected)
{
TcpClient.Close();
StopHeartbeat();
}
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource = new();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
// 停止设备的心跳
public void StopHeartbeat()
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await WriteSingleRegisterAsync(1, 0, 1);
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool resultConnect = await ConnectAsync(ct);
if (resultConnect)
{
ReConnectionAttempts = 0;
}
}
catch (Exception ex)
{
}
}
#endregion
public virtual async Task (byte , ushort , ushort )
{
@ -30,5 +127,14 @@ namespace DeviceCommand.Device
{
await WriteMultipleRegistersAsync(, , );
}
public virtual async Task<ushort> (byte , ushort , CancellationToken ct = default)
{
var result = await ReadInputRegistersAsync(, , 1, ct);
return result[0];
}
public virtual async Task<ushort[]> (byte , ushort , ushort , CancellationToken ct = default)
{
return await ReadInputRegistersAsync(, , , ct);
}
}
}

View File

@ -1,7 +1,10 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
@ -14,8 +17,112 @@ namespace DeviceCommand.Device
{
ConfigureDevice(COMPort, BaudRate, DataBits, stopBits, parity, ReadTimeout, ReceiveTimeout);
}
#region
private CancellationTokenSource? _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
try
{
if (SerialPort.IsOpen)
SerialPort.Close();
SerialPort.PortName = PortName;
SerialPort.BaudRate = BaudRate;
SerialPort.DataBits = DataBits;
SerialPort.StopBits = StopBits;
SerialPort.Parity = Parity;
SerialPort.ReadTimeout = ReadTimeout;
SerialPort.WriteTimeout = WriteTimeout;
if (SerialPort.IsOpen) return true;
SerialPort.Open();
IsActive = true;
StartHeartbeat();
return true;
}
finally
{
}
}
public override void Close()
{
StopHeartbeat();
if (SerialPort.IsOpen) SerialPort.Close();
}
public void StartHeartbeat()
{
if (_heartbeatTask != null && !_heartbeatTask.IsCompleted)
return;
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
public void StopHeartbeat()
{
try
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
catch { }
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await (ct);
}
catch(Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (ReConnectionAttempts > MaxReconnectAttempts)
{
LoggerHelper.InfoWithNotify("IT6724C重连多次失败");
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool ok = await ConnectAsync(ct);
if (ok)
ReConnectionAttempts = 0;
}
catch { }
}
#endregion
public IT6724C() { }
#region

View File

@ -1,5 +1,6 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.IO.Ports;
using System.Threading;
@ -14,8 +15,110 @@ namespace DeviceCommand.Device
{
ConfigureDevice(COMPort, BaudRate, DataBits, stopBits, parity, ReadTimeout, ReceiveTimeout);
}
#region
private CancellationTokenSource? _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public IT6724CReverse() { }
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
try
{
if (SerialPort.IsOpen)
SerialPort.Close();
SerialPort.PortName = PortName;
SerialPort.BaudRate = BaudRate;
SerialPort.DataBits = DataBits;
SerialPort.StopBits = StopBits;
SerialPort.Parity = Parity;
SerialPort.ReadTimeout = ReadTimeout;
SerialPort.WriteTimeout = WriteTimeout;
if (SerialPort.IsOpen) return true;
SerialPort.Open();
IsActive = true;
StartHeartbeat();
return true;
}
finally
{
}
}
public override void Close()
{
StopHeartbeat();
if (SerialPort.IsOpen) SerialPort.Close();
}
public void StartHeartbeat()
{
if (_heartbeatTask != null && !_heartbeatTask.IsCompleted)
return;
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
public void StopHeartbeat()
{
try
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
catch { }
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await (ct);
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (ReConnectionAttempts > MaxReconnectAttempts)
{
LoggerHelper.InfoWithNotify("IT6724C重连多次失败");
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool ok = await ConnectAsync(ct);
if (ok)
ReConnectionAttempts = 0;
}
catch { }
}
#endregion
#region
@ -63,6 +166,12 @@ namespace DeviceCommand.Device
public virtual async Task (string , CancellationToken ct = default)
=>await SendAsync($"{指令}\r\n", ct);
public virtual async Task<string> (CancellationToken ct = default)
{
await SendAsync("*IDN?\r\n", ct);
return await ReadAsync(ct: ct);
}
#endregion
}

View File

@ -1,7 +1,9 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.IO.Ports;
using System.Net;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@ -15,8 +17,110 @@ namespace DeviceCommand.Device
{
ConfigureDevice(, , , , , , );
}
#region
private CancellationTokenSource? _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public LQ7500_D() { }
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
try
{
if (SerialPort.IsOpen)
SerialPort.Close();
SerialPort.PortName = PortName;
SerialPort.BaudRate = BaudRate;
SerialPort.DataBits = DataBits;
SerialPort.StopBits = StopBits;
SerialPort.Parity = Parity;
SerialPort.ReadTimeout = ReadTimeout;
SerialPort.WriteTimeout = WriteTimeout;
if (SerialPort.IsOpen) return true;
SerialPort.Open();
IsActive = true;
StartHeartbeat();
return true;
}
finally
{
}
}
public override void Close()
{
StopHeartbeat();
if (SerialPort.IsOpen) SerialPort.Close();
}
public void StartHeartbeat()
{
if (_heartbeatTask != null && !_heartbeatTask.IsCompleted)
return;
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
public void StopHeartbeat()
{
try
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
catch { }
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await WriteSingleRegisterAsync(1,0,1);
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (ReConnectionAttempts > MaxReconnectAttempts)
{
LoggerHelper.InfoWithNotify("IT6724C重连多次失败");
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool ok = await ConnectAsync(ct);
if (ok)
ReConnectionAttempts = 0;
}
catch { }
}
#endregion
public byte { get; set; } = 1; // 默认从站地址

View File

@ -1,5 +1,6 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.Threading;
using System.Threading.Tasks;
@ -7,126 +8,316 @@ using System.Threading.Tasks;
namespace DeviceCommand.Device
{
[BOBCommand]
public class PSB11000 : ModbusTcp
public class PSB11000 : Tcp
{
public PSB11000(string IpAddress, int port, int SendTimeout, int ReceiveTimeout)
{
ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout);
}
public PSB11000() { }
#region
public virtual async Task (bool , byte slaveAddress = 1, CancellationToken ct = default)
#region
private CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
ushort value = (ushort)( ? 0xFF00 : 0x0000);
await WriteSingleRegisterAsync(slaveAddress, 402, value, ct);
await _commLock.WaitAsync(ct);
try
{
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
if (TcpClient.Connected)
{
return true;
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
IsActive = true;
StartHeartbeat();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_commLock.Release();
}
}
public override void Close()
{
if (!TcpClient.Connected)
{
throw new InvalidOperationException("TCP 没有连接成功");
}
if (TcpClient.Connected)
{
TcpClient.Close();
StopHeartbeat();
}
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource = new();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
public virtual async Task (bool , byte slaveAddress = 1, CancellationToken ct = default)
// 停止设备的心跳
public void StopHeartbeat()
{
ushort value = (ushort)( ? 0xFF00 : 0x0000);
await WriteSingleRegisterAsync(slaveAddress, 405, value, ct);
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
public virtual async Task (bool 使, byte slaveAddress = 1, CancellationToken ct = default)
private async Task HeartbeatLoop(CancellationToken ct)
{
ushort value = (ushort)(使 ? 0xFF00 : 0x0000);
await WriteSingleRegisterAsync(slaveAddress, 409, value, ct);
}
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
public virtual async Task (byte slaveAddress = 1, CancellationToken ct = default)
try
{
await (true);
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
await WriteSingleRegisterAsync(slaveAddress, 411, 0xFF00, ct);
}
try
{
bool resultConnect = await ConnectAsync(ct);
if (resultConnect)
{
ReConnectionAttempts = 0;
}
}
catch (Exception ex)
{
public virtual async Task<bool> (byte slaveAddress = 1, CancellationToken ct = default)
{
ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 402, 1, ct);
return result[0] == 0xFF00;
}
}
public virtual async Task<bool> (byte slaveAddress = 1, CancellationToken ct = default)
{
ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 405, 1, ct);
return result[0] == 0xFF00;
}
public virtual async Task<bool> (byte slaveAddress = 1, CancellationToken ct = default)
{
ushort[] result = await ReadHoldingRegistersAsync(slaveAddress, 409, 1, ct);
return result[0] == 0xFF00;
}
#endregion
#region ///
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询设备信息
public virtual async Task<string> (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 500, value, ct);
return await WriteReadAsync($"*IDN?\r\n", "\n", ct: ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 重置设备
public virtual async Task (CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 500, 1, ct);
return reg[0] / (double)0xCCCC * ;
await SendAsync($"*RST\r\n", ct);
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"OUTPut:PROTection:CLEar\r\n", ct);
}
// 打开输出
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"OUTPut ON\r\n", ct);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 关闭输出
public virtual async Task (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 501, value, ct);
await SendAsync($"OUTPut OFF\r\n", ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 设置远程控制
public virtual async Task (bool , CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 501, 1, ct);
return reg[0] / (double)0xCCCC * ;
await SendAsync($"SYSTem:LOCK {(激活 ? "ON" : "OFF")}\r\n", ct);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 查询远程控制状态
public virtual async Task<string> (CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 502, value, ct);
return await WriteReadAsync($"SYSTem:LOCK:OWNer?\r\n", "\n", ct: ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 设置电压
public virtual async Task (double , CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 502, 1, ct);
return reg[0] / (double)0xCCCC * ;
await SendAsync($"SOURce:VOLTage {电压}V\r\n", ct);
}
public virtual async Task (double , double , byte slaveAddress = 1, CancellationToken ct = default)
// 设置电流
public virtual async Task (double , CancellationToken ct = default)
{
ushort value = (ushort)( / * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 503, value, ct);
await SendAsync($"SOURce:CURRent {电流}A\r\n", ct);
}
public virtual async Task<double> (double , byte slaveAddress = 1, CancellationToken ct = default)
// 设置功率
public virtual async Task (double , CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 503, 1, ct);
return reg[0] / (double)0xCCCC * ;
await SendAsync($"SOURce:POWer {功率}W\r\n", ct);
}
#endregion
#region Sink功率设定
public virtual async Task Sink功率(double , double Sink额定功率, byte slaveAddress = 1, CancellationToken ct = default)
// 设置电阻
public virtual async Task (double , CancellationToken ct = default)
{
ushort value = (ushort)( / Sink额定功率 * 0xCCCC);
await WriteSingleRegisterAsync(slaveAddress, 498, value, ct);
await SendAsync($"SOURce:RESistance {电阻}Ω\r\n", ct);
}
public virtual async Task<double> Sink功率(double Sink额定功率, byte slaveAddress = 1, CancellationToken ct = default)
// 设置过压保护
public virtual async Task (double , CancellationToken ct = default)
{
ushort[] reg = await ReadHoldingRegistersAsync(slaveAddress, 498, 1, ct);
return reg[0] / (double)0xCCCC * Sink额定功率;
await SendAsync($"SOURce:VOLTage:PROTection {电压}V\r\n", ct);
}
// 设置过流保护
public virtual async Task (double , CancellationToken ct = default)
{
await SendAsync($"SOURce:CURRent:PROTection {电流}A\r\n", ct);
}
// 设置过功率保护
public virtual async Task (double , CancellationToken ct = default)
{
await SendAsync($"SOURce:POWer:PROTection {功率}W\r\n", ct);
}
// 查询电压
public virtual async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"MEASure:VOLTage?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
// 查询电流
public virtual async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"MEASure:CURRent?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
// 查询功率
public virtual async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"MEASure:POWer?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
// 批量查询电压、电流、功率
public virtual async Task<(double , double , double )> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"MEASure:ARRay?\r\n", "\n", ct: ct);
var values = str.Split(',');
return (
Convert.ToDouble(values[0]),
Convert.ToDouble(values[1]),
Convert.ToDouble(values[2])
);
}
// 查询标称电压
public virtual async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"SYSTem:NOMinal:VOLTage?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
// 查询标称电流
public virtual async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"SYSTem:NOMinal:CURRent?\r\n", "\n", ct: ct);
return Convert.ToDouble(str);
}
#region
// 激活指定通道
public virtual async Task (int , CancellationToken ct = default)
{
await SendAsync($"INST:SEL CH{通道号}\r\n", ct);
}
// 查询当前激活的通道
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"INST:SEL?\r\n", "\n", ct);
}
// 激活所有通道
public virtual async Task (CancellationToken ct = default)
{
await SendAsync("INST:SEL ALL\r\n", ct);
}
// 设置指定通道电压
public virtual async Task (int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:VOLT {电压}V\r\n", ct);
}
// 设置指定通道电流
public virtual async Task (int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:CURR {电流}A\r\n", ct);
}
// 设置指定通道功率
public virtual async Task (int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:POW {功率}W\r\n", ct);
}
// 设置指定通道 Sink 模式电流
public virtual async Task Sink电流(int , double , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:SINK:CURR {电流}A\r\n", ct);
}
// 启动指定通道输出
public virtual async Task (int , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:OUTP ON\r\n", ct);
}
// 关闭指定通道输出
public virtual async Task (int , CancellationToken ct = default)
{
await SendAsync($"CH{通道号}:OUTP OFF\r\n", ct);
}
// 同时启停所有通道输出
public virtual async Task (CancellationToken ct = default)
{
await SendAsync("INST:ALL:OUTP ON\r\n", ct);
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync("INST:ALL:OUTP OFF\r\n", ct);
}
// 查询指定通道的电压、电流和功率(批量)
public virtual async Task<(double , double , double )> (int , CancellationToken ct = default)
{
var str = await WriteReadAsync($"CH{通道号}:MEAS:ARR?\r\n", "\n", ct);
var values = str.Split(',');
return (
Convert.ToDouble(values[0]), // 电压
Convert.ToDouble(values[1]), // 电流
Convert.ToDouble(values[2]) // 功率
);
}
#endregion
}
}

View File

@ -1,5 +1,6 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
@ -13,8 +14,106 @@ namespace DeviceCommand.Device
{
ConfigureDevice(ip, port, sendTimeout, receiveTimeout);
}
#region
private CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
{
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
if (TcpClient.Connected)
{
return true;
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
IsActive = true;
StartHeartbeat();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_commLock.Release();
}
}
public override void Close()
{
if (!TcpClient.Connected)
{
throw new InvalidOperationException("TCP 没有连接成功");
}
if (TcpClient.Connected)
{
TcpClient.Close();
StopHeartbeat();
}
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource = new();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
public SQ0030G1D() { }
// 停止设备的心跳
public void StopHeartbeat()
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await ();
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool resultConnect = await ConnectAsync(ct);
if (resultConnect)
{
ReConnectionAttempts = 0;
}
}
catch (Exception ex)
{
}
}
#endregion
// ===================== 基础封装 =====================
@ -65,9 +164,6 @@ namespace DeviceCommand.Device
public virtual async Task<double> (CancellationToken ct = default)
=> double.Parse((await ("VOLT?", ct)).Replace("V", ""), CultureInfo.InvariantCulture);
public virtual Task (double freq, CancellationToken ct = default)
=> ($"FREQ {freq}", ct);
public virtual async Task<double> (CancellationToken ct = default)
=> double.Parse((await ("FREQ?", ct)).Replace("Hz", ""), CultureInfo.InvariantCulture);
@ -108,5 +204,53 @@ namespace DeviceCommand.Device
double.Parse(parts[2].Replace("W", ""), CultureInfo.InvariantCulture)
);
}
// 切换到远程控制模式
public virtual Task (CancellationToken ct = default)
=> ("SYST:REM", ct);
// 切换到本地控制模式
public virtual Task (CancellationToken ct = default)
=> ("SYST:LOC", ct);
// 设定三相电压高低档
public virtual Task (int range, CancellationToken ct = default)
=> ($"OUTP:RANG {range}", ct); // 设定高低档166低档/333高档
// 设定通用输出电压
public virtual Task (double value, CancellationToken ct = default)
=> ($"VOLT {value}", ct);
// 设定三相输出电压
public virtual Task (double U, double V, double W, CancellationToken ct = default)
=> ($"VOLT:PHAS A, {U}, B, {V}, C, {W}", ct);
// 设定输出频率
public virtual Task (double freq, CancellationToken ct = default)
=> ($"FREQ {freq}", ct);
// 设定步阶输出电压
public virtual Task (double targetVoltage, double stepTime, CancellationToken ct = default)
=> ($"TRIG:TRAN:VOLT:STEP {targetVoltage}, {stepTime}", ct);
// 设定步阶输出频率
public virtual Task (double targetFrequency, double stepTime, CancellationToken ct = default)
=> ($"TRIG:TRAN:FREQ:STEP {targetFrequency}, {stepTime}", ct);
// 设定渐变输出电压
public virtual Task (double startVoltage, double endVoltage, double sweepTime, CancellationToken ct = default)
=> ($"TRIG:TRAN:VOLT:SWEEP {startVoltage}, {endVoltage}, {sweepTime}", ct);
// 设定渐变输出频率
public virtual Task (double startFreq, double endFreq, double sweepTime, CancellationToken ct = default)
=> ($"TRIG:TRAN:FREQ:SWEEP {startFreq}, {endFreq}, {sweepTime}", ct);
// 设定软件启动功能起始电压与额定电压
public virtual Task (double startVoltage, double ratedVoltage, CancellationToken ct = default)
=> ($"PON:VOLT {startVoltage}, {ratedVoltage}", ct);
// 设定软件启动功能起始电压与起始频率
public virtual Task (double startVoltage, double startFrequency, CancellationToken ct = default)
=> ($"PON:FREQ {startVoltage}, {startFrequency}", ct);
}
}

View File

@ -1,5 +1,6 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.Threading;
using System.Threading.Tasks;
@ -13,31 +14,129 @@ namespace DeviceCommand.Device
{
ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout);
}
#region
private CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
{
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
if (TcpClient.Connected)
{
return true;
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
IsActive = true;
StartHeartbeat();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_commLock.Release();
}
}
public override void Close()
{
if (!TcpClient.Connected)
{
throw new InvalidOperationException("TCP 没有连接成功");
}
if (TcpClient.Connected)
{
TcpClient.Close();
StopHeartbeat();
}
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource = new();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
public WS_68030_380T() { }
// 停止设备的心跳
public void StopHeartbeat()
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await WriteSingleRegisterAsync(1,0,1);
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool resultConnect = await ConnectAsync(ct);
if (resultConnect)
{
ReConnectionAttempts = 0;
}
}
catch (Exception ex)
{
}
}
#endregion
private const byte SlaveAddress = 1;
public async Task _KW(float , CancellationToken ct = default)
public virtual async Task _KW(float , CancellationToken ct = default)
{
var send = ConvertFromFloat();
await WriteMultipleRegistersAsync(1, 58, send).WaitAsync(ct);
}
public async Task (CancellationToken ct = default)
public virtual async Task (CancellationToken ct = default)
{
var tmp = new ushort();
ushort send = (ushort)(tmp | (1 << 8));
await WriteSingleRegisterAsync(1, 70, send).WaitAsync(ct);
}
public async Task (CancellationToken ct = default)
public virtual async Task (CancellationToken ct = default)
{
await WriteSingleRegisterAsync(1, 70, new()).WaitAsync(ct);
}
public async Task<float> _KW(CancellationToken ct = default)
public virtual async Task<float> _KW(CancellationToken ct = default)
{
var re = await ReadHoldingRegistersAsync(1, 58, 2).WaitAsync(ct);
return ConvertToFloat(re);
@ -46,7 +145,7 @@ namespace DeviceCommand.Device
#region
protected virtual float ConvertToFloat(ushort[] values)
protected float ConvertToFloat(ushort[] values)
{
byte[] bytes = new byte[4];
bytes[3] = (byte)(values[0] >> 8);
@ -56,7 +155,7 @@ namespace DeviceCommand.Device
return BitConverter.ToSingle(bytes, 0);
}
protected virtual ushort[] ConvertFromFloat(float value)
protected ushort[] ConvertFromFloat(float value)
{
byte[] bytes = BitConverter.GetBytes(value);
return new ushort[]

View File

@ -1,5 +1,6 @@
using Common.Attributes;
using DeviceCommand.Base;
using Logger;
using System;
using System.Collections.Generic;
using System.Linq;
@ -16,9 +17,105 @@ namespace DeviceCommand.Device
ConfigureDevice(IpAddress, port, SendTimeout, ReceiveTimeout);
}
public ZXKS()
#region
private CancellationTokenSource _cancellationTokenSource;
private Task? _heartbeatTask;
private const int HeartbeatInterval = 3000;
public bool IsActive = false;
public int ReConnectionAttempts = 0;
public const int MaxReconnectAttempts = 10;
public override async Task<bool> ConnectAsync(CancellationToken ct = default)
{
await _commLock.WaitAsync(ct);
try
{
if (TcpClient != null && !TcpClient.Connected) TcpClient = new();
if (TcpClient.Connected)
{
return true;
}
await TcpClient.ConnectAsync(IPAddress, Port, ct);
IsActive = true;
StartHeartbeat();
return true;
}
catch (Exception ex)
{
return false;
}
finally
{
_commLock.Release();
}
}
public override void Close()
{
if (!TcpClient.Connected)
{
throw new InvalidOperationException("TCP 没有连接成功");
}
if (TcpClient.Connected)
{
TcpClient.Close();
StopHeartbeat();
}
}
// 启动设备的心跳
public void StartHeartbeat()
{
if (_heartbeatTask != null)
return;
if (_cancellationTokenSource == null || _cancellationTokenSource.IsCancellationRequested)
_cancellationTokenSource = new();
_heartbeatTask = Task.Run(() => HeartbeatLoop(_cancellationTokenSource.Token));
}
// 停止设备的心跳
public void StopHeartbeat()
{
IsActive = false;
_cancellationTokenSource.Cancel();
_heartbeatTask = null;
}
private async Task HeartbeatLoop(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await Task.Delay(HeartbeatInterval, ct);
try
{
await WriteSingleRegisterAsync(1, 0, 1);
}
catch (Exception ex)
{
IsActive = false;
ReConnectionAttempts++;
if (MaxReconnectAttempts < ReConnectionAttempts)
{
StopHeartbeat();
return;
}
await ReconnectDevice(ct);
}
}
}
private async Task ReconnectDevice(CancellationToken ct)
{
try
{
bool resultConnect = await ConnectAsync(ct);
if (resultConnect)
{
ReConnectionAttempts = 0;
}
}
catch (Exception ex)
{
}
}
#endregion
}
}

View File

@ -14,6 +14,7 @@
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\Logger\Logger.csproj" />
<ProjectReference Include="..\Model\Model.csproj" />
</ItemGroup>

View File

@ -56,7 +56,37 @@ namespace Logger
{
Progress.Report((message, color, depth));
}
// 解析堆栈,找到项目文件路径和行号
public static void Info(string message, int depth = 0)
{
Logger.Info(message); // 写入 NLog
}
public static void Success(string message, int depth = 0)
{
Logger.Info(message);
}
public static void Warn(string message, string stackTrace = null, int depth = 0)
{
if (!string.IsNullOrEmpty(stackTrace))
{
string location = GetProjectStackLine(stackTrace);
message = $"{message} ({location})";
}
Logger.Warn(message);
}
public static void Error(string message, string stackTrace = null, int depth = 0)
{
if (!string.IsNullOrEmpty(stackTrace))
{
string location = GetProjectStackLine(stackTrace);
message = $"{message} ({location})";
}
Logger.Error(message);
}
public static string GetProjectStackLine(string stackTrace)
{
if (string.IsNullOrEmpty(stackTrace))

View File

@ -8,9 +8,13 @@ public class LoggingInterceptor : IInterceptor
{
string className = invocation.TargetType.Name;
string methodName = invocation.Method.Name;
if (methodName== "ConnectAsync"|| methodName == "Close")
{
invocation.Proceed();
return;
}
LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 开始");
LoggerHelper.Info($"调用 {className}.{methodName}() 开始");
var sw = Stopwatch.StartNew();
@ -29,12 +33,12 @@ public class LoggingInterceptor : IInterceptor
sw.Stop();
LoggerHelper.InfoWithNotify($"调用 {className}.{methodName}() 完成,耗时 {sw.ElapsedMilliseconds} ms");
LoggerHelper.Info($"调用 {className}.{methodName}() 完成,耗时 {sw.ElapsedMilliseconds} ms");
}
catch (Exception ex)
{
sw.Stop();
LoggerHelper.ErrorWithNotify($"调用 {className}.{methodName}() 异常:{ex.Message}", ex.StackTrace);
LoggerHelper.Error($"调用 {className}.{methodName}() 异常:{ex.Message}", ex.StackTrace);
throw;
}
}
@ -67,41 +71,41 @@ public class LoggingInterceptor : IInterceptor
if (resultType == typeof(bool))
{
bool result = (bool)((dynamic)task).Result;
LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms结果: {result}");
LoggerHelper.Success($"调用 {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)}]");
LoggerHelper.Success($"调用 {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)}]");
LoggerHelper.Success($"调用 {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)}]");
LoggerHelper.Success($"调用 {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)}]");
LoggerHelper.Success($"调用 {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");
LoggerHelper.Success($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms");
}
else
{
LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms结果: {((dynamic)task).Result}");
LoggerHelper.Success($"调用 {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);
LoggerHelper.Error($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 异常:{ex.Message}", ex.StackTrace);
var exception = new Exception($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 时发生异常:{ex.Message}");
invocation.ReturnValue = Task.FromException<object>(exception);
@ -112,13 +116,13 @@ public class LoggingInterceptor : IInterceptor
{
// 如果是普通的 Task无需处理泛型返回值
await (Task)invocation.ReturnValue;
LoggerHelper.SuccessWithNotify($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 完成,耗时 {sw.ElapsedMilliseconds} ms");
LoggerHelper.Success($"调用 {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);
LoggerHelper.Error($"调用 {invocation.TargetType.Name}.{invocation.Method.Name}() 异常:{ex.Message}", ex.StackTrace);
}
}

View File

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model
{
public class DeviceInfoModel
{
public string DeviceName { get; set; }
public string DeviceType { get; set; }
public string Remark { get; set; }
public bool IsEnabled { get; set; }
public bool IsConnected { get; set; }
public ICommunicationConfig CommunicationConfig { get; set; }
}
}