设备单独控制界面

This commit is contained in:
“hsc”
2026-07-29 16:54:56 +08:00
parent e4107c9997
commit 252c70ef05
25 changed files with 2057 additions and 11 deletions

View File

@@ -841,10 +841,7 @@ namespace ACP.ViewModels
_regionManager.RequestNavigate(settingRegion, "SettingView", settingParameters);
IsLeftDrawerOpen = false;
break;
case "台架移动界面":
if (_globalInfo.CurrentScope != "default") return;
_regionManager.RequestNavigate("ShellViewManager", "BenchMovementView");
break;
case "曲线回读界面":
if (_globalInfo.CurrentScope != "default") return;
_regionManager.RequestNavigate("ShellViewManager", "CurveRecallView");

View File

@@ -61,11 +61,7 @@
Style="{StaticResource MaterialDesignFlatButton}"
Margin="8" />
<Button Content="台架移动界面"
Command="{Binding NavigateCommand}"
CommandParameter="{Binding Content, RelativeSource={RelativeSource Self}}"
Style="{StaticResource MaterialDesignFlatButton}"
Margin="8" />
<Button Content="曲线回读界面"
Command="{Binding NavigateCommand}"
CommandParameter="{Binding Content, RelativeSource={RelativeSource Self}}"

View File

