Oscilloscope Operate Skill
通过 SCPI 命令 + LXI 网口 远程操作示波器的自动化测试技能。
- 示波器型号与 IP 优先从全局配置(
.openclaw/workspace/test_config/test_config.json)读取(示波器.model/示波器.ip_address) - 回退规则:若全局
test_config.json不存在,或存在但没有示波器配置 / model 或 ip_address 缺失,则自动回退读取本技能自带的config/test_config.json - SCPI 命令库由一个一次性别解析步骤从编程手册 PDF 生成(纯文本解析,不用 LLM,节省 token)
- 运行时按提示词语义在命令库中查找匹配命令;找不到则明确提示「不支持」
- 连接通过 PyVISA,VISA 后端优先系统 VISA(NI-VISA),缺失时自动回退纯 Python 的
pyvisa-py;资源串TCPIP0::<ip>::INSTR
入口脚本: oscilloscope_operate.py
依赖
- PyVISA(Python 包):
pip install pyvisa - VISA 后端(二选一):
- 系统级 NI-VISA 驱动(推荐):https://www.ni.com/visa/
- 或 pyvisa-py(纯 Python,TCPIP 够用,无需系统驱动):
pip install pyvisa-py
> 均未安装时无法枚举/打开资源;代码会自动优先系统 VISA,缺失则回退@py。 - 解析手册 PDF(一次性)还需
pdfplumber(首选)或PyMuPDF(备选)
依赖自检:
python skills/oscilloscope-operate-skill/scripts/check_dependency.py
配置要求
示波器型号与 IP 的配置按以下优先级读取:
- 全局配置:
workspace/test_config/test_config.json(或workspace/test_config.json) - 技能自带配置:
skills/oscilloscope-operate-skill/config/test_config.json
> 只要全局配置存在且包含可用的 示波器.model + 示波器.ip_address,就用全局;
> 否则(全局不存在 / 全局缺 示波器 / model、ip 任一为空)自动回退到技能自带 config。
配置内容格式:
{
"示波器": {
"model": "RIGOL DS2302A",
"ip_address": "192.168.2.35"
}
}
命令行 --model / --ip 可覆盖配置文件值。
用法
0) 生成命令库(一次性,按手册型号各跑一次)
python skills/oscilloscope-operate-skill/scripts/scpi_manual_to_json.py \
--pdf "C:/Users/admin/Downloads/MSO2000ADS2000AProgrammingGuideCN.pdf" \
--model RIGOL_DS2302A
- 输出:
skills/oscilloscope-operate-skill/data/RIGOL_DS2302A.json - 纯正则/文本结构解析(优先 pdfplumber,回退 PyMuPDF),不消耗 LLM token
- 后续有新型号示波器,用其手册再跑一次,生成
<厂家>_<型号>.json
1) 查询设备信息(调试用)
python skills/oscilloscope-operate-skill/scripts/oscilloscope_operate.py --query "*IDN?"
2) 按语义查找命令(不执行)
python skills/oscilloscope-operate-skill/scripts/oscilloscope_operate.py --find "打开通道1"
3) 按语义查找并执行
python skills/oscilloscope-operate-skill/scripts/oscilloscope_operate.py --do "读取波形数据"
4) 直接发送命令
python skills/oscilloscope-operate-skill/scripts/oscilloscope_operate.py --send ":CHANnel1:DISPlay ON"
命令行参数
| 参数 | 说明 |
|---|---|
--query <cmd> |
查询命令(如 *IDN?),执行并返回结果 |
--send <cmd> |
直接发送一条 SCPI 命令(写或查询自动判定) |
--find <意图> |
按语义查找候选命令,不连接设备 |
--do <意图> |
按语义查找最佳命令并执行 |
--model <型号> |
覆盖配置中的型号 |
--ip <IP> |
覆盖配置中的 IP |
--timeout <ms> |
VISA 超时(默认 8000ms) |
命令库 JSON 结构
{
"vendor": "RIGOL",
"model": "RIGOL_DS2302A",
"source_pdf": "...",
"extractor": "pdfplumber",
"page_count": 385,
"command_count": 423,
"commands": [
{
"command": ":CHANnel<n>:DISPlay",
"command_short": ":CHANnel<n>:DISPlay",
"is_query": false,
"command_format": {
"set": [":CHANnel<n>:DISPlay <bool>"],
"query": [":CHANnel<n>:DISPlay?"],
"raw": ":CHANnel<n>:DISPlay <bool> \n:CHANnel<n>:DISPlay?"
},
"function": "打开或关闭指定的模拟通道,或查询指定模拟通道的状态。",
"parameters": {
"raw": "名称 类型 范围 默认值 ...",
"parameters": [
{"name": "<n>", "type": "离散型", "range": "{1|2}", "default": "—"},
{"name": "<bool>", "type": "布尔型", "range": "{{1|ON}|{0|OFF}}", "default": "1|ON"}
]
},
"return_format": "查询返回1 或0。",
"notes": "",
"example": "",
"related_commands": ""
}
]
}
测试流程
1. 读取 test_config.json → 示波器型号/ip_address
2. 加载 data/<型号>.json 命令库
3. ┌─ --find/--do:按提示词语义打分查找候选命令
│ 命中 → 取最佳命令(优先 set 格式)
│ 未命中 → result.passed=false,提示"不支持"
└─ --query/--send:直接使用给定命令
4. 打开 VISA 会话 TCPIP0::<ip>::INSTR
5. 执行命令(查询用 query(),写用 write())
6. 保存结果 JSON → test_output/oscilloscope-operate-skill/
7. 关闭会话
输出
结果文件:test_output/oscilloscope-operate-skill/<时间戳>.json
{
"skill": "oscilloscope-operate-skill",
"time": "2026-09-18 11:41:02",
"oscilloscope": {"model": "RIGOL DS2302A", "ip_address": "192.168.2.200"},
"command": "*IDN?",
"visa_resource": "TCPIP0::192.168.2.200::INSTR",
"response": "RIGOL TECHNOLOGIES,DS2302A,DS2A000000001,00.03.04.SP2",
"error": null,
"result": {"passed": true, "messages": "命令执行成功:*IDN? -> RIGOL TECHNOLOGIES,..."}
}
| 字段 | 说明 |
|---|---|
oscilloscope |
使用的型号与 IP |
command |
实际发送的命令 |
matched_command |
--do 模式下命中的命令库命令 |
candidates |
--find/--do 的候选命令(含得分) |
supported |
语义查找是否命中(false = 不支持) |
visa_resource |
使用的 VISA 资源串 |
response |
查询返回值 |
error |
错误信息(失败时) |
result.passed |
整体结果:true 成功 / false 失败 |
result.messages |
结果描述 |
> 保持通用技能结果约定:result: {passed, messages} 为必备字段。
注意事项
- 设备未连接时:连接失败会在
result.messages明确给出原因(如未装 PyVISA / 未装 NI-VISA 驱动 / 连接超时)。 - 命令不支持时:
--find/--do未命中返回supported=false且result.passed=false,提示"不支持"。 - 命令库与型号绑定:不同型号手册生成的 JSON 不同,运行时按
示波器.model自动匹配data/<型号>.json。 - 手册 PDF 解析为一次性操作;日常测试只做「查命令 + 连设备 + 执行」。
变更记录
- v1.0.1(2026-09-18):配置来源改为「全局优先 + 技能自带回退」。新增
_load_config_with_fallback():优先读workspace/test_config/test_config.json;当全局不存在,或存在但缺示波器配置 /model、ip_address任一为空时,自动回退读取技能自带config/test_config.json。VISA 后端在系统 VISA 缺失时自动回退pyvisa-py。新增实机验证的辅助脚本read_screen_waveform.py(读屏幕波形 BYTE)与save_screen_image.py(:DISPlay:DATA?保存屏幕 BMP)。 - v1.0.0(2026-09-18):首版。支持从编程手册 PDF 一次性解析生成 SCPI 命令库 JSON(
RIGOL_DS2302A.json,423 条命令),支持按语义查找/执行命令,PyVISA+LXI 连接,.result{passed,messages}结果输出。以*IDN?作为调试基准命令。