连接器开发
连接器(Connector)是 ATEBOX 中用于执行和仪器/设备对接的模块,根据平台下发的指令完成对设备的控制和数据采集。
ATEBOX 中已经内置了连接器,可以完成和绝大多数仪器的对接和程控。

什么时候需要自定义连接器
内置连接器无法覆盖时,需要自定义开发:
- 调用**动态链接库(DLL)**控制设备
- 单指令-多响应的设备
- 设备主动上报数据的场景

开发前置能力
- 了解使用仪器
- 了解程控的基本过程
- 具备基本开发能力
连接器模式的核心是一套通信协议,开发者可以使用任何开发语言完成开发。官方提供 Python 示例模板用于熟悉机制与快速验证,实际项目中有性能要求时可自行换用其他语言。
开发过程
连接器与 ATEBOX 的交互关系

连接器与平台之间有三类消息:心跳注册、指令下发、数据推送。
心跳消息(连接器 → edge)
连接器主动发给 edge,完成连接器及仪器资源的注册,采用 HTTP POST,默认每 10 秒一次。
POST http://{edge_host}:{edge_port}/heartedge_host:ATEBOX 的 IP 地址edge_port:ATEBOX 的端口,默认 5000
消息内容(JSON):
{
"svc": "at-conn-zkcx-pxi",
"ver": "1.0.1",
"hb": 10,
"kind": "conn",
"host": "192.168.0.100",
"port": 27001,
"insts": [
{
"cfg": {
"res": "PXI::zkcx-1063::INSTR",
"timeout": "500"
},
"sn": "zkcx-1063",
"model": "PXI-1063",
"mfr": "zkcx",
"res": "PXI::zkcx-1063::INSTR",
"status": 1,
"auto": 1
}
],
"ress": [],
"psrs": []
}顶层字段:
| 字段名 | 类型 | 说明 |
|---|---|---|
| svc | string | 服务名称 |
| ver | string | 服务版本 |
| hb | integer | 心跳间隔(秒),默认 10 |
| kind | string | 服务类型,固定为 "conn" |
| host | string | 本机 IP 地址 |
| port | integer | 服务端口号 |
| insts | array | 仪器列表 |
| ress / psrs | array | 预留,当前为空数组 |
仪器信息字段(insts 内每个对象):
| 字段名 | 类型 | 说明 |
|---|---|---|
| sn | string | 仪器序列号 |
| model | string | 仪器型号 |
| mfr | string | 制造商 |
| res | string | 资源地址 |
| cfg | object | 预留 |
| auto | integer | 是否自动检测(1 自动 / 0 手动) |
| status | integer | 仪器状态(1 在线 / 0 离线) |
下发指令(edge → 连接器)
edge 把需要执行的指令任务通过 HTTP 下发给连接器。连接器可选择:
- 同步处理:在 HTTP 返回内容中直接携带数据
- 异步处理:HTTP 返回只含状态码,后续通过推送接口把数据推给 edge
POST http://{connector_host}:{connector_port}/test/{tid}/inst/{sn}connector_host/connector_port:连接器程序部署的电脑 IP 与服务端口tid:测试任务 IDsn:仪器序列号
消息内容(JSON):
{
"nid": "node_001",
"type": 3,
"code": "VOLT_DC",
"template": "MEAS:VOLT:DC? {{range}}, {{resolution}}",
"params": [
{ "key": "range", "value": "10" },
{ "key": "resolution", "value": "0.001" }
],
"replys": [
{
"key": "voltage",
"label": "直流电压",
"kind": "电压",
"type": 0,
"unit": "V",
"decimals": 3,
"scale": 1,
"regexps": ["[-+]?\\d+\\.\\d+"]
}
]
}| 字段名 | 类型 | 说明 |
|---|---|---|
| nid | string | 节点 ID,用于标识测试节点 |
| code | integer | 指令代码,用于标识指令 |
| type | integer | 指令类型:1 读取 / 2 配置 |
| template | string | 指令模板, 占位符表示参数 |
| params | array | 参数列表 |
| replys | array | 响应数据解析规则(仅读取指令需要) |
replys 字段说明:
| 字段名 | 类型 | 说明 |
|---|---|---|
| key | string | 数据键名 |
| label | string | 数据标签 |
| type | integer | 数据类型:0 单一数值 / 2 字符串 / 5 逗号分隔多组数据 |
| kind | string | 数据种类 |
| unit | string | 数据单位 |
| scale | number | 缩放比例 |
| decimals | integer | 小数位数 |
| regexps | array | 正则表达式列表,用于解析返回数据 |
响应格式:
// 配置指令成功
{ "code": 200, "message": "success" }
// 读取指令成功
{
"code": 200,
"message": "success",
"datas": [
{
"key": "data",
"type": 0,
"label": "测量数据",
"kind": "voltage",
"unit": "V",
"value": "1.234"
}
]
}
// 失败
{ "code": 400, "message": "fail" }推送数据(连接器 → edge)
连接器完成数据采集后(尤其是异步场景),用 HTTP 把数据推送给 edge:
POST http://{edge_host}:{edge_port}/test/{tid}/node/{nid}
Content-Type: application/jsontid:测试实例 IDnid:测试节点 ID(需与下发指令时的 nid 一致)
{
"time": 1650712470239209500,
"datas": [
{
"key": "curr",
"label": "输出电流",
"kind": "电流",
"type": 0,
"unit": "mA",
"value": "12.4"
},
{
"key": "volt",
"label": "输入电压",
"kind": "电压",
"type": 0,
"unit": "mV",
"value": "8.5"
}
]
}响应:
{ "code": 200, "message": "success" }实战:用 Python 模板开发一个连接器
准备设备通信协议
根据设备提供的通信方式准备通信协议或 SDK 说明文档。教程使用虚拟仪器 VirtuScope 的通信协议(教程附件)。
安装 Python 3.12
从 python.org 下载安装,然后验证:
python --version
# Python 3.12.10设置国内源(加速依赖安装):
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
pip config list下载初始项目模板
git clone https://gitee.com/ate-connector/ate-conn-py-seed.git更改配置参数
按实际情况修改 const.py:
# HTTP服务配置
PORT = 27081
# 服务信息
SERVICE_NAME = "ate-conn-ns"
SERVICE_VERSION = "6.0.1"
# Edge平台配置
EDGE_HOST = "127.0.0.1"安装依赖并启动
# 安装项目依赖
pip install -r requirements.txt
# 启动模拟仪器(两个终端分别执行,端口 10013 / 10014)
python mock_oscilloscope.py --port 10013
python mock_oscilloscope.py --port 10014
# 启动连接器
python main.pyWARNING
模拟器终端窗口不要关闭,否则模拟器停止。
连接器正常启动后可在终端看到启动输出:

