Compare commits

..
5 Commits
Author SHA1 Message Date
“hsc” 80a2cbd80b 子程序使用优化 2026-08-07 13:46:11 +08:00
“hsc” 57db6776b8 示波器兼容 2026-08-07 10:31:46 +08:00
“hsc” 062582e238 CAN驱动修改优化 2026-08-07 09:06:43 +08:00
“hsc” deb3544143 设备命令修改 2026-08-06 14:04:28 +08:00
“hsc” 5a565f7361 Flexray,Lin添加 2026-08-05 11:53:51 +08:00
156 changed files with 731405 additions and 708 deletions
+30 -3
View File
@@ -18,6 +18,7 @@ using UIShare.GlobalVariable;
using UIShare.PubEvent;
using UIShare.UIViewModel;
using SqlSugar;
using TSMasterCAN;
namespace ACP.ViewModels
{
@@ -43,6 +44,16 @@ namespace ACP.ViewModels
private readonly DispatcherTimer _uiRefreshTimer;
#endregion
#region
/// <summary>
/// 当前台架是否可以返回上一级
/// </summary>
public bool CanGoBack => CurrentContext?.CanGoBack ?? false;
#endregion
#region
public string Title
{
@@ -155,6 +166,7 @@ namespace ACP.ViewModels
public ICommand MonitorValueSettingCommand { get; set; }
public ICommand GetFileStringCommand { get; set; }
public ICommand SilenceBuzzerCommand { get; set; }
public ICommand SettingChannelCommand { get; set; }
#endregion
public ShellViewModel(IContainerProvider containerProvider)
@@ -204,7 +216,8 @@ namespace ACP.ViewModels
MonitorValueSettingCommand = new DelegateCommand(MonitorValueSetting);
GetFileStringCommand = new DelegateCommand(GetFileString);
SilenceBuzzerCommand = new AsyncDelegateCommand(SilenceBuzzer);
SettingChannelCommand = new AsyncDelegateCommand(SilenceBuzzer);
SettingChannelCommand = new DelegateCommand(SettingChannel);
_globalInfo.ContextDic.Add("default", new ScopedContext());
_eventAggregator.GetEvent<LoginSuccessEvent>().Subscribe(() =>
@@ -234,10 +247,20 @@ namespace ACP.ViewModels
RaisePropertyChanged(nameof(RunIcon));
RaisePropertyChanged(nameof(RunningTime));
RaisePropertyChanged(nameof(IsTerminate));
RaisePropertyChanged(nameof(CanGoBack));
}
#region
private void SettingChannel()
{
var re = CAN.ShowChannelMappingWindow(true);
if (re != 0)
{
var msg = CAN.GetErrorDescription(re);
if(CurrentConfig!=null)
LoggerHelper.ErrorWithNotify(CurrentConfig.Title,$"同星通道映射界面打开失败:{msg}");
}
}
private async Task SilenceBuzzer()
{
_eventAggregator.GetEvent<SilenceBuzzerEvent>().Publish(_globalInfo.CurrentScope);
@@ -507,6 +530,9 @@ namespace ACP.ViewModels
targetContext.IsTerminate = false;
}
// 清空子程序导航栈,回到根程序
targetContext.ResetNavigation();
if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
}
@@ -589,6 +615,7 @@ namespace ACP.ViewModels
targetContext.Program.Parameters.Clear();
targetContext.Program.StepCollection.Clear();
targetContext.Program.ErrorStepCollection.Clear();
targetContext.ResetNavigation();
foreach (var item in CurrentConfig.ParameterList)
{
var param = CurrentConfig.SharedParameterList.FirstOrDefault(x => x.ParameterName == item.Name);
@@ -653,7 +680,7 @@ namespace ACP.ViewModels
targetContext.Program.StepCollection = program.StepCollection;
targetContext.Program.ErrorStepCollection = program.ErrorStepCollection;
targetContext.CurrentFilePath = filePath;
targetContext.ResetNavigation();
foreach (var item in CurrentConfig.SharedParameterList)
{
var parameter = targetContext?.Program?.Parameters?.FirstOrDefault(x => x.Name == item.ParameterName);
+13 -15
View File
@@ -190,15 +190,19 @@
Foreground="Black" />
</MenuItem.Icon>
</MenuItem>
<!-- CAN信号监控 -->
<MenuItem Header="CAN信号监控"
Foreground="Black"
Command="{Binding SelectCANSignalMonitorCommand}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="Message"
<MenuItem Header="同星CAN"
Foreground="Black">
<MenuItem Header="通道映射"
Command="{Binding SettingChannelCommand}"
Foreground="Black" />
<MenuItem Header="CAN信号采集设置"
Command="{Binding SelectCANSignalMonitorCommand}"
Foreground="Black" />
<MenuItem Header="CAN报文字符串获取"
Command="{Binding SelectCANMessageCommand}"
Foreground="Black" />
</MenuItem.Icon>
</MenuItem>
<!-- 监控设置 -->
<MenuItem Header="监控设置"
Foreground="Black"
@@ -208,14 +212,6 @@ Command="{Binding MonitorValueSettingCommand}">
Foreground="Black" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="CAN报文选择"
Foreground="Black"
Command="{Binding SelectCANMessageCommand}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="Message"
Foreground="Black" />
</MenuItem.Icon>
</MenuItem>
<!-- 获得文件路径字符串 -->
<MenuItem Header="获得文件路径字符串"
@@ -248,6 +244,8 @@ Command="{Binding GetFileStringCommand}">
Foreground="Black" />
</MenuItem.Icon>
</MenuItem>
<Separator/>
</MenuItem>
<MenuItem Header="切换初始主界面"
FontSize="13"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

+47
View File
@@ -0,0 +1,47 @@
===== Sheet: Sheet1 (45行x16列) =====
集成化测试系统:ACP交流源适应性系统控制接线图(三工位系统)
注:以下操作是在执行就地系统合上断路器(QF1、)后按下SB1启动按钮后仪器设备得电后才能操作。
序号 | 对应设备 | | IO输入口 | 控制对应中间继电器 | 对应输出元件通断/吸合 | 功能 | | | | 备注
1 | 1#产品 | IO继电器模块 1# | Y1 | KA2-1 | KM2 | Y1输出控制KA2-1执行,KM2吸合,产品充电(三相) | | | | 对应控制1# (低压直流电源)/电子锁/温度检测/CC/CP信号。
2 | | | Y2 | KA3-1 | KM3 | Y2输出控制KA3-1执行,KM3吸合,产品放电(三相)
| | | Y3 | KA4-1 | KL30通断 | Y3输出控制KA4-1执行KL30通断
| | | Y4 | KA5-1 | KL15通断 | Y4输出控制KA5-1执行KL15通断
| | | Y5 | KA6-1 | 电子锁60Ω电阻 | Y5输出控制KA6-1执行电子锁信号通断(60Ω)
| | | Y6 | KA7-1 | 温度检测1KΩ电阻 | Y6输出控制KA7-1执行温度检测信号通断(1KΩ)
3 | | | Y7 | KA8-1 | CC信号串1KΩ电阻 | Y7输出控制KA8-1执行CC信号通断(1KΩ)
4 | | | Y8 | KA9-1 | CP信号串1KΩ电阻 | Y8输出控制KA9-1执行CP信号通断(1KΩ)
5 | | | Y9 | KA10-1 | CC信号串680Ω电阻 | Y9输出控制KA10-1执行CC信号通断(680Ω)
6 | | | Y10 | KA11-1 | CC信号串220Ω电阻 | Y10输出控制KA11-1执行CC信号通断(220Ω)
7 | | | Y11 | KA12-1 | CC信号串100Ω电阻 | Y11输出控制KA12-1执行CC信号通断(100Ω)
8 | | | Y12 | KA13-1 | CC信号空载 | Y12输出控制KA13-1执行CC信号通断(100Ω)
13 | | | Y13 | KA14-1 | 蜂鸣器 1#响应 | Y13输出控制KA14-1执行蜂鸣器1#信号通断
15 | 2#产品 | IO继电器模块 2# | Y1 | KA2-2 | KM4 | Y2输出控制KA2-2执行,KM4吸合,产品充电(三相) | | | | 对应控制2# (低压直流电源)/电子锁/温度检测/CC/CP信号。
16 | | | Y2 | KA3-2 | KM5 | Y2输出控制KA3-2执行,KM5吸合,产品放电(三相)
| | | Y3 | KA4-2 | KL30通断 | Y3输出控制KA4-2执行KL30通断
| | | Y4 | KA5-2 | KL15通断 | Y4输出控制KA5-2执行KL15通断
17 | | | Y5 | KA6-2 | 电子锁60Ω电阻 | Y5输出控制KA6-2执行电子锁信号通断(60Ω)
18 | | | Y6 | KA7-2 | 温度检测1KΩ电阻 | Y6输出控制KA7-2执行温度检测信号通断(1KΩ)
19 | | | Y7 | KA8-2 | CC信号串1KΩ电阻 | Y7输出控制KA8-2执行CC信号通断(1KΩ)
20 | | | Y8 | KA9-2 | CP信号串1KΩ电阻 | Y8输出控制KA9-2执行CP信号通断(1KΩ)
21 | | | Y9 | KA10-2 | CC信号串680Ω电阻 | Y9输出控制KA10-2执行CC信号通断(680Ω)
22 | | | Y10 | KA11-2 | CC信号串220Ω电阻 | Y10输出控制KA11-2执行CC信号通断(220Ω)
23 | | | Y11 | KA12-2 | CC信号串100Ω电阻 | Y11输出控制KA12-2执行CC信号通断(100Ω)
24 | | | Y12 | KA13-2 | CC信号空载 | Y12输出控制KA13-2执行CC信号通断(100Ω)
25 | | | Y13 | KA14-2 | 蜂鸣器 2#响应 | Y13输出控制KA14-2执行蜂鸣器2#信号通断
28 | 3#产品 | IO继电器模块 3# | Y1 | KA2-3 | KM6 | Y1输出控制KA2-3执行,KM6吸合,产品充电(三相) | | | | 对应控制3# (低压直流电源)/电子锁/温度检测/CC/CP信号。
29 | | | Y2 | KA3-3 | KM7 | Y2输出控制KA3-3执行,KM7吸合,产品放电(三相)
30 | | | Y3 | KA4-3 | KL30通断 | Y3输出控制KA4-3执行KL30通断
31 | | | Y4 | KA5-3 | KL15通断 | Y4输出控制KA5-3执行KL15通断
32 | | | Y5 | KA6-3 | 电子锁60Ω电阻 | Y5输出控制KA6-3执行电子锁信号通断(60Ω)
33 | | | Y6 | KA7-3 | 温度检测1KΩ电阻 | Y6输出控制KA7-3执行温度检测信号通断(1KΩ)
34 | | | Y7 | KA8-3 | CC信号串1KΩ电阻 | Y7输出控制KA8-3执行CC信号通断(1KΩ)
35 | | | Y8 | KA9-3 | CP信号串1KΩ电阻 | Y8输出控制KA9-3执行CP信号通断(1KΩ)
36 | | | Y9 | KA10-3 | CC信号串680Ω电阻 | Y9输出控制KA10-3执行CC信号通断(680Ω)
37 | | | Y10 | KA11-3 | CC信号串220Ω电阻 | Y10输出控制KA11-3执行CC信号通断(220Ω)
38 | | | Y11 | KA12-3 | CC信号串100Ω电阻 | Y11输出控制KA12-3执行CC信号通断(100Ω)
39 | | | Y12 | KA13-3 | CC信号空载 | Y12输出控制KA13-3执行CC信号通断(100Ω)
40 | | | Y13 | KA14-3 | 蜂鸣器 3#响应 | Y13输出控制KA14-3执行蜂鸣器2#信号通断
41 | | | Y14 | KA15-3 | KM8 | Y14输出控制KA15-3执行KM8抛负载通断 | | | | HV
42 | | | Y15 | KA16-3 | KM9 | Y15输出控制KA16-3执行KM9短路测试
43 | | | Y16 | KA17-3 | KM10 | Y16输出控制KA17-3执行KM10短路测试 | | | | LV
+54
View File
@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
"""分析 D:\ACP 下所有 .ACP 测试项/子程序的结构。"""
import json, os, glob
def walk_steps(steps, depth, out):
for s in steps:
st = s.get("StepType")
name = s.get("Name")
ind = " " * depth
if st == "方法":
m = s.get("Method") or {}
full = m.get("FullName", "?")
cls = full.split(".")[-1]
params = []
for p in (m.get("Parameters") or []):
if p.get("Category") == 0: # Input
v = p.get("Value")
if p.get("IsUseVar"):
v = f"${p.get('VariableName')}"
params.append(f"{p.get('Name')}={v}")
out.append(f"{ind}[方法] {name} <- {cls}({', '.join(params)})")
elif st == "子程序":
out.append(f"{ind}[子程序] {name}")
sp = s.get("SubProgram")
if sp and sp.get("StepCollection"):
walk_steps(sp["StepCollection"], depth + 1, out)
elif st == "循环开始":
lc = s.get("LoopCount")
out.append(f"{ind}[循环开始] 次数={lc}")
elif st == "循环结束":
out.append(f"{ind}[循环结束]")
elif st == "跳转":
out.append(f"{ind}[跳转] {name} expr={s.get('OKExpression')}")
else:
out.append(f"{ind}[{st}] {name}")
dirs = [r"D:\ACP\测试项", r"D:\ACP\子程序"]
for d in dirs:
for fp in sorted(glob.glob(os.path.join(d, "*.ACP"))):
print("=" * 70)
print("FILE:", os.path.basename(fp))
with open(fp, encoding="utf-8") as f:
data = json.load(f)
out = []
walk_steps(data.get("StepCollection") or [], 0, out)
# 只打印前 60 行,避免过长
for line in out[:60]:
print(line)
if len(out) > 60:
print(f"... (共 {len(out)} 步,已省略)")
# 参数
print(" -- Parameters --")
for p in (data.get("Parameters") or []):
print(f" {p.get('Name')} = {p.get('Value')}")
+215
View File
@@ -0,0 +1,215 @@
# -*- coding: utf-8 -*-
"""
极电子程序测试项转换脚本
将极电子程序的 .ats 文件转换为我的项目的 .ats 文件
设备映射关系:
- EA3040_40C → ANEVH80(水冷机,占位符)
- IT6724C → IT6724C(直流源)
- PSB11500_60 → PSB11500_60(交流源/负载)
- SQ0090G1D1 → SQ0090G1D1(三相交流源)
- IOBoardCard → IOBoardGroup(占位符,只传台架序号)
- TSMasterCAN.CAN → TSMasterCAN.CAN(相同)
"""
import json
import os
import uuid
import re
from pathlib import Path
# 输入输出路径
INPUT_DIR = Path(r"C:\Users\kk\Desktop\ACP\极电子程序")
OUTPUT_DIR = Path(r"D:\ACP\测试项\极电子对应")
# 设备映射
DEVICE_MAPPING = {
"DeviceCommand.Device.EA3040_40C": "DeviceCommand.Device.ANEVH80", # 水冷机(占位符)
"DeviceCommand.Device.IT6724C": "DeviceCommand.Device.IT6724C",
"DeviceCommand.Device.PSB11500_60": "DeviceCommand.Device.PSB11500_60",
"DeviceCommand.Device.SQ0090G1D1": "DeviceCommand.Device.SQ0090G1D1",
"DeviceCommand.Device.IOBoardCard": "DeviceCommand.Device.IOBoardGroup", # IO板卡(占位符)
"TSMasterCAN.CAN": "TSMasterCAN.CAN",
}
# 方法映射(ANEVH80 占位符方法)
ANVH80_METHOD_MAPPING = {
"Set_RemoteMode": "Placeholder_SetRemoteMode",
"Set_Voltage": "Placeholder_SetVoltage",
"Set_Current": "Placeholder_SetCurrent",
"Set_Power": "Placeholder_SetPower",
"ON": "Placeholder_ON",
"OFF": "Placeholder_OFF",
}
# IOBoardGroup 占位符方法
IOBOARDGROUP_METHOD_MAPPING = {
"WriteMultiIO": "Placeholder_WriteMultiIO",
"WriteSingleIO": "Placeholder_WriteSingleIO",
"ReadMultiIO": "Placeholder_ReadMultiIO",
"ReadSingleIO": "Placeholder_ReadSingleIO",
}
def generate_guid():
"""生成新的 GUID"""
return str(uuid.uuid4())
def transform_parameter(param, add_station_var=False):
"""转换参数格式"""
new_param = {
"ID": generate_guid(),
"IsVisible": param.get("IsVisible", True),
"Name": param.get("Name", ""),
"Type": param.get("Type", ""),
"Category": param.get("Category", 0),
"IsGlobal": param.get("IsGlobal", False),
"InitialValue": param.get("InitialValue"),
"Value": param.get("Value"),
"LowerLimit": param.get("LowerLimit"),
"UpperLimit": param.get("UpperLimit"),
"Result": param.get("Result", True),
"IsUseVar": param.get("IsUseVar", False),
"IsSave": param.get("IsSave", False),
"VariableName": param.get("VariableName"),
"VariableID": param.get("VariableID"),
"IsOutputToReport": param.get("IsOutputToReport", False),
}
return new_param
def transform_method(method, step_name=""):
"""转换方法"""
if method is None:
return None
full_name = method.get("FullName", "")
method_name = method.get("Name", "")
# 设备映射
new_full_name = DEVICE_MAPPING.get(full_name, full_name) if full_name else None
# 方法映射(占位符)
if new_full_name and "ANEVH80" in new_full_name:
new_method_name = ANVH80_METHOD_MAPPING.get(method_name, method_name)
elif new_full_name and "IOBoardGroup" in new_full_name:
new_method_name = IOBOARDGROUP_METHOD_MAPPING.get(method_name, method_name)
else:
new_method_name = method_name
# 转换参数
new_params = []
for param in method.get("Parameters", []):
new_param = transform_parameter(param)
new_params.append(new_param)
new_method = {
"Name": new_method_name,
"FullName": new_full_name,
"DeviceID": method.get("DeviceID"),
"Parameters": new_params,
}
return new_method
def transform_step(step):
"""转换步骤"""
new_step = {
"ID": generate_guid(),
"IsUsed": step.get("IsUsed", True),
"Index": step.get("Index", 1),
"Name": step.get("Name", ""),
"StepType": step.get("StepType", "方法"),
"Method": None,
"SubProgram": None,
"LoopCount": step.get("LoopCount"),
"LoopStartStepId": step.get("LoopStartStepId"),
"OKExpression": step.get("OKExpression"),
"GotoSettingString": step.get("GotoSettingString", ""),
"OKGotoStepID": step.get("OKGotoStepID"),
"NGGotoStepID": step.get("NGGotoStepID"),
"Description": step.get("Description"),
}
# 转换方法
if step.get("Method"):
new_step["Method"] = transform_method(step["Method"], step.get("Name", ""))
# 转换子程序
if step.get("SubProgram"):
sub_program = step["SubProgram"]
new_sub_steps = []
for sub_step in sub_program.get("StepCollection", []):
new_sub_step = transform_step(sub_step)
new_sub_steps.append(new_sub_step)
new_step["SubProgram"] = {
"ID": generate_guid(),
"StepCollection": new_sub_steps,
"Parameters": [transform_parameter(p) for p in sub_program.get("Parameters", [])],
"Devices": sub_program.get("Devices", []),
}
return new_step
def transform_program(program):
"""转换整个程序"""
new_steps = []
for step in program.get("StepCollection", []):
new_step = transform_step(step)
new_steps.append(new_step)
new_program = {
"ID": generate_guid(),
"StepCollection": new_steps,
"Parameters": [transform_parameter(p) for p in program.get("Parameters", [])],
"Devices": program.get("Devices", []),
}
return new_program
def process_file(input_file, output_file):
"""处理单个文件"""
print(f"处理: {input_file.name}")
# 读取文件(支持 UTF-8 BOM
with open(input_file, 'r', encoding='utf-8-sig') as f:
program = json.load(f)
# 转换
new_program = transform_program(program)
# 写入文件
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(new_program, f, ensure_ascii=False, indent=2)
print(f" -> 已生成: {output_file.name}")
def main():
"""主函数"""
# 创建输出目录
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
# 获取所有 .ats 文件
ats_files = list(INPUT_DIR.glob("*.ats"))
print(f"找到 {len(ats_files)} 个 .ats 文件")
print(f"输出目录: {OUTPUT_DIR}")
print()
# 处理每个文件
for input_file in ats_files:
output_file = OUTPUT_DIR / input_file.name
process_file(input_file, output_file)
print()
print(f"完成!共处理 {len(ats_files)} 个文件")
if __name__ == "__main__":
main()
+38
View File
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
"""将 ACP.pdf 逐页渲染为 PNG,并把 Excel 接线图导出为文本。"""
import fitz
import openpyxl
import os
pdf_path = r"C:\Users\kk\Desktop\ACP\ACP电路图\ACP.pdf"
xlsx_path = r"C:\Users\kk\Desktop\ACP\ACP电路图\ACP硬件接线图.xlsx"
out_dir = r"C:\Users\kk\Desktop\ACP\ACP电路图\_pages"
os.makedirs(out_dir, exist_ok=True)
# ---- 渲染 PDF ----
doc = fitz.open(pdf_path)
mat = fitz.Matrix(2.0, 2.0) # 2倍缩放,保证清晰度
for i, page in enumerate(doc):
pix = page.get_pixmap(matrix=mat)
png_path = os.path.join(out_dir, f"page_{i+1:02d}.png")
pix.save(png_path)
print(f"saved {png_path}")
doc.close()
# ---- 导出 Excel ----
wb = openpyxl.load_workbook(xlsx_path, data_only=True)
txt_path = os.path.join(out_dir, "接线图.txt")
with open(txt_path, "w", encoding="utf-8") as f:
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
f.write(f"===== Sheet: {sheet_name} ({ws.max_row}行x{ws.max_column}列) =====\n")
for row in ws.iter_rows(values_only=True):
cells = ["" if c is None else str(c).strip() for c in row]
# 去掉行尾空单元格
while cells and cells[-1] == "":
cells.pop()
if not cells:
continue
f.write(" | ".join(cells) + "\n")
f.write("\n")
print(f"saved {txt_path}")
+280
View File
@@ -0,0 +1,280 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\AC侧电流检测.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ENUM_LOAD_MODE = "DeviceCommand.Devices.S7200负载模式_枚举, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def s7200_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.S7200", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, var_name=None, var_id=None):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_RATED_FREQ = guid() # 额定频率
VAR_25PCT_POWER = guid() # 25%负载功率
VAR_50PCT_POWER = guid() # 50%负载功率
VAR_75PCT_POWER = guid() # 75%负载功率
VAR_100PCT_POWER = guid() # 100%负载功率
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_STABLE_TIME = guid() # 稳定等待时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_RATED_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_25PCT_POWER, "IsVisible": True, "IsEditable": True, "Name": "25%负载功率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_50PCT_POWER, "IsVisible": True, "IsEditable": True, "Name": "50%负载功率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_75PCT_POWER, "IsVisible": True, "IsEditable": True, "Name": "75%负载功率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_100PCT_POWER, "IsVisible": True, "IsEditable": True, "Name": "100%负载功率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_STABLE_TIME, "IsVisible": True, "IsEditable": True, "Name": "稳定等待时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源设置额定输入 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(6, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(7, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(8, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(9, "启动List输出(额定输入)", "启动List输出", []))
steps.append(delay_step(10, "等待OBC启动", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
# ---- 三、负载(S7200)初始化 ----
steps.append(s7200_step(11, "设置为远程模式", "设置为远程模式", []))
steps.append(s7200_step(12, "设置负载工作模式CC", "设置负载工作模式",
[param("模式", ENUM_LOAD_MODE, 0)])) # CC=0
# ---- 四、25%负载点测试 ----
steps.append(s7200_step(13, "设置CC模式电流(25%负载)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="25%负载功率", var_id=VAR_25PCT_POWER)]))
steps.append(s7200_step(14, "打开通道(25%负载)", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", True)]))
steps.append(delay_step(15, "等待25%负载稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(16, "测量25%负载输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、50%负载点测试 ----
steps.append(s7200_step(17, "设置CC模式电流(50%负载)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="50%负载功率", var_id=VAR_50PCT_POWER)]))
steps.append(delay_step(18, "等待50%负载稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(19, "测量50%负载输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 六、75%负载点测试 ----
steps.append(s7200_step(20, "设置CC模式电流(75%负载)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="75%负载功率", var_id=VAR_75PCT_POWER)]))
steps.append(delay_step(21, "等待75%负载稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(22, "测量75%负载输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 七、100%负载点测试 ----
steps.append(s7200_step(23, "设置CC模式电流(100%负载)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="100%负载功率", var_id=VAR_100PCT_POWER)]))
steps.append(delay_step(24, "等待100%负载稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(25, "测量100%负载输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 八、收尾 ----
steps.append(s7200_step(26, "关闭负载通道", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", False)]))
steps.append(chroma_step(27, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(28, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(pw8001_step(29, "清除状态", "清除状态", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\AC侧电流检测.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n测试负载点:")
print(" - 25% 额定负载")
print(" - 50% 额定负载")
print(" - 75% 额定负载")
print(" - 100% 额定负载")
+281
View File
@@ -0,0 +1,281 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\AC侧电压检测.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, var_name=None, var_id=None):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_UPPER_VOLT = guid() # 输入电压上限
VAR_LOWER_VOLT = guid() # 输入电压下限
VAR_FREQ = guid() # 额定频率
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_HOLD_TIME = guid() # 各电压点保持时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_UPPER_VOLT, "IsVisible": True, "IsEditable": True, "Name": "输入电压上限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_LOWER_VOLT, "IsVisible": True, "IsEditable": True, "Name": "输入电压下限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_HOLD_TIME, "IsVisible": True, "IsEditable": True, "Name": "各电压点保持时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源初始化 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(6, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
# ---- 三、额定电压测试点 ----
steps.append(chroma_step(7, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(8, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(9, "启动List输出(额定电压)", "启动List输出", []))
steps.append(delay_step(10, "等待额定电压稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(11, "测量额定电压点实际电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 四、上限电压测试点 ----
steps.append(chroma_step(12, "配置List交流起始电压(上限)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT)]))
steps.append(chroma_step(13, "配置List交流结束电压(上限)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT)]))
steps.append(delay_step(14, "等待上限电压稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(15, "测量上限电压点实际电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、下限电压测试点 ----
steps.append(chroma_step(16, "配置List交流起始电压(下限)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT)]))
steps.append(chroma_step(17, "配置List交流结束电压(下限)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT)]))
steps.append(delay_step(18, "等待下限电压稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(19, "测量下限电压点实际电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 六、恢复额定电压 ----
steps.append(chroma_step(20, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(21, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(delay_step(22, "等待额定电压稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 七、收尾 ----
steps.append(chroma_step(23, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(24, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(pw8001_step(25, "清除状态", "清除状态", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\AC侧电压检测.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n测试点:")
print(" - 额定输入电压点")
print(" - 输入电压上限点")
print(" - 输入电压下限点")
+253
View File
@@ -0,0 +1,253 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\输入频率范围测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def delay_step(index, name, var_name=None, var_id=None):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
# 程序变量(Parameters 中 Category=0,供步骤绑定)
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_RATED_FREQ = guid() # 额定频率
VAR_UPPER_FREQ = guid() # 频率上限
VAR_LOWER_FREQ = guid() # 频率下限
VAR_HOLD_TIME = guid() # 各频率点保持时间(ms)
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_RATED_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_UPPER_FREQ, "IsVisible": True, "IsEditable": True, "Name": "频率上限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_LOWER_FREQ, "IsVisible": True, "IsEditable": True, "Name": "频率下限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_HOLD_TIME, "IsVisible": True, "IsEditable": True, "Name": "各频率点保持时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、初始化交流源 ----
steps.append(chroma_step(1, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(2, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(3, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(4, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
# ---- 二、额定频率启动OBC ----
steps.append(chroma_step(5, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(6, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(7, "启动List输出(额定频率)", "启动List输出", []))
steps.append(delay_step(8, "等待OBC启动稳定", var_name="各频率点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 三、升频至上限 ----
steps.append(chroma_step(9, "升频至频率上限", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="频率上限", var_id=VAR_UPPER_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="频率上限", var_id=VAR_UPPER_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="频率上限", var_id=VAR_UPPER_FREQ)]))
steps.append(chroma_step(10, "保持频率上限", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="频率上限", var_id=VAR_UPPER_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="频率上限", var_id=VAR_UPPER_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="频率上限", var_id=VAR_UPPER_FREQ)]))
steps.append(delay_step(11, "频率上限保持时间", var_name="各频率点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 四、降频至下限 ----
steps.append(chroma_step(12, "降频至频率下限", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="频率下限", var_id=VAR_LOWER_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="频率下限", var_id=VAR_LOWER_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="频率下限", var_id=VAR_LOWER_FREQ)]))
steps.append(chroma_step(13, "保持频率下限", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="频率下限", var_id=VAR_LOWER_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="频率下限", var_id=VAR_LOWER_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="频率下限", var_id=VAR_LOWER_FREQ)]))
steps.append(delay_step(14, "频率下限保持时间", var_name="各频率点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 五、恢复额定频率 ----
steps.append(chroma_step(15, "恢复额定频率", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(16, "额定频率保持", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(delay_step(17, "额定频率保持时间", var_name="各频率点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 六、收尾 ----
steps.append(chroma_step(18, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(19, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(20, "清除错误队列", "清除错误队列", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\输入频率范围测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
+211
View File
@@ -0,0 +1,211 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\输入电流测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, var_name=None, var_id=None):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_RATED_FREQ = guid() # 额定频率
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_STABLE_TIME = guid() # 稳定等待时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_RATED_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_STABLE_TIME, "IsVisible": True, "IsEditable": True, "Name": "稳定等待时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "U1")]))
# ---- 二、交流源设置额定输入 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(6, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(7, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(8, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(9, "启动List输出(额定输入)", "启动List输出", []))
# ---- 三、等待OBC启动并稳定在额定负载 ----
steps.append(delay_step(10, "等待OBC启动稳定(额定负载)", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
# ---- 四、功率分析仪测量输入电流(有效值) ----
steps.append(pw8001_step(11, "测量输入电流有效值", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、收尾 ----
steps.append(chroma_step(12, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(13, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(14, "清除错误队列", "清除错误队列", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\输入电流测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
+253
View File
@@ -0,0 +1,253 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\启动冲击电流试验.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ENUM_ACQ_MODE = "DeviceCommand.Devices.TekAcquisitionMode, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ENUM_MEAS_TYPE = "DeviceCommand.Devices.TekMeasurementType, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def tek_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.TektronixMSO", method_name, params)
def delay_step(index, name, ms=None, var_name=None, var_id=None):
if var_name and var_id:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
else:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, str(ms))])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_RATED_FREQ = guid() # 额定频率
VAR_OSC_CHANNEL = guid() # 示波器电流通道号
VAR_MEAS_NUM = guid() # 测量项编号
VAR_SCREENSHOT_PATH = guid() # 截图保存路径
VAR_TEST_COUNT = guid() # 测试次数
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_RATED_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_OSC_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "示波器电流通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_MEAS_NUM, "IsVisible": True, "IsEditable": True, "Name": "测量项编号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_SCREENSHOT_PATH, "IsVisible": True, "IsEditable": True, "Name": "截图保存路径",
"Type": STRING_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_TEST_COUNT, "IsVisible": True, "IsEditable": True, "Name": "测试次数",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、示波器初始化(峰值检测模式) ----
steps.append(tek_step(1, "设置采集模式为峰值检测", "设置采集模式",
[param("模式", ENUM_ACQ_MODE, 1)])) # PEAKdetect=1
steps.append(tek_step(2, "设置水平刻度(20ms/div)", "设置水平刻度",
[param("秒每格", DOUBLE_TYPE, 0.02)])) # 20ms/div 捕获冲击波形
steps.append(tek_step(3, "设置记录长度", "设置记录长度",
[param("长度", "System.Int64, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", 10000)]))
# ---- 二、添加冲击电流最大值测量 ----
steps.append(tek_step(4, "开启测量项", "开启测量项",
[param("测量项编号", INT_TYPE, use_var=True,
var_name="测量项编号", var_id=VAR_MEAS_NUM)]))
steps.append(tek_step(5, "设置测量类型为MAXimum", "设置测量类型",
[param("测量项编号", INT_TYPE, use_var=True,
var_name="测量项编号", var_id=VAR_MEAS_NUM),
param("类型", ENUM_MEAS_TYPE, 4)])) # MAXimum=4
steps.append(tek_step(6, "设置测量源为电流通道", "设置测量源",
[param("测量项编号", INT_TYPE, use_var=True,
var_name="测量项编号", var_id=VAR_MEAS_NUM),
param("源名称", STRING_TYPE, use_var=True,
var_name="示波器电流通道号", var_id=VAR_OSC_CHANNEL)]))
# ---- 三、交流源设置额定输入(初始0V,准备突然施加) ----
steps.append(chroma_step(7, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(8, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(9, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
# 初始电压设为0V,准备突然施加额定电压
steps.append(chroma_step(10, "配置List交流起始电压(0V)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(11, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(12, "配置List执行时间(快速上升)", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 10.0), # 10ms 快速上升
param("step2", DOUBLE_TYPE, 10.0),
param("step3", DOUBLE_TYPE, 10.0)]))
# ---- 四、启动示波器采集,然后突然施加额定电压 ----
steps.append(tek_step(13, "启动示波器采集", "设置采集状态",
[param("运行", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", True)]))
steps.append(delay_step(14, "等待示波器就绪", 100))
steps.append(chroma_step(15, "启动List输出(突然施加额定电压)", "启动List输出", []))
# ---- 五、等待冲击电流事件完成,读取最大值 ----
steps.append(delay_step(16, "等待冲击电流事件完成", 500))
steps.append(tek_step(17, "查询冲击电流最大值", "查询测量项当前值",
[param("测量项编号", INT_TYPE, use_var=True,
var_name="测量项编号", var_id=VAR_MEAS_NUM)]))
# ---- 六、保存波形截图 ----
steps.append(tek_step(18, "保存冲击电流波形截图", "保存屏幕截图",
[param("上位机文件路径", STRING_TYPE, use_var=True,
var_name="截图保存路径", var_id=VAR_SCREENSHOT_PATH)]))
# ---- 七、收尾 ----
steps.append(tek_step(19, "停止示波器采集", "设置采集状态",
[param("运行", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", False)]))
steps.append(chroma_step(20, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(21, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(22, "清除错误队列", "清除错误队列", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\启动冲击电流试验.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
+247
View File
@@ -0,0 +1,247 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\负载冲击试验.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
BOOL_TYPE = "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ENUM_SRC_MODE = "DeviceCommand.Devices.S7200直流源模式_枚举, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ENUM_LOAD_MODE = "DeviceCommand.Devices.S7200负载模式_枚举, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def s7200_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.S7200", method_name, params)
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def delay_step(index, name, ms):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, str(ms))])
# 程序变量(Parameters 中 Category=0,供步骤绑定)
VAR_LOAD_CURRENT = guid() # 满载电流(100%负载)
VAR_FULL_HOLD_MS = guid() # 满载保持时间ms
VAR_ZERO_HOLD_MS = guid() # 空载保持时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0
{"ID": VAR_LOAD_CURRENT, "IsVisible": True, "IsEditable": True, "Name": "满载电流",
"Type": DOUBLE_TYPE, "Category": 0, "Value": 100.0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FULL_HOLD_MS, "IsVisible": True, "IsEditable": True, "Name": "满载保持时间ms",
"Type": INT_TYPE, "Category": 0, "Value": 100, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_ZERO_HOLD_MS, "IsVisible": True, "IsEditable": True, "Name": "空载保持时间ms",
"Type": INT_TYPE, "Category": 0, "Value": 100, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、交流源:额定输入(三相 380V/50Hz,持续输出) ----
steps.append(chroma_step(1, "初始化三相List模式(无限循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "0")]))
steps.append(chroma_step(2, "配置List起始频率(额定50Hz)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, 50.0),
param("step2", DOUBLE_TYPE, 50.0),
param("step3", DOUBLE_TYPE, 50.0)]))
steps.append(chroma_step(3, "配置List交流起始电压(额定380V)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 380.0),
param("step2", DOUBLE_TYPE, 380.0),
param("step3", DOUBLE_TYPE, 380.0)]))
steps.append(chroma_step(4, "配置List交流结束电压(额定380V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 380.0),
param("step2", DOUBLE_TYPE, 380.0),
param("step3", DOUBLE_TYPE, 380.0)]))
steps.append(chroma_step(5, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(6, "启动List输出(额定输入)", "启动List输出", []))
steps.append(delay_step(7, "等待输入稳定", 3000))
# ---- 二、负载(S7200)CC 模式预置 100% 满载电流,斜率最大 ----
steps.append(s7200_step(8, "设置为远程模式", "设置为远程模式", []))
steps.append(s7200_step(9, "清除保护状态", "清除保护状态", []))
steps.append(s7200_step(10, "设置直流源工作模式CC", "设置直流源工作模式",
[param("模式", ENUM_SRC_MODE, 0)])) # VOLTage=0? 见说明
# 说明: S7200直流源模式_枚举 CC 不在该枚举,负载模式用 设置负载工作模式
steps.pop() # 撤销上一步,改用负载模式枚举
steps.append(s7200_step(10, "设置负载工作模式CC", "设置负载工作模式",
[param("模式", ENUM_LOAD_MODE, 0)])) # CC=0
steps.append(s7200_step(11, "设置CC模式电流(100%满载)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="满载电流", var_id=VAR_LOAD_CURRENT)]))
steps.append(s7200_step(12, "上升斜率设为负载最大能力", "发送自定义命令",
[param("指令", "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"CURRent:SLEW MAX")]))
steps.append(s7200_step(13, "打开通道(100%负载)", "设置通道开关",
[param("开关", BOOL_TYPE, True)]))
steps.append(delay_step(14, "等待负载稳定", 1000))
# ---- 三、循环 5000 次:0% ↔ 100% 跳变 ----
loop_start_id = guid()
loop_start_step = {
"ID": loop_start_id,
"IsUsed": True,
"Index": 15,
"Name": "循环开始",
"StepType": "循环开始",
"Method": {
"Name": None,
"FullName": None,
"Parameters": [
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "循环次数",
"Type": INT_TYPE, "Category": 0, "Value": 5000, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
],
},
"SubProgram": None,
"LoopCount": 5000,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": "负载0%与100%跳变冲击 5000次",
}
steps.append(loop_start_step)
steps.append(s7200_step(16, "跳变至0%负载(断开通道)", "设置通道开关",
[param("开关", BOOL_TYPE, False)]))
steps.append(method_step(17, "空载保持", "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name="空载保持时间ms", var_id=VAR_ZERO_HOLD_MS)]))
steps.append(s7200_step(18, "跳变至100%负载(接通通道)", "设置通道开关",
[param("开关", BOOL_TYPE, True)]))
steps.append(method_step(19, "满载保持", "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name="满载保持时间ms", var_id=VAR_FULL_HOLD_MS)]))
loop_end_step = {
"ID": guid(),
"IsUsed": True,
"Index": 20,
"Name": "循环结束",
"StepType": "循环结束",
"Method": None,
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": loop_start_id,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
steps.append(loop_end_step)
# ---- 四、收尾 ----
steps.append(s7200_step(21, "关闭负载通道", "设置通道开关",
[param("开关", BOOL_TYPE, False)]))
steps.append(s7200_step(22, "清除保护状态", "清除保护状态", []))
steps.append(chroma_step(23, "清除错误队列", "清除错误队列", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\负载冲击试验.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验:能反序列化回基本结构
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. [{s['StepType']}] {s['Name']}")
+306
View File
@@ -0,0 +1,306 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\输出电流范围测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ENUM_LOAD_MODE = "DeviceCommand.Devices.S7200负载模式_枚举, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def s7200_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.S7200", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, ms=None, var_name=None, var_id=None):
if var_name and var_id:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
else:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, str(ms))])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_FREQ = guid() # 额定频率
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_HOLD_TIME = guid() # 各电压点保持时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_HOLD_TIME, "IsVisible": True, "IsEditable": True, "Name": "各电压点保持时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源设置额定输入 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(6, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(7, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(8, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(9, "启动List输出(额定输入)", "启动List输出", []))
steps.append(delay_step(10, "等待OBC启动", 5000))
# ---- 三、负载(S7200)初始化 ----
steps.append(s7200_step(11, "设置为远程模式", "设置为远程模式", []))
steps.append(s7200_step(12, "设置负载工作模式CC", "设置负载工作模式",
[param("模式", ENUM_LOAD_MODE, 0)])) # CC=0
# ---- 四、测试点1250Vdc ----
steps.append(s7200_step(13, "设置CC模式电流(250Vdc最大电流)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, 67.0)])) # 三相模式最大67A
steps.append(s7200_step(14, "打开通道(加载至250Vdc)", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", True)]))
steps.append(delay_step(15, "等待250Vdc稳定", 3000))
steps.append(pw8001_step(16, "测量250Vdc点输出电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(17, "250Vdc持续运行", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(18, "记录250Vdc最大电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、测试点2300Vdc ----
steps.append(s7200_step(19, "设置CC模式电流(300Vdc最大电流)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, 67.0)]))
steps.append(delay_step(20, "等待300Vdc稳定", 3000))
steps.append(pw8001_step(21, "测量300Vdc点输出电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(22, "300Vdc持续运行", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(23, "记录300Vdc最大电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 六、测试点3350Vdc ----
steps.append(s7200_step(24, "设置CC模式电流(350Vdc最大电流)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, 67.0)]))
steps.append(delay_step(25, "等待350Vdc稳定", 3000))
steps.append(pw8001_step(26, "测量350Vdc点输出电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(27, "350Vdc持续运行", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(28, "记录350Vdc最大电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 七、测试点4400Vdc ----
steps.append(s7200_step(29, "设置CC模式电流(400Vdc最大电流)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, 67.0)]))
steps.append(delay_step(30, "等待400Vdc稳定", 3000))
steps.append(pw8001_step(31, "测量400Vdc点输出电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(32, "400Vdc持续运行", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(33, "记录400Vdc最大电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 八、测试点5450Vdc ----
steps.append(s7200_step(34, "设置CC模式电流(450Vdc最大电流)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, 67.0)]))
steps.append(delay_step(35, "等待450Vdc稳定", 3000))
steps.append(pw8001_step(36, "测量450Vdc点输出电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(37, "450Vdc持续运行", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(38, "记录450Vdc最大电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 九、测试点6500Vdc ----
steps.append(s7200_step(39, "设置CC模式电流(500Vdc最大电流)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, 67.0)]))
steps.append(delay_step(40, "等待500Vdc稳定", 3000))
steps.append(pw8001_step(41, "测量500Vdc点输出电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(42, "500Vdc持续运行", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(43, "记录500Vdc最大电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 十、收尾 ----
steps.append(s7200_step(44, "关闭负载通道", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", False)]))
steps.append(chroma_step(45, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(46, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(pw8001_step(47, "清除状态", "清除状态", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\输出电流范围测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n测试电压点(250Vdc - 500Vdc):")
print(" - 250Vdc:最大持续输出电流 ≤ 67A(三相)/ ≤ 22A(单相)")
print(" - 300Vdc:最大持续输出电流 ≤ 67A(三相)/ ≤ 22A(单相)")
print(" - 350Vdc:最大持续输出电流 ≤ 67A(三相)/ ≤ 22A(单相)")
print(" - 400Vdc:最大持续输出电流 ≤ 67A(三相)/ ≤ 22A(单相)")
print(" - 450Vdc:最大持续输出电流 ≤ 67A(三相)/ ≤ 22A(单相)")
print(" - 500Vdc:最大持续输出电流 ≤ 67A(三相)/ ≤ 22A(单相)")
print("\n电流精度要求:")
print(" - 0~10A:误差 ≤ ±0.2A")
print(" - 10A以上:误差 ≤ ±2%")
print("\n注意:步骤13-43的电流值当前为67A(三相模式),单相模式请改为22A")
+269
View File
@@ -0,0 +1,269 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\输出电压范围测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ENUM_LOAD_MODE = "DeviceCommand.Devices.S7200负载模式_枚举, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def s7200_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.S7200", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, ms=None, var_name=None, var_id=None):
if var_name and var_id:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
else:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, str(ms))])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_FREQ = guid() # 额定频率
VAR_VOLT_LOWER = guid() # OBC输出电压下限
VAR_VOLT_UPPER = guid() # OBC输出电压上限
VAR_LOAD_LOWER = guid() # 达到下限电压的负载电流
VAR_LOAD_UPPER = guid() # 达到上限电压的负载电流
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_HOLD_TIME = 60000 # 1min = 60000ms (固定值)
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_VOLT_LOWER, "IsVisible": True, "IsEditable": True, "Name": "OBC输出电压下限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_VOLT_UPPER, "IsVisible": True, "IsEditable": True, "Name": "OBC输出电压上限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_LOAD_LOWER, "IsVisible": True, "IsEditable": True, "Name": "达到下限电压的负载电流",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_LOAD_UPPER, "IsVisible": True, "IsEditable": True, "Name": "达到上限电压的负载电流",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源设置额定输入 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(6, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(7, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(8, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(9, "启动List输出(额定输入)", "启动List输出", []))
steps.append(delay_step(10, "等待OBC启动", 5000))
# ---- 三、负载(S7200)初始化 ----
steps.append(s7200_step(11, "设置为远程模式", "设置为远程模式", []))
steps.append(s7200_step(12, "设置负载工作模式CC", "设置负载工作模式",
[param("模式", ENUM_LOAD_MODE, 0)])) # CC=0
# ---- 四、调节负载使输出电压为下限值 ----
steps.append(s7200_step(13, "设置CC模式电流(达到下限电压)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="达到下限电压的负载电流", var_id=VAR_LOAD_LOWER)]))
steps.append(s7200_step(14, "打开通道(加载至下限电压)", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", True)]))
steps.append(delay_step(15, "等待输出电压稳定在下限", 3000))
steps.append(pw8001_step(16, "测量下限电压点输出电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(17, "下限电压持续运行1min", VAR_HOLD_TIME))
steps.append(pw8001_step(18, "记录下限电压最大值", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、调节负载使输出电压为上限值 ----
steps.append(s7200_step(19, "设置CC模式电流(达到上限电压)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="达到上限电压的负载电流", var_id=VAR_LOAD_UPPER)]))
steps.append(delay_step(20, "等待输出电压稳定在上限", 3000))
steps.append(pw8001_step(21, "测量上限电压点输出电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(delay_step(22, "上限电压持续运行1min", VAR_HOLD_TIME))
steps.append(pw8001_step(23, "记录上限电压最大值", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 六、收尾 ----
steps.append(s7200_step(24, "关闭负载通道", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", False)]))
steps.append(chroma_step(25, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(26, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(pw8001_step(27, "清除状态", "清除状态", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\输出电压范围测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n测试点:")
print(" - OBC输出电压下限:调节负载使输出电压达到下限,持续运行1min")
print(" - OBC输出电压上限:调节负载使输出电压达到上限,持续运行1min")
print("\n注意:需要用户根据OBC规格填写输出电压上下限及对应的负载电流值")
+240
View File
@@ -0,0 +1,240 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\三相交流相位不平衡测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, var_name=None, var_id=None):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
# 程序变量
VAR_PHASE_VOLT = guid() # 相电压
VAR_FREQ = guid() # 额定频率
VAR_PHASE_DEVIATION = guid() # 相位偏差角度(如5°)
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_STABLE_TIME = guid() # 稳定等待时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_PHASE_VOLT, "IsVisible": True, "IsEditable": True, "Name": "相电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PHASE_DEVIATION, "IsVisible": True, "IsEditable": True, "Name": "相位偏差角度",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_STABLE_TIME, "IsVisible": True, "IsEditable": True, "Name": "稳定等待时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源初始化 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
# ---- 三、正常相位测试(基准) ----
# 三相正常相位:L1=0°, L2=120°, L3=240°
steps.append(chroma_step(5, "配置List起始角度(正常相位)", "配置List起始角度Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 120.0),
param("step3", DOUBLE_TYPE, 240.0)]))
steps.append(chroma_step(6, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="相电压", var_id=VAR_PHASE_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="相电压", var_id=VAR_PHASE_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="相电压", var_id=VAR_PHASE_VOLT)]))
steps.append(chroma_step(7, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="相电压", var_id=VAR_PHASE_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="相电压", var_id=VAR_PHASE_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="相电压", var_id=VAR_PHASE_VOLT)]))
steps.append(chroma_step(8, "启动List输出(正常相位)", "启动List输出", []))
steps.append(delay_step(9, "等待正常相位稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(10, "测量正常相位输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 四、相位偏差+5°测试 ----
# L1=0°+5°=5°, L2=120°+5°=125°, L3=240°+5°=245°
steps.append(chroma_step(11, "配置List起始角度(+5°偏差)", "配置List起始角度Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="相位偏差角度", var_id=VAR_PHASE_DEVIATION),
param("step2", DOUBLE_TYPE, 125.0),
param("step3", DOUBLE_TYPE, 245.0)]))
steps.append(delay_step(12, "等待+5°偏差稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(13, "测量+5°偏差输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、相位偏差-5°测试 ----
# L1=0°-5°=-5°(或355°), L2=120°-5°=115°, L3=240°-5°=235°
steps.append(chroma_step(14, "配置List起始角度(-5°偏差)", "配置List起始角度Async",
[param("step1", DOUBLE_TYPE, -5.0),
param("step2", DOUBLE_TYPE, 115.0),
param("step3", DOUBLE_TYPE, 235.0)]))
steps.append(delay_step(15, "等待-5°偏差稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(16, "测量-5°偏差输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 六、恢复正常相位 ----
steps.append(chroma_step(17, "配置List起始角度(恢复正常)", "配置List起始角度Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 120.0),
param("step3", DOUBLE_TYPE, 240.0)]))
steps.append(delay_step(18, "等待恢复正常", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
# ---- 七、收尾 ----
steps.append(chroma_step(19, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(20, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(pw8001_step(21, "清除状态", "清除状态", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\三相交流相位不平衡测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n测试相位点:")
print(" - 正常相位:L1=0°, L2=120°, L3=240°")
print(" - +5°偏差:L1=5°, L2=125°, L3=245°")
print(" - -5°偏差:L1=-5°, L2=115°, L3=235°")
+267
View File
@@ -0,0 +1,267 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\功率因数测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ENUM_LOAD_MODE = "DeviceCommand.Devices.S7200负载模式_枚举, DeviceCommand, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def s7200_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.S7200", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, ms=None, var_name=None, var_id=None):
if var_name and var_id:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
else:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, str(ms))])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_RATED_FREQ = guid() # 额定频率
VAR_RATED_POWER = guid() # OBC额定功率
VAR_50PCT_POWER = guid() # 50%负载功率
VAR_300W_OR_5PCT = guid() # 300W或5%功率(取大者)
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_STABLE_TIME = guid() # 稳定等待时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_RATED_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_RATED_POWER, "IsVisible": True, "IsEditable": True, "Name": "OBC额定功率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_50PCT_POWER, "IsVisible": True, "IsEditable": True, "Name": "50%负载功率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_300W_OR_5PCT, "IsVisible": True, "IsEditable": True, "Name": "300W或5%功率(取大者)",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_STABLE_TIME, "IsVisible": True, "IsEditable": True, "Name": "稳定等待时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化(IEC模式,包含功率因数测量) ----
steps.append(pw8001_step(1, "设置测试模式IEC", "设置测试模式_IEC", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源设置额定输入 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_RATED_FREQ)]))
steps.append(chroma_step(6, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(7, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(8, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(9, "启动List输出(额定输入)", "启动List输出", []))
steps.append(delay_step(10, "等待OBC启动", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
# ---- 三、负载(S7200)设置:50%负载点测试 ----
steps.append(s7200_step(11, "设置为远程模式", "设置为远程模式", []))
steps.append(s7200_step(12, "设置负载工作模式CC", "设置负载工作模式",
[param("模式", ENUM_LOAD_MODE, 0)])) # CC=0
steps.append(s7200_step(13, "设置CC模式电流(50%负载)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="50%负载功率", var_id=VAR_50PCT_POWER)]))
steps.append(s7200_step(14, "打开通道(50%负载)", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", True)]))
steps.append(delay_step(15, "等待50%负载稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
# ---- 四、测量50%负载点的功率因数 ----
steps.append(pw8001_step(16, "测量50%负载有功功率", "查询功率_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(pw8001_step(17, "测量50%负载功率因数", "发送自定义命令",
[param("命令", STRING_TYPE, ":MEAS:PF?")]))
steps.append(delay_step(18, "记录50%负载数据", 1000))
# ---- 五、切换到300W或5%负载点测试 ----
steps.append(s7200_step(19, "设置CC模式电流(300W或5%负载)", "设置CC模式电流",
[param("电流", DOUBLE_TYPE, use_var=True,
var_name="300W或5%功率(取大者)", var_id=VAR_300W_OR_5PCT)]))
steps.append(delay_step(20, "等待300W/5%负载稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
# ---- 六、测量300W或5%负载点的功率因数 ----
steps.append(pw8001_step(21, "测量300W/5%负载有功功率", "查询功率_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(pw8001_step(22, "测量300W/5%负载功率因数", "发送自定义命令",
[param("命令", STRING_TYPE, ":MEAS:PF?")]))
steps.append(delay_step(23, "记录300W/5%负载数据", 1000))
# ---- 七、收尾 ----
steps.append(s7200_step(24, "关闭负载通道", "设置通道开关",
[param("开关", "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", False)]))
steps.append(chroma_step(25, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(26, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(27, "清除错误队列", "清除错误队列", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\功率因数测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n判定标准:")
print(" - 50%负载点:功率因数 ≥ 0.99")
print(" - 300W或5%负载点:功率因数 ≥ 0.9")
+256
View File
@@ -0,0 +1,256 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\输入电压范围测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
BOOL_TYPE = "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def delay_step(index, name, ms=None, var_name=None, var_id=None):
if var_name and var_id:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
else:
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, str(ms))])
# 程序变量(Parameters 中 Category=0,供步骤绑定)
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_UPPER_VOLT = guid() # 输入电压上限
VAR_LOWER_VOLT = guid() # 输入电压下限
VAR_FREQ = guid() # 额定频率
VAR_HOLD_TIME = guid() # 各电压点保持时间(ms)
VAR_STEP_VOLT = guid() # 电压步进值
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_UPPER_VOLT, "IsVisible": True, "IsEditable": True, "Name": "输入电压上限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_LOWER_VOLT, "IsVisible": True, "IsEditable": True, "Name": "输入电压下限",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_HOLD_TIME, "IsVisible": True, "IsEditable": True, "Name": "各电压点保持时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_STEP_VOLT, "IsVisible": True, "IsEditable": True, "Name": "电压步进值",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、初始化交流源 ----
steps.append(chroma_step(1, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(2, "配置List起始频率", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(3, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
# ---- 二、额定电压启动OBC ----
steps.append(chroma_step(4, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(5, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(6, "启动List输出(额定电压)", "启动List输出", []))
steps.append(delay_step(7, "等待OBC启动稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 三、逐步升压至上限 ----
steps.append(chroma_step(8, "升压至上限电压", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT)]))
steps.append(chroma_step(9, "保持上限电压", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压上限", var_id=VAR_UPPER_VOLT)]))
steps.append(delay_step(10, "上限电压保持时间", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 四、逐步降压至下限 ----
steps.append(chroma_step(11, "降压至下限电压", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT)]))
steps.append(chroma_step(12, "保持下限电压", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="输入电压下限", var_id=VAR_LOWER_VOLT)]))
steps.append(delay_step(13, "下限电压保持时间", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 五、恢复额定电压 ----
steps.append(chroma_step(14, "恢复额定电压", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(15, "额定电压保持", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(delay_step(16, "额定电压保持时间", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 六、收尾 ----
steps.append(chroma_step(17, "停止输出", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(18, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(19, "清除错误队列", "清除错误队列", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\输入电压范围测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
+299
View File
@@ -0,0 +1,299 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\限压特性.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, var_name=None, var_id=None):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
# 程序变量
VAR_RATED_VOLT = guid() # 额定输入电压
VAR_FREQ = guid() # 额定频率
VAR_LIMIT_VOLT = guid() # 限压保护阈值(预期值)
VAR_STEP_VOLT = guid() # 电压步进值
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_HOLD_TIME = guid() # 各电压点保持时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定输入电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_LIMIT_VOLT, "IsVisible": True, "IsEditable": True, "Name": "限压保护阈值(预期)",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_STEP_VOLT, "IsVisible": True, "IsEditable": True, "Name": "电压步进值",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_HOLD_TIME, "IsVisible": True, "IsEditable": True, "Name": "各电压点保持时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源初始化 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(6, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
# ---- 三、额定电压启动OBC ----
steps.append(chroma_step(7, "配置List交流起始电压(额定)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(8, "配置List交流结束电压(额定)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(9, "启动List输出(额定电压)", "启动List输出", []))
steps.append(delay_step(10, "等待OBC启动稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(11, "测量额定电压点输入电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 四、逐步升压至限压阈值(示例:额定+5%、+10%、+15%... ----
# 这里使用固定示例值,实际需要根据用户填写的额定电压和步进值计算
# 假设额定220V,步进10V,测试点:231V(105%)、242V(110%)、253V(115%)、264V(120%)
steps.append(chroma_step(12, "升压至105%额定电压", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 231.0),
param("step2", DOUBLE_TYPE, 231.0),
param("step3", DOUBLE_TYPE, 231.0)]))
steps.append(chroma_step(13, "保持105%额定电压", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 231.0),
param("step2", DOUBLE_TYPE, 231.0),
param("step3", DOUBLE_TYPE, 231.0)]))
steps.append(delay_step(14, "等待105%电压稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(15, "测量105%电压点输入电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(chroma_step(16, "升压至110%额定电压", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 242.0),
param("step2", DOUBLE_TYPE, 242.0),
param("step3", DOUBLE_TYPE, 242.0)]))
steps.append(chroma_step(17, "保持110%额定电压", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 242.0),
param("step2", DOUBLE_TYPE, 242.0),
param("step3", DOUBLE_TYPE, 242.0)]))
steps.append(delay_step(18, "等待110%电压稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(19, "测量110%电压点输入电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(chroma_step(20, "升压至115%额定电压", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 253.0),
param("step2", DOUBLE_TYPE, 253.0),
param("step3", DOUBLE_TYPE, 253.0)]))
steps.append(chroma_step(21, "保持115%额定电压", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 253.0),
param("step2", DOUBLE_TYPE, 253.0),
param("step3", DOUBLE_TYPE, 253.0)]))
steps.append(delay_step(22, "等待115%电压稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(23, "测量115%电压点输入电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
steps.append(chroma_step(24, "升压至120%额定电压(限压点)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 264.0),
param("step2", DOUBLE_TYPE, 264.0),
param("step3", DOUBLE_TYPE, 264.0)]))
steps.append(chroma_step(25, "保持120%额定电压(限压点)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 264.0),
param("step2", DOUBLE_TYPE, 264.0),
param("step3", DOUBLE_TYPE, 264.0)]))
steps.append(delay_step(26, "等待限压点稳定", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
steps.append(pw8001_step(27, "测量限压点输入电压", "查询电压_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、降压恢复额定电压 ----
steps.append(chroma_step(28, "降压至额定电压", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(29, "保持额定电压", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定输入电压", var_id=VAR_RATED_VOLT)]))
steps.append(delay_step(30, "等待恢复正常", var_name="各电压点保持时间ms", var_id=VAR_HOLD_TIME))
# ---- 六、收尾 ----
steps.append(chroma_step(31, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(32, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(pw8001_step(33, "清除状态", "清除状态", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\限压特性.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n测试电压点(示例,220V系统):")
print(" - 额定电压:220V (100%)")
print(" - 105%额定:231V")
print(" - 110%额定:242V")
print(" - 115%额定:253V")
print(" - 120%额定:264V (限压测试点)")
print("\n注意:步骤12-27的电压值为示例(220V系统),请根据实际额定电压和限压阈值调整")
+257
View File
@@ -0,0 +1,257 @@
# -*- coding: utf-8 -*-
"""生成 D:\\ACP\\测试项\\三相交流电压不平衡测试.ACP"""
import json
import uuid
CT_TYPE = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
INT_TYPE = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
DOUBLE_TYPE = "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
STRING_TYPE = "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ZERO_GUID = "00000000-0000-0000-0000-000000000000"
def guid():
return str(uuid.uuid4())
def param(name, ptype, value=None, use_var=False, var_name=None, var_id=None):
return {
"ID": guid(),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": ptype,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": use_var,
"VariableName": var_name,
"VariableID": var_id,
}
def ct_param():
return param("ct", CT_TYPE)
def method_step(index, name, full_name, method_name, params):
return {
"ID": guid(),
"IsUsed": True,
"Index": index,
"Name": name,
"StepType": "方法",
"Method": {
"Name": method_name,
"FullName": full_name,
"Parameters": params + [ct_param()],
},
"SubProgram": None,
"LoopCount": None,
"LoopStartStepId": None,
"OKExpression": None,
"GotoSettingString": "",
"OKGotoStepID": ZERO_GUID,
"NGGotoStepID": ZERO_GUID,
"Description": None,
}
def chroma_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Devices.Chroma61800", method_name, params)
def pw8001_step(index, name, method_name, params):
return method_step(index, name, "DeviceCommand.Device.PW8001", method_name, params)
def delay_step(index, name, var_name=None, var_id=None):
return method_step(index, name, "Command.Delay", "Delay_ms",
[param("millisecond", INT_TYPE, use_var=True,
var_name=var_name, var_id=var_id)])
# 程序变量
VAR_RATED_VOLT = guid() # 额定相电压
VAR_FREQ = guid() # 额定频率
VAR_UNBALANCE_PCT = guid() # 电压不平衡度(%)
VAR_PW_CHANNEL = guid() # 功率分析仪通道号
VAR_STABLE_TIME = guid() # 稳定等待时间ms
program_params = [
# 标准系统参数(Category=2
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "台架序号",
"Type": INT_TYPE, "Category": 2, "Value": 1, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "CAN通道",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "示波器通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道1",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": guid(), "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道2",
"Type": INT_TYPE, "Category": 2, "Value": 0, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
# 测试项可调变量(Category=0)- 用户手动填值
{"ID": VAR_RATED_VOLT, "IsVisible": True, "IsEditable": True, "Name": "额定相电压",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_FREQ, "IsVisible": True, "IsEditable": True, "Name": "额定频率",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_UNBALANCE_PCT, "IsVisible": True, "IsEditable": True, "Name": "电压不平衡度(%)",
"Type": DOUBLE_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_PW_CHANNEL, "IsVisible": True, "IsEditable": True, "Name": "功率分析仪通道号",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
{"ID": VAR_STABLE_TIME, "IsVisible": True, "IsEditable": True, "Name": "稳定等待时间ms",
"Type": INT_TYPE, "Category": 0, "Value": None, "LowerLimit": None,
"UpperLimit": None, "Result": True, "IsUseVar": False,
"VariableName": None, "VariableID": None},
]
steps = []
# ---- 一、功率分析仪初始化 ----
steps.append(pw8001_step(1, "设置测试模式WIDE", "设置测试模式_WIDE", []))
steps.append(pw8001_step(2, "设置同步源U1", "设置同步源",
[param("", STRING_TYPE, "U1")]))
# ---- 二、交流源初始化 ----
steps.append(chroma_step(3, "初始化三相List模式(单次循环)", "初始化三相List模式",
[param("loopCount", INT_TYPE, "1")]))
steps.append(chroma_step(4, "配置List起始频率(额定)", "配置List起始频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(5, "配置List结束频率(额定)", "配置List结束频率Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定频率", var_id=VAR_FREQ)]))
steps.append(chroma_step(6, "配置List执行时间", "配置List执行时间Async",
[param("step1", DOUBLE_TYPE, 100.0),
param("step2", DOUBLE_TYPE, 100.0),
param("step3", DOUBLE_TYPE, 100.0)]))
steps.append(chroma_step(7, "配置List起始角度(标准120°)", "配置List起始角度Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 120.0),
param("step3", DOUBLE_TYPE, 240.0)]))
# ---- 三、正常电压测试(基准) ----
# 三相额定电压:L1=L2=L3=额定
steps.append(chroma_step(8, "配置List交流起始电压(额定平衡)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(9, "配置List交流结束电压(额定平衡)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(10, "启动List输出(额定平衡电压)", "启动List输出", []))
steps.append(delay_step(11, "等待额定电压稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(12, "测量额定平衡电压输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 四、5%电压不平衡测试(L1相降低5%) ----
# 假设额定220V5%不平衡=11VL1=209VL2=L3=220V
# 这里使用固定值示例,实际需要根据用户填写的额定电压和不平衡度计算
steps.append(chroma_step(13, "配置List交流起始电压(5%不平衡-L1降低)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 209.0), # 220V * 0.95 = 209V
param("step2", DOUBLE_TYPE, 220.0),
param("step3", DOUBLE_TYPE, 220.0)]))
steps.append(chroma_step(14, "配置List交流结束电压(5%不平衡-L1降低)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 209.0),
param("step2", DOUBLE_TYPE, 220.0),
param("step3", DOUBLE_TYPE, 220.0)]))
steps.append(delay_step(15, "等待5%不平衡电压稳定", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
steps.append(pw8001_step(16, "测量5%不平衡电压输入电流", "查询电流_不含变比",
[param("通道号", INT_TYPE, use_var=True,
var_name="功率分析仪通道号", var_id=VAR_PW_CHANNEL)]))
# ---- 五、恢复正常电压 ----
steps.append(chroma_step(17, "配置List交流起始电压(恢复正常)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT)]))
steps.append(chroma_step(18, "配置List交流结束电压(恢复正常)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step2", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT),
param("step3", DOUBLE_TYPE, use_var=True,
var_name="额定相电压", var_id=VAR_RATED_VOLT)]))
steps.append(delay_step(19, "等待恢复正常", var_name="稳定等待时间ms", var_id=VAR_STABLE_TIME))
# ---- 六、收尾 ----
steps.append(chroma_step(20, "停止输出(电压归零)", "配置List交流起始电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(chroma_step(21, "配置List交流结束电压(0V)", "配置List交流结束电压Async",
[param("step1", DOUBLE_TYPE, 0.0),
param("step2", DOUBLE_TYPE, 0.0),
param("step3", DOUBLE_TYPE, 0.0)]))
steps.append(pw8001_step(22, "清除状态", "清除状态", []))
program = {
"ID": guid(),
"StepCollection": steps,
"ErrorStepCollection": [],
"Parameters": program_params,
}
out_path = r"D:\ACP\测试项\三相交流电压不平衡测试.ACP"
with open(out_path, "w", encoding="utf-8") as f:
json.dump(program, f, ensure_ascii=False, indent=2)
# 校验
with open(out_path, encoding="utf-8") as f:
data = json.load(f)
print(f"已生成: {out_path}")
print(f"步骤数: {len(data['StepCollection'])}, 参数数: {len(data['Parameters'])}")
print("\n需要手动填写的变量参数:")
for p in data["Parameters"]:
if p["Category"] == 0:
print(f" - {p['Name']} ({p['Type'].split(',')[0].split('.')[-1]})")
print("\n步骤流程:")
for s in data["StepCollection"]:
print(f" {s['Index']:>2}. {s['Name']}")
print("\n测试电压点:")
print(" - 额定平衡电压:L1=L2=L3=额定")
print(" - 5%不平衡电压:L1=95%额定,L2=L3=额定(示例:209V/220V/220V")
print("\n注意:步骤13-14的电压值为示例(220V系统),请根据实际额定电压调整")
+3
View File
@@ -1,3 +1,4 @@
using CANModule.ViewModels;
using CANModule.Views;
namespace CANModule
@@ -12,7 +13,9 @@ namespace CANModule
{
containerRegistry.RegisterDialog<SelectCanMessageView>("SelectCanMessageView");
containerRegistry.RegisterDialog<CollectCANSignalSettingView>("CollectCANSignalSettingView");
containerRegistry.RegisterDialog<DBCInfoView>("DBCInfo");
containerRegistry.RegisterForNavigation<CANView>("CANView");
containerRegistry.Register<CANViewModel>();
}
}
}
+9 -5
View File
@@ -18,10 +18,11 @@ using System.Windows.Threading;
using TSMasterCAN;
using UIShare.GlobalVariable;
using UIShare.UIViewModel;
using UIShare.ViewModelBase;
namespace CANModule.ViewModels
{
public class CANViewModel : BindableBase, IDialogAware
public class CANViewModel : NavigateViewModelBase
{
#region
@@ -269,17 +270,15 @@ namespace CANModule.ViewModels
#endregion
private IEventAggregator _eventAggregator { get; set; }
private CAN? _canfd;
private SystemConfig? _systemConfig;
private readonly DeviceManager _deviceManager;
private IDialogService _dialogService { get; set; }
CancellationTokenSource cts = new CancellationTokenSource();
public CANViewModel(IContainerProvider containerProvider)
public CANViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
_systemConfig = containerProvider.Resolve<SystemConfig>();
_deviceManager = containerProvider.Resolve<DeviceManager>();
_canfd = _deviceManager.CANFD;
_dialogService = containerProvider.Resolve<IDialogService>();
SelectBLFPathCommand = new DelegateCommand(SelectBLFPath);
SaveBLFPathCommand = new DelegateCommand(SaveBLFPath);
@@ -299,6 +298,7 @@ namespace CANModule.ViewModels
LoadMessageCommand = new DelegateCommand(LoadMessage);
DeleteDcAutoLoadCommand = new DelegateCommand(DeleteDcAutoLoad);
SendCustomMessageCommand = new DelegateCommand(SendCustomMessage);
Task.Run(() => Refresh(cts.Token), cts.Token);
}
#region
@@ -496,7 +496,7 @@ namespace CANModule.ViewModels
{
while (ct.IsCancellationRequested == false)
{
var temp = CAN.RealTimeMessages.Select(s => s.Value).ToArray();
var temp = _deviceManager._CANMonitoringService.RealTimeMessages.Select(s => s.Value).ToArray();
foreach (var item in temp)
{
var find = CanMessageList.FirstOrDefault(s => s.ID == item.FIdentifier);
@@ -571,6 +571,10 @@ namespace CANModule.ViewModels
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
public override void OnNavigatedTo(NavigationContext context)
{
Task.Run(() => Refresh(cts.Token), cts.Token);
}
+138
View File
@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Model;
using Model.Models;
using TSMasterCAN;
using UIShare.GlobalVariable;
using UIShare.PubEvent;
using UIShare.UIViewModel;
namespace CANModule.ViewModels
{
public class DBCInfoViewModel :BindableBase, IDialogAware
{
private can_network _can_Network;
public required can_network can_Network
{
get { return _can_Network; }
set { SetProperty(ref _can_Network, value); }
}
private List<_Msg_> _MessageInfo;
public required List<_Msg_> MessageInfo
{
get { return _MessageInfo; }
set { SetProperty(ref _MessageInfo, value); }
}
private ObservableCollection<InstructionNode> _CanNetWorkNode = new();
public ObservableCollection<InstructionNode> CanNetWorkNode
{
get => _CanNetWorkNode;
set => SetProperty(ref _CanNetWorkNode, value);
}
private ObservableCollection<InstructionNode> _MessgaeNode = new();
public ObservableCollection<InstructionNode> MessgaeNode
{
get => _MessgaeNode;
set => SetProperty(ref _MessgaeNode, value);
}
public ICommand CloseCommand { get; set; }
public DialogCloseListener RequestClose { get; set; }
public DBCInfoViewModel()
{
CloseCommand = new DelegateCommand(Close);
}
private void Close()
{
RequestClose.Invoke();
}
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
if (parameters.ContainsKey("can_Network"))
{
can_Network = parameters.GetValue<can_network>("can_Network");
}
if (parameters.ContainsKey("MsgDatabase"))
{
MessageInfo = parameters.GetValue<List<_Msg_>>("MsgDatabase");
}
InitTreeNode();
}
private void InitTreeNode()
{
foreach(var item in can_Network.can_nodes)
{
var tx = new ObservableCollection<InstructionNode>();
var rx = new ObservableCollection<InstructionNode>();
foreach (var can_Message in item.rx_can_Messages)
{
rx.Add(new InstructionNode
{
Name = can_Message.message_name
});
}
foreach (var can_Message in item.tx_can_Messages)
{
tx.Add(new InstructionNode
{
Name = can_Message.message_name
});
}
var children = new ObservableCollection<InstructionNode>();
children.Add(new InstructionNode
{
Name = "TX",
Children = tx
});
children.Add(new InstructionNode
{
Name = "RX",
Children = rx
});
CanNetWorkNode.Add(new InstructionNode
{
Name = item.node_name,
Children = children
});
}
foreach(var item in MessageInfo)
{
var children = new ObservableCollection<InstructionNode>();
foreach(var Signalname in item.signal_Name)
{
children.Add(new InstructionNode
{
Name = Signalname
});
}
string hexValue = "[0x" + item.msg_id.ToString("X") + "]";
MessgaeNode.Add(new InstructionNode
{
Name = hexValue+item.msg_name,
Children=children
});
}
}
}
}
+2 -2
View File
@@ -34,12 +34,12 @@
Foreground="White"
VerticalAlignment="Center"
Margin="5,0,10,0" />
<Button Content="关闭"
<!--<Button Content="关闭"
Grid.Column="2"
Margin="150 0 0 0"
Width="60"
Command="{Binding CloseCommand}"
Height="25" />
Height="25" />-->
</Grid>
</GroupBox.Header>
<Grid>
+76
View File
@@ -0,0 +1,76 @@
<UserControl x:Class="CANModule.Views.DBCInfoView"
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:oxy="http://oxyplot.org/wpf"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
xmlns:cons="clr-namespace:UIShare.Converters;assembly=UIShare"
Background="White"
xmlns:model="clr-namespace:Model.Models;assembly=Model"
prism:ViewModelLocator.AutoWireViewModel="True"
Height="400"
Width="800">
<prism:Dialog.WindowStyle>
<Style BasedOn="{StaticResource DialogUserManageStyle}"
TargetType="Window" />
</prism:Dialog.WindowStyle>
<GroupBox MouseLeftButtonDown="MouseLeftButtonDown">
<GroupBox.Header>
<Grid Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="*"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="CAN报文查看"
Foreground="White"
VerticalAlignment="Center"
Margin="5,0,10,0" />
<Button Content="关闭"
Grid.Column="2"
Margin="150 0 0 0"
Width="60"
Command="{Binding CloseCommand}"
Height="25"
/>
</Grid>
</GroupBox.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="5" />
<!-- Splitter 列 -->
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TreeView ItemsSource="{Binding MessgaeNode}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type model:InstructionNode}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
<GridSplitter Grid.Column="1"
Width="5"
Background="Gray"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ResizeBehavior="PreviousAndNext"
ShowsPreview="True" />
<TreeView Grid.Column="2"
ItemsSource="{Binding CanNetWorkNode}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type model:InstructionNode}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
</GroupBox>
</UserControl>
+36
View File
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CANModule.Views
{
/// <summary>
/// DBCInfoView.xaml 的交互逻辑
/// </summary>
public partial class DBCInfoView : UserControl
{
public DBCInfoView()
{
InitializeComponent();
}
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Window.GetWindow(this)?.DragMove();
}
}
}
}
+13 -1
View File
@@ -3,6 +3,7 @@ using DeviceCommand.Base;
using Model.Models;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -10,13 +11,24 @@ using System.Threading.Tasks;
namespace DeviceCommand.Devices
{
/// <summary>
/// 水冷机 一对
/// 负载 一对
/// </summary>
[ACPCommand]
public class ANEVH80 : Tcp
{
// Chroma SCPI 默认使用 \n 作为结束符
private const string ScpiDelimiter = "\n";
public ANEVH80(TcpConfig config) : base(config)
{
}
/// <summary>
/// 占位符,可能的操作先占位
/// </summary>
public virtual async Task<double> (CancellationToken ct = default)
{
string resp = await WriteReadAsync($"MEAS:FREQ?{ScpiDelimiter}", ScpiDelimiter, ct);
return double.TryParse(resp, NumberStyles.Any, CultureInfo.InvariantCulture, out double val) ? val : 0.0;
}
}
}
+132 -132
View File
@@ -2,16 +2,14 @@
using DeviceCommand.Base;
using Model.Models;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace DeviceCommand.Devices
{
/// <summary>
/// 交流源 一拖三
/// 交流源 一拖三 (Chroma 61800系列)
/// </summary>
[ACPCommand]
public class Chroma61800 : Tcp
@@ -23,185 +21,187 @@ namespace DeviceCommand.Devices
{
}
#region 1.
#region 1.
public virtual async Task (CancellationToken ct = default)
/// <summary>
/// 清除错误队列 (*CLS)[cite: 1]
/// </summary>
public virtual async Task Async(CancellationToken ct = default)
{
await SendAsync($"*CLS{ScpiDelimiter}", ct);
}
#endregion
#region 2. LIST
/// <summary>
/// 重设仪器为初始状态 (*RST)[cite: 1]
/// </summary>
public virtual async Task Async(CancellationToken ct = default)
{
await SendAsync($"*RST{ScpiDelimiter}", ct);
}
/// <summary>
/// 初始化 LIST 模式的三相独立编辑环境
/// 查询仪器识别码 (*IDN?)[cite: 1]
/// </summary>
/// <param name="loopCount">循环次数,0代表无限循环</param>
public virtual async Task List模式(int loopCount = 0, CancellationToken ct = default)
public virtual async Task<string> Async(CancellationToken ct = default)
{
await SendAsync($"INST:PHAS THRE{ScpiDelimiter}", ct); // 选择三相模式
await SendAsync($"INST:EDIT EACH{ScpiDelimiter}", ct); // 选择编辑电压方式为分别编辑
await SendAsync($"LIST:COUN {loopCount}{ScpiDelimiter}", ct); // 循环次数设定
await SendAsync($"LIST:TRIG AUTO{ScpiDelimiter}", ct); // 设定触发方式
await SendAsync($"LIST:BASE TIME{ScpiDelimiter}", ct); // 选择执行时间类别
return await WriteReadAsync($"*IDN?{ScpiDelimiter}", ScpiDelimiter, ct);
}
#endregion
#region 3. LIST ( - )
#region 2. (OUTPut )[cite: 1]
/// <summary>
/// 切换目标相位并设置波形为正弦波
/// 建议在发送具体 LIST 参数前调用一次即可
/// 设置输出开关状态 (OUTP ON / OFF)[cite: 1]
/// </summary>
/// <param name="phase">相位 (1: L1, 2: L2, 3: L3)</param>
public virtual async Task Async(int phase, CancellationToken ct = default)
/// <param name="isOn">true: 开启输出, false: 关闭输出</param>
public virtual async Task Async(bool isOn, CancellationToken ct = default)
{
if (phase < 1 || phase > 3)
throw new ArgumentOutOfRangeException(nameof(phase), "相位必须为 1, 2, 或 3");
await SendAsync($"INST:NSEL {phase}{ScpiDelimiter}", ct);
await SendAsync($"FUNC:SHAP:A SINE{ScpiDelimiter}", ct);
string state = isOn ? "ON" : "OFF";
await SendAsync($"OUTP {state}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步起始角度
/// 设置输出耦合模式 (OUTP:COUP AC | DC | ACDC)[cite: 1]
/// </summary>
public virtual async Task List起始角度Async(double step1, double step2, double step3, CancellationToken ct = default)
public virtual async Task Async(string couplingMode, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:DEGR {strValues}{ScpiDelimiter}", ct);
// 有效参数: AC, DC, ACDC
await SendAsync($"OUTP:COUP {couplingMode}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步交流起始电压
/// 设置输出继电器状态 (OUTP:REL ON | OFF)[cite: 1]
/// </summary>
public virtual async Task List交流起始电压Async(double step1, double step2, double step3, CancellationToken ct = default)
public virtual async Task Async(bool isOn, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:VOLT:AC:STAR {strValues}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步交流结束电压
/// </summary>
public virtual async Task List交流结束电压Async(double step1, double step2, double step3, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:VOLT:AC:END {strValues}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步直流起始电压
/// </summary>
public virtual async Task List直流起始电压Async(double step1, double step2, double step3, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:VOLT:DC:STAR {strValues}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步直流结束电压
/// </summary>
public virtual async Task List直流结束电压Async(double step1, double step2, double step3, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:VOLT:DC:END {strValues}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步起始频率
/// </summary>
public virtual async Task List起始频率Async(double step1, double step2, double step3, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:FREQ:STAR {strValues}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步结束频率
/// </summary>
public virtual async Task List结束频率Async(double step1, double step2, double step3, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:FREQ:END {strValues}{ScpiDelimiter}", ct);
}
/// <summary>
/// 配置 LIST 各步执行时间 (单位: 毫秒)
/// </summary>
public virtual async Task List执行时间Async(double step1, double step2, double step3, CancellationToken ct = default)
{
string strValues = JoinParameters(step1, step2, step3);
await SendAsync($"LIST:DWEL {strValues}{ScpiDelimiter}", ct);
}
/// <summary>
/// 辅助方法:将三个 double 值转换为逗号分隔的字符串,确保小数点格式正确
/// </summary>
private string JoinParameters(double val1, double val2, double val3)
{
return $"{val1.ToString("0.###", CultureInfo.InvariantCulture)}," +
$"{val2.ToString("0.###", CultureInfo.InvariantCulture)}," +
$"{val3.ToString("0.###", CultureInfo.InvariantCulture)}";
string state = isOn ? "ON" : "OFF";
await SendAsync($"OUTP:REL {state}{ScpiDelimiter}", ct);
}
#endregion
#region 4. LIST
#region 3. (SOURCE )[cite: 1]
/// <summary>
/// 切换到 LIST 模式并触发输出
/// 设置交流电压 (VOLT:AC)[cite: 1]
/// </summary>
public virtual async Task List输出(CancellationToken ct = default)
/// <param name="voltage">电压值 (0 ~ 300V 或高压选配范围)</param>
public virtual async Task Async(double voltage, CancellationToken ct = default)
{
await SendAsync($"OUTP:MODE LIST{ScpiDelimiter}", ct);
await SendAsync($"TRIG ON{ScpiDelimiter}", ct);
string valStr = voltage.ToString("0.###", CultureInfo.InvariantCulture);
await SendAsync($"VOLT:AC {valStr}{ScpiDelimiter}", ct);
}
/// <summary>
/// 查询 LIST 序列是否正在运行
/// 设置直流电压 (VOLT:DC)[cite: 1]
/// </summary>
public virtual async Task<bool> List是否运行中(CancellationToken ct = default)
public virtual async Task Async(double voltage, CancellationToken ct = default)
{
string state = await WriteReadAsync($"TRIG:STATE?{ScpiDelimiter}", ScpiDelimiter, ct);
state = state?.Trim().ToUpper();
return state == "ON" || state == "1";
string valStr = voltage.ToString("0.###", CultureInfo.InvariantCulture);
await SendAsync($"VOLT:DC {valStr}{ScpiDelimiter}", ct);
}
/// <summary>
/// 阻塞异步等待直到 LIST 序列执行完毕 (带安全超时保护)
/// 设置输出频率 (FREQ)[cite: 1]
/// </summary>
/// <param name="timeoutMs">最大等待超时时间(建议比实际LIST总时长多5-10秒)</param>
public virtual async Task List执行结束(int timeoutMs = 60000, CancellationToken ct = default)
/// <param name="frequency">频率值 (Hz)</param>
public virtual async Task Async(double frequency, CancellationToken ct = default)
{
// 给仪器留出响应触发的时间
await Task.Delay(500, ct);
Stopwatch sw = Stopwatch.StartNew();
bool isRunning = true;
while (isRunning)
{
ct.ThrowIfCancellationRequested();
if (sw.ElapsedMilliseconds > timeoutMs)
{
throw new TimeoutException($"等待 LIST 执行结束超时 ({timeoutMs} ms)。");
string valStr = frequency.ToString("0.###", CultureInfo.InvariantCulture);
await SendAsync($"FREQ {valStr}{ScpiDelimiter}", ct);
}
// 读取当前状态
isRunning = await List是否运行中(ct);
if (isRunning)
/// <summary>
/// 设置波形选择 (FUNC:SHAP:A SINE / SQUA / CSIN 等)[cite: 1]
/// </summary>
public virtual async Task Async(string shape, CancellationToken ct = default)
{
// 还在运行,适当休眠后继续轮询,避免总线阻塞
await Task.Delay(500, ct);
}
}
await SendAsync($"FUNC:SHAP:A {shape}{ScpiDelimiter}", ct);
}
#endregion
#region 4. (INST & PHASE )[cite: 1]
/// <summary>
/// 设置单/三相工作模式 (INST:PHAS THREE / SINGLE)[cite: 1]
/// </summary>
/// <param name="isThreePhase">true: 三相模式, false: 单相模式</param>
public virtual async Task Async(bool isThreePhase, CancellationToken ct = default)
{
string mode = isThreePhase ? "THREE" : "SINGLE";
await SendAsync($"INST:PHAS {mode}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置三相模式下的相互关系 (PHASE:THREE INDEPEND / SAMEFREQ / BALANCE)[cite: 1]
/// </summary>
public virtual async Task Async(string relation, CancellationToken ct = default)
{
// 有效参数: INDEPEND, SAMEFREQ, BALANCE
await SendAsync($"PHASE:THREE {relation}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置输出开启相位角 (PHASE:ON)[cite: 1]
/// </summary>
public virtual async Task Async(double degree, CancellationToken ct = default)
{
string valStr = degree.ToString("0.###", CultureInfo.InvariantCulture);
await SendAsync($"PHASE:ON {valStr}{ScpiDelimiter}", ct);
}
/// <summary>
/// 设置输出关闭相位角 (PHASE:OFF)[cite: 1]
/// </summary>
public virtual async Task Async(double degree, CancellationToken ct = default)
{
string valStr = degree.ToString("0.###", CultureInfo.InvariantCulture);
await SendAsync($"PHASE:OFF {valStr}{ScpiDelimiter}", ct);
}
#endregion
#region 5. (MEASure )[cite: 1]
/// <summary>
/// 查询交流电压均方根值 (MEAS:VOLT:AC?)[cite: 1]
/// </summary>
public virtual async Task<double> Async(CancellationToken ct = default)
{
string resp = await WriteReadAsync($"MEAS:VOLT:AC?{ScpiDelimiter}", ScpiDelimiter, ct);
return double.TryParse(resp, NumberStyles.Any, CultureInfo.InvariantCulture, out double val) ? val : 0.0;
}
/// <summary>
/// 查询交流电流均方根值 (MEAS:CURR:AC?)[cite: 1]
/// </summary>
public virtual async Task<double> Async(CancellationToken ct = default)
{
string resp = await WriteReadAsync($"MEAS:CURR:AC?{ScpiDelimiter}", ScpiDelimiter, ct);
return double.TryParse(resp, NumberStyles.Any, CultureInfo.InvariantCulture, out double val) ? val : 0.0;
}
/// <summary>
/// 查询输出频率 (MEAS:FREQ?)[cite: 1]
/// </summary>
public virtual async Task<double> Async(CancellationToken ct = default)
{
string resp = await WriteReadAsync($"MEAS:FREQ?{ScpiDelimiter}", ScpiDelimiter, ct);
return double.TryParse(resp, NumberStyles.Any, CultureInfo.InvariantCulture, out double val) ? val : 0.0;
}
/// <summary>
/// 查询真实输出功率 (MEAS:POW:AC?)[cite: 1]
/// </summary>
public virtual async Task<double> Async(CancellationToken ct = default)
{
string resp = await WriteReadAsync($"MEAS:POW:AC?{ScpiDelimiter}", ScpiDelimiter, ct);
return double.TryParse(resp, NumberStyles.Any, CultureInfo.InvariantCulture, out double val) ? val : 0.0;
}
#endregion
}
}
+41 -1
View File
@@ -168,8 +168,48 @@ namespace DeviceCommand.Devices
await .(_slaveAddress, io信息.Address, );
}
// =================================================================================
// 以下为新增的原生命令透传接口,使用台架序号自动路由至对应 IOBoard
// =================================================================================
/// <summary>
/// 内部路由辅助方法:根据板卡索引安全获取当前连接的实例对象
/// 针对指定台架直接写入单个输出开关
/// </summary>
public async Task (int , byte , ushort , bool data)
{
IOBoard targetBoard = GetBoardInstance();
await targetBoard.(, , data);
}
/// <summary>
/// 针对指定台架直接批量写入输出开关
/// </summary>
public async Task (int , byte , ushort , bool[] datas)
{
IOBoard targetBoard = GetBoardInstance();
await targetBoard.(, , datas);
}
/// <summary>
/// 针对指定台架直接读取单个输出开关状态
/// </summary>
public async Task (int , byte , ushort )
{
IOBoard targetBoard = GetBoardInstance();
await targetBoard.(, );
}
/// <summary>
/// 针对指定台架直接批量读取输出开关状态
/// </summary>
public async Task<bool[]> (int , byte , ushort , ushort )
{
IOBoard targetBoard = GetBoardInstance();
return await targetBoard.(, , );
}
/// <summary>
/// 内部路由辅助方法:根据板卡/台架索引安全获取当前连接的实例对象
/// </summary>
private IOBoard GetBoardInstance(int moduleIndex)
{
+1 -1
View File
@@ -10,7 +10,7 @@ namespace DeviceCommand.Device
/// <summary>
/// 功率分析仪(型号:HIOKI PW8001) 一拖三
/// </summary>
[ACPCommand]
public class PW8001 : Tcp
{
/// <summary>
+22
View File
@@ -53,6 +53,28 @@ namespace DeviceCommand.Devices
// SCPI 指令结束符 (消息终止符需使用 LF)
private const string ScpiDelimiter = "\n";
#region MSO44B ACP
public enum AcquireMode { Sample = 0, PeakDetect = 1, HiRes = 2, Average = 3, Envelope = 4 }
public enum BandwidthLimit { Full = 0, BW20MHz = 1 }
public enum Channel { Channel1 = 1, Channel2 = 2, Channel3 = 3, Channel4 = 4 }
public enum CouplingMode { DC = 0, AC = 1, GND = 2 }
public enum MeasurementType
{
Amplitude = 1, Frequency = 2, Mean = 3, PK2PK = 4,
Maximum = 5, Minimum = 6, RMS = 7, Overshoot = 8,
Undershoot = 9, PositiveOvershoot = 10, NegativeOvershoot = 11,
RiseTime = 12, FallTime = 13, DutyCycle = 14,
Period = 15, Phase = 16, Delay = 17,
BurstWidth = 18, SlewRateRising = 19, SlewRateFalling = 20,
High = 21
}
public enum StopAfter { Sequence = 0, RunStop = 1 }
public enum TriggerMode { Auto = 0, Normal = 1 }
public enum TriggerSlope { Rising = 0, Falling = 1 }
#endregion
public TektronixMSO(TcpConfig config) : base(config)
{
}
@@ -197,7 +197,6 @@ namespace MonitorModule.ViewModels.Dialogs
/// </summary>
private IEnumerable<(string DisplayName, string Fingerprint, string MethodName)> DiscoverCanSignals()
{
if (_deviceManager?.CANFD == null) yield break;
if (_systemConfig?.ConfigurationList == null) yield break;
var msgDb = DBCParse.MsgDatabase;
@@ -331,7 +330,6 @@ namespace MonitorModule.ViewModels.Dialogs
private void OnDbcLoaded(DBCLoadedArgs args)
{
if (args.Scope != _systemConfig?.Title) return;
if (_deviceManager?.CANFD == null) return;
int channel = (int)args.Channel;
var msgDb = DBCParse.MsgDatabase;
@@ -535,7 +535,6 @@ namespace MonitorModule.ViewModels
private void RefreshConfiguredCanSignals()
{
if (_systemConfig?.ConfigurationList == null || _systemConfig.ConfigurationList.Count == 0) return;
if (_deviceManager?.CANFD == null) return;
var msgDb = DBCParse.MsgDatabase;
foreach (var channel in _systemConfig.ConfigurationList.Select(c => c.Channel).Distinct())
@@ -633,7 +632,6 @@ namespace MonitorModule.ViewModels
private void OnDbcLoaded(DBCLoadedArgs args)
{
if (args.Scope != TestStatus) return;
if (_deviceManager?.CANFD == null) return;
int channel = (int)args.Channel;
var msgDb = DBCParse.MsgDatabase;
if (channel < 0 || channel >= msgDb.Count) return;
+6 -266
View File
@@ -11,275 +11,15 @@ using TSMaster;
namespace TSMasterCAN
{
[ACPCommand]
public class CAN : IDisposable
public class CAN
{
#region
public static event Action? ConnectEvent;
public static event Action? DisConnectEvent;
public static event Action ConnectEvent;
public static event Action DisConnectEvent;
public static bool ConnectFlag { get; set; } = false;
/// <summary>
/// 实时接收到的 CAN 报文缓存(按报文 ID 索引,保留最新帧)。
/// 供 CANViewModel.Refresh 等界面轮询读取。
/// </summary>
public static ConcurrentDictionary<int, TLIBCANFD> RealTimeMessages { get; } = new();
#endregion
#region
/// <summary>设备类型号(43 = USBCANFD-400U 等,TSMaster 中作为配置参考保留)</summary>
public uint DeviceType { get; }
/// <summary>设备索引</summary>
public uint DeviceIndex { get; }
/// <summary>最大通道数</summary>
public int MaxChannels { get; }
/// <summary>仲裁域波特率</summary>
public string ABitBaud { get; }
/// <summary>数据域波特率</summary>
public string DBitBaud { get; }
/// <summary>是否开启终端电阻</summary>
public bool EnableTerminalResistance { get; }
/// <summary>DBC 解析器(提供 MsgDatabase、MaxChannels 等访问)</summary>
public DBCParse DBCParser => DBCParse.Instance;
/// <summary>
/// DBC 报文解码事件:当接收到 CAN 帧并通过 DBC 解码后触发。
/// 参数:(通道号, 解码后的报文信息)
/// </summary>
public event Action<uint, DBCMessage>? OnDbcMessageDecoded;
private bool _disposed;
private bool _isOpened;
private TCANFDQueueEvent_Win32? _instanceListener;
#endregion
#region
/// <summary>默认构造函数(兼容 SystemConfig.CANFD = new() 等场景)</summary>
public CAN() : this(43, 0, 4, "500000", "2000000", true) { }
/// <summary>
/// 带配置参数的构造函数(兼容原 ZLG 设备管理流程)。
/// </summary>
/// <param name="deviceType">设备类型号</param>
/// <param name="deviceIndex">设备索引</param>
/// <param name="maxChannels">最大通道数</param>
/// <param name="aBitBaud">仲裁域波特率</param>
/// <param name="dBitBaud">数据域波特率</param>
/// <param name="enableTerminalResistance">是否开启终端电阻</param>
public CAN(uint deviceType, uint deviceIndex, int maxChannels, string aBitBaud, string dBitBaud, bool enableTerminalResistance)
{
DeviceType = deviceType;
DeviceIndex = deviceIndex;
MaxChannels = maxChannels;
ABitBaud = aBitBaud;
DBitBaud = dBitBaud;
EnableTerminalResistance = enableTerminalResistance;
}
#endregion
#region ZLG
/// <summary>
/// 打开设备:初始化 TSMaster 库 → 设置通道数 → 配置波特率 → 连接 → 启动 RBS → 注册监听。
/// </summary>
/// <returns>true 表示成功</returns>
public bool ()
{
if (_isOpened) return true;
if (ConnectFlag) { _isOpened = true; return true; }
try
{
// 1. 初始化 TSMaster 库
var re = Init("ACP");
if (re != 0)
{
Debug.WriteLine($"TSMaster 初始化失败,错误代码:{re}");
return false;
}
// 2. 设置通道数
TsMasterApi.tsapp_set_can_channel_count(MaxChannels);
// 3. 配置各通道波特率
float arbKbps = float.Parse(ABitBaud) / 1000f;
float dataKbps = float.Parse(DBitBaud) / 1000f;
for (int ch = 0; ch < MaxChannels; ch++)
{
TsMasterApi.tsapp_configure_baudrate_canfd(
ch, arbKbps, dataKbps,
TLIBCANFDControllerType.lfdtISOCAN,
TLIBCANFDControllerMode.lfdmNormal,
EnableTerminalResistance);
}
// 4. 连接硬件
re = Connect();
if (re != 0)
{
Debug.WriteLine($"CAN 连接失败,错误代码:{re}");
return false;
}
// 5. 注册接收监听(用于 DBC 信号解码广播)
_instanceListener = new TCANFDQueueEvent_Win32(OnCanFdReceived);
RegisterListener(_instanceListener);
_isOpened = true;
return true;
}
catch (Exception ex)
{
Debug.WriteLine($"打开设备异常:{ex.Message}");
return false;
}
}
/// <summary>
/// 关闭 CAN 卡设备:注销监听 → 断开连接。
/// </summary>
public void CAN卡设备()
{
if (!_isOpened && !ConnectFlag) return;
try
{
if (_instanceListener != null)
{
UnRegisterListener(_instanceListener);
_instanceListener = null;
}
DisConnect();
}
catch (Exception ex)
{
Debug.WriteLine($"关闭CAN卡设备异常:{ex.Message}");
}
finally
{
_isOpened = false;
}
}
/// <summary>
/// 初始化并启动指定通道(配置波特率,TSMaster 在 Connect 时已自动启动所有通道)。
/// </summary>
/// <param name="channel">通道号</param>
public void (uint channel)
{
if (channel >= MaxChannels) return;
try
{
float arbKbps = float.Parse(ABitBaud) / 1000f;
float dataKbps = float.Parse(DBitBaud) / 1000f;
TsMasterApi.tsapp_configure_baudrate_canfd(
(int)channel, arbKbps, dataKbps,
TLIBCANFDControllerType.lfdtISOCAN,
TLIBCANFDControllerMode.lfdmNormal,
EnableTerminalResistance);
}
catch (Exception ex)
{
Debug.WriteLine($"初始化通道 {channel} 异常:{ex.Message}");
}
}
/// <summary>
/// 加载通道 DBC 文件。
/// </summary>
/// <param name="channel">通道号</param>
/// <param name="filePath">DBC 文件路径</param>
/// <returns>true 表示加载成功</returns>
public bool DBC文件(uint channel, string filePath)
{
try
{
var re = LoadDBC(filePath, [(int)channel], out _);
return re == 0;
}
catch (Exception ex)
{
Debug.WriteLine($"加载通道 {channel} DBC 文件异常:{ex.Message}");
return false;
}
}
/// <summary>
/// CAN FD 接收回调:接收原始帧 → 查找 DBC → 解码信号 → 触发 OnDbcMessageDecoded 事件。
/// </summary>
private void OnCanFdReceived(ref int AObj, ref TLIBCANFD AData)
{
if (_disposed) return;
// 始终缓存最新报文,供界面轮询刷新
int identifier = AData.FIdentifier;
var canfdCopy = AData;
RealTimeMessages[identifier] = canfdCopy;
if (OnDbcMessageDecoded == null) return;
try
{
uint channel = AData.FIdxChn;
if (channel >= DBCParse.MsgDatabase.Count) return;
// 在 DBC 数据库中查找匹配的报文
var msgList = DBCParse.MsgDatabase[(int)channel];
var match = msgList.FirstOrDefault(m => m.msg_id == identifier);
if (match == null || match.signal_Name == null || match.signal_Name.Length == 0) return;
// 解码各信号值
var signals = new DBCSignal[match.signal_Name.Length];
for (int i = 0; i < match.signal_Name.Length; i++)
{
double value = 0;
TsMasterApi.tsdb_get_signal_value_canfd(ref canfdCopy, match.msg_name, match.signal_Name[i], ref value);
signals[i] = new DBCSignal
{
strName = Encoding.Default.GetBytes(match.signal_Name[i]),
nRawvalue = value,
nFactor = 1,
nOffset = 0
};
}
var decoded = new DBCMessage
{
nID = (uint)identifier,
nSignalCount = signals.Length,
vSignals = signals
};
OnDbcMessageDecoded?.Invoke(channel, decoded);
}
catch (Exception ex)
{
Debug.WriteLine($"DBC 信号解码异常:{ex.Message}");
}
}
#endregion
#region IDisposable
public void Dispose()
{
if (_disposed) return;
_disposed = true;
CAN卡设备();
GC.SuppressFinalize(this);
}
#endregion
/// <summary>
/// 初始化TSMasterCAN
/// 初始化CAN驱动
/// </summary>
/// <param name="ProjectName"></param>
/// <param name="filePath"></param>
@@ -298,7 +38,7 @@ namespace TSMasterCAN
}
/// <summary>
/// 释放TSMasterCAN
/// 释放CAN驱动
/// </summary>
[Browsable(false)]
public static void Release()
@@ -391,7 +131,7 @@ namespace TSMasterCAN
public static int LoadDBC(string filePath, int[] channel, out uint databaseID)
{
databaseID = 0;
if (!Path.Exists(filePath)) return -1;
var re = TsMasterApi.tsdb_load_can_db(Path.GetFullPath(filePath), string.Join(",", channel), ref databaseID);
foreach (var item in channel)
{
-36
View File
@@ -120,44 +120,8 @@ namespace TSMasterCAN
NODE_RX_CANFD_MESSAGE_INDEX = 110,
}
/// <summary>
/// DBC 解码后的信号信息(替代原 ZLG ZDBC.DBCSignal)。
/// </summary>
public struct DBCSignal
{
/// <summary>信号名称(原始字节,兼容 Encoding.Default 解码)</summary>
public byte[] strName;
/// <summary>原始值(TSMaster tsdb_get_signal_value_canfd 返回的物理值)</summary>
public double nRawvalue;
/// <summary>因子(TSMaster 返回物理值,因子固定为 1</summary>
public double nFactor;
/// <summary>偏移(TSMaster 返回物理值,偏移固定为 0</summary>
public double nOffset;
}
/// <summary>
/// DBC 解码后的报文信息(替代原 ZLG ZDBC.DBCMessage)。
/// 在 CAN 接收回调中对原始 TLIBCANFD 帧解码后构建此对象并触发 OnDbcMessageDecoded 事件。
/// </summary>
public class DBCMessage
{
/// <summary>报文 ID</summary>
public uint nID;
/// <summary>信号数量</summary>
public int nSignalCount;
/// <summary>信号数组</summary>
public DBCSignal[] vSignals;
}
public class DBCParse
{
private static DBCParse? _instance;
/// <summary>单例实例,供 CAN.DBCParser 属性使用(MsgDatabase 等成员为 static,实例仅用于属性访问兼容)。</summary>
public static DBCParse Instance => _instance ??= new DBCParse();
/// <summary>最大通道数(等于 MsgDatabase 的维度)</summary>
public int MaxChannels => MsgDatabase.Count;
public static List<List<_Msg_>> MsgDatabase { get; set; } =
[.. Enumerable.Range(0, 12).Select(_ => new List<_Msg_>())];
public static can_network can_Network;
@@ -16,6 +16,7 @@ using System.Xml;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
using Prism.Events;
using Prism.Commands;
namespace TestingModule.ViewModels
{
@@ -94,6 +95,44 @@ namespace TestingModule.ViewModels
public ICommand DeleteStepCommand { get;set; }
public ICommand TabSelectionChangedCommand { get;set; }
public ICommand SelectionChangedCommand { get;set; }
public ICommand OpenSubProgramCommand { get; set; }
public ICommand GoBackCommand { get; set; }
#endregion
#region
/// <summary>
/// 当前显示的程序(绑定到 DataGrid 的 ItemsSource 根)。
/// 委托到 ScopedContext.CurrentProgram,保证 ShellViewModel 也能通过 ScopedContext 访问。
/// </summary>
public ProgramVM CurrentProgram
{
get => _ScopedContext.CurrentProgram;
set
{
if (_ScopedContext.CurrentProgram != value)
{
_ScopedContext.CurrentProgram = value;
RaisePropertyChanged();
}
}
}
public string BreadcrumbPath
{
get => _ScopedContext.BreadcrumbPath;
set
{
if (_ScopedContext.BreadcrumbPath != value)
{
_ScopedContext.BreadcrumbPath = value;
RaisePropertyChanged();
}
}
}
public bool CanGoBack => _ScopedContext.CanGoBack;
#endregion
public StepsManagerViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider)
@@ -108,9 +147,31 @@ namespace TestingModule.ViewModels
DeleteStepCommand = new DelegateCommand(DeleteStep);
TabSelectionChangedCommand = new DelegateCommand<string>(TabSelectionChanged);
SelectionChangedCommand = new DelegateCommand<object>(SelectionChanged);
OpenSubProgramCommand = new DelegateCommand(OpenSubProgram);
GoBackCommand = new DelegateCommand(GoBack);
SubscribeStepCollections();
Program.PropertyChanged += Program_PropertyChanged;
Admin = _globalInfo.IsAdmin;
// 初始化 CurrentProgram 为根程序
_ScopedContext.CurrentProgram = Program;
_ScopedContext.BreadcrumbPath = "主程序";
// 订阅 ScopedContext 属性变化,外部(ShellViewModel)修改时转发通知给 UI
_ScopedContext.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(ScopedContext.CurrentProgram))
RaisePropertyChanged(nameof(CurrentProgram));
else if (e.PropertyName == nameof(ScopedContext.BreadcrumbPath))
RaisePropertyChanged(nameof(BreadcrumbPath));
else if (e.PropertyName == nameof(ScopedContext.CanGoBack))
RaisePropertyChanged(nameof(CanGoBack));
};
// 订阅子程序导航事件(运行时由 StepRunning 发布)
_eventAggregator.GetEvent<SubProgramNavigateEvent>()
.Subscribe(OnSubProgramNavigate, ThreadOption.UIThread, false,
payload => payload.Scope == _systemConfig.Title);
}
private void SelectionChanged(object parameter)
@@ -208,6 +269,72 @@ namespace TestingModule.ViewModels
}
#endregion
#region
/// <summary>
/// 编辑模式:右键打开子程序
/// </summary>
private void OpenSubProgram()
{
if (SelectedStep == null || SelectedStep.StepType != "子程序" || SelectedStep.SubProgram == null)
return;
// 压栈:保存当前程序
_ScopedContext.SubProgramNavigationStack.Push(CurrentProgram);
_ScopedContext.UpdateCanGoBack();
// 更新面包屑
var stepName = SelectedStep.Name ?? "子程序";
BreadcrumbPath = $"{BreadcrumbPath} > {stepName}";
// 切换到子程序
CurrentProgram = SelectedStep.SubProgram;
RaisePropertyChanged(nameof(CanGoBack));
}
/// <summary>
/// 返回上一级程序
/// </summary>
private void GoBack()
{
if (_ScopedContext.SubProgramNavigationStack.Count == 0)
return;
// 出栈:恢复上一级程序
var parentProgram = _ScopedContext.SubProgramNavigationStack.Pop();
_ScopedContext.UpdateCanGoBack();
CurrentProgram = parentProgram;
// 更新面包屑:去掉最后一段
var parts = BreadcrumbPath.Split(" > ");
if (parts.Length > 1)
BreadcrumbPath = string.Join(" > ", parts.Take(parts.Length - 1));
else
BreadcrumbPath = "主程序";
RaisePropertyChanged(nameof(CanGoBack));
}
/// <summary>
/// 运行时:处理 StepRunning 发布的子程序导航事件
/// </summary>
private void OnSubProgramNavigate(SubProgramNavigatePayload payload)
{
if (payload.Action == NavigateAction.Enter && payload.SubProgram != null)
{
_ScopedContext.SubProgramNavigationStack.Push(CurrentProgram);
_ScopedContext.UpdateCanGoBack();
CurrentProgram = payload.SubProgram;
var stepName = payload.StepName ?? "子程序";
BreadcrumbPath = $"{BreadcrumbPath} > {stepName}";
RaisePropertyChanged(nameof(CanGoBack));
}
else if (payload.Action == NavigateAction.Exit)
{
GoBack();
}
}
#endregion
#region
/// <summary>
@@ -304,9 +431,9 @@ namespace TestingModule.ViewModels
Program.PropertyChanged -= Program_PropertyChanged;
}
// 3. 【核心修复】必须显式退订 Prism 全局事件AlarmEvent
// 注意:因为订阅时使用的是匿名 Lambda,最安全稳妥的退订方式是把整个事件上的当前 VM 订阅者全部注销
// 3. 【核心修复】必须显式退订 Prism 全局事件
_eventAggregator?.GetEvent<AlarmEvent>()?.Unsubscribe(null);
_eventAggregator?.GetEvent<SubProgramNavigateEvent>()?.Unsubscribe(null);
// 4. 清空临时缓存集合与 UI 绑定列表,避免悬挂指针
tmpCopyList?.Clear();
+24 -11
View File
@@ -8,11 +8,26 @@
xmlns:behaviors="clr-namespace:UIShare.Behaviors;assembly=UIShare"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:prism="http://prismlibrary.com/"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<UserControl.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid>
<GroupBox Header="{Binding Title}">
<DockPanel>
<!-- 面包屑导航栏 -->
<Border DockPanel.Dock="Top" Background="#F0F0F0" Padding="6,3" Visibility="{Binding CanGoBack, Converter={StaticResource BooleanToVisibilityConverter}}">
<DockPanel>
<Button DockPanel.Dock="Right" Content="↩ 返回上一级"
Command="{Binding GoBackCommand}"
Style="{StaticResource MaterialDesignFlatButton}"
FontSize="12" Padding="8,2" Margin="8,0,0,0"/>
<TextBlock Text="{Binding BreadcrumbPath}" VerticalAlignment="Center" FontSize="12" Foreground="#555"/>
</DockPanel>
</Border>
<TabControl SelectedIndex="{Binding SelectedTabIndex, Mode=TwoWay}">
<i:Interaction.Behaviors>
<behaviors:TabControlSelectionChangedBehavior Command="{Binding TabSelectionChangedCommand}"
@@ -29,7 +44,7 @@
Background="Transparent"
CanUserAddRows="False"
CanUserSortColumns="False"
ItemsSource="{Binding Program.StepCollection}"
ItemsSource="{Binding CurrentProgram.StepCollection}"
SelectedItem="{Binding SelectedStep, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectionMode="Extended"
SelectionUnit="FullRow">
@@ -120,6 +135,9 @@
<MenuItem Header="删除"
Foreground="Red"
Command="{Binding DeleteStepCommand}" />
<Separator/>
<MenuItem Header="打开子程序"
Command="{Binding OpenSubProgramCommand}" />
</ContextMenu>
</DataGrid.ContextMenu>
@@ -135,7 +153,7 @@
Background="Transparent"
CanUserAddRows="False"
CanUserSortColumns="False"
ItemsSource="{Binding Program.ErrorStepCollection}"
ItemsSource="{Binding CurrentProgram.ErrorStepCollection}"
SelectedItem="{Binding SelectedStep, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectionMode="Extended"
SelectionUnit="FullRow">
@@ -226,21 +244,16 @@
<MenuItem Header="删除"
Foreground="Red"
Command="{Binding DeleteStepCommand}" />
<Separator/>
<MenuItem Header="打开子程序"
Command="{Binding OpenSubProgramCommand}" />
</ContextMenu>
</DataGrid.ContextMenu>
<!-- 键盘 删除键绑定 Delete 命令 -->
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewKeyDown">
<i:InvokeCommandAction Command="{Binding DeleteStepCommand}"
CommandParameter="{Binding SelectedStep}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>-->
</DataGrid>
</TabItem>
</TabControl>
</DockPanel>
</GroupBox>
</Grid>
@@ -0,0 +1,106 @@
using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TSMasterCAN;
using TSMaster;
namespace UIShare.GlobalVariable
{
public class CANMonitoringService
{
public bool IsStopped { get; set; } = false;
public bool IsInitialized { get; set; } = false;
public bool IsRegistered { get; set; } = false;
private SystemConfig _systemConfig { get; set; }
public CANMonitoringService(SystemConfig systemConfig)
{
_systemConfig = systemConfig;
CANSignalBroadcaster.RegisterService(this);
IsRegistered = true;
}
public int Init(CancellationToken ct = default)
{
int re = 0;
if (IsInitialized == false)
{
re = CAN.Init(_systemConfig.TSMasterName);
}
if (IsInitialized == false)
{
re = CAN.RegisterListener(MonitorEvent);
if (re == 0) IsInitialized = true;
}
return re;
}
public ConcurrentDictionary<string, TLIBCANFD> RealTimeMessages { get; set; } = new();
public ConcurrentDictionary<string, double> RealTimeSignals { get; set; } = new();
public void MonitorEvent(ref int AObj, ref TLIBCANFD AData)
{
if (IsStopped) return;
byte[] oldbytes = null;
//记录至实时报文数据库
var cpAData = AData;
cpAData.FData = ArrayPool<byte>.Shared.Rent(64);
Array.Copy(AData.FData, 0, cpAData.FData, 0, cpAData.FData.Length);
var MessageName = $"{AData.FIdxChn}/{AData.FIdentifier}";
if (RealTimeMessages.TryGetValue(MessageName, out var v))
{
oldbytes = v.FData;
}
RealTimeMessages[MessageName] = cpAData;
//记录至DBC数据库
var dbcfind = DBCParse.MsgDatabase[AData.FIdxChn].FirstOrDefault(s => s.msg_id == cpAData.FIdentifier);
if (dbcfind != null)
{
Array.Copy(cpAData.FData, 0, dbcfind.ACANFD.FData, 0, cpAData.FData.Length);
dbcfind.ACANFD.FTimeUS = cpAData.FTimeUS;
dbcfind.ACANFD.FIsFD = cpAData.FIsFD;
dbcfind.ACANFD.FIsBRS = cpAData.FIsBRS;
dbcfind.ACANFD.FIsESI = cpAData.FIsESI;
dbcfind.ACANFD.FIsError = cpAData.FIsError;
dbcfind.ACANFD.FIsRemote = cpAData.FIsRemote;
dbcfind.ACANFD.FIsExt = cpAData.FIsExt;
}
if (oldbytes is not null) ArrayPool<byte>.Shared.Return(oldbytes);
var id = AData.FIdentifier;
var ch = AData.FIdxChn;
var canSignalList = _systemConfig.ConfigurationList.Where(s => s.MessageID == id && s.Channel == ch).ToArray();
if (canSignalList.Length > 0)
{
var find = DBCParse.MsgDatabase[ch].First(s => s.msg_id == id);
foreach (var item in canSignalList)
{
double Signalre = double.NaN;
var re = CAN.GetSignalValue(ref cpAData, item.MessageName, item.SignalName, ref Signalre);
//Debug.Assert(re == 0);
var SinalName = $"{AData.FIdxChn}/{item.MessageName}/{item.SignalName}";
RealTimeSignals[SinalName] = Signalre;
}
}
}
/// <summary>
/// 停止监测:从广播器注销并清理实时数据。
/// </summary>
public void Stop()
{
IsStopped = true;
if (IsRegistered)
{
CANSignalBroadcaster.UnregisterService(this);
IsRegistered = false;
}
RealTimeSignals.Clear();
RealTimeMessages.Clear();
}
}
}
+137 -88
View File
@@ -1,131 +1,191 @@
using Model.Models;
using Prism.Events;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TSMasterCAN;
using System.Threading;
using System.Threading.Tasks;
using UIShare.PubEvent;
using UIShare.UIViewModel;
namespace UIShare.GlobalVariable
{
/// <summary>
/// CAN 信号广播器(全局单例):
/// 统一订阅 GlobalInfo.CanPool 中所有已实例化的 ZLGCANFD 设备,
/// 将 DBC 解码后的信号值广播给所有引用该 CAN 设备的作用域,
/// 并同步检查各作用域 ValueLimitList 的超限报警。
/// 不再订阅 CAN 实体实例的事件,改为从所有已注册的 <see cref="CANMonitoringService"/>
/// 的 RealTimeSignals 字典中轮询读取信号值,并通过 <see cref="HardwareDataReportedEvent"/> 广播。
/// </summary>
public class CANSignalBroadcaster : IDisposable
public class CANSignalBroadcaster
{
private readonly IEventAggregator _eventAggregator;
private readonly GlobalInfo _globalInfo;
private bool _disposed;
private readonly SystemConfig _systemConfig;
/// <summary>已订阅解码事件的 CANFD 实例 → 委托 映射</summary>
private readonly Dictionary<CAN, Action<uint, DBCMessage>> _handlers = new();
public CANSignalBroadcaster(GlobalInfo globalInfo, IEventAggregator eventAggregator)
/// <summary>全局已注册的 CANMonitoringService 实例列表(静态,跨作用域共享)</summary>
private static readonly ConcurrentDictionary<CANMonitoringService, byte> _registeredServices = new();
private CancellationTokenSource? _cts;
private Task? _broadcastTask;
/// <summary>广播轮询间隔(毫秒)</summary>
public int PollingIntervalMs { get; set; } = 100;
public CANSignalBroadcaster(SystemConfig systemConfig, IEventAggregator eventAggregator)
{
_globalInfo = globalInfo;
_systemConfig = systemConfig;
_eventAggregator = eventAggregator;
}
/// <summary>
/// 扫描 GlobalInfo.CanPool 中已创建的 CANFD 实例并订阅解码事件。
/// 幂等:已订阅的实例不会重复订阅。
/// </summary>
public void Discover()
#region CANMonitoringService
/// <summary>注册一个 CANMonitoringService,使其信号纳入广播</summary>
public static void RegisterService(CANMonitoringService service)
{
if (_disposed) return;
foreach (var kvp in _globalInfo.CanPool)
{
string fingerprint = kvp.Key;
var lazy = kvp.Value;
if (!lazy.IsValueCreated || lazy.Value == null) continue;
var canfd = lazy.Value;
if (_handlers.ContainsKey(canfd)) continue;
// 使用闭包捕获指纹,回调时即可区分不同 CAN 卡
Action<uint, DBCMessage> handler = (channel, msg) => OnDbcMessageDecoded(fingerprint, channel, msg);
canfd.OnDbcMessageDecoded += handler;
_handlers[canfd] = handler;
}
_registeredServices.TryAdd(service, 0);
}
/// <summary>
/// 启动广播器(目前 Discover 已完成订阅,此处保留以兼容 HardwareDataBroadcaster 的使用模式)。
/// </summary>
/// <summary>注销一个 CANMonitoringService</summary>
public static void UnregisterService(CANMonitoringService service)
{
_registeredServices.TryRemove(service, out _);
}
#endregion
#region /
/// <summary>启动广播(幂等:多次调用只启动一次)</summary>
public void Start()
{
Discover();
if (_broadcastTask != null && !_broadcastTask.IsCompleted) return;
_cts = new CancellationTokenSource();
_broadcastTask = Task.Run(() => BroadcastLoop(_cts.Token));
}
/// <summary>停止广播</summary>
public void Stop()
{
_cts?.Cancel();
_broadcastTask = null;
}
/// <summary>兼容旧接口:Discover 已无需执行任何操作</summary>
public void Discover() { }
#endregion
#region 广
/// <summary>
/// DBC 解码回调:提取所有信号,向引用该 CAN 设备的作用域广播,并检查报警。
/// 轮询所有已注册的 CANMonitoringService 的 RealTimeSignals
/// 结合 ConfigurationList 映射出 MessageID/Channel,广播 HardwareDataReportedEvent。
/// </summary>
private void OnDbcMessageDecoded(string canFingerprint, uint channel, DBCMessage msg)
private async Task BroadcastLoop(CancellationToken ct)
{
if (_disposed) return;
string signalFingerprint = BuildFingerprint(canFingerprint, channel);
var now = DateTime.Now;
// 获取引用该 CAN 设备的所有作用域
var scopes = GetScopesForFingerprint(canFingerprint);
if (scopes.Count == 0) return;
for (int i = 0; i < msg.nSignalCount; i++)
while (!ct.IsCancellationRequested)
{
var signal = msg.vSignals[i];
string signalName = Encoding.Default.GetString(signal.strName).TrimEnd('\0');
if (string.IsNullOrEmpty(signalName)) continue;
double physicalValue = signal.nRawvalue * signal.nFactor + signal.nOffset;
string methodName = BuildMethodName(msg.nID, signalName);
foreach (var scope in scopes)
try
{
// 预构建信号名 → 配置 的映射(避免内层循环重复查找)
var configMap = BuildConfigMap();
string scope = _systemConfig.Title;
foreach (var service in _registeredServices.Keys)
{
if (service.IsStopped) continue;
foreach (var kvp in service.RealTimeSignals)
{
if (ct.IsCancellationRequested) return;
// 信号 Key 格式: "{channel}/{MessageName}/{SignalName}"
if (!TryParseSignalKey(kvp.Key, out int channel, out string? messageName, out string? signalName))
continue;
// 从配置映射中查找对应的 MessageID
if (!configMap.TryGetValue($"{channel}/{messageName}/{signalName}", out var cfg))
continue;
string canFingerprint = $"CAN:{channel}";
string fingerprint = BuildFingerprint(canFingerprint, (uint)channel);
string methodName = BuildMethodName((uint)cfg.MessageID, signalName);
// 广播信号值
_eventAggregator.GetEvent<HardwareDataReportedEvent>().Publish(new HardwareReportArgs
{
Scope = scope,
HardwareFingerprint = signalFingerprint,
HardwareFingerprint = fingerprint,
MethodName = methodName,
Value = physicalValue,
Time = now
Value = kvp.Value,
Time = DateTime.Now
});
string MonitorStatus = ValueLimitAlarmHelper.CheckAlarm(scope, signalFingerprint, methodName, physicalValue, _globalInfo);
if (MonitorStatus != "" && MonitorStatus != "未报警")
// 报警检查
string alarmStatus = ValueLimitAlarmHelper.CheckAlarm(fingerprint, methodName, kvp.Value, _systemConfig);
if (!string.IsNullOrEmpty(alarmStatus) && alarmStatus != "未报警")
{
_eventAggregator.GetEvent<AlarmEvent>().Publish((scope,canFingerprint, MonitorStatus));
}
_eventAggregator.GetEvent<AlarmEvent>().Publish((scope, canFingerprint, alarmStatus));
}
}
}
/// <summary>获取指定硬件指纹当前被哪些作用域引用</summary>
private List<string> GetScopesForFingerprint(string fingerprint)
{
if (_globalInfo.DeviceAndScopeDic.TryGetValue(fingerprint, out var lazy))
{
var scopeList = lazy.Value;
lock (scopeList) return scopeList.ToList();
await Task.Delay(PollingIntervalMs, ct);
}
catch (OperationCanceledException) { break; }
catch (Exception ex)
{
Logger.LoggerHelper.Error($"CANSignalBroadcaster 广播异常: {ex.Message}");
await Task.Delay(1000, ct); // 异常后等待一段时间再重试
}
}
return new List<string>();
}
/// <summary>
/// 生成 CAN 信号的 DisplayName 格式:"{MessageName}.{SignalName}"
/// 从 SystemConfig.ConfigurationList 构建 "channel/MessageName/SignalName" → CANSignalConfig 的映射
/// </summary>
private Dictionary<string, CANSignalConfig> BuildConfigMap()
{
var map = new Dictionary<string, CANSignalConfig>(StringComparer.OrdinalIgnoreCase);
if (_systemConfig?.ConfigurationList == null) return map;
foreach (var cfg in _systemConfig.ConfigurationList)
{
if (string.IsNullOrEmpty(cfg.SignalName) || string.IsNullOrEmpty(cfg.MessageName)) continue;
string key = $"{cfg.Channel}/{cfg.MessageName}/{cfg.SignalName}";
map.TryAdd(key, cfg); // 第一个匹配的优先
}
return map;
}
/// <summary>解析信号 Key: "{channel}/{MessageName}/{SignalName}"</summary>
private static bool TryParseSignalKey(string key, out int channel, out string? messageName, out string? signalName)
{
channel = 0;
messageName = null;
signalName = null;
var parts = key.Split('/');
if (parts.Length < 3) return false;
if (!int.TryParse(parts[0], out channel)) return false;
messageName = parts[1];
signalName = parts[2];
return !string.IsNullOrEmpty(messageName) && !string.IsNullOrEmpty(signalName);
}
#endregion
#region
/// <summary>生成 CAN 信号的 DisplayName 格式:"{MessageName}.{SignalName}"</summary>
public static string BuildDisplayName(string messageName, string signalName)
{
return $"{messageName}.{signalName}";
}
/// <summary>
/// 生成 CAN 信号的 MethodName 格式:"{MessageId:X}.{SignalName}"
/// </summary>
/// <summary>生成 CAN 信号的 MethodName 格式:"{MessageId:X}.{SignalName}"</summary>
public static string BuildMethodName(uint messageId, string signalName)
{
return $"{messageId:X}.{signalName}";
@@ -140,17 +200,6 @@ namespace UIShare.GlobalVariable
return $"{canDeviceFingerprint}:{channel}";
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
foreach (var kvp in _handlers)
{
if (kvp.Key != null)
kvp.Key.OnDbcMessageDecoded -= kvp.Value;
}
_handlers.Clear();
}
#endregion
}
}
+20 -124
View File
@@ -13,7 +13,6 @@ using System.Reflection;
using TSMasterCAN;
using UIShare.PubEvent;
using UIShare.UIViewModel;
using TSMasterCAN;
namespace UIShare.GlobalVariable
{
@@ -25,6 +24,7 @@ namespace UIShare.GlobalVariable
{
private object _lockObj = new object();
public SystemConfig _systemConfig { get; set; }
public CANMonitoringService _CANMonitoringService { get; set; }
private readonly GlobalInfo _globalInfo;
private readonly string _scopeName;
private readonly IEventAggregator _eventAggregator;
@@ -35,7 +35,6 @@ namespace UIShare.GlobalVariable
/// <summary>类名 → Type 的反射缓存(仅扫描一次)。</summary>
private static readonly IReadOnlyDictionary<string, Type> _deviceTypeMap = BuildDeviceTypeMap();
public CAN CANFD { get; set; }
public IOBoardGroup IOGroup { get; set; }
public DeviceManager(SystemConfig systemConfig, GlobalInfo globalInfo, IEventAggregator eventAggregator)
@@ -43,11 +42,17 @@ namespace UIShare.GlobalVariable
_systemConfig = systemConfig;
_globalInfo = globalInfo;
_eventAggregator = eventAggregator;
_CANMonitoringService=new CANMonitoringService(_systemConfig);
// 用 SystemConfig.Title 作为作用域唯一标识,无需反查 ConfigDic
_scopeName = _systemConfig.Title;
InitDevices();
InitCAN();
}
public void InitCAN()
{
var re1 = _CANMonitoringService.Init();
}
/// <summary>
/// 根据设备配置提取唯一的硬件指纹字符串。
/// <para>Tcp → "Tcp:IP:Port"Serial → "Serial:PortName";无法识别则返回空字符串。</para>
@@ -98,55 +103,6 @@ namespace UIShare.GlobalVariable
{
if (config == null || !config.IsEnabled) continue;
// CAN 设备:ZLGCANFD 不实现 IBaseInterface,通过 SystemConfig.CANFD 单独管理,
// 按指纹从全局 CanPool 创建/复用实例,并注册作用域引用计数。
if (string.Equals(config.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase))
{
var fingerprint = ExtractHardwareFingerprint(config);
if (string.IsNullOrEmpty(fingerprint))
{
LoggerHelper.Warn($"设备 [{config.DeviceName}] 无法提取硬件指纹(连接方式={config.ConnectionType}),已跳过。");
continue;
}
if (config.CANConfig == null)
{
LoggerHelper.Warn($"设备 [{config.DeviceName}] 缺少 CAN 连接参数,已跳过。");
continue;
}
try
{
// 按指纹全局唯一创建同星 CAN 实例(maxChannels 默认 4,对应 USBCANFD-400U
// 波特率与终端电阻从 CANConfigVM 传入,初始化并启动通道 时直接使用
var canLazy = _globalInfo.CanPool.GetOrAdd(fingerprint, key => new Lazy<CAN>(() =>
new CAN(config.CANConfig.DeviceType, config.CANConfig.DeviceIndex, 4,
config.CANConfig.ABitBaud, config.CANConfig.DBitBaud, config.CANConfig.EnableTerminalResistance)));
_systemConfig.CANFD = canLazy.Value;
CANFD = canLazy.Value;
// 注册作用域引用计数
if (!string.IsNullOrEmpty(_scopeName))
{
var scopeList = _globalInfo.DeviceAndScopeDic.GetOrAdd(fingerprint,
_ => new Lazy<List<string>>(() => new List<string>())).Value;
lock (scopeList)
{
if (!scopeList.Contains(_scopeName))
scopeList.Add(_scopeName);
}
}
LoggerHelper.Info($"已加载 CAN 设备 [{config.DeviceName}] 指纹={fingerprint}(通过 SystemConfig.CANFD 管理)");
}
catch (Exception ex)
{
LoggerHelper.ErrorWithNotify(_scopeName, $"CAN 设备 [{config.DeviceName}] 实例化失败:{ex.Message}");
}
continue;
}
if (string.IsNullOrWhiteSpace(config.DeviceType) ||
!_deviceTypeMap.TryGetValue(config.DeviceType, out var deviceType))
{
@@ -302,7 +258,7 @@ namespace UIShare.GlobalVariable
// CAN 设备:直接关闭 CAN 卡
if (info != null && string.Equals(info.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase))
{
await CloseCanAsync(info);
CloseCan();
return;
}
@@ -325,7 +281,7 @@ namespace UIShare.GlobalVariable
lock (_lockObj)
{
if (DeviceMap.Count == 0 && (CANFD == null)) return;
if (DeviceMap.Count == 0 ) return;
foreach (var kvp in DeviceMap)
{
@@ -338,17 +294,7 @@ namespace UIShare.GlobalVariable
}
}
// CAN 设备:直接关闭 CAN 卡
if (CANFD != null)
{
var canInfo = _systemConfig?.DeviceList?
.FirstOrDefault(d => d != null && string.Equals(d.ConnectionType, "CAN", StringComparison.OrdinalIgnoreCase));
if (canInfo != null)
{
tasks.Add(CloseCanAsync(canInfo));
}
}
CAN.DisConnect();
await Task.WhenAll(tasks);
LoggerHelper.Info("所有设备已执行关闭操作。");
}
@@ -456,26 +402,11 @@ namespace UIShare.GlobalVariable
/// </summary>
private async Task<bool> ConnectCanAsync(DeviceInfoVM info)
{
string name = info.DeviceName ?? "CAN";
try
{
if (CANFD == null)
{
LoggerHelper.Warn($"CAN 设备 [{name}] 尚未实例化,无法连接。");
info.IsConnected = false;
return false;
}
if (info.IsConnected)
{
LoggerHelper.Info($"CAN 设备 [{name}] 已连接,跳过。");
return true;
}
bool ok = await Task.Run(() =>
{
if (!CANFD.()) return false;
// 自动加载 DBC 文件
if (_systemConfig?.DBCAutoLoadList != null)
{
@@ -495,8 +426,7 @@ namespace UIShare.GlobalVariable
LoggerHelper.Warn($"CAN 通道 {item.DBCChannel} 自动加载 DBC 失败:文件不存在 [{item.DBCFilePath}]");
continue;
}
CANFD.((uint)item.DBCChannel);
bool loadOk = CANFD.DBC文件((uint)item.DBCChannel, item.DBCFilePath);
bool loadOk = CAN.LoadDBC(item.DBCFilePath,new int[] { item.DBCChannel },out _ )==0;
if (loadOk)
{
LoggerHelper.Info($"CAN 通道 {item.DBCChannel} 已自动加载 DBC{item.DBCFilePath}");
@@ -518,16 +448,16 @@ namespace UIShare.GlobalVariable
}
}
}
if (CAN.Connect() != 0) return false;
return true;
});
info.IsConnected = ok;
if (ok)
LoggerHelper.Info($"CAN 设备 [{name}] 连接成功,已初始化 {CANFD.DBCParser.MaxChannels} 个通道。");
LoggerHelper.Info($"CAN 设备 连接成功");
else
LoggerHelper.Warn($"CAN 设备 [{name}] 连接失败。");
LoggerHelper.Warn($"CAN 设备连接失败。");
return ok;
}
@@ -535,7 +465,7 @@ namespace UIShare.GlobalVariable
{
info.IsConnected = false;
var inner = ex.InnerException?.Message ?? ex.Message;
LoggerHelper.ErrorWithNotify(_scopeName, $"CAN 设备 [{name}] 连接异常:{inner}");
LoggerHelper.ErrorWithNotify(_scopeName, $"CAN 设备 连接异常:{inner}");
return false;
}
}
@@ -543,36 +473,9 @@ namespace UIShare.GlobalVariable
/// <summary>
/// 关闭 CAN 卡
/// </summary>
private async Task CloseCanAsync(DeviceInfoVM info)
private void CloseCan()
{
string name = info.DeviceName ?? "CAN";
try
{
if (CANFD == null)
{
info.IsConnected = false;
return;
}
if (!info.IsConnected)
{
LoggerHelper.Info($"CAN 设备 [{name}] 本就处于断开状态。");
return;
}
await Task.Run(() => CANFD.CAN卡设备());
LoggerHelper.Info($"CAN 设备 [{name}] 已成功关闭连接。");
}
catch (Exception ex)
{
var inner = ex.InnerException?.Message ?? ex.Message;
LoggerHelper.Error($"CAN 设备 [{name}] 关闭连接时出现异常: {inner}");
}
finally
{
info.IsConnected = false;
}
CAN.DisConnect();
}
private static IReadOnlyDictionary<string, Type> BuildDeviceTypeMap()
@@ -620,6 +523,9 @@ namespace UIShare.GlobalVariable
public void Dispose()
{
// 停止 CAN 信号监测服务
_CANMonitoringService?.Stop();
if (string.IsNullOrEmpty(_scopeName)) return;
// 遍历当前作用域用到的所有指纹,逐一移除本作用域的引用
@@ -655,16 +561,6 @@ namespace UIShare.GlobalVariable
}
}
// 尝试从 CanPool 取出并销毁
if (_globalInfo.CanPool.TryRemove(fingerprint, out var canLazy))
{
if (canLazy.IsValueCreated)
{
try { canLazy.Value.Dispose(); }
catch { /* 销毁时忽略异常 */ }
LoggerHelper.Info($"指纹 [{fingerprint}] 无作用域引用,已销毁 CAN 设备实例。");
}
}
// 同步清除 DeviceAndScopeDic 中的空条目
_globalInfo.DeviceAndScopeDic.TryRemove(fingerprint, out _);
+65 -1
View File
@@ -1,5 +1,6 @@
using DeviceCommand.Base;
using MaterialDesignThemes.Wpf;
using Prism.Mvvm;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -14,9 +15,72 @@ using UIShare.UIViewModel;
namespace UIShare.GlobalVariable
{
public class ScopedContext
public class ScopedContext : BindableBase
{
private static readonly Random _randomSeed = new Random();
#region
/// <summary>
/// 子程序导航栈:记录从根程序进入子程序的路径。
/// 每个台架(ScopedContext 实例)各自维护一个独立的栈,互不干扰。
/// </summary>
public Stack<ProgramVM> SubProgramNavigationStack { get; } = new();
private ProgramVM _currentProgram;
/// <summary>
/// 当前在 StepManager 中显示的程序(可能是根程序,也可能是某层子程序)。
/// UI 的 DataGrid 绑定此属性,而非直接绑定 Program。
/// </summary>
public ProgramVM CurrentProgram
{
get => _currentProgram;
set => SetProperty(ref _currentProgram, value);
}
private string _breadcrumbPath = "主程序";
/// <summary>
/// 面包屑导航路径,如 "主程序 > 连接流程 > 初始化"
/// </summary>
public string BreadcrumbPath
{
get => _breadcrumbPath;
set => SetProperty(ref _breadcrumbPath, value);
}
private bool _canGoBack;
/// <summary>
/// 是否可以返回上一级(导航栈不为空时为 true)
/// </summary>
public bool CanGoBack
{
get => _canGoBack;
set => SetProperty(ref _canGoBack, value);
}
/// <summary>
/// 清空导航栈,回到根程序界面
/// </summary>
public void ResetNavigation()
{
SubProgramNavigationStack.Clear();
CurrentProgram = Program;
BreadcrumbPath = "主程序";
CanGoBack = false;
}
/// <summary>
/// 根据栈状态刷新 CanGoBack
/// </summary>
public void UpdateCanGoBack() => CanGoBack = SubProgramNavigationStack.Count > 0;
/// <summary>
/// 当前导航深度(0 = 根程序,1 = 第一层子程序,以此类推)
/// </summary>
public int NavigationDepth => SubProgramNavigationStack.Count;
#endregion
public ProgramVM Program { get; set; } = new();
public String SelectedStepList { get; set; } = "主程序";
public string CurrentFilePath { get; set; }
+37 -5
View File
@@ -2,6 +2,7 @@
using UIShare.PubEvent;
using Common.Tools;
using Logger;
using MaterialDesignThemes.Wpf;
using Model.Entity;
using Service.Interface;
@@ -181,7 +182,21 @@ namespace UIShare
_scopedContext.SingleStep = false;
}
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
// 发布进入子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Enter,
SubProgram = step.SubProgram,
StepName = step.Name
});
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
// 发布退出子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Exit
});
UpdateCurrentStepResult(step, true, stepSuccess, depth);
if (SubSingleStep)
{
@@ -239,6 +254,7 @@ namespace UIShare
tmpParameters.Clear();
TestRoundID = Guid.NewGuid();
}
int initialLoopStackCount = loopStack.Count;
foreach (var item in program.Parameters)
{
tmpParameters.TryAdd(item.ID, item);
@@ -356,7 +372,21 @@ namespace UIShare
_scopedContext.SingleStep = false;
}
LoggerHelper.InfoWithNotify(_systemConfig.Title, $"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
// 发布进入子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Enter,
SubProgram = step.SubProgram,
StepName = step.Name
});
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
// 发布退出子程序导航事件
_eventAggregator.GetEvent<SubProgramNavigateEvent>().Publish(new SubProgramNavigatePayload
{
Scope = _systemConfig.Title,
Action = NavigateAction.Exit
});
UpdateCurrentStepResult(step, true, stepSuccess, depth);
if (SubSingleStep)
{
@@ -403,9 +433,15 @@ namespace UIShare
_eventAggregator.GetEvent<RunSingalCompletedEvent>().Publish("Play");
}
await SaveStepRecordAsync(step, depth, false);
// 仅检查本层执行期间压入的循环是否全部弹出,不关心父程序遗留的循环上下文
}
}
bool finalResult = loopStack.Count == initialLoopStackCount && stepSuccess;
if (depth > 0) // 子程序
{
return finalResult;
}
return loopStack.Count == 0 && stepSuccess;
}
@@ -578,11 +614,7 @@ namespace UIShare
{
try
{
if(targetType.Name== "ZLGCANFD")
{
instance = _deviceManager.CANFD;
}
else if (targetType.Name == "IOBoardGroup")
if (targetType.Name == "IOBoardGroup")
{
instance = _deviceManager.IOGroup;
}
@@ -20,11 +20,21 @@ namespace UIShare.GlobalVariable
{
if (globalInfo?.ConfigDic == null) return "";
if (!globalInfo.ConfigDic.TryGetValue(scope, out var systemConfig)) return "";
if (systemConfig.ValueLimitList == null) return "";
return CheckAlarm(fingerprint, methodName, value, systemConfig);
}
/// <summary>
/// 直接根据 SystemConfig 的 ValueLimitList 检查当前值是否超限。
/// 适用于不持有 GlobalInfo 引用的场景(如 CANSignalBroadcaster)。
/// </summary>
public static string CheckAlarm(string fingerprint, string methodName, double value, SystemConfig systemConfig)
{
if (systemConfig?.ValueLimitList == null) return "";
var limit = systemConfig.ValueLimitList.FirstOrDefault(x =>
x.Fingerprint == fingerprint && x.MethodName == methodName);
if (limit == null) return "";
if (value > limit.UpperExtreme)
{
limit.IsAlarm = true;
@@ -0,0 +1,34 @@
using Prism.Events;
using UIShare.UIViewModel;
namespace UIShare.PubEvent
{
/// <summary>
/// 子程序导航事件:运行时进入/退出子程序时发布,
/// StepsManagerViewModel 订阅后自动切换显示。
/// </summary>
public class SubProgramNavigateEvent : PubSubEvent<SubProgramNavigatePayload>
{
}
public class SubProgramNavigatePayload
{
/// <summary>目标台架的作用域标识</summary>
public string Scope { get; set; } = "";
/// <summary>Enter = 进入子程序,Exit = 退出回到上一级</summary>
public NavigateAction Action { get; set; }
/// <summary>进入时:子程序的 ProgramVM;退出时可为 null</summary>
public ProgramVM? SubProgram { get; set; }
/// <summary>子程序步骤的名称(用于面包屑显示)</summary>
public string? StepName { get; set; }
}
public enum NavigateAction
{
Enter,
Exit
}
}
+6 -1
View File
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
@@ -26,4 +26,9 @@
<ProjectReference Include="..\Service\Service.csproj" />
<ProjectReference Include="..\TSMasterCAN\TSMasterCAN.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Interop.TSMasterAPI">
<HintPath>..\TSMasterCAN\Interop.TSMasterAPI.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
+443
View File
@@ -0,0 +1,443 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
将极电子程序 .ats 文件转换为 ACP 项目 .ACP 文件
- 设备 FullName 映射
- 方法名映射
- 参数格式转换.ats .ACP
- IOBoardGroup 只保留台架序号参数
"""
import json
import glob
import os
import uuid
import copy
# ============================================================
# 1. 设备 FullName 映射
# ============================================================
DEVICE_MAPPING = {
# 相同设备(无需改 FullName)
"TSMasterCAN.CAN": "TSMasterCAN.CAN",
"Command.Delay": "Command.Delay",
"Command.CommandMath": "Command.CommandMath",
"DeviceCommand.Device.PW8001": "DeviceCommand.Device.PW8001",
# 需要映射的设备
"DeviceCommand.Device.IOBoardCard": "DeviceCommand.Device.IOBoardGroup",
"DeviceCommand.Device.IT6724C": "DeviceCommand.Devices.IT6720",
"DeviceCommand.Device.SQ0090G1D1": "DeviceCommand.Devices.Chroma61800", # 三相交流源 → Chroma61800
"DeviceCommand.Device.PSB11500_60": "DeviceCommand.Devices.S7200", # 交流源/负载 → S7200 直流源载一体机
"DeviceCommand.Device.MSO44B": "DeviceCommand.Devices.TektronixMSO",
"DeviceCommand.Device.EA3040_40C": "DeviceCommand.Devices.ANEVH80", # 水冷机/负载 → ANEVH80
"DeviceCommand.Device.Chroma_63206A": "DeviceCommand.Devices.ANEVH80", # 电子负载 → ANEVH80
# 暂无对应设备,保持原 FullName(方法名使用占位符)
"DeviceCommand.Device.WS_68070": "DeviceCommand.Device.WS_68070",
"DeviceCommand.Device.AFV33030": "DeviceCommand.Device.AFV33030",
"DeviceCommand.Device.DAQ970A": "DeviceCommand.Device.DAQ970A",
"DeviceCommand.Device.XcpDevice": "DeviceCommand.Device.XcpDevice",
"ATS.Commands.CurveMonitorCommands": "ATS.Commands.CurveMonitorCommands",
}
# ============================================================
# 2. 方法名映射 {(旧FullName): {旧方法名: 新方法名}}
# ============================================================
# --- IOBoardCard → IOBoardGroup ---
IOBOARD_METHOD_MAP = {
"WriteMultiIO": "批量写输出开关",
"WriteSingleIO": "写输出开关",
}
# --- IT6724C → IT6720 ---
IT6720_METHOD_MAP = {
"RemoteMode": "切换远程控制模式",
"DCOutput_OFF": "设置输出开关", # 参数值 false
"OFF": "设置输出开关", # 参数值 false
"ON": "设置输出开关", # 参数值 true
"SetVoltage": "设置输出电压",
"SetCurrent": "设置输出电流",
}
# --- PSB11500_60 → S7200 (直流源载一体机) ---
S7200_METHOD_MAP = {
"Set_RemoteMode": "设置为远程模式",
"Set_SourceMode_SetVoltage": "设置电压",
"Set_SourceMode_SetCurrent": "设置CC模式电流",
"Set_SourceMode_SetPower": "设置正向功率阈值",
"Set_SinkMode_SetVoltage": "设置电压",
"Set_SinkMode_SetCurrent": "设置CC模式电流",
"Set_SinkMode_SetPower": "设置反向功率阈值",
"Set_DC_Input": "设置电压",
"Set_DC_Output": "设置电压",
"LoadOn": "设置通道开关", # 开启负载
"LoadOff": "设置通道开关", # 关闭负载
"Get_ActualVoltage": "查询实时电压",
"Get_ActualCurrent": "查询实时电流",
"Get_ActualPower": "查询功率",
"MeasureVoltage": "查询实时电压",
"MeasureCurrent": "查询实时电流",
"MeasurePower": "查询功率",
}
# --- SQ0090G1D1 → Chroma61800 (交流源) ---
CHROMA61800_METHOD_MAP = {
"RemoteMode": "设置输出开关Async", # true=远程
"ON": "设置输出开关Async", # true=开启
"OFF": "设置输出开关Async", # false=关闭
"SetVoltage": "设置交流电压Async",
"SetFrequency": "设置频率Async",
"SetOutputMode": "设置单三相模式Async",
"SetPhaseAngle": "设置开机角度Async",
"SetIndividualVoltage": "设置交流电压Async",
"MeasureVoltage": "读取交流电压Async",
"MeasureCurrent": "读取交流电流Async",
}
# --- EA3040_40C → ANEVH80 ---
ANEVH80_METHOD_MAP = {
"Set_RemoteMode": "占位符",
"Set_Voltage": "占位符",
"Set_Current": "占位符",
"DCOutput_ON": "占位符",
"DCOutput_OFF": "占位符",
}
# --- Chroma_63206A → ANEVH80 ---
CHROMA63206A_METHOD_MAP = {
"SetModeCC": "占位符",
"SetModeCV": "占位符",
"SetModeCR": "占位符",
"ON": "占位符",
"OFF": "占位符",
"SetVoltageL1": "占位符",
"SetVoltageL2": "占位符",
"SetCurrentL1": "占位符",
"SetCurrentL2": "占位符",
"SetResistanceL1": "占位符",
"SetResistanceL2": "占位符",
"SetCurrentSlewRatePositive": "占位符",
"SetCurrentSlewRateNegative": "占位符",
"MeasureVoltage": "占位符",
"MeasureCurrent": "占位符",
"MeasurePower": "占位符",
}
# --- MSO44B → TektronixMSO ---
TEKTRONIX_METHOD_MAP = {
"Acquire_Run": "设置采集状态",
"Acquire_Stop": "设置采集状态",
"ClearStatus": "清除状态",
"Reset": "清除状态",
"Set_AcquireMode": "设置采集模式",
"Set_ChannelState": "设置通道显示开关",
"Set_ChannelScale": "设置通道垂直刻度",
"Set_ChannelUnit": "设置通道垂直刻度",
"Set_ChannelCoupling": "设置通道垂直刻度",
"Set_ChannelProbe": "设置通道垂直刻度",
"Set_ChannelBandwidth": "设置通道垂直刻度",
"Set_HorizontalScale": "设置水平刻度",
"Set_RecordLength": "设置记录长度",
"Set_StopAfter": "设置采集状态",
"Set_TriggerMode": "设置采集模式",
"Set_TriggerType_Edge": "设置采集模式",
"Set_TriggerEdgeSource": "设置测量源",
"Set_TriggerEdgeSlope": "设置测量类型",
"Set_TriggerLevel": "设置通道垂直位置",
"Set_WaveformSource": "设置测量源",
"Setup_Measurement": "开启测量项",
"Get_MeasurementValue": "查询测量项当前值",
"Save_Screenshot": "保存屏幕截图",
"Save_Waveform": "保存屏幕截图",
}
# --- PW8001 → PW8001 (同设备,方法名需适配) ---
PW8001_METHOD_MAP = {
"Set_TestMode_WIDE": "设置测试模式_WIDE",
"Set_TestMode_IEC": "设置测试模式_IEC",
"QueryVoltageWithRatio": "查询电压_含变比",
"QueryCurrentWithRatio": "查询电流_含变比",
"QueryPowerWithoutRatio": "查询功率_不含变比",
"QueryTotalPowerP123": "查询总功率P123",
"QueryVoltageTHD": "查询电压THD",
"QueryCurrentTHD": "查询电流THD",
}
# --- WS_68070 (占位符) ---
WS68070_METHOD_MAP = {
"Get_ThreePhase_Frequency": "占位符_GetFrequency",
"Get_ThreePhase_MaxCurrent": "占位符_GetMaxCurrent",
"Get_ThreePhase_MaxVoltage": "占位符_GetMaxVoltage",
"Get_ThreePhase_SumActivePower": "占位符_GetSumActivePower",
"Set_ATE_Load_A_Current": "占位符_SetLoadCurrent",
"Set_ATE_Load_CurrentMode": "占位符_SetLoadMode",
"Set_ATE_Load_Load": "占位符_SetLoad",
"Set_ATE_Load_PowerMode": "占位符_SetPowerMode",
"Set_ATE_Load_Uninstall": "占位符_SetUninstall",
"Set_ThreePhase_SumActivePower": "占位符_SetSumActivePower",
}
# --- AFV33030 (占位符) ---
AFV33030_METHOD_MAP = {
"Set_General_OutputVoltage": "占位符_SetOutputVoltage",
"Set_ThreePhase_OutputVoltage": "占位符_SetThreePhaseVoltage",
}
# --- DAQ970A (占位符) ---
DAQ970A_METHOD_MAP = {
"Set_DCDefaultCurrent": "占位符_SetCurrent",
"Set_DCDefaultVoltage": "占位符_SetVoltage",
}
# --- XcpDevice (占位符) ---
XCP_METHOD_MAP = {
"Connect": "占位符_Connect",
"Disconnect": "占位符_Disconnect",
"ReadMemory": "占位符_ReadMemory",
"WriteMemory": "占位符_WriteMemory",
}
# --- CurveMonitorCommands (占位符) ---
CURVE_MONITOR_METHOD_MAP = {
"CAN曲线记录_启动": "占位符_StartCANRecord",
"CAN曲线记录_停止": "占位符_StopCANRecord",
"设备参数记录_启动": "占位符_StartDeviceRecord",
"设备参数记录_停止": "占位符_StopDeviceRecord",
}
# 汇总所有方法映射
METHOD_MAPPING = {
"DeviceCommand.Device.IOBoardCard": IOBOARD_METHOD_MAP,
"DeviceCommand.Device.IT6724C": IT6720_METHOD_MAP,
"DeviceCommand.Device.PSB11500_60": S7200_METHOD_MAP,
"DeviceCommand.Device.SQ0090G1D1": CHROMA61800_METHOD_MAP,
"DeviceCommand.Device.EA3040_40C": ANEVH80_METHOD_MAP,
"DeviceCommand.Device.Chroma_63206A": CHROMA63206A_METHOD_MAP,
"DeviceCommand.Device.MSO44B": TEKTRONIX_METHOD_MAP,
"DeviceCommand.Device.PW8001": PW8001_METHOD_MAP,
"DeviceCommand.Device.WS_68070": WS68070_METHOD_MAP,
"DeviceCommand.Device.AFV33030": AFV33030_METHOD_MAP,
"DeviceCommand.Device.DAQ970A": DAQ970A_METHOD_MAP,
"DeviceCommand.Device.XcpDevice": XCP_METHOD_MAP,
"ATS.Commands.CurveMonitorCommands": CURVE_MONITOR_METHOD_MAP,
}
# ============================================================
# 3. 格式转换函数
# ============================================================
def convert_param_ats_to_acp(param):
"""将 .ats 参数格式转换为 .ACP 参数格式"""
new_param = {}
new_param["ID"] = param.get("ID", str(uuid.uuid4()))
new_param["IsVisible"] = param.get("IsVisible", True)
new_param["IsEditable"] = True # .ACP 新增字段
new_param["Name"] = param.get("Name", "")
new_param["Type"] = param.get("Type", "")
new_param["Category"] = param.get("Category", 0)
new_param["Value"] = param.get("Value", None)
new_param["LowerLimit"] = param.get("LowerLimit", None)
new_param["UpperLimit"] = param.get("UpperLimit", None)
new_param["Result"] = param.get("Result", True)
new_param["IsUseVar"] = param.get("IsUseVar", False)
new_param["VariableName"] = param.get("VariableName", None)
new_param["VariableID"] = param.get("VariableID", None)
# 不包含: IsGlobal, InitialValue, IsSave, IsOutputToReport
return new_param
def convert_ioboard_params(params, old_method_name):
"""IOBoardGroup 参数处理:
根据 IOBoardGroup 的方法签名重新生成参数
写输出开关(台架序号, 站号, 开始地址, data)
批量写输出开关(台架序号, 站号, 开始地址, datas)
只保留台架序号参数使用公共变量其他参数先不写
"""
int_type = "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
byte_type = "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ushort_type = "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
bool_type = "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
bool_arr_type = "System.Boolean[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
ct_type = "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e"
# 台架序号参数(使用公共变量,Value=nullIsUseVar=true
station_param = {
"ID": str(uuid.uuid4()),
"IsVisible": True,
"IsEditable": True,
"Name": "台架序号",
"Type": int_type,
"Category": 0,
"Value": None,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": True,
"VariableName": "台架序号",
"VariableID": None
}
new_params = [station_param]
# 根据方法类型添加对应的参数(值设为 null,用户后续填写)
if "批量" in old_method_name or "Multi" in old_method_name:
# 批量写输出开关: 台架序号, 站号, 开始地址, datas
new_params.append(make_param("站号", byte_type, None))
new_params.append(make_param("开始地址", ushort_type, None))
new_params.append(make_param("datas", bool_arr_type, None))
else:
# 写输出开关: 台架序号, 站号, 开始地址, data
new_params.append(make_param("站号", byte_type, None))
new_params.append(make_param("开始地址", ushort_type, None))
new_params.append(make_param("data", bool_type, None))
return new_params
def make_param(name, type_str, value):
"""创建一个 ACP 格式的参数"""
return {
"ID": str(uuid.uuid4()),
"IsVisible": True,
"IsEditable": True,
"Name": name,
"Type": type_str,
"Category": 0,
"Value": value,
"LowerLimit": None,
"UpperLimit": None,
"Result": True,
"IsUseVar": False,
"VariableName": None,
"VariableID": None
}
def convert_method(method, old_full_name):
"""转换 Method 对象"""
if not method:
return None
new_method = {}
old_name = method.get("Name", "")
# 映射 FullName
new_full_name = DEVICE_MAPPING.get(old_full_name, old_full_name)
new_method["Name"] = old_name
new_method["FullName"] = new_full_name
# 映射方法名
method_map = METHOD_MAPPING.get(old_full_name, {})
if old_name in method_map:
new_method["Name"] = method_map[old_name]
# 转换参数(不包含 DeviceID)
old_params = method.get("Parameters", [])
if old_full_name == "DeviceCommand.Device.IOBoardCard":
new_method["Parameters"] = convert_ioboard_params(old_params, old_name)
else:
new_method["Parameters"] = [convert_param_ats_to_acp(p) for p in old_params]
return new_method
def convert_step(step):
"""转换单个 Step"""
new_step = {}
new_step["ID"] = step.get("ID", str(uuid.uuid4()))
new_step["IsUsed"] = step.get("IsUsed", True)
new_step["Index"] = step.get("Index", 0)
new_step["Name"] = step.get("Name", "")
new_step["StepType"] = step.get("StepType", "方法")
# 转换 Method
old_method = step.get("Method")
if old_method:
old_full_name = old_method.get("FullName", "")
new_step["Method"] = convert_method(old_method, old_full_name)
else:
new_step["Method"] = None
# 转换 SubProgram(嵌套的子程序)
sub_program = step.get("SubProgram")
if sub_program and isinstance(sub_program, dict):
new_step["SubProgram"] = convert_program(sub_program)
else:
new_step["SubProgram"] = None
# 循环相关
new_step["LoopCount"] = step.get("LoopCount", None)
new_step["LoopStartStepId"] = step.get("LoopStartStepId", None)
# 跳转相关
new_step["OKExpression"] = step.get("OKExpression", None)
new_step["GotoSettingString"] = step.get("GotoSettingString", "")
new_step["OKGotoStepID"] = step.get("OKGotoStepID", None)
new_step["NGGotoStepID"] = step.get("NGGotoStepID", None)
new_step["Description"] = step.get("Description", None)
return new_step
def convert_program(program):
"""转换整个 ProgramVM 结构"""
new_program = {}
new_program["ID"] = program.get("ID", str(uuid.uuid4()))
# 转换 StepCollection
old_steps = program.get("StepCollection", [])
new_program["StepCollection"] = [convert_step(s) for s in old_steps]
# ErrorStepCollection
new_program["ErrorStepCollection"] = []
# 转换 Parameters(顶层参数)
old_params = program.get("Parameters", [])
new_program["Parameters"] = [convert_param_ats_to_acp(p) for p in old_params]
return new_program
def convert_file(input_path, output_path):
"""转换单个文件"""
with open(input_path, encoding='utf-8-sig') as f:
data = json.load(f)
result = convert_program(data)
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(result, f, ensure_ascii=False, indent=2)
# ============================================================
# 4. 主程序
# ============================================================
if __name__ == "__main__":
input_dir = r"C:\Users\kk\Desktop\ACP\极电子程序"
output_dir = r"D:\ACP\测试项\ACP输出"
os.makedirs(output_dir, exist_ok=True)
files = glob.glob(os.path.join(input_dir, "*.ats"))
print(f"找到 {len(files)} 个 .ats 文件")
success = 0
failed = 0
for f in files:
basename = os.path.splitext(os.path.basename(f))[0]
output_path = os.path.join(output_dir, f"{basename}.ACP")
try:
convert_file(f, output_path)
print(f"{basename}.ats → {basename}.ACP")
success += 1
except Exception as e:
print(f"{basename}.ats 失败: {e}")
failed += 1
print(f"\n转换完成: 成功 {success}, 失败 {failed}")
print(f"输出目录: {output_dir}")
+40
View File
@@ -0,0 +1,40 @@
import re, glob, json
files = glob.glob(r'C:\Users\kk\Desktop\ACP\极电子程序\*.ats')
full_names = set()
method_names = {}
for f in files:
content = open(f, encoding='utf-8-sig').read()
# Find all FullName values
for m in re.finditer(r'"FullName":\s*"([^"]+)"', content):
full_names.add(m.group(1))
# Find all Method Name + FullName pairs
data = json.loads(content)
def extract_methods(steps):
for step in steps:
method = step.get('Method')
if method and method.get('Name') and method.get('FullName'):
key = method['FullName']
if key not in method_names:
method_names[key] = set()
method_names[key].add(method['Name'])
# Check SubProgram (nested steps)
sub = step.get('SubProgram')
if sub and isinstance(sub, dict):
sub_steps = sub.get('StepCollection', [])
extract_methods(sub_steps)
steps = data.get('StepCollection', [])
extract_methods(steps)
print("=== All FullName values ===")
for name in sorted(full_names):
print(f" {name}")
print("\n=== Methods per device ===")
for device in sorted(method_names.keys()):
print(f"\n {device}:")
for method in sorted(method_names[device]):
print(f" - {method}")
+50
View File
@@ -0,0 +1,50 @@
import json, glob, os
output_dir = r"D:\ACP\测试项\ACP输出"
# 验证一个文件的格式
test_file = os.path.join(output_dir, "NCE-13——OBC放电.ACP")
d = json.load(open(test_file, encoding='utf-8'))
print("=== 设备方法映射验证 ===")
for s in d['StepCollection']:
m = s.get('Method')
if m:
params_info = ", ".join([f"{p['Name']}={'VAR' if p.get('IsUseVar') else str(p.get('Value'))}" for p in m.get('Parameters', [])])
print(f" [{s['Index']}] {m['FullName']}.{m['Name']} ({params_info})")
print("\n=== 格式验证 ===")
# 检查是否有 .ats 特有字段
has_old_fields = False
def check_steps(steps, prefix=""):
global has_old_fields
for s in steps:
m = s.get('Method')
if m:
if 'DeviceID' in m:
has_old_fields = True
print(f"{prefix}Step {s['Index']} 仍包含 DeviceID")
for p in m.get('Parameters', []):
for field in ['IsGlobal', 'InitialValue', 'IsSave', 'IsOutputToReport']:
if field in p:
has_old_fields = True
print(f"{prefix}Step {s['Index']} 参数 {p['Name']} 仍包含 {field}")
if 'IsEditable' not in p:
has_old_fields = True
print(f"{prefix}Step {s['Index']} 参数 {p.get('Name','')} 缺少 IsEditable")
sub = s.get('SubProgram')
if sub and isinstance(sub, dict):
check_steps(sub.get('StepCollection', []), prefix + " Sub.")
check_steps(d['StepCollection'])
if not has_old_fields:
print(" [OK] 无残留 .ats 字段")
print(" [OK] 所有参数包含 IsEditable")
print(" [OK] 无 DeviceID")
# 检查子程序
sub_count = sum(1 for s in d['StepCollection'] if s.get('SubProgram'))
print(f" 子程序步骤数: {sub_count}")
print(f" 总步骤数: {len(d['StepCollection'])}")
print(f" 顶层参数数: {len(d.get('Parameters', []))}")
File diff suppressed because it is too large Load Diff
+477
View File
@@ -0,0 +1,477 @@
{
"ID": "d5d396fb-e531-4487-99bf-460bf8177b67",
"StepCollection": [
{
"ID": "d0d63f54-dcfc-491f-918a-ac4c672f5732",
"IsUsed": false,
"Index": 1,
"Name": "IO板卡(16)全开",
"StepType": "方法",
"Method": {
"Name": "WriteMultiIO",
"FullName": "DeviceCommand.Device.IOBoardCard",
"DeviceID": "e7ffcb06-f74c-4ddb-bfba-151203678c16",
"Parameters": [
{
"ID": "2d70fab8-0f5a-491b-9148-a43cbb5b7670",
"IsVisible": true,
"Name": "slaveAddress",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "8b67a8d2-c5ee-4e0c-bd18-6150bff358d5",
"IsVisible": true,
"Name": "startAddress",
"Type": "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "f8dc953e-83d7-4bb4-8fb5-f0b18acc9037",
"IsVisible": true,
"Name": "values",
"Type": "System.Boolean[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "[true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true]",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "02588f6e-c1a4-43c2-8c8e-0ea2fc81a43b",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "4ac2e4be-0038-46a7-b19c-ddda4a12ba78",
"IsUsed": false,
"Index": 2,
"Name": "IO板卡(8)全开",
"StepType": "方法",
"Method": {
"Name": "WriteMultiIO",
"FullName": "DeviceCommand.Device.IOBoardCard",
"DeviceID": "179bd18e-35ca-4891-969a-fcca332bf584",
"Parameters": [
{
"ID": "054a5496-c2cb-4b5a-84a2-f25b36b9ffbe",
"IsVisible": true,
"Name": "slaveAddress",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "15c798eb-1c54-43f1-8549-ea8d3eb4eeea",
"IsVisible": true,
"Name": "startAddress",
"Type": "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "3a039b24-63de-4b73-a1b7-c5df51f50361",
"IsVisible": true,
"Name": "values",
"Type": "System.Boolean[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "[true,true,true,true,true,true,true,true]",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "07cda00a-ecd3-4e8b-a723-e2586d615b10",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "cdab9217-417d-4c56-a38a-0b396712d55f",
"IsUsed": true,
"Index": 3,
"Name": "IO板卡(16)全关",
"StepType": "方法",
"Method": {
"Name": "WriteMultiIO",
"FullName": "DeviceCommand.Device.IOBoardCard",
"DeviceID": "e7ffcb06-f74c-4ddb-bfba-151203678c16",
"Parameters": [
{
"ID": "ff35f6c2-9002-48f4-887f-ed90fb690bf0",
"IsVisible": true,
"Name": "slaveAddress",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "40bf5b67-cffd-4748-94fb-2faa26e14031",
"IsVisible": true,
"Name": "startAddress",
"Type": "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "15053e63-d3fb-471e-924e-c6705fe087c9",
"IsVisible": true,
"Name": "values",
"Type": "System.Boolean[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "d58e8512-98fd-4eed-a0a9-7e2fea91fb73",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "5dc85c07-2b91-4ca1-a853-7824e328cce9",
"IsUsed": true,
"Index": 4,
"Name": "IO板卡(8)全关",
"StepType": "方法",
"Method": {
"Name": "WriteMultiIO",
"FullName": "DeviceCommand.Device.IOBoardCard",
"DeviceID": "179bd18e-35ca-4891-969a-fcca332bf584",
"Parameters": [
{
"ID": "ec3b0ac7-9431-44f5-a960-5b353c5f4749",
"IsVisible": true,
"Name": "slaveAddress",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "3e79134f-b6d0-4225-9c0c-26cac669877d",
"IsVisible": true,
"Name": "startAddress",
"Type": "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "5963ce52-6e22-4631-87b1-f4f3fd524c94",
"IsVisible": true,
"Name": "values",
"Type": "System.Boolean[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "[false,false,false,false,false,false,false,false]",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "f4477e20-9bc9-4a8f-b059-b97c4125d53c",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "544f892f-f3e4-4494-8ae6-aeb67c8aca4b",
"IsUsed": false,
"Index": 5,
"Name": "WriteSingleIO",
"StepType": "方法",
"Method": {
"Name": "WriteSingleIO",
"FullName": "DeviceCommand.Device.IOBoardCard",
"DeviceID": "179bd18e-35ca-4891-969a-fcca332bf584",
"Parameters": [
{
"ID": "c811b7a4-9a36-4b38-beb0-ab8895bd06f1",
"IsVisible": true,
"Name": "slaveAddress",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "0402d8b1-f310-4db9-b8be-71529d9ccca6",
"IsVisible": true,
"Name": "coilAddress",
"Type": "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "31071ec7-d3e7-400b-afd0-02382087107b",
"IsVisible": true,
"Name": "value",
"Type": "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "true",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "a56b7490-774c-417a-aeed-0ba780b0a255",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
}
],
"Parameters": [],
"Devices": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,915 @@
{
"ID": "8e478d06-14c6-45de-9df4-c546b36b2da6",
"StepCollection": [
{
"ID": "ee1dd564-757a-42e1-92ee-8ac38ffbd238",
"IsUsed": true,
"Index": 1,
"Name": "CAN曲线记录停止",
"StepType": "方法",
"Method": {
"Name": "CAN曲线记录_停止",
"FullName": "ATS.Commands.CurveMonitorCommands",
"DeviceID": "e7ffcb06-f74c-4ddb-bfba-151203678c16",
"Parameters": []
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "566812d1-f080-4ba5-b752-72bfc4260690",
"IsUsed": true,
"Index": 2,
"Name": "设备参数记录_停止",
"StepType": "方法",
"Method": {
"Name": "设备参数记录_停止",
"FullName": "ATS.Commands.CurveMonitorCommands",
"DeviceID": null,
"Parameters": []
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "0631b65e-4de9-431a-9ac8-aee3552385e4",
"IsUsed": true,
"Index": 3,
"Name": "设置报文",
"StepType": "方法",
"Method": {
"Name": "SetSignalValue",
"FullName": "TSMasterCAN.CAN",
"DeviceID": "faa7d5ea-2a49-4c33-b57f-3f29ec0dbc18",
"Parameters": [
{
"ID": "37b38f93-cdb8-4b2b-9f9a-2986db04c4ac",
"IsVisible": true,
"Name": "channel",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "c612a729-356a-4ff6-97fd-047e498948c9",
"IsVisible": true,
"Name": "AMsgName",
"Type": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "\"PcmuHvEnergeCanFr01\"",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "8bd51944-d315-40e9-9073-819480e9e61e",
"IsVisible": true,
"Name": "ASgnName",
"Type": "System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "\"ChrgrPwrModCtlMst\"",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "73125622-84c3-4fb6-b323-b6d156f83f95",
"IsVisible": true,
"Name": "AValue",
"Type": "System.Double, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "45112e65-2e78-4fca-b5fe-8451b8b0ed6d",
"IsVisible": true,
"Name": "isSend",
"Type": "System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "true",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "26a3d01d-4a38-4e63-99e2-cc100d05b8e8",
"IsVisible": true,
"Name": "sendPeriod",
"Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "20",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "44f26d57-09a2-444f-b6b2-be7a542cff6d",
"IsVisible": true,
"Name": "Result",
"Type": "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 1,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "3b317dbc-8ba9-4ba1-9d60-20b30367f6a4",
"IsUsed": true,
"Index": 4,
"Name": "延时",
"StepType": "方法",
"Method": {
"Name": "Delay_s",
"FullName": "Command.Delay",
"DeviceID": null,
"Parameters": [
{
"ID": "95855137-9a4d-4189-a2ce-c84480ab8ac3",
"IsVisible": true,
"Name": "second",
"Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "a2bacfcc-4948-4afd-90a0-98d06666582b",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "88c98d7a-1abf-4356-8185-7db1ebed8e38",
"IsUsed": true,
"Index": 5,
"Name": "IO板卡(8)写输出",
"StepType": "方法",
"Method": {
"Name": "WriteMultiIO",
"FullName": "DeviceCommand.Device.IOBoardCard",
"DeviceID": "179bd18e-35ca-4891-969a-fcca332bf584",
"Parameters": [
{
"ID": "0c79c43f-6803-4e1f-afd3-f0d172de5d93",
"IsVisible": true,
"Name": "slaveAddress",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "60bf7c19-dbd4-4d7c-aa7e-55336bd93e23",
"IsVisible": true,
"Name": "startAddress",
"Type": "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "8037e189-948c-49ae-aa94-049fa479a33a",
"IsVisible": true,
"Name": "values",
"Type": "System.Boolean[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "[false,false,false,false,false,false,false,false]",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "01df2ac1-1436-4d47-83d0-e332140bd5a5",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "044dc15d-e1ee-4f5e-85bf-bbdbddf35ce3",
"IsUsed": true,
"Index": 6,
"Name": "IO板卡(16)写输出",
"StepType": "方法",
"Method": {
"Name": "WriteMultiIO",
"FullName": "DeviceCommand.Device.IOBoardCard",
"DeviceID": "e7ffcb06-f74c-4ddb-bfba-151203678c16",
"Parameters": [
{
"ID": "0c79c43f-6803-4e1f-afd3-f0d172de5d93",
"IsVisible": true,
"Name": "slaveAddress",
"Type": "System.Byte, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "60bf7c19-dbd4-4d7c-aa7e-55336bd93e23",
"IsVisible": true,
"Name": "startAddress",
"Type": "System.UInt16, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "0",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "8037e189-948c-49ae-aa94-049fa479a33a",
"IsVisible": true,
"Name": "values",
"Type": "System.Boolean[], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "01df2ac1-1436-4d47-83d0-e332140bd5a5",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "4aebb5ee-bd04-4782-b67c-91e0435cbb0a",
"IsUsed": true,
"Index": 7,
"Name": "延时",
"StepType": "方法",
"Method": {
"Name": "Delay_s",
"FullName": "Command.Delay",
"DeviceID": null,
"Parameters": [
{
"ID": "95855137-9a4d-4189-a2ce-c84480ab8ac3",
"IsVisible": true,
"Name": "second",
"Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "a2bacfcc-4948-4afd-90a0-98d06666582b",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "de0357b3-90ff-4e3b-bb2a-1ec1215c40a3",
"IsUsed": true,
"Index": 8,
"Name": "停止CAN日志记录",
"StepType": "方法",
"Method": {
"Name": "StopLogging",
"FullName": "TSMasterCAN.CAN",
"DeviceID": "faa7d5ea-2a49-4c33-b57f-3f29ec0dbc18",
"Parameters": [
{
"ID": "24ecb6b0-bf3e-487d-b724-864dd4cc42db",
"IsVisible": true,
"Name": "Result",
"Type": "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 1,
"IsGlobal": false,
"InitialValue": null,
"Value": 0,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "032ecf5c-e816-4a30-804e-cf89e6bf1118",
"IsUsed": true,
"Index": 9,
"Name": "断开连接",
"StepType": "方法",
"Method": {
"Name": "DisConnect",
"FullName": "TSMasterCAN.CAN",
"DeviceID": "faa7d5ea-2a49-4c33-b57f-3f29ec0dbc18",
"Parameters": [
{
"ID": "5eb2684d-4c77-4c90-ab25-b878ab14723d",
"IsVisible": true,
"Name": "Result",
"Type": "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 1,
"IsGlobal": false,
"InitialValue": null,
"Value": 0,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "17261600-7ff2-4ec4-94e9-f95a85476a68",
"IsUsed": true,
"Index": 10,
"Name": "延时",
"StepType": "方法",
"Method": {
"Name": "Delay_s",
"FullName": "Command.Delay",
"DeviceID": null,
"Parameters": [
{
"ID": "95855137-9a4d-4189-a2ce-c84480ab8ac3",
"IsVisible": true,
"Name": "second",
"Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "a2bacfcc-4948-4afd-90a0-98d06666582b",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "f841385c-a895-4156-b1c9-63779e7f88ec",
"IsUsed": true,
"Index": 11,
"Name": "关闭AC源",
"StepType": "方法",
"Method": {
"Name": "OFF",
"FullName": "DeviceCommand.Device.SQ0090G1D1",
"DeviceID": "a89ed16a-32f2-48b6-9d22-8da0aad68183",
"Parameters": [
{
"ID": "e7fd1b17-f98c-4cba-8011-7fbec800e81d",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "fef2b22e-8ece-4be2-a2d2-dc8518b459f0",
"IsUsed": true,
"Index": 12,
"Name": "延时",
"StepType": "方法",
"Method": {
"Name": "Delay_s",
"FullName": "Command.Delay",
"DeviceID": null,
"Parameters": [
{
"ID": "95855137-9a4d-4189-a2ce-c84480ab8ac3",
"IsVisible": true,
"Name": "second",
"Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "a2bacfcc-4948-4afd-90a0-98d06666582b",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "42e03756-b71c-4d4d-98a1-418691164eb6",
"IsUsed": true,
"Index": 13,
"Name": "关闭高压双向电源",
"StepType": "方法",
"Method": {
"Name": "LoadOff",
"FullName": "DeviceCommand.Device.PSB11500_60",
"DeviceID": "57f4e8d9-8598-41b7-88af-3987143816b1",
"Parameters": [
{
"ID": "88f48df7-b8d4-4116-adbf-e24e30599a6d",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "4cfab9c1-a23f-48e1-97e3-7944c9300405",
"IsUsed": true,
"Index": 14,
"Name": "延时",
"StepType": "方法",
"Method": {
"Name": "Delay_s",
"FullName": "Command.Delay",
"DeviceID": null,
"Parameters": [
{
"ID": "95855137-9a4d-4189-a2ce-c84480ab8ac3",
"IsVisible": true,
"Name": "second",
"Type": "System.Single, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": "1",
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
},
{
"ID": "a2bacfcc-4948-4afd-90a0-98d06666582b",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "dc35f9e0-8f18-4509-82b0-4e072bfc302d",
"IsUsed": true,
"Index": 15,
"Name": "关闭低压电源",
"StepType": "方法",
"Method": {
"Name": "DCOutput_OFF",
"FullName": "DeviceCommand.Device.EA3040_40C",
"DeviceID": "ca8e197d-c5ee-4502-95b8-c15fb5145a0e",
"Parameters": [
{
"ID": "d3341618-d2e0-46c6-90c2-e9b6bb6deb3f",
"IsVisible": true,
"Name": "ct",
"Type": "System.Threading.CancellationToken, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 0,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
},
{
"ID": "2b510d3f-a664-47b1-bbe6-246ab254e4ad",
"IsUsed": true,
"Index": 16,
"Name": "清空所有CAN报文",
"StepType": "方法",
"Method": {
"Name": "DeleteCyclicMsgs",
"FullName": "TSMasterCAN.CAN",
"DeviceID": null,
"Parameters": [
{
"ID": "02c22d25-50c5-4233-960e-d6ca6beaa0e4",
"IsVisible": true,
"Name": "Result",
"Type": "System.Int32, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e",
"Category": 1,
"IsGlobal": false,
"InitialValue": null,
"Value": null,
"LowerLimit": null,
"UpperLimit": null,
"Result": true,
"IsUseVar": false,
"IsSave": false,
"VariableName": null,
"VariableID": null,
"IsOutputToReport": false
}
]
},
"SubProgram": null,
"LoopCount": null,
"LoopStartStepId": null,
"OKExpression": null,
"GotoSettingString": "",
"OKGotoStepID": null,
"NGGotoStepID": null,
"Description": null
}
],
"Parameters": [],
"Devices": []
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More