@@ -0,0 +1,300 @@
using Common.Attributes;
using DeviceCommand.Base;
using Model.Models;
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
namespace DeviceCommand.Devices
{
[ACPCommand]
public class IT6015C : Tcp
{
// SCPI 指令结束符
private const string ScpiDelimiter = "\n";
public IT6015C(TcpConfig config) : base(config)
{
}
#region 1. IEEE 488.2
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"*CLS{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"*IDN?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"*RST{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"*STB?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
public virtual async Task<string> SCPI版本号(CancellationToken ct = default)
{
return await WriteReadAsync($":SYSTem:VERSion?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
#endregion
#region 2.
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"SYSTem:REMote{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"SYSTem:LOCal{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"SYSTem:RWLock{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"SYSTem:ERRor?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"SYSTem:CLEar{ScpiDelimiter}", ct); //[cite: 1]
}
#endregion
#region 3.
/// <summary>
/// 设置电源优先工作模式 (CV 电压优先 或 CC 电流优先)
/// </summary>
public virtual async Task (IT6000CPriorityMode , CancellationToken ct = default)
{
await SendAsync($"FUNCTION {模式}{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"FUNCTION?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
/// <summary>
/// 设置瞬变/功能模式 (固定, LIST, 电池测试, PV曲线, 汽车波形)
/// </summary>
public virtual async Task (IT6000CFunctionMode , CancellationToken ct = default)
{
await SendAsync($"FUNCTION:MODE {模式}{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"FUNCTION:MODE?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
#endregion
#region 4.
public virtual async Task (bool , CancellationToken ct = default)
{
string = ? "ON" : "OFF";
await SendAsync($"OUTPut {参数}{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"OUTPut:STATe?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"OUTPut:PROTection:CLEar{ScpiDelimiter}", ct); //[cite: 1]
}
#endregion
#region 5. /
/// <summary>
/// 设置输出电压 (仅在 CV 模式下生效)
/// </summary>
public virtual async Task (double , CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "VOLTage {0:F2}{1}", , ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
/// <summary>
/// 设置输出电流 (仅在 CC 模式下生效)
/// </summary>
public virtual async Task (double , CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "CURRent {0:F3}{1}", , ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
/// <summary>
/// 设置 CV 优先模式下的电流限制上限值 (I+, 限流保护)
/// </summary>
public virtual async Task (double , CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "CURRent:LIMit:POSitive {0:F3}{1}", , ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"CURRent:LIMit:POSitive?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
/// <summary>
/// 设置电压上升/下降斜率 (单位: V/s, 数值越大变化越快)[cite: 1]
/// </summary>
public virtual async Task (double Vs, CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "VOLTage:SLEW {0:F4}{1}", Vs, ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
#endregion
#region 6. (OVP, OCP, OPP)
/// <summary>
/// 开启或关闭过压保护 (OVP)[cite: 1]
/// </summary>
public virtual async Task (bool , CancellationToken ct = default)
{
string = ? "ON" : "OFF";
await SendAsync($"VOLTage:PROTection:STATe {参数}{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task (double , CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "VOLTage:PROTection {0:F2}{1}", , ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
/// <summary>
/// 开启或关闭过流保护 (OCP)[cite: 1]
/// </summary>
public virtual async Task (bool , CancellationToken ct = default)
{
string = ? "ON" : "OFF";
await SendAsync($"CURRent:PROTection:STATe {参数}{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task (double , CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "CURRent:PROTection {0:F3}{1}", , ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
/// <summary>
/// 开启或关闭过功率保护 (OPP)[cite: 1]
/// </summary>
public virtual async Task (bool , CancellationToken ct = default)
{
string = ? "ON" : "OFF";
await SendAsync($"POWER:PROTection:STATe {参数}{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task (double , CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "POWER:PROTection {0:F2}{1}", , ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
#endregion
#region 7. (MEASure FETCh)
[Monitorable("直流源载实际电压")]
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
[Monitorable("直流源载实际电流")]
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
[Monitorable("直流源载实际功率")]
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"MEASure:POWER?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"FETCh:VOLTage:MAXimum?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
public virtual async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"FETCh:CURRent:MINimum?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
#endregion
#region 8. /CR模式设置 ( CC )
/// <summary>
/// 开启或关闭恒阻 (CR) 负载模式[cite: 1]
/// </summary>
/// <remarks>执行该指令前,必须确保设备处于 CC 优先模式,否则会报错</remarks>
public virtual async Task CR模式开关(bool , CancellationToken ct = default)
{
string = ? "ON" : "OFF";
await SendAsync($"SINK:RESistance:STATe {参数}{ScpiDelimiter}", ct); //[cite: 1]
}
public virtual async Task<string> CR模式开关(CancellationToken ct = default)
{
return await WriteReadAsync($"SINK:RESistance:STATe?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
/// <summary>
/// 设置恒阻 (CR) 模式下的电阻值 (单位: Ω)[cite: 1]
/// </summary>
/// <remarks>必须在先开启 CR 模式才能使用,设置为 0 相当于关闭 CR 模式</remarks>
public virtual async Task CR电阻值(double , CancellationToken ct = default)
{
string cmd = string.Format(CultureInfo.InvariantCulture, "SINK:RESistance {0:F2}{1}", , ScpiDelimiter); //[cite: 1]
await SendAsync(cmd, ct);
}
public virtual async Task<string> CR电阻值(CancellationToken ct = default)
{
return await WriteReadAsync($"SINK:RESistance?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
}
#endregion
}
}

View File

@@ -41,12 +41,12 @@ namespace DeviceCommand.Devices
#endregion
[ACPCommand]
public class IT6000C : Tcp
public class IT6036C : Tcp
{
// SCPI 指令结束符
private const string ScpiDelimiter = "\n";
public IT6000C(TcpConfig config) : base(config)
public IT6036C (TcpConfig config) : base(config)
{
}

View File

@@ -0,0 +1,147 @@
using DeviceCommand.Devices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
namespace DeviceEditModule.ViewModels
{
public class DG1000ZViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private DG1000Z? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "DG1000Z";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary>正在执行设备命令时为 true用于 UI 忙碌状态指示。</summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private string _responseLog = string.Empty;
/// <summary>命令响应日志(最新消息在顶部)。</summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
#endregion
public DG1000ZViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
#region / Navigation
/// <summary>
/// 从 DeviceManager 中查找DG1000Z设备实例。
/// 优先按 <paramref name="deviceName"/> 查找,否则取第一个匹配类型的设备。
/// </summary>
public void Initialize(string? deviceName = null)
{
DG1000Z? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is DG1000Z e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is DG1000Z it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "IT7800E (未找到)";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $"已关联设备 [{DeviceName}],连接状态:{(IsConnected ? "" : "")}"
: "未在 DeviceManager 中找到 IT7800E 设备,请先初始化设备配置。");
}
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("错误:未关联到设备实例,请检查设备配置。");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("命令超时或已取消。");
}
catch (Exception ex)
{
AppendLog($"错误:{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
}
}

View File

@@ -0,0 +1,147 @@
using DeviceCommand.Devices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
namespace DeviceEditModule.ViewModels
{
public class IT6015CViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private IT6015C? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "IT6015C";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary>正在执行设备命令时为 true用于 UI 忙碌状态指示。</summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private string _responseLog = string.Empty;
/// <summary>命令响应日志(最新消息在顶部)。</summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
#endregion
public IT6015CViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
#region / Navigation
/// <summary>
/// 从 DeviceManager 中查找IT6015C设备实例。
/// 优先按 <paramref name="deviceName"/> 查找,否则取第一个匹配类型的设备。
/// </summary>
public void Initialize(string? deviceName = null)
{
IT6015C? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is IT6015C e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is IT6015C it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "IT7800E (未找到)";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $"已关联设备 [{DeviceName}],连接状态:{(IsConnected ? "" : "")}"
: "未在 DeviceManager 中找到 IT7800E 设备,请先初始化设备配置。");
}
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("错误:未关联到设备实例,请检查设备配置。");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("命令超时或已取消。");
}
catch (Exception ex)
{
AppendLog($"错误:{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
}
}

View File

@@ -0,0 +1,147 @@
using DeviceCommand.Devices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
namespace DeviceEditModule.ViewModels
{
public class IT6036CViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private IT6036C? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "IT6036C";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary>正在执行设备命令时为 true用于 UI 忙碌状态指示。</summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private string _responseLog = string.Empty;
/// <summary>命令响应日志(最新消息在顶部)。</summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
#endregion
public IT6036CViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
#region / Navigation
/// <summary>
/// 从 DeviceManager 中查找IT6036C设备实例。
/// 优先按 <paramref name="deviceName"/> 查找,否则取第一个匹配类型的设备。
/// </summary>
public void Initialize(string? deviceName = null)
{
IT6036C? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is IT6036C e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is IT6036C it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "IT7800E (未找到)";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $"已关联设备 [{DeviceName}],连接状态:{(IsConnected ? "" : "")}"
: "未在 DeviceManager 中找到 IT7800E 设备,请先初始化设备配置。");
}
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("错误:未关联到设备实例,请检查设备配置。");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("命令超时或已取消。");
}
catch (Exception ex)
{
AppendLog($"错误:{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
}
}

View File

@@ -0,0 +1,147 @@
using DeviceCommand.Devices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
namespace DeviceEditModule.ViewModels
{
public class IT6720ViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private IT6720? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "IT6720";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary>正在执行设备命令时为 true用于 UI 忙碌状态指示。</summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private string _responseLog = string.Empty;
/// <summary>命令响应日志(最新消息在顶部)。</summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
#endregion
public IT6720ViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
#region / Navigation
/// <summary>
/// 从 DeviceManager 中查找IT6720设备实例。
/// 优先按 <paramref name="deviceName"/> 查找,否则取第一个匹配类型的设备。
/// </summary>
public void Initialize(string? deviceName = null)
{
IT6720? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is IT6720 e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is IT6720 it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "IT7800E (未找到)";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $"已关联设备 [{DeviceName}],连接状态:{(IsConnected ? "" : "")}"
: "未在 DeviceManager 中找到 IT7800E 设备,请先初始化设备配置。");
}
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("错误:未关联到设备实例,请检查设备配置。");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("命令超时或已取消。");
}
catch (Exception ex)
{
AppendLog($"错误:{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
}
}

View File

@@ -0,0 +1,310 @@
using DeviceCommand.Devices;
using Prism.Commands;
using Prism.Ioc;
using System;
using System.Threading;
using System.Windows.Input;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
namespace DeviceEditModule.ViewModels
{
/// <summary>
/// IT7800E 交直流电源控制面板 ViewModel。
/// <para>
/// 注册为 Navigation View既可由 Region 导航进入,
/// 也可由外部直接实例化后作为 Tab 内容塞入 DialogMangerView
/// <code>
/// var view = container.Resolve&lt;IT7800EView&gt;();
/// (view.DataContext as IT7800EViewModel)?.Initialize("IT7800E");
/// _eventAggregator.GetEvent&lt;AddDialogTabEvent&gt;().Publish(
/// new DialogTabInfo { Title = "IT7800E", Content = view });
/// </code>
/// </para>
/// </summary>
public class IT7800EViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private IT7800E? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "IT7800E";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary>正在执行设备命令时为 true用于 UI 忙碌状态指示。</summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
#endregion
#region
private double _acVoltage = 220.0;
/// <summary>待设置的交流电压值V。</summary>
public double AcVoltage
{
get => _acVoltage;
set => SetProperty(ref _acVoltage, value);
}
private double _dcVoltage = 0.0;
/// <summary>待设置的直流偏置电压值V。</summary>
public double DcVoltage
{
get => _dcVoltage;
set => SetProperty(ref _dcVoltage, value);
}
private double _frequency = 50.0;
/// <summary>待设置的交流频率Hz。</summary>
public double Frequency
{
get => _frequency;
set => SetProperty(ref _frequency, value);
}
private double _currentLimit = 10.0;
/// <summary>待设置的限流值A。</summary>
public double CurrentLimit
{
get => _currentLimit;
set => SetProperty(ref _currentLimit, value);
}
private PowerCouplingMode _selectedMode = PowerCouplingMode.AC;
/// <summary>待设置的电源工作模式AC / DC / ACDC。</summary>
public PowerCouplingMode SelectedMode
{
get => _selectedMode;
set => SetProperty(ref _selectedMode, value);
}
private double _ovpValue = 260.0;
/// <summary>过压保护值V。</summary>
public double OvpValue
{
get => _ovpValue;
set => SetProperty(ref _ovpValue, value);
}
private double _ocpValue = 15.0;
/// <summary>过流保护值A。</summary>
public double OcpValue
{
get => _ocpValue;
set => SetProperty(ref _ocpValue, value);
}
#endregion
#region
private string _measuredVoltage = "—";
public string MeasuredVoltage
{
get => _measuredVoltage;
set => SetProperty(ref _measuredVoltage, value);
}
private string _measuredCurrent = "—";
public string MeasuredCurrent
{
get => _measuredCurrent;
set => SetProperty(ref _measuredCurrent, value);
}
private string _measuredPower = "—";
public string MeasuredPower
{
get => _measuredPower;
set => SetProperty(ref _measuredPower, value);
}
private string _measuredFrequency = "—";
public string MeasuredFrequency
{
get => _measuredFrequency;
set => SetProperty(ref _measuredFrequency, value);
}
private string _responseLog = string.Empty;
/// <summary>命令响应日志(最新消息在顶部)。</summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
public ICommand QueryIdentityCommand { get; }
public ICommand ResetDeviceCommand { get; }
public ICommand OutputOnCommand { get; }
public ICommand OutputOffCommand { get; }
public ICommand SetModeCommand { get; }
public ICommand SetAcVoltageCommand { get; }
public ICommand SetDcVoltageCommand { get; }
public ICommand SetFrequencyCommand { get; }
public ICommand SetCurrentCommand { get; }
public ICommand QueryAllMeasureCommand { get; }
public ICommand SetRemoteModeCommand { get; }
public ICommand SetLocalModeCommand { get; }
public ICommand SetOvpCommand { get; }
public ICommand SetOcpCommand { get; }
public ICommand ClearAlarmCommand { get; }
public ICommand ClearErrorCommand { get; }
#endregion
public IT7800EViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
QueryIdentityCommand = new DelegateCommand(async () => await Exec(async () => AppendLog("IDN: " + await _device!.(Ct()))));
ResetDeviceCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); AppendLog("设备已重置"); }));
OutputOnCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.DC输出(true, Ct()); AppendLog("输出已开启"); }));
OutputOffCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.DC输出(false, Ct()); AppendLog("输出已关闭"); }));
SetModeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(SelectedMode, Ct()); AppendLog($"模式已设为 {SelectedMode}"); }));
SetAcVoltageCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(AcVoltage, Ct()); AppendLog($"AC电压已设为 {AcVoltage} V"); }));
SetDcVoltageCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(DcVoltage, Ct()); AppendLog($"DC偏置已设为 {DcVoltage} V"); }));
SetFrequencyCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Frequency, Ct()); AppendLog($"频率已设为 {Frequency} Hz"); }));
SetCurrentCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(CurrentLimit, Ct()); AppendLog($"限流已设为 {CurrentLimit} A"); }));
SetOvpCommand = new DelegateCommand(async () => await Exec(async () => { await _device!._OVP(OvpValue, Ct()); AppendLog($"OVP已设为 {OvpValue} V"); }));
SetOcpCommand = new DelegateCommand(async () => await Exec(async () => { await _device!._OCP(OcpValue, Ct()); AppendLog($"OCP已设为 {OcpValue} A"); }));
SetRemoteModeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); AppendLog("已切换到远程控制模式"); }));
SetLocalModeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); AppendLog("已切换到本地控制模式"); }));
ClearAlarmCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); AppendLog("保护告警已清除"); }));
ClearErrorCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); AppendLog("错误队列已清除"); }));
QueryAllMeasureCommand = new DelegateCommand(async () => await Exec(async () =>
{
MeasuredVoltage = await _device!.(Ct());
MeasuredCurrent = await _device!.(Ct());
MeasuredPower = await _device!.(Ct());
MeasuredFrequency = await _device!.(Ct());
AppendLog($"测量 → 电压:{MeasuredVoltage}V 电流:{MeasuredCurrent}A 功率:{MeasuredPower}W 频率:{MeasuredFrequency}Hz");
}));
Initialize();
}
#region / Navigation
/// <summary>
/// 从 DeviceManager 中查找 IT7800E 设备实例。
/// 优先按 <paramref name="deviceName"/> 查找,否则取第一个匹配类型的设备。
/// </summary>
public void Initialize(string? deviceName = null)
{
IT7800E? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is IT7800E e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is IT7800E it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "IT7800E (未找到)";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $"已关联设备 [{DeviceName}],连接状态:{(IsConnected ? "" : "")}"
: "未在 DeviceManager 中找到 IT7800E 设备,请先初始化设备配置。");
}
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("错误:未关联到设备实例,请检查设备配置。");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("命令超时或已取消。");
}
catch (Exception ex)
{
AppendLog($"错误:{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
}
}

