From 38f594e4aae56c1bad33bb0a58c25bb02cf395c6 Mon Sep 17 00:00:00 2001 From: hsc Date: Wed, 19 Aug 2026 19:03:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E8=BF=94=E5=9B=9E=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E8=BD=ACdouble?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DeviceCommand/Devices/IT7800E.cs | 31 ++-- DeviceCommand/Devices/N36200.cs | 37 ++++- DeviceCommand/Devices/N36600.cs | 29 ++-- DeviceCommand/Devices/N69200.cs | 132 +++++++++++++----- DeviceCommand/Devices/SDS2000X_HD.cs | 42 ++++-- DeviceCommand/Devices/SPAW7000.cs | 42 ++++-- .../ViewModels/IT7800EViewModel.cs | 16 +-- .../ViewModels/N36200ViewModel.cs | 12 +- .../ViewModels/N36600ViewModel.cs | 12 +- .../ViewModels/N69200ViewModel.cs | 12 +- .../ViewModels/SDS2000X_HDViewModel.cs | 91 +++--------- .../ViewModels/SPAW7000ViewModel.cs | 75 +++------- 12 files changed, 283 insertions(+), 248 deletions(-) diff --git a/DeviceCommand/Devices/IT7800E.cs b/DeviceCommand/Devices/IT7800E.cs index 666c2d7..cb0fea4 100644 --- a/DeviceCommand/Devices/IT7800E.cs +++ b/DeviceCommand/Devices/IT7800E.cs @@ -208,9 +208,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实际电压测量值 (单位: V) [Monitorable("交流电源电压")] - public virtual async Task 查询实际电压(CancellationToken ct = default) + public virtual async Task 查询实际电压(CancellationToken ct = default) { - return await WriteReadAsync($":MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1] + string response = await WriteReadAsync($":MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -219,9 +220,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实际电流测量值 (单位: A) [Monitorable("交流电源电流")] - public virtual async Task 查询实际电流(CancellationToken ct = default) + public virtual async Task 查询实际电流(CancellationToken ct = default) { - return await WriteReadAsync($":MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1] + string response = await WriteReadAsync($":MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -230,9 +232,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实际有功功率测量值 (单位: W) [Monitorable("交流电源功率")] - public virtual async Task 查询实际功率(CancellationToken ct = default) + public virtual async Task 查询实际功率(CancellationToken ct = default) { - return await WriteReadAsync($":MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1] + string response = await WriteReadAsync($":MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -240,9 +243,10 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 视在功率测量值 (单位: VA) - public virtual async Task 查询视在功率(CancellationToken ct = default) + public virtual async Task 查询视在功率(CancellationToken ct = default) { - return await WriteReadAsync($":MEASure:POWer:APParent?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1] + string response = await WriteReadAsync($":MEASure:POWer:APParent?{ScpiDelimiter}", ScpiDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -250,9 +254,10 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 实际频率测量值 (单位: Hz) - public virtual async Task 查询实际频率(CancellationToken ct = default) + public virtual async Task 查询实际频率(CancellationToken ct = default) { - return await WriteReadAsync($":MEASure:FREQuency?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1] + string response = await WriteReadAsync($":MEASure:FREQuency?{ScpiDelimiter}", ScpiDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -260,11 +265,11 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 功率因数测量值 - public virtual async Task 查询功率因数(CancellationToken ct = default) + public virtual async Task 查询功率因数(CancellationToken ct = default) { - return await WriteReadAsync($":MEASure:POWer:PFACtor?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1] + string response = await WriteReadAsync($":MEASure:POWer:PFACtor?{ScpiDelimiter}", ScpiDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } - #endregion #region 5. 保护参数设置与系统监控 diff --git a/DeviceCommand/Devices/N36200.cs b/DeviceCommand/Devices/N36200.cs index 2ffe085..b599796 100644 --- a/DeviceCommand/Devices/N36200.cs +++ b/DeviceCommand/Devices/N36200.cs @@ -3,6 +3,7 @@ using DeviceCommand.Base; using Model.Models; using System; using System.Globalization; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -22,6 +23,25 @@ namespace DeviceCommand.Devices { } + /// + /// 从设备返回的 SCPI 响应字符串中提取数值部分并转换为 double。 + /// 先按逗号分割取数据段,再提取数值。 + /// + private static double ExtractDouble(string raw) + { + if (string.IsNullOrWhiteSpace(raw)) return 0; + + string dataPart = raw; + int commaIdx = raw.LastIndexOf(','); + if (commaIdx >= 0 && commaIdx < raw.Length - 1) + dataPart = raw.Substring(commaIdx + 1); + + var match = Regex.Match(dataPart, @"[+-]?(?:\d+\.?\d*|\.\d+)(?:[Ee][+-]?\d+)?"); + return match.Success && double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double val) + ? val + : 0; + } + #region 3.1. IEEE 488.2 公共命令 /// @@ -270,9 +290,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实时测量电压值 (单位: V) [Monitorable("高压直流电源电压")] - public virtual async Task 查询实际电压(CancellationToken ct = default) + public virtual async Task 查询实际电压(CancellationToken ct = default) { - return await WriteReadAsync($"MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); + string res = await WriteReadAsync($"MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); + return ExtractDouble(res); } /// @@ -281,9 +302,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实时测量电流值 (单位: A) [Monitorable("高压直流电源电流")] - public virtual async Task 查询实际电流(CancellationToken ct = default) + public virtual async Task 查询实际电流(CancellationToken ct = default) { - return await WriteReadAsync($"MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); + string res = await WriteReadAsync($"MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); + return ExtractDouble(res); } /// @@ -291,10 +313,11 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 实时测量功率值 (单位: W) - [Monitorable("高压直流电源功率")] - public virtual async Task 查询实际功率(CancellationToken ct = default) + [Monitorable("高压直流电源功率")] + public virtual async Task 查询实际功率(CancellationToken ct = default) { - return await WriteReadAsync($"MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct); + string res = await WriteReadAsync($"MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct); + return ExtractDouble(res); } /// diff --git a/DeviceCommand/Devices/N36600.cs b/DeviceCommand/Devices/N36600.cs index 9e24038..561989c 100644 --- a/DeviceCommand/Devices/N36600.cs +++ b/DeviceCommand/Devices/N36600.cs @@ -212,10 +212,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实测直流电流值 (单位: A) [Monitorable("低压直流电源电流")] - public virtual async Task 查询实际电流(CancellationToken ct = default) + public virtual async Task 查询实际电流(CancellationToken ct = default) { - // 修正:去除前缀冒号,改用标准 MEAS:CURR? - return await WriteReadAsync($"MEAS:CURR?{SCPIDelimiter}", SCPIDelimiter, ct); + string response = await WriteReadAsync($"MEAS:CURR?{SCPIDelimiter}", SCPIDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -224,10 +224,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实测直流功率值 (单位: W) [Monitorable("低压直流电源功率")] - public virtual async Task 查询实际功率(CancellationToken ct = default) + public virtual async Task 查询实际功率(CancellationToken ct = default) { - // 修正:去除前缀冒号,改用标准 MEAS:POW? - return await WriteReadAsync($"MEAS:POW?{SCPIDelimiter}", SCPIDelimiter, ct); + string response = await WriteReadAsync($"MEAS:POW?{SCPIDelimiter}", SCPIDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -236,10 +236,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实测直流电压值 (单位: V) [Monitorable("低压直流电源电压")] - public virtual async Task 查询实际电压(CancellationToken ct = default) + public virtual async Task 查询实际电压(CancellationToken ct = default) { - // 修正:去除前缀冒号,改用标准 MEAS:VOLT? - return await WriteReadAsync($"MEAS:VOLT?{SCPIDelimiter}", SCPIDelimiter, ct); + string response = await WriteReadAsync($"MEAS:VOLT?{SCPIDelimiter}", SCPIDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } /// @@ -253,16 +253,15 @@ namespace DeviceCommand.Devices return await WriteReadAsync($"MEAS:VAP?{SCPIDelimiter}", SCPIDelimiter, ct); } - /// /// 3.5.5 查询通道输出端子上测得的输出时间长度 /// /// 取消令牌 /// 输出时间长度 - public virtual async Task 查询总输出时间长度(CancellationToken ct = default) + public virtual async Task 查询总输出时间长度(CancellationToken ct = default) { - // 修正:去除前缀冒号 - return await WriteReadAsync($"MEAS:TIME:OUTP?{SCPIDelimiter}", SCPIDelimiter, ct); + string response = await WriteReadAsync($"MEAS:TIME:OUTP?{SCPIDelimiter}", SCPIDelimiter, ct); + return double.TryParse(response, out double result) ? result : double.NaN; } #endregion @@ -435,6 +434,7 @@ namespace DeviceCommand.Devices string cmd = string.Format(CultureInfo.InvariantCulture, "VOLT:LIM {0:F3}{1}", 电压, SCPIDelimiter); await SendAsync(cmd, ct); } + /// /// 3.7.2.9 清除电压上限限制(恢复为设备物理允许的最大电压值) /// @@ -444,6 +444,7 @@ namespace DeviceCommand.Devices // 发送 MAXimum 设为最大值以达到"清除限制"的效果 await SendAsync($"VOLT:LIMIT MAX{SCPIDelimiter}", ct); // 对应手册 3.7.2.8 } + /// /// 3.7.3.1 设置输出功率值 (W) /// @@ -548,4 +549,4 @@ namespace DeviceCommand.Devices #endregion } -} +} \ No newline at end of file diff --git a/DeviceCommand/Devices/N69200.cs b/DeviceCommand/Devices/N69200.cs index 652715b..491c18b 100644 --- a/DeviceCommand/Devices/N69200.cs +++ b/DeviceCommand/Devices/N69200.cs @@ -3,6 +3,7 @@ using DeviceCommand.Base; using Model.Models; using System; using System.Globalization; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -21,6 +22,23 @@ namespace DeviceCommand.Devices { } + /// + /// 辅助方法:从带有单位的字符串中提取数值并转换为 double。 + /// 例如将 "12.34A", "5.00 V", "1.2e-3 W" 转换为纯数字。解析失败返回 double.NaN。 + /// + private double ParseResponseWithUnit(string response) + { + if (string.IsNullOrWhiteSpace(response)) return double.NaN; + + // 使用正则提取数字部分(支持正负号、小数点、科学计数法 e/E) + var match = Regex.Match(response, @"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?"); + if (match.Success && double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double result)) + { + return result; + } + return double.NaN; + } + #region 3.1. IEEE 488.2 公共命令 /// @@ -38,7 +56,7 @@ namespace DeviceCommand.Devices /// 错误代码和描述信息 public virtual async Task 查询错误信息(CancellationToken ct = default) { - return await WriteReadAsync($":SYSTem:ERRor?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1] + return await WriteReadAsync($":SYSTem:ERRor?{ScpiDelimiter}", ScpiDelimiter, ct); // } /// @@ -190,9 +208,10 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 设定的拉载电流值 (单位: A) - public virtual async Task 查询恒电流CC设定(CancellationToken ct = default) + public virtual async Task 查询恒电流CC设定(CancellationToken ct = default) { - return await WriteReadAsync($"STATic:CC:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + string response = await WriteReadAsync($"STATic:CC:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); } /// @@ -211,9 +230,10 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 设定的拉载电压值 (单位: V) - public virtual async Task 查询恒电压CV设定(CancellationToken ct = default) + public virtual async Task 查询恒电压CV设定(CancellationToken ct = default) { - return await WriteReadAsync($"STATic:CV:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + string response = await WriteReadAsync($"STATic:CV:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); } /// @@ -232,9 +252,10 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 设定的拉载功率值 (单位: W) - public virtual async Task 查询恒功率CP设定(CancellationToken ct = default) + public virtual async Task 查询恒功率CP设定(CancellationToken ct = default) { - return await WriteReadAsync($"STATic:CP:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + string response = await WriteReadAsync($"STATic:CP:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); } /// @@ -253,9 +274,10 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 设定的拉载电阻值 (单位: Ω) - public virtual async Task 查询恒电阻CR设定(CancellationToken ct = default) + public virtual async Task 查询恒电阻CR设定(CancellationToken ct = default) { - return await WriteReadAsync($"STATic:CR:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + string response = await WriteReadAsync($"STATic:CR:HIGH:LEVel?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); } #endregion @@ -268,9 +290,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实时测量电压值 (单位: V) [Monitorable("高压直流负载电压")] - public virtual async Task 查询实际电压(CancellationToken ct = default) + public virtual async Task 查询实际电压(CancellationToken ct = default) { - return await WriteReadAsync($"MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); + string response = await WriteReadAsync($"MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); } /// @@ -279,9 +302,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实时测量电流值 (单位: A) [Monitorable("高压直流负载电流")] - public virtual async Task 查询实际电流(CancellationToken ct = default) + public virtual async Task 查询实际电流(CancellationToken ct = default) { - return await WriteReadAsync($"MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); + string response = await WriteReadAsync($"MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); } /// @@ -290,9 +314,10 @@ namespace DeviceCommand.Devices /// 取消令牌 /// 实时测量功率值 (单位: W) [Monitorable("高压直流负载功率")] - public virtual async Task 查询实际功率(CancellationToken ct = default) + public virtual async Task 查询实际功率(CancellationToken ct = default) { - return await WriteReadAsync($"MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct); + string response = await WriteReadAsync($"MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); } #endregion @@ -650,16 +675,22 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 当前放电已持续时间 (单位: s) - public virtual async Task 查询放电实时时间(CancellationToken ct = default) - => await WriteReadAsync($"DISCHarge:ECHO:TIMe?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 查询放电实时时间(CancellationToken ct = default) + { + string response = await WriteReadAsync($"DISCHarge:ECHO:TIMe?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 查询放电实时容量 /// /// 取消令牌 /// 当前放电已输出的容量 (单位: Ah) - public virtual async Task 查询放电实时容量(CancellationToken ct = default) - => await WriteReadAsync($"DISCHarge:ECHo:CAPacity?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 查询放电实时容量(CancellationToken ct = default) + { + string response = await WriteReadAsync($"DISCHarge:ECHo:CAPacity?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 设置充电电流 @@ -734,8 +765,11 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// OCP测试触发时的电流值 (单位: A) - public virtual async Task 读取OCP结果电流(CancellationToken ct = default) - => await WriteReadAsync($"OCP:RCURrent?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取OCP结果电流(CancellationToken ct = default) + { + string response = await WriteReadAsync($"OCP:RCURrent?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 设置OPP初始功率 @@ -782,8 +816,11 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// OPP测试触发时的功率值 (单位: W) - public virtual async Task 读取OPP结果功率(CancellationToken ct = default) - => await WriteReadAsync($"OPP:RPOWer?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取OPP结果功率(CancellationToken ct = default) + { + string response = await WriteReadAsync($"OPP:RPOWer?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } #endregion @@ -842,8 +879,11 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 当前扫频运行频率 (单位: Hz) - public virtual async Task 读取扫频当前运行频率(CancellationToken ct = default) - => await WriteReadAsync($"SWEEP:CFRequency?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取扫频当前运行频率(CancellationToken ct = default) + { + string response = await WriteReadAsync($"SWEEP:CFRequency?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 读取扫频测试结果 @@ -950,8 +990,11 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// ESR测试结果 (单位: Ω) - public virtual async Task 读取ESR结果(CancellationToken ct = default) - => await WriteReadAsync($"ESR:RESult?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取ESR结果(CancellationToken ct = default) + { + string response = await WriteReadAsync($"ESR:RESult?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } #endregion @@ -994,40 +1037,55 @@ namespace DeviceCommand.Devices /// /// 取消令牌 /// 最大功率值 (单位: W) - public virtual async Task 读取MPPT最大功率(CancellationToken ct = default) - => await WriteReadAsync($"MPP:MPOWer?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取MPPT最大功率(CancellationToken ct = default) + { + string response = await WriteReadAsync($"MPP:MPOWer?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 读取MPPT最大功率电压 /// /// 取消令牌 /// 最大功率点对应电压 (单位: V) - public virtual async Task 读取MPPT最大功率电压(CancellationToken ct = default) - => await WriteReadAsync($"MPP:MVOLtage?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取MPPT最大功率电压(CancellationToken ct = default) + { + string response = await WriteReadAsync($"MPP:MVOLtage?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 读取MPPT最大功率电流 /// /// 取消令牌 /// 最大功率点对应电流 (单位: A) - public virtual async Task 读取MPPT最大功率电流(CancellationToken ct = default) - => await WriteReadAsync($"MPP:MCURrent?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取MPPT最大功率电流(CancellationToken ct = default) + { + string response = await WriteReadAsync($"MPP:MCURrent?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 读取MPPT开路电压 /// /// 取消令牌 /// 开路电压值 (单位: V) - public virtual async Task 读取MPPT开路电压(CancellationToken ct = default) - => await WriteReadAsync($"MPP:OVOLtage?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取MPPT开路电压(CancellationToken ct = default) + { + string response = await WriteReadAsync($"MPP:OVOLtage?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } /// /// 读取MPPT短路电流 /// /// 取消令牌 /// 短路电流值 (单位: A) - public virtual async Task 读取MPPT短路电流(CancellationToken ct = default) - => await WriteReadAsync($"MPP:SCURrent?{ScpiDelimiter}", ScpiDelimiter, ct); + public virtual async Task 读取MPPT短路电流(CancellationToken ct = default) + { + string response = await WriteReadAsync($"MPP:SCURrent?{ScpiDelimiter}", ScpiDelimiter, ct); + return ParseResponseWithUnit(response); + } #endregion diff --git a/DeviceCommand/Devices/SDS2000X_HD.cs b/DeviceCommand/Devices/SDS2000X_HD.cs index ef76112..78223d6 100644 --- a/DeviceCommand/Devices/SDS2000X_HD.cs +++ b/DeviceCommand/Devices/SDS2000X_HD.cs @@ -4,6 +4,7 @@ using Model.Models; using System; using System.Globalization; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -22,6 +23,29 @@ namespace DeviceCommand.Devices { } + /// + /// 从示波器返回的 SCPI 响应字符串中提取数值部分并转换为 double。 + /// 响应格式示例: "C1:PAVA PKPK,2.48E-03V" → 按逗号分割后提取 2.48E-03 + /// + /// 示波器返回的原始字符串 + /// 提取到的数值,解析失败时返回 0 + private static double ExtractDouble(string raw) + { + if (string.IsNullOrWhiteSpace(raw)) return 0; + + string dataPart = raw; + // 按逗号分割,取最后一段(数值通常在逗号后面) + int commaIdx = raw.LastIndexOf(','); + if (commaIdx >= 0 && commaIdx < raw.Length - 1) + dataPart = raw.Substring(commaIdx + 1); + + // 从数据段中提取数值(含正负号、小数点、科学计数法) + var match = Regex.Match(dataPart, @"[+-]?(?:\d+\.?\d*|\.\d+)(?:[Ee][+-]?\d+)?"); + return match.Success && double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double val) + ? val + : 0; + } + #region 1. IEEE 488.2 公共命令 /// @@ -175,9 +199,10 @@ namespace DeviceCommand.Devices /// 通道号 (1 - 4) /// 取消令牌 /// 当前电压档位值 (Volts/Div) - public virtual async Task 查询通道电压档位(int channel, CancellationToken ct = default) + public virtual async Task 查询通道电压档位(int channel, CancellationToken ct = default) { - return await WriteReadAsync($"C{channel}:VDIV?{ScpiDelimiter}", ScpiDelimiter, ct); + string res = await WriteReadAsync($"C{channel}:VDIV?{ScpiDelimiter}", ScpiDelimiter, ct); + return ExtractDouble(res); } /// @@ -278,11 +303,12 @@ namespace DeviceCommand.Devices /// 通道号 (1 - 4) /// 测量参数名称 (如 "PKPK", "FREQ", "RMS" 等) /// 取消令牌 - /// 测量参数的实时数值字符串 - public virtual async Task 查询通道测量项参数(int channel, string paramName, CancellationToken ct = default) + /// 测量参数的实时数值 (double) + public virtual async Task 查询通道测量项参数(int channel, string paramName, CancellationToken ct = default) { string query = string.Format(CultureInfo.InvariantCulture, "C{0}:PAVA? {1}{2}", channel, paramName.ToUpper(), ScpiDelimiter); - return await WriteReadAsync(query, ScpiDelimiter, ct); + string res = await WriteReadAsync(query, ScpiDelimiter, ct); + return ExtractDouble(res); } /// @@ -291,7 +317,7 @@ namespace DeviceCommand.Devices /// 通道号 (1 - 4) /// 取消令牌 /// 电压峰峰值 (Vpp) - public virtual async Task 查询实际电压峰峰值(int channel, CancellationToken ct = default) + public virtual async Task 查询实际电压峰峰值(int channel, CancellationToken ct = default) { return await 查询通道测量项参数(channel, "PKPK", ct); } @@ -302,7 +328,7 @@ namespace DeviceCommand.Devices /// 通道号 (1 - 4) /// 取消令牌 /// 频率值 (单位: Hz) - public virtual async Task 查询实际频率(int channel, CancellationToken ct = default) + public virtual async Task 查询实际频率(int channel, CancellationToken ct = default) { return await 查询通道测量项参数(channel, "FREQ", ct); } @@ -313,7 +339,7 @@ namespace DeviceCommand.Devices /// 通道号 (1 - 4) /// 取消令牌 /// 真均方根电压值 (Vrms) - public virtual async Task 查询实际电压均方根(int channel, CancellationToken ct = default) + public virtual async Task 查询实际电压均方根(int channel, CancellationToken ct = default) { return await 查询通道测量项参数(channel, "RMS", ct); } diff --git a/DeviceCommand/Devices/SPAW7000.cs b/DeviceCommand/Devices/SPAW7000.cs index 272c2d2..1d9fcf9 100644 --- a/DeviceCommand/Devices/SPAW7000.cs +++ b/DeviceCommand/Devices/SPAW7000.cs @@ -22,6 +22,21 @@ namespace DeviceCommand.Devices { } + /// + /// 辅助方法:解析科学计数法字符串为普通 double。解析失败返回 double.NaN。 + /// + private double ParseScientificResponse(string response) + { + if (string.IsNullOrWhiteSpace(response)) return double.NaN; + + // 使用 NumberStyles.Float 允许原生的科学计数法解析 (例如 "1.23E+04") + if (double.TryParse(response.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double result)) + { + return result; + } + return double.NaN; + } + #region 1. IEEE 488.2 公共命令 /// @@ -79,7 +94,7 @@ namespace DeviceCommand.Devices /// 通道号/单元号 /// 取消令牌 /// 实时 RMS 电压值 (单位: V) - public virtual async Task 查询实际电压(int channel, CancellationToken ct = default) + public virtual async Task 查询实际电压(int channel, CancellationToken ct = default) { // 1. 先配置 ITEM1 为指定通道的电压有效值 (URMS) string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 URMS,{0}{1}", channel, ScpiDelimiter); @@ -87,7 +102,8 @@ namespace DeviceCommand.Devices // 2. 再读取 ITEM1 的值 string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); - return await WriteReadAsync(query, ScpiDelimiter, ct); + string response = await WriteReadAsync(query, ScpiDelimiter, ct); + return ParseScientificResponse(response); } /// @@ -96,7 +112,7 @@ namespace DeviceCommand.Devices /// 通道号/单元号 /// 取消令牌 /// 实时 RMS 电流值 (单位: A) - public virtual async Task 查询实际电流(int channel, CancellationToken ct = default) + public virtual async Task 查询实际电流(int channel, CancellationToken ct = default) { // 1. 配置 ITEM1 为指定通道的电流有效值 (IRMS) string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 IRMS,{0}{1}", channel, ScpiDelimiter); @@ -104,7 +120,8 @@ namespace DeviceCommand.Devices // 2. 读取 ITEM1 的值 string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); - return await WriteReadAsync(query, ScpiDelimiter, ct); + string response = await WriteReadAsync(query, ScpiDelimiter, ct); + return ParseScientificResponse(response); } /// @@ -113,7 +130,7 @@ namespace DeviceCommand.Devices /// 通道号/单元号 /// 取消令牌 /// 实时有功功率值 (单位: W) - public virtual async Task 查询实际功率(int channel, CancellationToken ct = default) + public virtual async Task 查询实际功率(int channel, CancellationToken ct = default) { // 1. 配置 ITEM1 为指定通道的有功功率 (P) string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 P,{0}{1}", channel, ScpiDelimiter); @@ -121,7 +138,8 @@ namespace DeviceCommand.Devices // 2. 读取 ITEM1 的值 string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); - return await WriteReadAsync(query, ScpiDelimiter, ct); + string response = await WriteReadAsync(query, ScpiDelimiter, ct); + return ParseScientificResponse(response); } /// @@ -130,7 +148,7 @@ namespace DeviceCommand.Devices /// 通道号/单元号 /// 取消令牌 /// 实时频率值 (单位: Hz) - public virtual async Task 查询频率(int channel, CancellationToken ct = default) + public virtual async Task 查询频率(int channel, CancellationToken ct = default) { // 1. 配置 ITEM1 为指定通道的电压频率 (FU) string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 FU,{0}{1}", channel, ScpiDelimiter); @@ -138,7 +156,8 @@ namespace DeviceCommand.Devices // 2. 读取 ITEM1 的值 string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); - return await WriteReadAsync(query, ScpiDelimiter, ct); + string response = await WriteReadAsync(query, ScpiDelimiter, ct); + return ParseScientificResponse(response); } /// @@ -147,7 +166,7 @@ namespace DeviceCommand.Devices /// 通道号/单元号 /// 取消令牌 /// 功率因数值 - public virtual async Task 查询功率因数(int channel, CancellationToken ct = default) + public virtual async Task 查询功率因数(int channel, CancellationToken ct = default) { // 1. 配置 ITEM1 为指定通道的功率因数 (LAMBda) string setItem = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:ITEM1 LAMBda,{0}{1}", channel, ScpiDelimiter); @@ -155,7 +174,8 @@ namespace DeviceCommand.Devices // 2. 读取 ITEM1 的值 string query = string.Format(CultureInfo.InvariantCulture, ":NUMeric:NORMal:VALue? 1{0}", ScpiDelimiter); - return await WriteReadAsync(query, ScpiDelimiter, ct); + string response = await WriteReadAsync(query, ScpiDelimiter, ct); + return ParseScientificResponse(response); } #endregion @@ -287,4 +307,4 @@ namespace DeviceCommand.Devices #endregion } -} +} \ No newline at end of file diff --git a/DeviceEditModule/ViewModels/IT7800EViewModel.cs b/DeviceEditModule/ViewModels/IT7800EViewModel.cs index ef01228..753f8c1 100644 --- a/DeviceEditModule/ViewModels/IT7800EViewModel.cs +++ b/DeviceEditModule/ViewModels/IT7800EViewModel.cs @@ -120,29 +120,29 @@ namespace DeviceEditModule.ViewModels #region 测量结果属性 - private string _measuredVoltage = "—"; - public string MeasuredVoltage + private double _measuredVoltage; + public double MeasuredVoltage { get => _measuredVoltage; set => SetProperty(ref _measuredVoltage, value); } - private string _measuredCurrent = "—"; - public string MeasuredCurrent + private double _measuredCurrent; + public double MeasuredCurrent { get => _measuredCurrent; set => SetProperty(ref _measuredCurrent, value); } - private string _measuredPower = "—"; - public string MeasuredPower + private double _measuredPower; + public double MeasuredPower { get => _measuredPower; set => SetProperty(ref _measuredPower, value); } - private string _measuredFrequency = "—"; - public string MeasuredFrequency + private double _measuredFrequency; + public double MeasuredFrequency { get => _measuredFrequency; set => SetProperty(ref _measuredFrequency, value); diff --git a/DeviceEditModule/ViewModels/N36200ViewModel.cs b/DeviceEditModule/ViewModels/N36200ViewModel.cs index ec934c2..c42b060 100644 --- a/DeviceEditModule/ViewModels/N36200ViewModel.cs +++ b/DeviceEditModule/ViewModels/N36200ViewModel.cs @@ -118,22 +118,22 @@ namespace DeviceEditModule.ViewModels #region 测量结果属性 - private string _measuredVoltage = "—"; - public string MeasuredVoltage + private double _measuredVoltage; + public double MeasuredVoltage { get => _measuredVoltage; set => SetProperty(ref _measuredVoltage, value); } - private string _measuredCurrent = "—"; - public string MeasuredCurrent + private double _measuredCurrent; + public double MeasuredCurrent { get => _measuredCurrent; set => SetProperty(ref _measuredCurrent, value); } - private string _measuredPower = "—"; - public string MeasuredPower + private double _measuredPower; + public double MeasuredPower { get => _measuredPower; set => SetProperty(ref _measuredPower, value); diff --git a/DeviceEditModule/ViewModels/N36600ViewModel.cs b/DeviceEditModule/ViewModels/N36600ViewModel.cs index 4e56926..469fa38 100644 --- a/DeviceEditModule/ViewModels/N36600ViewModel.cs +++ b/DeviceEditModule/ViewModels/N36600ViewModel.cs @@ -93,22 +93,22 @@ namespace DeviceEditModule.ViewModels #region 测量结果属性 - private string _measuredVoltage = "—"; - public string MeasuredVoltage + private double _measuredVoltage; + public double MeasuredVoltage { get => _measuredVoltage; set => SetProperty(ref _measuredVoltage, value); } - private string _measuredCurrent = "—"; - public string MeasuredCurrent + private double _measuredCurrent; + public double MeasuredCurrent { get => _measuredCurrent; set => SetProperty(ref _measuredCurrent, value); } - private string _measuredPower = "—"; - public string MeasuredPower + private double _measuredPower; + public double MeasuredPower { get => _measuredPower; set => SetProperty(ref _measuredPower, value); diff --git a/DeviceEditModule/ViewModels/N69200ViewModel.cs b/DeviceEditModule/ViewModels/N69200ViewModel.cs index c944fcb..a647a1b 100644 --- a/DeviceEditModule/ViewModels/N69200ViewModel.cs +++ b/DeviceEditModule/ViewModels/N69200ViewModel.cs @@ -94,22 +94,22 @@ namespace DeviceEditModule.ViewModels #region 测量结果属性 - private string _measuredVoltage = "—"; - public string MeasuredVoltage + private double _measuredVoltage; + public double MeasuredVoltage { get => _measuredVoltage; set => SetProperty(ref _measuredVoltage, value); } - private string _measuredCurrent = "—"; - public string MeasuredCurrent + private double _measuredCurrent; + public double MeasuredCurrent { get => _measuredCurrent; set => SetProperty(ref _measuredCurrent, value); } - private string _measuredPower = "—"; - public string MeasuredPower + private double _measuredPower; + public double MeasuredPower { get => _measuredPower; set => SetProperty(ref _measuredPower, value); diff --git a/DeviceEditModule/ViewModels/SDS2000X_HDViewModel.cs b/DeviceEditModule/ViewModels/SDS2000X_HDViewModel.cs index 599be74..611f36a 100644 --- a/DeviceEditModule/ViewModels/SDS2000X_HDViewModel.cs +++ b/DeviceEditModule/ViewModels/SDS2000X_HDViewModel.cs @@ -3,7 +3,6 @@ using Prism.Commands; using Prism.Ioc; using System; using System.Globalization; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; @@ -113,22 +112,22 @@ namespace DeviceEditModule.ViewModels #region 测量结果属性 - private string _measuredVpp = "—"; - public string MeasuredVpp + private double _measuredVpp; + public double MeasuredVpp { get => _measuredVpp; set => SetProperty(ref _measuredVpp, value); } - private string _measuredFrequency = "—"; - public string MeasuredFrequency + private double _measuredFrequency; + public double MeasuredFrequency { get => _measuredFrequency; set => SetProperty(ref _measuredFrequency, value); } - private string _measuredRms = "—"; - public string MeasuredRms + private double _measuredRms; + public double MeasuredRms { get => _measuredRms; set => SetProperty(ref _measuredRms, value); @@ -207,40 +206,30 @@ namespace DeviceEditModule.ViewModels QueryMeasurementsCommand = new DelegateCommand(async () => await Exec(async () => { - // 1. 保留设备原生吐出的完整原始字符串 - string rawVpp = await _device!.查询实际电压峰峰值(Channel, Ct()); - string rawFreq = await _device!.查询实际频率(Channel, Ct()); - string rawRms = await _device!.查询实际电压均方根(Channel, Ct()); + // 设备层已自动提取纯数值并返回 double + MeasuredVpp = await _device!.查询实际电压峰峰值(Channel, Ct()); + MeasuredFrequency = await _device!.查询实际频率(Channel, Ct()); + MeasuredRms = await _device!.查询实际电压均方根(Channel, Ct()); - // 2. 清洗数据并将科学计数法转为常规小数后赋值给 UI 属性 - MeasuredVpp = ParseMeasurement(rawVpp); - MeasuredFrequency = ParseMeasurement(rawFreq); - MeasuredRms = ParseMeasurement(rawRms); - - // 3. 在日志中同时体现设备原始报文与解析呈现值,极方便联调 - AppendLog($"C{Channel} 测量原始数据 → Vpp:{rawVpp.Trim()} Freq:{rawFreq.Trim()} RMS:{rawRms.Trim()}"); - AppendLog($"C{Channel} 界面呈现数值 → Vpp:{MeasuredVpp}V Freq:{MeasuredFrequency}Hz RMS:{MeasuredRms}V"); + AppendLog($"C{Channel} 测量结果 → Vpp:{MeasuredVpp:0.######}V Freq:{MeasuredFrequency:0.######}Hz RMS:{MeasuredRms:0.######}V"); })); QueryVppCommand = new DelegateCommand(async () => await Exec(async () => { - string raw = await _device!.查询实际电压峰峰值(Channel, Ct()); - MeasuredVpp = ParseMeasurement(raw); - AppendLog($"C{Channel} Vpp: {MeasuredVpp} (Raw: {raw.Trim()})"); + MeasuredVpp = await _device!.查询实际电压峰峰值(Channel, Ct()); + AppendLog($"C{Channel} Vpp: {MeasuredVpp:0.######} V"); })); QueryFrequencyCommand = new DelegateCommand(async () => await Exec(async () => { - string raw = await _device!.查询实际频率(Channel, Ct()); - MeasuredFrequency = ParseMeasurement(raw); - AppendLog($"C{Channel} Freq: {MeasuredFrequency} (Raw: {raw.Trim()})"); + MeasuredFrequency = await _device!.查询实际频率(Channel, Ct()); + AppendLog($"C{Channel} Freq: {MeasuredFrequency:0.######} Hz"); })); QueryRmsCommand = new DelegateCommand(async () => await Exec(async () => { - string raw = await _device!.查询实际电压均方根(Channel, Ct()); - MeasuredRms = ParseMeasurement(raw); - AppendLog($"C{Channel} RMS: {MeasuredRms} (Raw: {raw.Trim()})"); + MeasuredRms = await _device!.查询实际电压均方根(Channel, Ct()); + AppendLog($"C{Channel} RMS: {MeasuredRms:0.######} V"); })); Initialize(); @@ -330,52 +319,6 @@ namespace DeviceEditModule.ViewModels : line + "\n" + ResponseLog; } - /// - /// 清洗示波器原始返回的测量字符串(例如 "C1:PAVA RMS,5.57E-03V")并安全转化为无科学计数法的小数形式。 - /// - /// 设备原始应答数据 - /// 可直接绑定到 UI 呈现的字符串数字 - private string ParseMeasurement(string rawResponse) - { - if (string.IsNullOrWhiteSpace(rawResponse)) return "—"; - - try - { - string cleanData = rawResponse.Trim(); - - // 1. 斩断报头,提取逗号后面的具体内容(如 "5.57E-03V" 或 "****") - int commaIndex = cleanData.IndexOf(','); - if (commaIndex == -1) return "—"; - - string valStr = cleanData.Substring(commaIndex + 1); - - var match = Regex.Match(valStr, @"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?"); - if (match.Success) - { - valStr = match.Value; - } - - // 3. 校验并拦截设备未测出时的无效星号 "****" - if (valStr.Contains("*") || string.IsNullOrWhiteSpace(valStr)) - { - return "0"; // 回归为零或 "—",防止触发数据异常 - } - - // 4. 解析科学计数法,并重新以不带科学计数法的小数样式展开 - if (double.TryParse(valStr, NumberStyles.Any, CultureInfo.InvariantCulture, out double result)) - { - // "0.######" 样式会自动消除末尾无用的冗余零,并显示为普通小数(如 0.00557) - return result.ToString("0.######", CultureInfo.InvariantCulture); - } - } - catch - { - // 捕获可能产生的边缘转换故障,保证轮询线程绝不崩溃 - } - - return "—"; - } - #endregion public void Dispose() diff --git a/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs b/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs index 4d0f41e..19b494e 100644 --- a/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs +++ b/DeviceEditModule/ViewModels/SPAW7000ViewModel.cs @@ -101,36 +101,36 @@ namespace DeviceEditModule.ViewModels #region 测量结果属性 - private string _measuredVoltage = "—"; - public string MeasuredVoltage + private double _measuredVoltage; + public double MeasuredVoltage { get => _measuredVoltage; set => SetProperty(ref _measuredVoltage, value); } - private string _measuredCurrent = "—"; - public string MeasuredCurrent + private double _measuredCurrent; + public double MeasuredCurrent { get => _measuredCurrent; set => SetProperty(ref _measuredCurrent, value); } - private string _measuredPower = "—"; - public string MeasuredPower + private double _measuredPower; + public double MeasuredPower { get => _measuredPower; set => SetProperty(ref _measuredPower, value); } - private string _measuredFrequency = "—"; - public string MeasuredFrequency + private double _measuredFrequency; + public double MeasuredFrequency { get => _measuredFrequency; set => SetProperty(ref _measuredFrequency, value); } - private string _measuredPowerFactor = "—"; - public string MeasuredPowerFactor + private double _measuredPowerFactor; + public double MeasuredPowerFactor { get => _measuredPowerFactor; set => SetProperty(ref _measuredPowerFactor, value); @@ -196,20 +196,14 @@ namespace DeviceEditModule.ViewModels // 只修改这里:保持你原本的 5 次驱动查询调用不变,仅对读回来的科学计数法进行两位小数格式化 QueryAllMeasureCommand = new DelegateCommand(async () => await Exec(async () => { - 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()); + // 设备层已返回 double 数值 + 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()); - // 转换科学计数法格式,如果失败会自动保持原样 - 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}"); + AppendLog($"CH{Channel} 测量 → U:{MeasuredVoltage:F2}V I:{MeasuredCurrent:F3}A P:{MeasuredPower:F2}W F:{MeasuredFrequency:F2}Hz PF:{MeasuredPowerFactor:F3}"); })); Initialize(); @@ -263,41 +257,6 @@ 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)