开发调试
连接器是整个测试过程的末梢环节:指令执行由平台发起 → edge 调度 → 连接器执行,调试时需要把三个环节衔接起来。
打开 BOX 在线日志窗口
连接器启动后,进入工位配置页面,可以看到工位上已经上线了两个设备,说明心跳推送正常。

点击工位右上角第三个图标,打开日志观察窗口:

默认显示 INFO 级别日志:

调试连接器时需要同时选择 DEBUG,才能看到更多后台日志:

通过页面下发指令
为了同时观察日志,用复制标签页的方式(浏览器标签页右键 → 复制)打开新标签页,进入仪器维护菜单,搜索自定义仪器型号 VirtuScope:

点击仪器型号操作按钮中的指令维护:

点击「查询峰峰值电压」指令:

点击验证按钮:

当前上线了两个同型号仪器,需点击「选择设备」指定本次验证发送到哪个设备:

设定设备、参数及指标精度后,点击发送。页面会显示发送的指令模板以及从连接器读取的数值:

查看两侧日志
在之前保留的日志窗口中,用指令编码 get_meas_vpp 搜索,可以看到调用连接器的细节(调用时间、传入参数):

连接器控制台同样能看到此次调用的过程:

项目架构(Python 模板)
├── main.py # 程序入口,系统初始化和启动逻辑
├── server.py # HTTP服务模块,基于Sanic提供RESTful API
├── conn.py # 连接器核心模块,管理仪器资源池和指令处理
├── inst.py # 仪器管理模块,封装Socket通信和读写操作
├── heartbeat.py # 心跳服务模块,定期上报服务状态和设备列表
├── push.py # 消息推送模块,向Edge平台发送HTTP消息
├── reply_spec.py # 响应格式定义,解析仪器指令响应
├── const.py # 常量定义,系统配置、超时、服务信息等
├── log.py # 日志管理模块,统一日志输出接口
├── mock_oscilloscope.py # 模拟示波器服务,用于测试开发
├── requirements.txt # 项目依赖
├── doc/ # 项目文档(架构/模块/数据结构/HTTP接口等)
└── tests/ # 单元/集成/契约测试模块依赖关系
┌─────────┐
│ main.py │
└────┬────┘
┌──────────────┼──────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ server.py │ │ conn.py │ │heartbeat │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
│ ▼ ▼
│ ┌───────────┐ ┌───────────┐
│ │ inst.py │ │ push.py │
│ └───────────┘ └───────────┘
│ │ │
└──────────────┴──────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ log.py │ │ const.py │ │reply_spec │
└───────────┘ └───────────┘ └───────────┘应用启动后的模块调用时序
main.py conn.py inst.py heartbeat.py server.py
│ │ │ │ │
│ ① 创建 Connector │ │ │
│───────────────>│ │ │ │
│ ② 调用 find() 发现设备 │ │ │
│───────────────>│ 创建 Instrument│ │ │
│ │───────────────>│ 建立 Socket │ │
│<───────────────│<───────────────│ │ │
│ ③ 注入 Connector 到 Sanic 上下文 │ │ │
│──────────────────────────────────────────────────────────────────>│
│ ④ 创建并启动 HeartbeatThread │ │ │
│────────────────────────────────────────────────>│ 启动心跳循环 │
│ ⑤ 启动 HTTP 服务器 │ │ │
│──────────────────────────────────────────────────────────────────>│
运行时阶段:
心跳线程(每15秒) heartbeat.py ──> conn.py ──> push.py ──> POST /heart
HTTP请求处理 Client ──> server.py ──> conn.py ──> inst.py ──> TCP Socket进阶练习
从修复错误入手
开发调试中会发现一个典型问题:连接器读取到数据了,但平台显示为 0。原因是推送数据的类型为数值,而从设备读取到的是带单位的字符串。基于对项目架构的理解,多个环节都可以修复这个错误——可作为理解代码的入门练习。
实现异步推送
模板目前对所有读取指令都是同步执行。当数据量很大或需要持续获取数据时,同步读取不再适合,需改用异步推送。
练习目标:把模拟仪器的查询波形数据指令(code: get_wave)改为异步处理——收到 HTTP 消息后立刻返回 code: 200,随后获取指令数据并通过推送接口推送给 edge(推送消息中的 nid 需与下发指令时的 nid 相同)。