View File

@@ -0,0 +1,148 @@
using DeviceCommand.Device;
using DeviceCommand.Devices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
namespace DeviceEditModule.ViewModels
{
public class PW8001ViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private PW8001? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "PW8001";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary>正在执行设备命令时为 true用于 UI 忙碌状态指示。</summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private string _responseLog = string.Empty;
/// <summary>命令响应日志(最新消息在顶部)。</summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
#endregion
public PW8001ViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
#region / Navigation
/// <summary>
/// 从 DeviceManager 中查找PW8001设备实例。
/// 优先按 <paramref name="deviceName"/> 查找,否则取第一个匹配类型的设备。
/// </summary>
public void Initialize(string? deviceName = null)
{
PW8001? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is PW8001 e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is PW8001 it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "IT7800E (未找到)";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $"已关联设备 [{DeviceName}],连接状态:{(IsConnected ? "" : "")}"
: "未在 DeviceManager 中找到 IT7800E 设备,请先初始化设备配置。");
}
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("错误:未关联到设备实例,请检查设备配置。");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("命令超时或已取消。");
}
catch (Exception ex)
{
AppendLog($"错误:{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
}
}

View File

@@ -0,0 +1,148 @@
using DeviceCommand.Device;
using DeviceCommand.Devices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
namespace DeviceEditModule.ViewModels
{
public class TektronixMSOViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private TektronixMSO? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "TektronixMSO";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary>正在执行设备命令时为 true用于 UI 忙碌状态指示。</summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
private string _responseLog = string.Empty;
/// <summary>命令响应日志(最新消息在顶部)。</summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
#endregion
public TektronixMSOViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
#region / Navigation
/// <summary>
/// 从 DeviceManager 中查找TektronixMSO设备实例。
/// 优先按 <paramref name="deviceName"/> 查找,否则取第一个匹配类型的设备。
/// </summary>
public void Initialize(string? deviceName = null)
{
TektronixMSO? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is TektronixMSO e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is TektronixMSO it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "IT7800E (未找到)";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $"已关联设备 [{DeviceName}],连接状态:{(IsConnected ? "" : "")}"
: "未在 DeviceManager 中找到 IT7800E 设备,请先初始化设备配置。");
}
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("错误:未关联到设备实例,请检查设备配置。");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("命令超时或已取消。");
}
catch (Exception ex)
{
AppendLog($"错误:{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
}
}

