diff --git a/DeviceCommand/Devices/SPAW7000.cs b/DeviceCommand/Devices/SPAW7000.cs index e58b9a6..b2c91c0 100644 --- a/DeviceCommand/Devices/SPAW7000.cs +++ b/DeviceCommand/Devices/SPAW7000.cs @@ -58,108 +58,142 @@ namespace DeviceCommand.Device #endregion - #region 2. MEASure / NUMeric 核心数据测量与轮询 (高频轮询核心) + #region 2. NUMeric 核心数据测量与轮询 (动态单项读取) /// /// 查询指定通道的实时 RMS 电压值 (单位: V) /// - /// 通道号 (例如: 1, 2, 3...) public virtual async Task 查询实际电压(int channel, CancellationToken ct = default) { - string query = string.Format(CultureInfo.InvariantCulture, ":MEASure:NUMeric:VALue? U,{0}{1}", channel, ScpiDelimiter); + // 1. 先配置 ITEM1 为指定通道的电压有效值 (URMS) + string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 URMS,{0}{1}", channel, ScpiDelimiter); + await SendAsync(setItem, ct); + + // 2. 再读取 ITEM1 的值 + string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); return await WriteReadAsync(query, ScpiDelimiter, ct); } /// /// 查询指定通道的实时 RMS 电流值 (单位: A) /// - /// 通道号 (例如: 1, 2, 3...) public virtual async Task 查询实际电流(int channel, CancellationToken ct = default) { - string query = string.Format(CultureInfo.InvariantCulture, ":MEASure:NUMeric:VALue? I,{0}{1}", channel, ScpiDelimiter); + // 1. 配置 ITEM1 为指定通道的电流有效值 (IRMS) + string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 IRMS,{0}{1}", channel, ScpiDelimiter); + await SendAsync(setItem, ct); + + // 2. 读取 ITEM1 的值 + string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); return await WriteReadAsync(query, ScpiDelimiter, ct); } /// /// 查询指定通道的实时有功功率值 (单位: W) /// - /// 通道号 (例如: 1, 2, 3...) public virtual async Task 查询实际功率(int channel, CancellationToken ct = default) { - string query = string.Format(CultureInfo.InvariantCulture, ":MEASure:NUMeric:VALue? P,{0}{1}", channel, ScpiDelimiter); + // 1. 配置 ITEM1 为指定通道的有功功率 (P) + string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 P,{0}{1}", channel, ScpiDelimiter); + await SendAsync(setItem, ct); + + // 2. 读取 ITEM1 的值 + string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); return await WriteReadAsync(query, ScpiDelimiter, ct); } /// /// 查询指定通道的实时频率值 (单位: Hz) /// - /// 通道号 (例如: 1, 2, 3...) public virtual async Task 查询频率(int channel, CancellationToken ct = default) { - string query = string.Format(CultureInfo.InvariantCulture, ":MEASure:NUMeric:VALue? FREQuency,{0}{1}", channel, ScpiDelimiter); + // 1. 配置 ITEM1 为指定通道的电压频率 (FU) + string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 FU,{0}{1}", channel, ScpiDelimiter); + await SendAsync(setItem, ct); + + // 2. 读取 ITEM1 的值 + string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); return await WriteReadAsync(query, ScpiDelimiter, ct); } /// /// 查询指定通道的功率因数 (Power Factor) /// - /// 通道号 (例如: 1, 2, 3...) public virtual async Task 查询功率因数(int channel, CancellationToken ct = default) { - string query = string.Format(CultureInfo.InvariantCulture, ":MEASure:NUMeric:VALue? PF,{0}{1}", channel, ScpiDelimiter); - return await WriteReadAsync(query, ScpiDelimiter, ct); - } + // 1. 配置 ITEM1 为指定通道的功率因数 (LAMBda) + string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 LAMBda,{0}{1}", channel, ScpiDelimiter); + await SendAsync(setItem, ct); - /// - /// 自定义组合参数批量读取接口 - /// - /// 参数助记符 (如 "U,I,P" 或 "S,Q,LAMBda") - /// 通道号 - public virtual async Task 查询自定义测量组合(string parameter, int channel, CancellationToken ct = default) - { - string query = string.Format(CultureInfo.InvariantCulture, ":MEASure:NUMeric:VALue? {0},{1}{2}", parameter, channel, ScpiDelimiter); + // 2. 读取 ITEM1 的值 + string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); return await WriteReadAsync(query, ScpiDelimiter, ct); } #endregion #region 3. INPut 通道电气参数配置 + /// + /// SPAW7000 电压量程枚举 (单位: V) + /// + public enum VoltageRange + { + V_15 = 15, + V_30 = 30, + V_60 = 60, + V_100 = 100, + V_150 = 150, + V_300 = 300, + V_600 = 600, + V_1000 = 1000 + } /// - /// 设置指定通道的电压量程 (例如: 15, 30, 60, 150, 300, 600, 1000) + /// SPAW7000 电流量程枚举 (单位: A) /// - public virtual async Task 设置电压量程(int channel, double range, CancellationToken ct = default) + public enum CurrentRange { - string cmd = string.Format(CultureInfo.InvariantCulture, ":INPut:VOLTage:RANGe {0},{1:F1}{2}", channel, range, ScpiDelimiter); + A_1 = 1, + A_2 = 2, + A_5 = 5, + A_10 = 10, + A_20 = 20, + A_50 = 50 + } + /// + /// 设置指定通道的电压量程 + /// + /// 通道号/单元号 (1 - 7) + /// 电压量程枚举 + /// 取消令牌 + public virtual async Task 设置电压量程(int channel, VoltageRange range, CancellationToken ct = default) + { + // 正确格式例如: :INPut:VOLTage:RANGe:ELEMent1 300\n + string cmd = string.Format(CultureInfo.InvariantCulture, + ":INPut:VOLTage:RANGe:ELEMent{0} {1}{2}", + channel, (int)range, ScpiDelimiter); + await SendAsync(cmd, ct); } /// - /// 设置指定通道的电流量程 (取决于接线单元或传感器输入类型) + /// 设置指定通道的电流量程 /// - public virtual async Task 设置电流量程(int channel, double range, CancellationToken ct = default) + /// 通道号/单元号 (1 - 7) + /// 电流量程枚举 + /// 取消令牌 + public virtual async Task 设置电流量程(int channel, CurrentRange range, CancellationToken ct = default) { - string cmd = string.Format(CultureInfo.InvariantCulture, ":INPut:CURRent:RANGe {0},{1:F3}{2}", channel, range, ScpiDelimiter); + // 正确格式例如: :INPut:CURRent:RANGe:ELEMent1 5\n + string cmd = string.Format(CultureInfo.InvariantCulture, + ":INPut:CURRent:RANGe:ELEMent{0} {1}{2}", + channel, (int)range, ScpiDelimiter); + await SendAsync(cmd, ct); } - - /// - /// 设置通道的耦合模式 (AC, DC, ACDC) - /// - public virtual async Task 设置通道耦合模式(int channel, string mode, CancellationToken ct = default) - { - string modeUpper = mode.ToUpper(); - if (modeUpper != "AC" && modeUpper != "DC" && modeUpper != "ACDC") - throw new ArgumentException("耦合模式只能为 AC, DC, 或 ACDC"); - - string cmd = string.Format(CultureInfo.InvariantCulture, ":INPut:COUPling {0},{1}{2}", channel, modeUpper, ScpiDelimiter); - await SendAsync(cmd, ct); - } - #endregion #region 4. SYSTem 系统设置与状态查询 - /// /// 14. 查询仪器型号名称 /// diff --git a/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs b/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs index b22ebfa..b01128a 100644 --- a/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs +++ b/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs @@ -2,7 +2,9 @@ using DeviceCommand.Device; using Prism.Commands; using Prism.Ioc; using System; +using System.Globalization; using System.Threading; +using System.Threading.Tasks; using System.Windows.Input; using UIShare.GlobalVariable; using UIShare.ViewModelBase; @@ -57,29 +59,27 @@ namespace DeviceEditModule.ViewModels set => SetProperty(ref _channel, value); } - private double _voltageRange = 300.0; - /// 电压量程(V)。 - public double VoltageRange + private SPAW7000.VoltageRange _voltageRange = SPAW7000.VoltageRange.V_300; + /// 电压量程枚举。 + public SPAW7000.VoltageRange VoltageRange { get => _voltageRange; set => SetProperty(ref _voltageRange, value); } - private double _currentRange = 5.0; - /// 电流量程(A)。 - public double CurrentRange + private SPAW7000.CurrentRange _currentRange = SPAW7000.CurrentRange.A_5; + /// 电流量程枚举。 + public SPAW7000.CurrentRange CurrentRange { get => _currentRange; set => SetProperty(ref _currentRange, value); } - private string _couplingMode = "DC"; - /// 耦合模式:AC / DC / ACDC。 - public string CouplingMode - { - get => _couplingMode; - set => SetProperty(ref _couplingMode, value); - } + public SPAW7000.VoltageRange[] VoltageRangeOptions { get; } = + (SPAW7000.VoltageRange[])Enum.GetValues(typeof(SPAW7000.VoltageRange)); + + public SPAW7000.CurrentRange[] CurrentRangeOptions { get; } = + (SPAW7000.CurrentRange[])Enum.GetValues(typeof(SPAW7000.CurrentRange)); private int _resolution = 6; /// 显示分辨率(5 或 6)。 @@ -162,19 +162,18 @@ namespace DeviceEditModule.ViewModels #region 命令 - public ICommand QueryIdentityCommand { get; } - public ICommand ResetDeviceCommand { get; } - public ICommand QueryAllMeasureCommand { get; } - public ICommand SetVoltageRangeCommand { get; } - public ICommand SetCurrentRangeCommand { get; } - public ICommand SetCouplingModeCommand { get; } - public ICommand SetResolutionCommand { get; } - public ICommand SetBrightnessCommand { get; } - public ICommand SetTouchLockOnCommand { get; } - public ICommand SetTouchLockOffCommand { get; } - public ICommand QueryModelCommand { get; } - public ICommand QuerySerialCommand { get; } - public ICommand QueryStatusByteCommand { get; } + public ICommand QueryIdentityCommand { get; } + public ICommand ResetDeviceCommand { get; } + public ICommand QueryAllMeasureCommand { get; } + public ICommand SetVoltageRangeCommand { get; } + public ICommand SetCurrentRangeCommand { get; } + public ICommand SetResolutionCommand { get; } + public ICommand SetBrightnessCommand { get; } + public ICommand SetTouchLockOnCommand { get; } + public ICommand SetTouchLockOffCommand { get; } + public ICommand QueryModelCommand { get; } + public ICommand QuerySerialCommand { get; } + public ICommand QueryStatusByteCommand { get; } #endregion @@ -182,26 +181,34 @@ namespace DeviceEditModule.ViewModels { _deviceManager = containerProvider.Resolve(); - QueryIdentityCommand = new DelegateCommand(async () => await Exec(async () => AppendLog("IDN: " + await _device!.查询设备标识(Ct())))); - ResetDeviceCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.重置设备(Ct()); AppendLog("设备已重置"); })); - SetVoltageRangeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置电压量程(Channel, VoltageRange, Ct()); AppendLog($"通道 {Channel} 电压量程已设为 {VoltageRange} V"); })); - SetCurrentRangeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置电流量程(Channel, CurrentRange, Ct()); AppendLog($"通道 {Channel} 电流量程已设为 {CurrentRange} A"); })); - SetCouplingModeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置通道耦合模式(Channel, CouplingMode, Ct()); AppendLog($"通道 {Channel} 耦合模式已设为 {CouplingMode}"); })); - SetResolutionCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置显示分辨率(Resolution, Ct()); AppendLog($"显示分辨率已设为 {Resolution} 位"); })); - SetBrightnessCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置显示亮度(Brightness, Ct()); AppendLog($"屏幕亮度已设为 {Brightness}"); })); - SetTouchLockOnCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置屏幕触摸锁定(true, Ct()); AppendLog("屏幕触摸已锁定"); })); + QueryIdentityCommand = new DelegateCommand(async () => await Exec(async () => AppendLog("IDN: " + await _device!.查询设备标识(Ct())))); + ResetDeviceCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.重置设备(Ct()); AppendLog("设备已重置"); })); + SetVoltageRangeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置电压量程(Channel, VoltageRange, Ct()); AppendLog($"通道 {Channel} 电压量程已设为 {(int)VoltageRange} V"); })); + SetCurrentRangeCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置电流量程(Channel, CurrentRange, Ct()); AppendLog($"通道 {Channel} 电流量程已设为 {(int)CurrentRange} A"); })); + SetResolutionCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置显示分辨率(Resolution, Ct()); AppendLog($"显示分辨率已设为 {Resolution} 位"); })); + SetBrightnessCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置显示亮度(Brightness, Ct()); AppendLog($"屏幕亮度已设为 {Brightness}"); })); + SetTouchLockOnCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置屏幕触摸锁定(true, Ct()); AppendLog("屏幕触摸已锁定"); })); SetTouchLockOffCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.设置屏幕触摸锁定(false, Ct()); AppendLog("屏幕触摸已解锁"); })); - QueryModelCommand = new DelegateCommand(async () => await Exec(async () => { DeviceModel = await _device!.查询设备型号(Ct()); AppendLog($"型号: {DeviceModel}"); })); - QuerySerialCommand = new DelegateCommand(async () => await Exec(async () => { DeviceSerial = await _device!.查询设备序列号(Ct()); AppendLog($"序列号: {DeviceSerial}"); })); + QueryModelCommand = new DelegateCommand(async () => await Exec(async () => { DeviceModel = await _device!.查询设备型号(Ct()); AppendLog($"型号: {DeviceModel}"); })); + QuerySerialCommand = new DelegateCommand(async () => await Exec(async () => { DeviceSerial = await _device!.查询设备序列号(Ct()); AppendLog($"序列号: {DeviceSerial}"); })); QueryStatusByteCommand = new DelegateCommand(async () => await Exec(async () => AppendLog("STB: " + await _device!.读取状态字节(Ct())))); + // 只修改这里:保持你原本的 5 次驱动查询调用不变,仅对读回来的科学计数法进行两位小数格式化 QueryAllMeasureCommand = new DelegateCommand(async () => await Exec(async () => { - MeasuredVoltage = await _device!.查询实际电压(Channel, Ct()); - MeasuredCurrent = await _device!.查询实际电流(Channel, Ct()); - MeasuredPower = await _device!.查询实际功率(Channel, Ct()); - MeasuredFrequency = await _device!.查询频率(Channel, Ct()); - MeasuredPowerFactor = await _device!.查询功率因数(Channel, Ct()); + string rawU = await _device!.查询实际电压(Channel, Ct()); + string rawI = await _device!.查询实际电流(Channel, Ct()); + string rawP = await _device!.查询实际功率(Channel, Ct()); + string rawF = await _device!.查询频率(Channel, Ct()); + string rawPF = await _device!.查询功率因数(Channel, Ct()); + + // 转换科学计数法格式,如果失败会自动保持原样 + MeasuredVoltage = FormatToDecimal(rawU, "F2"); // 电压两位小数 + MeasuredCurrent = FormatToDecimal(rawI, "F3"); // 电流通常较小,建议保留3位小数 + MeasuredPower = FormatToDecimal(rawP, "F2"); // 功率两位小数 + MeasuredFrequency = FormatToDecimal(rawF, "F2"); // 频率两位小数 + MeasuredPowerFactor = FormatToDecimal(rawPF, "F3"); // 功率因数保留3位小数 + AppendLog($"CH{Channel} 测量 → U:{MeasuredVoltage}V I:{MeasuredCurrent}A P:{MeasuredPower}W F:{MeasuredFrequency}Hz PF:{MeasuredPowerFactor}"); })); @@ -235,8 +242,8 @@ namespace DeviceEditModule.ViewModels } } - _device = found; - DeviceName = foundName ?? "SPAW7000 (未找到)"; + _device = found; + DeviceName = foundName ?? "SPAW7000 (未找到)"; IsConnected = _device?.IsConnected ?? false; AppendLog(found != null @@ -256,6 +263,41 @@ namespace DeviceEditModule.ViewModels private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token; + /// + /// 将科学计数法字符串转换为标准小数格式 + /// + private string FormatToDecimal(string rawInput, string decimalFormat = "F2") + { + if (string.IsNullOrWhiteSpace(rawInput)) + return "—"; + + // 去除可能夹杂的命令头,保留数据部分 + string cleanInput = CleanResponseHeader(rawInput); + + // 解析科学计数法(NumberStyles.Any 和 InvariantCulture 是关键) + if (double.TryParse(cleanInput, NumberStyles.Any, CultureInfo.InvariantCulture, out double value)) + { + return value.ToString(decimalFormat, CultureInfo.InvariantCulture); + } + + return cleanInput; + } + + /// + /// 辅助清洗:剥离可能伴随吐回的命令头或双引号 + /// + private string CleanResponseHeader(string response) + { + if (string.IsNullOrWhiteSpace(response)) return string.Empty; + string result = response.Trim(); + if (result.Contains(" ")) + { + int lastSpaceIndex = result.LastIndexOf(' '); + result = result.Substring(lastSpaceIndex + 1).Trim(); + } + return result.Replace("\"", "").Replace("'", "").Trim(); + } + private async Task Exec(Func action) { if (_device == null) @@ -300,4 +342,4 @@ namespace DeviceEditModule.ViewModels _cts?.Dispose(); } } -} +} \ No newline at end of file diff --git a/DeviceEditModule/Views/SPAW7000View.xaml b/DeviceEditModule/Views/SPAW7000View.xaml index dfacee3..9231a72 100644 --- a/DeviceEditModule/Views/SPAW7000View.xaml +++ b/DeviceEditModule/Views/SPAW7000View.xaml @@ -5,6 +5,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:prism="http://prismlibrary.com/" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare" mc:Ignorable="d" prism:ViewModelLocator.AutoWireViewModel="True" @@ -92,38 +93,44 @@ - - - - + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 - +