命令树优化,测试编辑区域优化

This commit is contained in:
“hsc”
2026-08-27 10:50:10 +08:00
parent 99ac3f2b8d
commit e144dc78a7
24 changed files with 1520 additions and 338 deletions
+235 -37
View File
@@ -1,65 +1,119 @@
using Common.Attributes;
using DeviceCommand.Base;
using Model.Models;
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
// 根据您的项目实际路径保留枚举的引用
// using 通讯驱动Base.枚举;
namespace DeviceCommand.Devices
{
/// <summary>
/// S7200 负载工作模式枚举 (恒流/恒压/恒功率/恒阻等)
/// </summary>
public enum S7200负载模式_枚举
{
/// <summary>恒流模式</summary>
CC,
/// <summary>恒压模式</summary>
CV,
/// <summary>恒功率模式</summary>
CP,
/// <summary>恒阻模式</summary>
CR,
/// <summary>恒压+恒流组合模式</summary>
CVCC,
/// <summary>恒阻+恒流组合模式</summary>
CRCC,
/// <summary>恒压+恒阻组合模式</summary>
CVCR,
/// <summary>自动模式</summary>
AUTO
}
/// <summary>
/// S7200 直流源工作模式枚举 (电压源/电流源/电池模拟/光伏模拟等)
/// </summary>
public enum S7200直流源模式_枚举
{
/// <summary>电压源模式</summary>
VOLTage,
/// <summary>电流源模式</summary>
CURRent,
/// <summary>电池测试模式</summary>
BATTest,
/// <summary>电池模拟模式</summary>
BATSim,
/// <summary>光伏模拟模式</summary>
SOLar,
/// <summary>EN50530 标准光伏曲线模式</summary>
EN50530,
/// <summary>列表输出模式</summary>
LIST,
/// <summary>用户自定义波形模式</summary>
UDW,
/// <summary>方波输出模式</summary>
SQUare,
/// <summary>三角波输出模式</summary>
TRIangle,
/// <summary>正弦波输出模式</summary>
SINusoid,
/// <summary>DIN40839 12V 启动曲线</summary>
DIN40839_12V,
/// <summary>DIN40839 24V 启动曲线</summary>
DIN40839_24V,
/// <summary>ISO16750 短时跌落 12V</summary>
IS016750_SHORTDROP_12V,
/// <summary>ISO16750 短时跌落 24V</summary>
IS016750_SHORTDROP_24V,
/// <summary>ISO16750 复位测试</summary>
IS016750_RESETTEST,
/// <summary>ISO16750 启动曲线 12V 第 1 组</summary>
IS016750_STARTINGPROFILE_12V_1,
/// <summary>ISO16750 启动曲线 12V 第 2 组</summary>
IS016750_STARTINGPROFILE_12V_2,
/// <summary>ISO16750 启动曲线 12V 第 3 组</summary>
IS016750_STARTINGPROFILE_12V_3,
/// <summary>ISO16750 启动曲线 12V 第 4 组</summary>
IS016750_STARTINGPROFILE_12V_4,
/// <summary>ISO16750 启动曲线 24V 第 1 组</summary>
IS016750_STARTINGPROFILE_24V_1,
/// <summary>ISO16750 启动曲线 24V 第 2 组</summary>
IS016750_STARTINGPROFILE_24V_2,
/// <summary>ISO16750 启动曲线 24V 第 3 组</summary>
IS016750_STARTINGPROFILE_24V_3,
/// <summary>ISO16750 抛负载测试 A 12V</summary>
IS016750_LOADDUMP_TESTA_12V,
/// <summary>ISO16750 抛负载测试 A 24V</summary>
IS016750_LOADDUMP_TESTA_24V,
/// <summary>ISO16750 抛负载测试 B 12V</summary>
IS016750_LOADDUMP_TESTB_12V,
/// <summary>ISO16750 抛负载测试 B 24V</summary>
IS016750_LOADDUMP_TESTB_24V,
/// <summary>LV123 高压曲线 1</summary>
LV123_HV_1,
/// <summary>LV123 高压曲线 2A</summary>
LV123_HV_2A,
/// <summary>LV123 高压曲线 2B</summary>
LV123_HV_2B,
/// <summary>LV123 高压曲线 3</summary>
LV123_HV_3
}
/// <summary>
/// S7200 工作模式枚举 (电源模式 / 负载模式)
/// </summary>
public enum S7200工作模式_枚举
{
/// <summary>作为电源输出</summary>
,
/// <summary>作为负载吸收</summary>
,
}
/// <summary>
/// 高压直流源载一体机 (适配 IT6000C SCPI指令集)
/// 高压直流源载一体机 (适配 IT6000C SCPI 指令集),支持电源输出与负载吸收双向工作
/// </summary>
[ACPCommand]
public class S7200 : Tcp
@@ -67,115 +121,239 @@ namespace DeviceCommand.Devices
// SCPI 指令结束符
private const string ScpiDelimiter = "\n";
#region
public async Task (CancellationToken ct = default)
/// <summary>
/// 构造函数:传入 <see cref="TcpConfig"/> 一次性初始化一体机通信参数
/// </summary>
public S7200(TcpConfig config) : base(config)
{
await SendAsync($"SYSTem:REMote{ScpiDelimiter}", ct); //[cite: 1]
}
/// <summary>
/// 从设备返回的 SCPI 响应字符串中提取数值部分并转换为 double。
/// 支持科学计数法(如 2.48E-03),结果保留两位小数。
/// </summary>
/// <param name="raw">设备返回的原始字符串</param>
/// <returns>提取到的数值(保留两位小数),解析失败时返回 0</returns>
private static double ExtractDouble(string raw)
{
if (string.IsNullOrWhiteSpace(raw)) return 0;
// 从响应中提取第一个数值(含正负号、小数点、科学计数法),可自动忽略单位后缀与命令头
var match = Regex.Match(raw, @"[+-]?(?:\d+\.?\d*|\.\d+)(?:[Ee][+-]?\d+)?");
return match.Success && double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double val)
? Math.Round(val, 2)
: 0;
}
#region
/// <summary>
/// 设置仪器为远程控制模式 (SYSTem:REMote)
/// </summary>
/// <param name="ct">取消令牌</param>
public async Task (CancellationToken ct = default)
{
await SendAsync($"SYSTem:REMote{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置电源工作模式 (电源/负载)。IT6000C 支持双向无缝切换,无需显式下发源载切换指令
/// </summary>
/// <param name="开关">工作模式枚举 (电源模式 / 负载模式)</param>
/// <param name="ct">取消令牌</param>
public async Task (S7200工作模式_枚举 , CancellationToken ct = default)
{
// IT6000C 为双向无缝切换,底层硬件无需显式发送源载切换指令
// 保留此方法仅为兼容原有上位机的工步调用流程,直接返回即可
// 保留此方法仅为兼容原有上位机的工步调用流程
await Task.CompletedTask;
}
/// <summary>
/// 设置直流源工作模式 (FUNCtion 指令,如 VOLTage / CURRent / SOLar 等)
/// </summary>
/// <param name="模式">直流源工作模式枚举</param>
/// <param name="ct">取消令牌</param>
public async Task (S7200直流源模式_枚举 , CancellationToken ct = default)
{
// 原指令: MODE {模式} -> 现 IT6000C 指令: FUNCtion {模式} (如 VOLTage / CURRent)[cite: 1]
// 若枚举 ToString() 后不匹配,建议在此处加 Switch 转换
await SendAsync($"FUNCtion {模式}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置负载工作模式。IT6000C 负载控制通过负向边界实现
/// </summary>
/// <param name="模式">负载工作模式枚举</param>
/// <param name="ct">取消令牌</param>
public async Task (S7200负载模式_枚举 , CancellationToken ct = default)
{
// IT6000C 负载控制通过负向边界实现。若是想开启纯电阻模式,可调用 SINK:RESistance:STATe ON[cite: 1]
// 想开启纯电阻模式,可调用 SINK:RESistance:STATe ON
await Task.CompletedTask;
}
/// <summary>
/// 开启或关闭通道输出 (OUTPut 指令)
/// </summary>
/// <param name="开关">true: 开启输出, false: 关闭输出</param>
/// <param name="ct">取消令牌</param>
public async Task (bool , CancellationToken ct = default)
{
await SendAsync($"OUTPut {(开关 ? 1 : 0)}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"OUTPut {(开关 ? 1 : 0)}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置恒流 (CC) 模式的电流值 (CURRent 指令)
/// </summary>
/// <param name="电流">电流设定值 (单位: A)</param>
/// <param name="ct">取消令牌</param>
public async Task CC模式电流(double , CancellationToken ct = default)
{
await SendAsync($"CURRent {电流}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"CURRent {电流}{ScpiDelimiter}", ct);
}
public async Task CC电压H(double , CancellationToken ct = default) // 沿用原参数名“电流”,实际是设定电压上限
/// <summary>
/// 设置恒流 (CC) 模式的电压上限 (VOLTage:LIMit:POSitive 指令)
/// </summary>
/// <param name="电流">电压上限设定值 (单位: V),沿用原参数名</param>
/// <param name="ct">取消令牌</param>
public async Task CC电压H(double , CancellationToken ct = default)
{
await SendAsync($"VOLTage:LIMit:POSitive {电流}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"VOLTage:LIMit:POSitive {电流}{ScpiDelimiter}", ct);
}
public async Task CC电压L(double , CancellationToken ct = default) // 沿用原参数名“电流”,实际是设定电压下限
/// <summary>
/// 设置恒流 (CC) 模式的电压下限 (VOLTage:LIMit:NEGative 指令)
/// </summary>
/// <param name="电流">电压下限设定值 (单位: V),沿用原参数名</param>
/// <param name="ct">取消令牌</param>
public async Task CC电压L(double , CancellationToken ct = default)
{
await SendAsync($"VOLTage:LIMit:NEGative {电流}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"VOLTage:LIMit:NEGative {电流}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置恒压 (CV) 模式的正向电流限制 (CURRent:LIMit:POSitive 指令)
/// </summary>
/// <param name="电流">正向电流限制值 (单位: A)</param>
/// <param name="ct">取消令牌</param>
public async Task CV正向电流(double , CancellationToken ct = default)
{
await SendAsync($"CURRent:LIMit:POSitive {电流}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"CURRent:LIMit:POSitive {电流}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置恒压 (CV) 模式的反向电流限制 (CURRent:LIMit:NEGative 指令)
/// </summary>
/// <param name="电流">反向电流限制值 (单位: A),负载模式需传负值</param>
/// <param name="ct">取消令牌</param>
public async Task CV反向电流(double , CancellationToken ct = default)
{
// 提醒: 此处传入的参数如果是正数建议在外部或此处转换为负值,因为载模式限制需要负数[cite: 1]
// 载模式限制需要负数,若传入正数建议在外部转换为负值
await SendAsync($"CURRent:LIMit:NEGative {电流}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置正向功率阈值 (POWer:LIMit:POSitive 指令)
/// </summary>
/// <param name="功率">正向功率阈值 (单位: W)</param>
/// <param name="ct">取消令牌</param>
public async Task (double , CancellationToken ct = default)
{
await SendAsync($"POWer:LIMit:POSitive {功率}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"POWer:LIMit:POSitive {功率}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置反向功率阈值 (POWer:LIMit:NEGative 指令)
/// </summary>
/// <param name="功率">反向功率阈值 (单位: W),必须为负数</param>
/// <param name="ct">取消令牌</param>
public async Task (double , CancellationToken ct = default)
{
// 提醒: 此处传入的参数必须为负数[cite: 1]
await SendAsync($"POWer:LIMit:NEGative {功率}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置输出电压值 (VOLTage 指令)
/// </summary>
/// <param name="电压">电压设定值 (单位: V)</param>
/// <param name="ct">取消令牌</param>
public async Task (double , CancellationToken ct = default)
{
await SendAsync($"VOLTage {电压}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"VOLTage {电压}{ScpiDelimiter}", ct);
}
/// <summary>
/// 清除保护状态 (OUTPut:PROTection:CLEar 指令)
/// </summary>
/// <param name="ct">取消令牌</param>
public async Task (CancellationToken ct = default)
{
await SendAsync($"OUTPut:PROTection:CLEar{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"OUTPut:PROTection:CLEar{ScpiDelimiter}", ct);
}
/// <summary>
/// 开启或关闭过流保护 (OCP) 功能 (CURRent:PROTection:STATe 指令)
/// </summary>
/// <param name="v">true: 开启过流保护, false: 关闭过流保护</param>
/// <param name="ct">取消令牌</param>
public async Task OCP开关(bool v, CancellationToken ct = default)
{
await SendAsync($"CURRent:PROTection:STATe {(v ? 1 : 0)}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"CURRent:PROTection:STATe {(v ? 1 : 0)}{ScpiDelimiter}", ct);
}
/// <summary>
/// 开启或关闭过压保护 (OVP) 功能 (VOLTage:PROTection:STATe 指令)
/// </summary>
/// <param name="v">true: 开启过压保护, false: 关闭过压保护</param>
/// <param name="ct">取消令牌</param>
public async Task OVP开关(bool v, CancellationToken ct = default)
{
await SendAsync($"VOLTage:PROTection:STATe {(v ? 1 : 0)}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"VOLTage:PROTection:STATe {(v ? 1 : 0)}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置过压保护 (OVP) 的触发电压值 (VOLTage:PROTection 指令)
/// </summary>
/// <param name="oVP电压">过压保护触发电压值 (单位: V)</param>
/// <param name="ct">取消令牌</param>
public async Task OVP电压(double oVP电压, CancellationToken ct = default)
{
await SendAsync($"VOLTage:PROTection {oVP电压}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"VOLTage:PROTection {oVP电压}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置过流保护 (OCP) 的触发电流值 (CURRent:PROTection 指令)
/// </summary>
/// <param name="oCP电流">过流保护触发电流值 (单位: A)</param>
/// <param name="ct">取消令牌</param>
public async Task OCP电流(double oCP电流, CancellationToken ct = default)
{
await SendAsync($"CURRent:PROTection {oCP电流}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"CURRent:PROTection {oCP电流}{ScpiDelimiter}", ct);
}
/// <summary>
/// 开启或关闭过功率保护 (OPP) 功能 (POWer:PROTection:STATe 指令)
/// </summary>
/// <param name="v">true: 开启过功率保护, false: 关闭过功率保护</param>
/// <param name="ct">取消令牌</param>
public async Task (bool v, CancellationToken ct = default)
{
await SendAsync($"POWer:PROTection:STATe {(v ? 1 : 0)}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"POWer:PROTection:STATe {(v ? 1 : 0)}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置过功率保护 (OPP) 的触发功率值 (POWer:PROTection 指令)
/// </summary>
/// <param name="oPP功率">过功率保护触发功率值 (单位: W)</param>
/// <param name="ct">取消令牌</param>
public async Task (double oPP功率, CancellationToken ct = default)
{
await SendAsync($"POWer:PROTection {oPP功率}{ScpiDelimiter}", ct); //[cite: 1]
await SendAsync($"POWer:PROTection {oPP功率}{ScpiDelimiter}", ct);
}
/// <summary>
/// 发送自定义 SCPI 指令
/// </summary>
/// <param name="指令">自定义指令字符串</param>
/// <param name="ct">取消令牌</param>
public async Task (string , CancellationToken ct = default)
{
await SendAsync($"{指令}{ScpiDelimiter}", ct);
@@ -185,29 +363,49 @@ namespace DeviceCommand.Devices
#region
/// <summary>
/// 查询设备识别信息 (*IDN? 指令)
/// </summary>
/// <param name="ct">取消令牌</param>
/// <returns>设备标识字符串 (制造商, 型号, 序列号, 固件版本)</returns>
public async Task<string> (CancellationToken ct = default)
{
return await WriteReadAsync($"*IDN?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
return await WriteReadAsync($"*IDN?{ScpiDelimiter}", ScpiDelimiter, ct);
}
/// <summary>
/// 查询实时输出电压 (MEASure:VOLTage? 指令)
/// </summary>
/// <param name="ct">取消令牌</param>
/// <returns>实时电压值 (单位: V,保留两位小数)</returns>
public async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
return double.TryParse(str, out double result) ? result : 0;
var str = await WriteReadAsync($"MEASure:VOLTage?{ScpiDelimiter}", ScpiDelimiter, ct);
return ExtractDouble(str);
}
/// <summary>
/// 查询实时输出电流 (MEASure:CURRent? 指令)
/// </summary>
/// <param name="ct">取消令牌</param>
/// <returns>实时电流值 (单位: A,保留两位小数)</returns>
public async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
return double.TryParse(str, out double result) ? result : 0;
var str = await WriteReadAsync($"MEASure:CURRent?{ScpiDelimiter}", ScpiDelimiter, ct);
return ExtractDouble(str);
}
/// <summary>
/// 查询实时功率 (MEASure:POWer? 指令)
/// </summary>
/// <param name="ct">取消令牌</param>
/// <returns>实时功率值 (单位: W,保留两位小数)</returns>
public async Task<double> (CancellationToken ct = default)
{
var str = await WriteReadAsync($"MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct); //[cite: 1]
return double.TryParse(str, out double result) ? result : 0;
var str = await WriteReadAsync($"MEASure:POWer?{ScpiDelimiter}", ScpiDelimiter, ct);
return ExtractDouble(str);
}
#endregion
}
}
}