View File

@@ -0,0 +1,15 @@
<UserControl x:Class="DeviceEditModule.Views.DG1000ZView"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
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 DeviceEditModule.Views
{
/// <summary>
/// DG1000ZView.xaml 的交互逻辑
/// </summary>
public partial class DG1000ZView : UserControl
{
public DG1000ZView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,15 @@
<UserControl x:Class="DeviceEditModule.Views.IT6015CView"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
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 DeviceEditModule.Views
{
/// <summary>
/// IT6015CView.xaml 的交互逻辑
/// </summary>
public partial class IT6015CView : UserControl
{
public IT6015CView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,16 @@
<Page x:Class="DeviceEditModule.Views.IT6036CView"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,28 @@
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 DeviceEditModule.Views
{
/// <summary>
/// IT6036CView.xaml 的交互逻辑
/// </summary>
public partial class IT6036CView : Page
{
public IT6036CView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,15 @@
<UserControl x:Class="DeviceEditModule.Views.IT6720View"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
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 DeviceEditModule.Views
{
/// <summary>
/// IT6720View.xaml 的交互逻辑
/// </summary>
public partial class IT6720View : UserControl
{
public IT6720View()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,272 @@
<UserControl x:Class="DeviceEditModule.Views.IT7800EView"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<UserControl.Resources>
<converters:BooleanToVisibilityConverter x:Key="BoolToVis"/>
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<StackPanel Margin="12">
<!-- ═══ 设备信息头 ═══ -->
<materialDesign:Card Margin="0,0,0,8" Padding="12,8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<materialDesign:PackIcon Kind="Flash" Width="22" Height="22"
Foreground="#1565C0" Margin="0,0,8,0"
VerticalAlignment="Center"/>
<TextBlock Text="IT7800E 交直流可编程电源"
FontSize="15" FontWeight="Bold"
VerticalAlignment="Center"/>
<TextBlock Text="{Binding DeviceName, StringFormat=' [{0}]'}"
FontSize="13" Foreground="#757575"
VerticalAlignment="Center" Margin="4,0,0,0"/>
</StackPanel>
<!-- 连接状态指示 -->
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center">
<Border Width="10" Height="10" CornerRadius="5" Margin="0,0,6,0">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="#F44336"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Background" Value="#4CAF50"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<TextBlock VerticalAlignment="Center" FontSize="12">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="未连接"/>
<Setter Property="Foreground" Value="#F44336"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Text" Value="已连接"/>
<Setter Property="Foreground" Value="#4CAF50"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<!-- 忙碌指示 -->
<ProgressBar IsIndeterminate="True" Width="80" Height="4"
Margin="12,0,0,0"
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVis}}"/>
</StackPanel>
</Grid>
</materialDesign:Card>
<!-- ═══ 主体 2 列 ═══ -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ─── 左列 ─── -->
<StackPanel Grid.Column="0" Margin="0,0,4,0">
<!-- 输出控制 -->
<GroupBox Header="输出控制" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<!-- 开关输出 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="主输出" Style="{StaticResource ParamLabel}"/>
<Button Content="开启输出" Command="{Binding OutputOnCommand}"
Style="{StaticResource MaterialDesignRaisedButton}"
Background="#388E3C" Foreground="White"
Height="32" Padding="12,0" FontSize="12" Margin="4,0"/>
<Button Content="关闭输出" Command="{Binding OutputOffCommand}"
Style="{StaticResource WarnBtn}"/>
</StackPanel>
<!-- 工作模式 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="工作模式" Style="{StaticResource ParamLabel}"/>
<ComboBox Width="90" Height="32" Margin="4,0"
materialDesign:HintAssist.Hint=""
SelectedItem="{Binding SelectedMode}"
VerticalContentAlignment="Center" FontSize="12">
<ComboBoxItem Content="AC"/>
<ComboBoxItem Content="DC"/>
<ComboBoxItem Content="ACDC"/>
</ComboBox>
<Button Content="设置模式" Command="{Binding SetModeCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
<!-- 远程/本地 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="控制模式" Style="{StaticResource ParamLabel}"/>
<Button Content="远程控制" Command="{Binding SetRemoteModeCommand}"
Style="{StaticResource CmdBtn}"/>
<Button Content="本地控制" Command="{Binding SetLocalModeCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
<!-- 清除 / 重置 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="系统操作" Style="{StaticResource ParamLabel}"/>
<Button Content="清除告警" Command="{Binding ClearAlarmCommand}"
Style="{StaticResource WarnBtn}"/>
<Button Content="清除错误" Command="{Binding ClearErrorCommand}"
Style="{StaticResource WarnBtn}"/>
<Button Content="重置设备" Command="{Binding ResetDeviceCommand}"
Style="{StaticResource WarnBtn}"/>
</StackPanel>
</StackPanel>
</GroupBox>
<!-- 参数设置 -->
<GroupBox Header="参数设置" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<!-- AC 电压 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="AC电压 (V)" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding AcVoltage, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="设置" Command="{Binding SetAcVoltageCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
<!-- DC 偏置 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="DC偏置 (V)" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding DcVoltage, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="设置" Command="{Binding SetDcVoltageCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
<!-- 频率 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="频率 (Hz)" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding Frequency, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="设置" Command="{Binding SetFrequencyCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
<!-- 限流 -->
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="限流 (A)" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding CurrentLimit, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="设置" Command="{Binding SetCurrentCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
</StackPanel>
</GroupBox>
<!-- 保护设置 -->
<GroupBox Header="保护设置" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="OVP (V)" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding OvpValue, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="设置 OVP" Command="{Binding SetOvpCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="OCP (A)" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding OcpValue, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="设置 OCP" Command="{Binding SetOcpCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
</StackPanel>
</GroupBox>
</StackPanel>
<!-- ─── 右列 ─── -->
<StackPanel Grid.Column="1" Margin="4,0,0,0">
<!-- 实时测量 -->
<GroupBox Header="实时测量" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="实际电压" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource MeasureBox}"
materialDesign:HintAssist.Hint=""
Text="{Binding MeasuredVoltage, Mode=OneWay}"/>
<TextBlock Text="V" VerticalAlignment="Center" Margin="2,0,8,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="实际电流" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource MeasureBox}"
materialDesign:HintAssist.Hint=""
Text="{Binding MeasuredCurrent, Mode=OneWay}"/>
<TextBlock Text="A" VerticalAlignment="Center" Margin="2,0,8,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="实际功率" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource MeasureBox}"
materialDesign:HintAssist.Hint=""
Text="{Binding MeasuredPower, Mode=OneWay}"/>
<TextBlock Text="W" VerticalAlignment="Center" Margin="2,0,8,0"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="输出频率" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource MeasureBox}"
materialDesign:HintAssist.Hint=""
Text="{Binding MeasuredFrequency, Mode=OneWay}"/>
<TextBlock Text="Hz" VerticalAlignment="Center" Margin="2,0,8,0"/>
</StackPanel>
<Button Content="刷新全部测量" Command="{Binding QueryAllMeasureCommand}"
Style="{StaticResource CmdBtn}"
HorizontalAlignment="Left" Margin="0,4,0,0"/>
</StackPanel>
</GroupBox>
<!-- 设备信息 -->
<GroupBox Header="设备信息" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Orientation="Horizontal" Margin="4,8">
<Button Content="查询 IDN" Command="{Binding QueryIdentityCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
</GroupBox>
<!-- 响应日志 -->
<GroupBox Header="响应日志" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<ScrollViewer Height="260" VerticalScrollBarVisibility="Auto">
<TextBox Text="{Binding ResponseLog, Mode=OneWay}"
materialDesign:HintAssist.Hint=""
IsReadOnly="True"
TextWrapping="Wrap"
FontSize="11"
FontFamily="Consolas"
Background="#FAFAFA"
BorderThickness="0"
VerticalAlignment="Top"/>
</ScrollViewer>
</GroupBox>
</StackPanel>
</Grid>
</StackPanel>
</ScrollViewer>
</UserControl>

View File

@@ -0,0 +1,28 @@
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 DeviceEditModule.Views
{
/// <summary>
/// IT7800EView.xaml 的交互逻辑
/// </summary>
public partial class IT7800EView : UserControl
{
public IT7800EView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,15 @@
<UserControl x:Class="DeviceEditModule.Views.PW8001View"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
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 DeviceEditModule.Views
{
/// <summary>
/// PW8001View.xaml 的交互逻辑
/// </summary>
public partial class PW8001View : UserControl
{
public PW8001View()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,15 @@
<UserControl x:Class="DeviceEditModule.Views.TektronixMSOView"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
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 DeviceEditModule.Views
{
/// <summary>
/// TektronixMSOView.xaml 的交互逻辑
/// </summary>
public partial class TektronixMSOView : UserControl
{
public TektronixMSOView()
{
InitializeComponent();
}
}
}