Skip to content

连接器开发

连接器(Connector)是 ATEBOX 中用于执行和仪器/设备对接的模块,根据平台下发的指令完成对设备的控制和数据采集。

ATEBOX 中已经内置了连接器,可以完成和绝大多数仪器的对接和程控。

什么是连接器

什么时候需要自定义连接器

内置连接器无法覆盖时,需要自定义开发:

  • 调用**动态链接库(DLL)**控制设备
  • 单指令-多响应的设备
  • 设备主动上报数据的场景

何时需要自定义连接器

开发前置能力

  • 了解使用仪器
  • 了解程控的基本过程
  • 具备基本开发能力

连接器模式的核心是一套通信协议,开发者可以使用任何开发语言完成开发。官方提供 Python 示例模板用于熟悉机制与快速验证,实际项目中有性能要求时可自行换用其他语言。

开发过程

连接器与 ATEBOX 的交互关系

连接器与 ATEBOX 交互关系

连接器与平台之间有三类消息:心跳注册指令下发数据推送

心跳消息(连接器 → edge)

连接器主动发给 edge,完成连接器及仪器资源的注册,采用 HTTP POST,默认每 10 秒一次。

http
POST http://{edge_host}:{edge_port}/heart
  • edge_host:ATEBOX 的 IP 地址
  • edge_port:ATEBOX 的端口,默认 5000

消息内容(JSON):

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": []
}

顶层字段:

字段名类型说明
svcstring服务名称
verstring服务版本
hbinteger心跳间隔(秒),默认 10
kindstring服务类型,固定为 "conn"
hoststring本机 IP 地址
portinteger服务端口号
instsarray仪器列表
ress / psrsarray预留,当前为空数组

仪器信息字段(insts 内每个对象):

字段名类型说明
snstring仪器序列号
modelstring仪器型号
mfrstring制造商
resstring资源地址
cfgobject预留
autointeger是否自动检测(1 自动 / 0 手动)
statusinteger仪器状态(1 在线 / 0 离线)

下发指令(edge → 连接器)

edge 把需要执行的指令任务通过 HTTP 下发给连接器。连接器可选择:

  • 同步处理:在 HTTP 返回内容中直接携带数据
  • 异步处理:HTTP 返回只含状态码,后续通过推送接口把数据推给 edge
http
POST http://{connector_host}:{connector_port}/test/{tid}/inst/{sn}
  • connector_host / connector_port:连接器程序部署的电脑 IP 与服务端口
  • tid:测试任务 ID
  • sn:仪器序列号

消息内容(JSON):

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+"]
    }
  ]
}
字段名类型说明
nidstring节点 ID,用于标识测试节点
codeinteger指令代码,用于标识指令
typeinteger指令类型:1 读取 / 2 配置
templatestring指令模板, 占位符表示参数
paramsarray参数列表
replysarray响应数据解析规则(仅读取指令需要)

replys 字段说明:

字段名类型说明
keystring数据键名
labelstring数据标签
typeinteger数据类型:0 单一数值 / 2 字符串 / 5 逗号分隔多组数据
kindstring数据种类
unitstring数据单位
scalenumber缩放比例
decimalsinteger小数位数
regexpsarray正则表达式列表,用于解析返回数据

响应格式:

json
// 配置指令成功
{ "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:

http
POST http://{edge_host}:{edge_port}/test/{tid}/node/{nid}
Content-Type: application/json
  • tid:测试实例 ID
  • nid:测试节点 ID(需与下发指令时的 nid 一致)
json
{
  "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"
    }
  ]
}

响应:

json
{ "code": 200, "message": "success" }

实战:用 Python 模板开发一个连接器

准备设备通信协议

根据设备提供的通信方式准备通信协议SDK 说明文档。教程使用虚拟仪器 VirtuScope 的通信协议(教程附件)。

安装 Python 3.12

python.org 下载安装,然后验证:

python
python --version
# Python 3.12.10

设置国内源(加速依赖安装):

python
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

下载初始项目模板

bash
git clone https://gitee.com/ate-connector/ate-conn-py-seed.git

更改配置参数

按实际情况修改 const.py

python
# HTTP服务配置
PORT = 27081

# 服务信息
SERVICE_NAME = "ate-conn-ns"
SERVICE_VERSION = "6.0.1"

# Edge平台配置
EDGE_HOST = "127.0.0.1"

安装依赖并启动

bash
# 安装项目依赖
pip install -r requirements.txt

# 启动模拟仪器(两个终端分别执行,端口 10013 / 10014)
python mock_oscilloscope.py --port 10013
python mock_oscilloscope.py --port 10014

# 启动连接器
python main.py

WARNING

模拟器终端窗口不要关闭,否则模拟器停止。

连接器正常启动后可在终端看到启动输出:

连接器启动成功

开发调试

连接器是整个测试过程的末梢环节:指令执行由平台发起 → edge 调度 → 连接器执行,调试时需要把三个环节衔接起来。

打开 BOX 在线日志窗口

连接器启动后,进入工位配置页面,可以看到工位上已经上线了两个设备,说明心跳推送正常。

工位设备上线

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

打开日志窗口

默认显示 INFO 级别日志:

INFO 日志

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

DEBUG 日志

通过页面下发指令

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

检索自定义仪器

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

进入指令维护

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

选择指令

点击验证按钮:

验证指令

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

选择设备

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

发送并查看结果

查看两侧日志

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

BOX 日志

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

连接器日志

项目架构(Python 模板)

text
├── 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/                  # 单元/集成/契约测试

模块依赖关系

text
                    ┌─────────┐
                    │ main.py │
                    └────┬────┘
          ┌──────────────┼──────────────┐
          ▼              ▼              ▼
    ┌───────────┐  ┌───────────┐  ┌───────────┐
    │ server.py │  │  conn.py  │  │heartbeat  │
    └─────┬─────┘  └─────┬─────┘  └─────┬─────┘
          │              │              │
          │              ▼              ▼
          │        ┌───────────┐  ┌───────────┐
          │        │  inst.py  │  │  push.py  │
          │        └───────────┘  └───────────┘
          │              │              │
          └──────────────┴──────────────┘

          ┌──────────────┼──────────────┐
          ▼              ▼              ▼
    ┌───────────┐  ┌───────────┐  ┌───────────┐
    │  log.py   │  │ const.py  │  │reply_spec │
    └───────────┘  └───────────┘  └───────────┘

应用启动后的模块调用时序

text
  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 相同)。

相关链接

基于 CC-BY-4.0 协议发布