Files
vd_test_fixture/.hermes/plans/2026-05-28_edc-web-implementation.md
wangfq 70dd3f8246 feat: 新增 edc-web Flask 前端管理系统 + 需求文档
- edc-web: Flask 项目骨架(设备管理、测试操作、测试信息三大页面)
- edc_server: 升级子模块(tb_serialnet 透传支持)
- docs: 测试工装EDC管理系统需求文档
2026-05-28 09:40:45 +08:00

9.8 KiB
Raw Permalink Blame History

edc-web 实施计划

目标

vd_test_fixture 项目中新增 edc-web Flask 前端 + 扩展 edc_server 后端,实现测试工装 EDC 的 Web 管理系统。

架构概览

┌──────────────────────┐     ┌──────────────────────┐
│   edc-web (Flask)    │     │  edc_server (asyncio) │
│   前端 Web 界面       │     │  后端通信服务          │
│   REST API           │     │  UDP/TCP + 轮询        │
└──────┬───────────────┘     └──────┬───────────────┘
       │                            │
       └────────┬───────────────────┘
                │
         ┌──────▼──────┐
         │    MySQL     │
         │  edc 数据库   │
         └─────────────┘

一、数据库变更

1.1 新增表 tb_serialnet(透传发送表)

CREATE TABLE IF NOT EXISTS `tb_serialnet` (
    `id` INT AUTO_INCREMENT PRIMARY KEY,
    `dnt_id` INT NOT NULL COMMENT 'FK → dnt_info.id',
    `send_pkg` VARCHAR(380) DEFAULT '' COMMENT '发送指令包(hex)',
    `rcv_pkg` VARCHAR(380) DEFAULT '' COMMENT '接收指令包(hex)',
    `state` TINYINT DEFAULT 0 COMMENT '0未发送, 1已发送, 2已完成, 3超时失败',
    `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
    `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX `idx_dnt_state` (`dnt_id`, `state`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

修改文件: edc_server/src/models.py — 在 _create_tables() 中添加建表语句

1.2 新增 tb_serialnet CRUD 函数

models.py 中添加:

函数 用途
get_pending_serialnet(dnt_id) 获取该设备 state=0 的第一个待发送记录
mark_serialnet_sent(id) 标记为 state=1 (已发送)
mark_serialnet_done(id, rcv_pkg) 标记为 state=2 (收到回复)
mark_serialnet_timeout(id) 标记为 state=3 (超时失败)
get_serialnet_stats(dnt_id) 返回 total/sent/done/failed 计数
insert_serialnet(dnt_id, send_pkg) 插入新指令

二、edc_server 扩展

2.1 新增 serialnet_loop() 轮询任务

handlers.py 中新增:

async def serialnet_loop():
    """轮询 tb_serialnet下发待发送的透传指令"""
    while True:
        for device_id, dnt_id in list(_registry.items()):
            record = await get_pending_serialnet(dnt_id)
            if record:
                # 构造 SerialNet JSON → 通过 UDP 发送
                # 更新 state=1
                ...
        await asyncio.sleep(0.2)

关键点

  • 同一设备同一时间只处理一条(避免冲突)
  • 需要在 UDP transport 上发送数据 — 这要求 server.py 把 transport 暴露出来

2.2 server.py 改造

  • EDCProtocol 的 transport 保存到全局/模块级变量,供 serialnet_loop 使用
  • TCP handler 也需要能发送 SerialNet → 需要保存 TCP writer 映射 {device_id: writer}

2.3 B2 响应匹配 tb_serialnet

tsreport_handler 收到 B2 数据包后,除了写入 tb_state_tst,还要:

  • 查找该设备 state=1 的 tb_serialnet 记录
  • 更新为 state=2写入 rcv_pkg

2.4 超时检测

serialnet_loop 中检查 state=1 且超过 10 秒的记录 → 标记为 state=3

三、edc-web Flask 应用

3.1 目录结构

vd_test_fixture/edc-web/
├── run.py                  # 入口
├── requirements.txt        # Flask, pymysql, ...
├── app/
│   ├── __init__.py         # Flask 工厂
│   ├── config.py           # 配置
│   ├── models.py           # 数据库操作(同步 pymysql
│   ├── routes/
│   │   ├── __init__.py
│   │   ├── devices.py      # 设备页面 API
│   │   ├── test_op.py      # 测试操作 API
│   │   └── test_data.py    # 测试信息 API
│   ├── templates/
│   │   ├── base.html       # 基模板(菜单)
│   │   ├── devices.html    # 设备列表页
│   │   ├── test_op.html    # 测试操作页
│   │   └── test_data.html  # 测试信息页
│   └── static/
│       ├── css/
│       │   └── style.css
│       └── js/
│           ├── devices.js
│           ├── test_op.js
│           └── test_data.js

3.2 页面路由

路由 页面 说明
/ devices.html 设备列表(默认首页)
/test/<int:dnt_id> test_op.html 测试操作页
/test-data test_data.html 测试信息页

3.3 REST API

设备相关

Method Path 说明
GET /api/devices 获取 dnt_info 列表(含在线状态)
PUT /api/devices/<id>/name 修改终端名称
GET /api/devices/<id>/status 获取设备最新测试状态

测试操作

Method Path 说明
POST /api/command 发送单次指令 {dnt_id, cmd}
POST /api/automation/start 开始自动化 {dnt_id, count}
POST /api/automation/stop 停止自动化 {dnt_id}
GET /api/automation/<dnt_id>/progress 获取进度 {total, done, failed, remaining}
GET /api/automation/<dnt_id>/averages 获取平均值

测试信息

Method Path 说明
GET /api/test-data 分页查询测试数据(join dnt_info + tb_state_tst)
GET /api/test-data/export 导出 CSV

3.4 前端实现要点

设备页面 (devices.html)

  • 表格列: 设备编码(serial)、名称(name,可编辑)、IP、在线状态(state)、版本(version)、操作(测试按钮)
  • 名称编辑: 点击名称单元格 → 变为 input → 回车/blur 提交 PUT
  • 在线状态: state=1 绿色"在线", state=0 灰色"离线"
  • 操作列: "测试" 按钮 → 跳转 /test/<dnt_id>

测试操作页 (test_op.html)

  • 左侧操作区:

    • 指令按钮: 开始测试(B0)、测试复原(B1)、电机前进(BA)、电机后退(BB)、电机停止(BC)
      • 点击 → POST /api/command → edc_server 通过 SerialNet 发送
    • 自动化区域:
      • 测试次数 input + 开始/结束按钮
      • 进度条(完成/总数 + 失败数)
      • 实现: 前端轮询 /api/automation//progress (1s间隔)
      • 开始后: 前端每次 state=2 时自动插入下一条 0xB0
      • 超时: 前端 JS 计时器10秒后 state 仍是 1 → 标记为失败
  • 右侧信息区:

    • 最近一次测试数据显示(实时刷新)
    • 平均值显示: 峰峰值、开始工作频率、进入工作频率、进入距离、离开距离、进入速度、离开速度
    • 平均值只计算成功记录(不计失败的 state=3

测试信息页 (test_data.html)

  • 表格: JOIN dnt_info.serial + tb_state_tst 全部字段
  • 分页: 后端 LIMIT/OFFSET
  • 搜索: 按 serial、日期范围筛选
  • 导出: CSV 下载

四、自动化流程详解

前端点击"开始"(次数=N)
  │
  ├─ 清空前端平均值缓存
  ├─ POST /api/automation/start (dnt_id, count=N)
  │   └─ 后端插入第1条 tb_serialnet (state=0, send_pkg=0xB0)
  │
  ├─ 前端开始轮询 (1s间隔)
  │   │
  │   ├─ GET /api/automation/<id>/progress
  │   │   └─ 返回 {total:N, done:M, failed:F, remaining:R}
  │   │
  │   └─ 前端逻辑:
  │       - 如果 state=2 (完成) → done++ → 如果 done < N: 插入下一条 0xB0
  │       - 如果 state=1 超过10秒 → 标记 timeout → failed++
  │       - 更新进度条
  │       - 如果 done + failed >= N 或 用户点击"结束" → 停止
  │
  └─ edc_server 后台:
      ├─ serialnet_loop: state=0 → 发送 UDP SerialNet → state=1
      └─ tsreport_handler: 收到 B2 → 写入 tb_state_tst → 匹配 state=1 → state=2

五、DG430 指令构造

所有指令基于 DG430 串口协议,通过 SerialNet 透传:

按钮 命令 hex 数据包 (addr=0x01) 备注
开始测试 0xB0 7F 81 01 B0 30 32
测试复原 0xB1 7F 81 01 B1 31 33
电机前进 0xBA 7F 81 01 BA 3A 3C
电机后退 0xBB 7F 81 01 BB 3B 3D
电机停止 0xBC 7F 81 01 BC 3C 3E

addr=0x01 → ADDR字段=0x80+0x01=0x81 XOR: 0x81 ^ 0x01 ^ 0xB0 = 0x30, SUM: (0x81+0x01+0xB0) & 0xFF = 0x32

六、实施步骤

步骤 内容 文件
1 添加 tb_serialnet 表 + CRUD 函数 edc_server/src/models.py
2 新增 serialnet_loop + 改造 server.py (暴露 transport) edc_server/src/handlers.py, server.py
3 B2 响应匹配 tb_serialnet edc_server/src/handlers.py
4 创建 edc-web 项目骨架 (Flask 工厂) edc-web/app/__init__.py
5 设备页面 API + 前端 edc-web/app/routes/devices.py, templates/devices.html
6 测试操作页 API + 前端 edc-web/app/routes/test_op.py, templates/test_op.html
7 测试信息页 API + 前端 edc-web/app/routes/test_data.py, templates/test_data.html
8 集成测试 -

七、注意事项

  1. 防止冲突: tb_serialnet 对同一设备同时只处理一条 (state=0/1 只有一条)
  2. 超时处理: 前端 JS 10 秒定时器 + 后端 serialnet_loop 也做超时兜底
  3. 平均值计算: 只计算 state=2 (成功) 的记录,排除 state=3 (失败)
  4. edc_server UDP 发送: 目前 edc_server 只接收 UDP需要在 EDCProtocol 中保存 transport 引用
  5. edc-web 用同步 pymysql: Flask 是同步框架,用 pymysql 直接连 MySQL与 edc_server 的 aiomysql 不冲突(同库不同连接)