Files
ReinLoopTest/ReinLoop/修改记录.md
2026-07-30 11:12:31 +08:00

717 lines
32 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 修改记录
> 当前状态说明:本节以 Git 基线提交 `5841f6d` 为参照,记录 2026-07-23 工作区中的最终代码差异。后面的“历史过程记录”仅用于追溯,若与本节冲突,以本节和当前代码为准。
## 当前修改总览
| 项目 | 当前值 |
| --- | --- |
| 仓库 | `https://github.com/azuki-m/pressure_control_gui.git` |
| 本地目录 | `C:\Users\31765\.codex\pressure_control_gui_source` |
| 分支 | `MT2-AM8` |
| 基线提交 | `5841f6d 修改默认值,增加压力滤波(暂未启用)` |
| 工作区状态 | 本文所列修改均尚未提交 |
相对基线,当前增加了三条主要业务链路:
1. 辨识前执行 `1000 -> 0` 的绝对行程稳态压力预扫描,上传不含时间字段的 JSON。
2. 辨识 9 参数改为从云端 CSV 获取;PRBS 结果保持 CSV 上传,并根据云端数字 `0/1` 显示审核结果。未通过时等待公司更新参数,再重新执行完整辨识。
3. 容积测试 8 参数改为按请求传递:客户点击“测试”只创建一次请求指令,公司端检测到后上传本次 JSON,客户端持续查询同一个请求,加载参数后删除临时文件和请求记录。
客户调试界面不再读取或显示这些参数输入框。旧控件对象仍保留以兼容现有代码,但不是新流程的数据来源。
## 当前文件差异
### 修改的原文件
| 文件 | 当前修改 |
| --- | --- |
| `core/identification.py` | 增加行程稳态预扫描;上传函数支持文本和字节;PRBS 原始结果改为 CSV 直传;增加上传回调;加强任务线程存活判断和启动返回值。 |
| `ui/main_window.py` | 增加辨识参数下载、反馈轮询、未通过后等待新参数、容积请求握手、超时/停止清理及 Qt 线程信号桥。 |
| `ui/debug_tab.py` | 隐藏客户不应输入的辨识/容积参数和高级设置;增加辨识审核状态显示。 |
| `setup.py` | 将 3 个新增核心模块加入 Cython 编译列表。 |
### 新增业务文件
| 文件 | 用途 |
| --- | --- |
| `core/identification_config.py` | 下载、解析、校验 9 参数 CSV。 |
| `core/identification_feedback.py` | 登记辨识 CSV、查询数字 `0/1`、确认并清理反馈。 |
| `core/volume_config.py` | 校验 8 参数 JSON,创建、查询、清理一次容积参数请求。 |
| `index.js` | 云函数入口,增加辨识参数、辨识反馈、容积请求接口。 |
| `config/identification_config.json` | 旧本地格式迁移提示;客户端不读取。 |
| `config/volume_measurement.json` | 旧本地格式迁移提示;客户端不读取。 |
### 新增公司端工具和示例
| 文件 | 用途 |
| --- | --- |
| `tool/identification_config.example.csv` | 9 参数 CSV 示例。 |
| `tool/upload_identification_config.py` | 校验并上传客户的固定辨识参数 CSV。 |
| `tool/submit_identification_feedback.py` | 提交辨识审核数字 `1``0`。 |
| `tool/volume_measurement.example.json` | 8 参数 JSON 示例。 |
| `tool/upload_volume_config.py` | 等待客户请求,检测到后校验、上传并关联本次 JSON。 |
### 新增测试
- `tests/test_initial_travel_scan.py`
- `tests/test_identification_config.py`
- `tests/test_identification_feedback.py`
- `tests/test_volume_config.py`
## 当前辨识流程
### 云端 9 参数 CSV
客户点击“开始辨识”后,客户端按许可证中的客户名称读取:
```text
ReinLoop_GUI/{客户名称}/identification_config/identification_config.csv
```
CSV 固定使用 `parameter,value` 两列:
```csv
parameter,value
q_in_val,50.0
dt,0.1
n_order,6
t_c,2.5
levels,"10,20,30,40,50,60,70,80"
dead_area,240.0
xa_full,1000.0
V_val,5.0
repeat,2
```
客户端要求且只允许这 9 个字段。主要约束:
| 参数 | 约束 |
| --- | --- |
| `q_in_val` | 有限数字且 `>= 0` |
| `dt` | 有限数字且 `> 0` |
| `n_order` | 整数且 `>= 2` |
| `t_c` | 有限数字且 `>= dt` |
| `levels` | 至少 2 项,长度为 2 的整数次幂,每项在 `0..100` |
| `dead_area` | `0 <= dead_area < xa_full` |
| `xa_full` | `>= 1000` |
| `V_val` | 有限数字且 `> 0` |
| `repeat` | 正整数 |
校验成功后,9 个参数通过 `**config` 传给 `start_identification()``conn_mgr``running_flag_check` 仍由客户端本地创建,不属于 CSV。
公司端上传命令:
```powershell
python tool/upload_identification_config.py "客户名称" "公司内部路径\identification_config.csv"
```
同一路径再次上传会覆盖固定 CSV。客户端只在开始一轮辨识或收到未通过结果后重新读取,不会在本轮运行中途替换参数。
### `1000 -> 0` 行程稳态预扫描
`start_identification()` 先扫描以下绝对行程,再调用原有 `collect_data_with_prbs()`
```text
1000, 900, 800, 700, 600, 500, 400, 300, 200, 100, 0
```
每个行程至少等待 5 秒,以 0.1 秒周期采样;使用最近 5 秒窗口,在压力极差 `<= 0.5 kPa`、压力斜率绝对值 `<= 0.05 kPa/s` 且连续稳定 3 秒后记录平均压力。每个行程最长等待 60 秒,超时跳过。停止、异常或结束时尝试把行程写回 `0`
结果上传到 `ReinLoop_GUI/{客户名称}/ind_data/`,文件名为 `travel_stability_pressures_时间戳.json`。内容只包含行程和稳定压力,不包含相对时间,也不保存压力变化过程数组:
```json
{
"stable_pressures": [
{"distance": 1000, "pressure": 12.3},
{"distance": 900, "pressure": 15.6}
]
}
```
预扫描 JSON 上传失败只记录日志,不阻止后续 PRBS。
### PRBS CSV 和 `0/1` 反馈
基线会把 PRBS 结果重新包装为 JSON;当前直接上传 `collect_data_with_prbs()` 返回的 `csv_data``.csv` 文件名,不改变采集器的原始 CSV 格式。
```text
上传 PRBS CSV
-> registerIdentificationResult 登记本轮 CSV 文件名为 runId
-> 客户端每 2 秒查询 getIdentificationFeedback
-> 数字 1:显示“已通过”,清理反馈记录,结束
-> 数字 0:显示“未通过”,清理反馈记录,等待云端 CSV 更新
-> 每 2 秒重新获取 identification_config.csv
-> 9 参数内容与本轮不同后,才重新执行完整辨识
```
反馈只接受数字 `0``1`,布尔值和其他数字均拒绝。公司端命令:
```powershell
python tool/submit_identification_feedback.py "客户名称" 1
python tool/submit_identification_feedback.py "客户名称" 0
```
云端集合 `identification_reviews` 对每个客户只保留当前待审核记录,客户端消费后调用 `ackIdentificationFeedback` 删除,防止下一轮误用旧结果。
## 当前容积测试流程
### 8 参数 JSON
```json
{
"q_in_val": 50.0,
"dt": 0.05,
"p_max": 200.0,
"fit_low": 50.0,
"fit_high": 150.0,
"T_delta": 30.0,
"xa_full": 1000.0,
"num_runs": 3
}
```
客户端要求且只允许这 8 个字段。主要约束:`q_in_val > 0``dt > 0``p_max > 0``0 <= fit_low < fit_high <= p_max``xa_full > 0``num_runs` 为正整数,其他数值必须有限。
### 最终请求握手
服务器不能主动向客户端或公司端推送,因此采用“一次创建请求 + 两端查询同一请求状态”:
```text
客户点击“测试”
-> 客户端只调用一次 createVolumeConfigRequest
-> 云端生成 requestId,写入 volume_config_requests,有效期 5 分钟
公司端工具
-> 每 2 秒查询 getPendingVolumeConfigRequest
-> 检测到 requestId 后才上传 8 参数 JSON
-> submitVolumeConfigFile 把文件与 requestId 关联
客户端等待期间
-> 每 2 秒查询 getVolumeConfigRequest,始终使用同一个 requestId
-> 状态查询不会重复创建请求,也不会重复要求公司端上传
-> 检测到本次新文件后下载并校验 JSON
-> ackVolumeConfigRequest 删除临时文件和请求记录
-> 执行一次 start_volume_measurement(..., **config)
```
公司端命令:
```powershell
python tool/upload_volume_config.py "客户名称" "公司内部路径\volume.json" --wait-seconds 300
```
云端文件固定为:
```text
ReinLoop_GUI/{客户名称}/volume_config_requests/{requestId}/volume_measurement.json
```
`submitVolumeConfigFile` 会核对 `file_records` 中的客户目录、`requestId`、文件名和上传时间。只有请求创建后、5 分钟内上传且属于该请求的 JSON 才能加载;旧目录或其他请求的文件不能关联。
### 临时文件处理
- 创建新请求时,云端清理该客户遗留的旧容积请求及临时 JSON。
- 客户端加载成功、用户停止或请求超时后,删除当前请求、云存储 JSON 和对应 `file_records` 记录。
- 公司端上传或关联失败时,工具尝试删除刚上传的文件。
- 测量开始后不再监听参数变化,也不会因云端更新而自动重测;下一次必须由客户再次点击“测试”。
- 辨识 CSV 是公司维护的固定文件,后续上传会覆盖;容积 JSON 是一次请求的临时文件,消费后删除。
上一版“公司预先写入最新 8 参数、客户端直接获取”的方案已移除。当前代码不存在 `pushVolumeConfig``getVolumeConfig``volume_measurement_configs` 的有效调用路径。
## 当前客户端和构建修改
- 调试页隐藏辨识、容积参数和高级设置,保留开始/停止按钮及辨识审核状态。
- 网络请求在后台线程中执行,通过 Qt `Signal` 回到主线程更新界面。
- 请求代数编号和 `inflight` 标志用于忽略停止后迟到的结果,并阻止同类请求并发。
- 辨识与容积测试互斥;停止或关闭窗口时停止定时器、使旧请求失效并尝试清理云端状态。
- `IdentificationManager.is_running` 同时检查运行标志和任务线程是否存活。
- `start_identification()``start_volume_measurement()` 返回布尔值,调用方可判断任务是否启动。
- `setup.py` 新增 `core/identification_config.py``core/identification_feedback.py``core/volume_config.py` 三个 Cython 编译目标。
## 当前新增云函数接口
| 接口 | 调用方 | 作用 |
| --- | --- | --- |
| `getIdentificationConfig` | 客户端 | 获取当前客户固定辨识 CSV 的临时地址。 |
| `registerIdentificationResult` | 客户端 | 登记刚上传的 PRBS CSV。 |
| `getIdentificationFeedback` | 客户端 | 查询本轮数字 `0/1`。 |
| `setIdentificationFeedback` | 公司端 | 提交本轮数字 `0/1`。 |
| `ackIdentificationFeedback` | 客户端 | 删除已消费反馈。 |
| `createVolumeConfigRequest` | 客户端 | 点击“测试”时创建一次 5 分钟请求。 |
| `getPendingVolumeConfigRequest` | 公司端 | 查询客户的待上传请求。 |
| `submitVolumeConfigFile` | 公司端 | 把 JSON 与本次请求关联。 |
| `getVolumeConfigRequest` | 客户端 | 查询同一请求是否已有有效 JSON。 |
| `ackVolumeConfigRequest` | 客户端 | 删除已消费、取消或超时的请求和文件。 |
## 当前验证结果
已执行:
```powershell
python -m unittest discover -s tests -p 'test_*.py' -v
```
- 23 项单元测试全部通过。
- 38 个 Python 文件通过 AST 语法解析。
- `git diff --check` 通过,仅有 Windows 的 LF/CRLF 转换提示。
- 测试覆盖 9 参数 CSV、预扫描 JSON 无时间字段、PRBS CSV 直传、数字 `0/1`、8 参数 JSON、一次请求创建、等待/就绪状态和请求清理。
## 尚未完成和发布风险
1. 尚未连接真实 MT2-AM8、真实云环境和公司端工具完成端到端联调。
2.`index.js` 尚未部署;部署前客户端无法使用新增接口。
3. 本机没有独立 Node.js`index.js` 尚未完成语法检查;上一次借用 VS Code 运行时的检查被中止,不计为通过。
4. 云数据库需要允许云函数读写 `identification_reviews``volume_config_requests` 和现有 `file_records`
5. 当前 HTTP 接口主要依赖 `deviceId` 区分客户,没有请求签名或设备令牌;正式发布前需要服务端身份认证。
6. 当前 `index.js` 含明文小程序 `SECRET`。不得直接提交或分发,应立即轮换,并改为从云函数环境变量或密钥服务读取。
7. `requirements.txt` 未声明程序实际使用的 `PySide6`,新机器仅按该文件安装仍不能启动。
8. 所有改动仍在工作区,尚未形成 Git 提交。
## 发布顺序建议
1. 轮换并移除 `index.js` 中的明文 `SECRET`
2. 在测试云环境部署 `index.js`,建立并授权新增集合。
3. 公司端先上传一份辨识参数 CSV。
4. 联调一次容积请求的创建、发现、上传、下载和删除。
5. 联调预扫描、PRBS CSV 上传和 `0/1` 反馈重测。
6. 补齐运行依赖和打包配置,再生成客户安装包。
<details>
<summary>历史过程记录(仅供追溯,当前行为以上述整理为准)</summary>
## 项目基线
- 仓库:`https://github.com/azuki-m/pressure_control_gui.git`
- 分支:`MT2-AM8`
- 基线提交:`5841f6d 修改默认值,增加压力滤波(暂未启用)`
- 本地目录:`C:\Users\31765\.codex\pressure_control_gui_source`
- 开始日期:2026-07-22
## 记录规则
每次修改应记录以下内容:
1. 修改目标和需求来源。
2. 涉及的文件、类和函数。
3. 修改前后的行为差异。
4. 参数、接口或数据格式变化。
5. 验证方法和验证结果。
6. 尚未完成的事项与风险。
## 修改历史
### 0. 基线建立
- 从 GitHub 重新克隆 `MT2-AM8` 分支。
- 保留原始代码,不继承此前测试版 1.0 的工作区修改。
- 对 28 个 Python 文件执行 AST 语法解析,全部通过。
### 1. 云函数恢复
- 将此前测试版云函数备份到 `pressure_control_gui_test_v1.0/cloud_index.latest-test.js`
- 恢复 `index.js` 的原始接口分发,仅保留:
`uploadDataFile``listModels``downloadModel``deleteFile``uploadUserInfo`
- 测试版新增的参数传输和多轮调试接口不再从云函数入口暴露。
- 已从恢复版 `index.js` 中完整移除测试版新增的参数传输和多轮会话函数。
- 恢复后的 `index.js` 已同步至 `C:\Users\31765\Desktop\index.js`
### 2. 容积测试的 8 个参数改为 JSON 输入(历史阶段,已由第 4 节替代)
#### 2.1 修改目标
- 客户端不再通过 UI 输入容积测试参数。
- 参数从固定 JSON 文件读取并校验后,传给 `start_volume_measurement()`
- 参数无效或文件读取失败时禁止启动设备,并在状态栏显示错误。
- 旧 UI 控件对象继续保留,避免影响仍依赖这些属性的历史代码。
#### 2.2 JSON 文件和字段
- 默认文件:`config/volume_measurement.json`
- 打包后默认位置:可执行文件同级的 `config/volume_measurement.json`
- 可使用环境变量 `REINLOOP_VOLUME_CONFIG` 覆盖默认路径。
- JSON 必须且只能包含下面 8 个字段:
```json
{
"q_in_val": 50.0,
"dt": 0.05,
"p_max": 200.0,
"fit_low": 50.0,
"fit_high": 150.0,
"T_delta": 30.0,
"xa_full": 1000.0,
"num_runs": 3
}
```
字段与 `start_volume_measurement()` 参数的对应关系:
| JSON 字段 | 类型 | 作用 |
| --- | --- | --- |
| `q_in_val` | float | 进气流量 |
| `dt` | float | 控制与采样周期 |
| `p_max` | float | 测量压力上限 |
| `fit_low` | float | 压力拟合区间下限 |
| `fit_high` | float | 压力拟合区间上限 |
| `T_delta` | float | 测量过程温升参数 |
| `xa_full` | float | 电机总行程/全开行程参数 |
| `num_runs` | int | 重复测量次数 |
#### 2.3 代码位置和改动
1. `core/volume_config.py`
- `REQUIRED_FIELDS`(约第 10 行):定义必须存在的 8 个字段。
- `default_config_path()`(约第 16 行):确定默认路径,并支持环境变量覆盖。
- `load_volume_config()`(约第 27 行):读取 JSON、拒绝缺失或多余字段、
校验数据类型及范围,最后返回可直接展开传参的字典。
- 范围约束包括:`dt > 0``p_max > 0`
`0 <= fit_low < fit_high <= p_max``xa_full > 0`
`num_runs` 为正整数。
2. `config/volume_measurement.json`
- 新增默认配置模板。
- 该文件中的值是当前测试默认值,部署前应由项目负责人确认。
3. `ui/main_window.py`
- 第 27 行附近:导入 `load_volume_config`
- `_on_volume_measure()`(约第 589 行):删除以下 UI 参数读取逻辑:
`get_identify_params()``get_advanced_params()`、控制页流量输入和 PID 周期。
- 新流程为:
```text
点击测试
-> load_volume_config()
-> 校验成功
-> start_volume_measurement(conn_mgr, running_flag_check, **config)
```
- 配置失败时调用 `set_volume_finished()`,恢复测试按钮状态,不启动测量线程。
4. `ui/debug_tab.py`
- 高级设置卡片创建完成后调用 `adv_card.hide()`(约第 123 行)。
- `_build_ident_section()` 末尾(约第 215 行)遍历布局并隐藏参数控件。
- 保留 `btn_wrap``seq_wrap`,因此测试和辨识操作按钮仍可见。
- `levels_entry` 单独隐藏。
- `get_identify_params()``get_advanced_params()` 和 QSettings 逻辑没有删除,
仅不再作为容积测试的数据来源。
5. `core/identification.py`
- `start_volume_measurement()`(约第 196 行)接口本身未改名。
- 仍接收上述 8 个业务参数,内部继续调用 `measure_volume()` 并上传测量结果。
6. `tests/test_volume_config.py`
- `test_load_valid_config()`:验证合法配置可以读取。
- `test_rejects_missing_field()`:验证缺少字段时拒绝启动。
- `test_rejects_invalid_range()`:验证非法拟合区间被拒绝。
#### 2.4 修改前后行为
修改前:
```text
UI 流量输入 + PID 周期 + 调试页参数 + 高级设置
-> main_window.py 组合参数
-> start_volume_measurement()
```
修改后:
```text
config/volume_measurement.json
-> load_volume_config() 严格校验
-> main_window.py 使用 **config
-> start_volume_measurement()
```
#### 2.5 验证结果
- `tests/test_volume_config.py`3 个测试全部通过。
- 30 个 Python 文件通过 AST 语法解析。
- `git diff --check` 通过,仅提示 Windows 的 LF/CRLF 转换警告。
- 未连接真实 MT2-AM8,因此尚未执行设备端容积测量联调。
#### 2.6 当前限制和安全说明
- 该阶段读取本地 JSON;当前实现已由第 4 节的云端单次请求替代。
- “隐藏”仅指参数不在客户 UI 中显示;如果 JSON 明文部署在客户电脑上,
有文件系统访问权限的用户仍可读取它。
- 若参数属于公司机密,后续应增加云端临时下载、身份校验、加密或用后销毁流程。
- 控制页面原有流量输入仍服务于其他控制功能,但容积测试不会读取该输入。
## 待修改事项
### 已完成:PRBS 前增加绝对行程稳态预扫描
- 修改文件:`core/identification.py`
- 新增函数:`IdentificationManager._run_initial_travel_scan()`
- `start_identification()` 的后台线程先调用新函数,完成后继续执行原有
`collect_data_with_prbs()`;PRBS 的生成、参数和上传逻辑未替换。
- 固定行程序列:`1000, 900, 800, 700, 600, 500, 400, 300, 200, 100, 0`
- 稳态判据:最短等待 5 s、采样周期 0.1 s、滑动窗口 5 s、压力极差
`<= 0.5 kPa`、斜率绝对值 `<= 0.05 kPa/s`、连续稳定 3 s、单行程
最大等待 60 s。
- 每个达到稳态的行程只记录行程和平均稳定压力,不保存相对时间或响应过程。
- 输出为 JSON 对象,格式如下:
```json
{
"stable_pressures": [
{"distance": 1000, "pressure": 12.3},
{"distance": 900, "pressure": 15.6}
]
}
```
- 压力单位为 kPa;未达到稳态或写入失败的行程不会写入结果,但其余记录仍能
通过 `distance` 明确对应行程。
- 预扫描结果单独上传至
`{客户名称}/ind_data/travel_stability_pressures_时间戳.json`
- 行程指令不通过实时 UI 回调显示;UI 只接收压力。
- 用户停止或发生异常时尝试将行程写回 `0`
- 预扫描上传失败不会改变后续 PRBS 行为,程序记录日志后继续 PRBS。
- 新增 `tests/test_initial_travel_scan.py`,模拟全部 11 个行程达到稳态,验证
上传文件为 JSON,且每条记录只包含 `distance``pressure`
- 验证结果:34 个 Python 文件通过 AST 语法解析;原
`collect_data_with_prbs()` 调用及其 9 个传参保持不变;已有 3 个 JSON
配置单元测试继续通过;`git diff --check` 通过。
- 尚未连接真实 MT2-AM8,稳态等待、行程方向和 `0` 是否为安全位置需要硬件联调。
### 3. 辨识的 9 个参数改为从云端 CSV 获取
#### 3.1 修改目标
- 客户端点击“开始辨识”后,不再读取调试页、控制页或高级设置中的本地参数。
- 客户端根据许可证中的客户名称,从云端读取固定 CSV 文件。
- CSV 解析和严格校验成功后,将 9 个业务参数一次性传给
`IdentificationManager.start_identification()`
- `conn_mgr``running_flag_check` 是客户端运行时对象,仍由本地创建,
不属于云端 CSV。
- 参数不在客户界面显示;之前隐藏的参数控件继续保留用于兼容旧代码,
但辨识流程不会读取这些控件。
- 既有的绝对行程稳态预扫描和原始 PRBS 采集顺序不变。
#### 3.2 云端文件和接口
- 固定云端目录:`{客户名称}/identification_config`
- 固定文件名:`identification_config.csv`
- 完整对象存储路径:
`ReinLoop_GUI/{客户名称}/identification_config/identification_config.csv`
- 客户名称来自 `api.py``the_folder`,生产环境中对应许可证的
`customer` 字段。
- `index.js` 第 318 行附近新增 `getIdentificationConfig(event)`
校验 `deviceId`,查询 `file_records` 中的固定记录,并返回腾讯云临时下载 URL。
- `index.js` 第 380 行附近新增同名分发入口。
- 仓库中的新版 `index.js` 已将固定查询文件改为 CSV;部署时应以仓库版本为准。
- 公司端仍通过既有 `uploadDataFile` 接口获取直传凭证;同一路径再次上传时,
云函数执行 upsert,客户端下一次辨识将读取覆盖后的版本。
#### 3.3 CSV 格式
`tool/identification_config.example.csv` 是公司端示例模板。实际客户配置应另存为
公司内部文件,不要放进客户安装包;CSV 固定使用 `parameter,value` 两列:
```csv
parameter,value
q_in_val,50.0
dt,0.1
n_order,6
t_c,2.5
levels,"10,20,30,40,50,60,70,80"
dead_area,240.0
xa_full,1000.0
V_val,5.0
repeat,2
```
| CSV 参数 | `start_identification()` 参数 | 校验要求 |
| --- | --- | --- |
| `q_in_val` | `q_in_val` | 有限数字,`>= 0` |
| `dt` | `dt` | 有限数字,`> 0` |
| `n_order` | `n_order` | 整数,`>= 2` |
| `t_c` | `t_c` | 有限数字,`>= dt` |
| `levels` | `levels` | 至少 2 项,长度为 2 的整数次幂,每项在 0~100 |
| `dead_area` | `dead_area` | 有限数字,`0 <= dead_area < xa_full` |
| `xa_full` | `xa_full` | 有限数字,`>= 1000` |
| `V_val` | `V_val` | 有限数字,`> 0` |
| `repeat` | `repeat` | 正整数 |
`xa_full >= 1000` 是因为辨识开始前的固定行程预扫描包含 1000;
`levels` 的长度要求来自原始 `generate_prbs()` 多电平映射算法。
#### 3.4 客户端代码位置和执行流程
1. `core/identification_config.py`
- `REQUIRED_FIELDS`(第 7 行附近):定义 9 个必需字段。
- `validate_identification_config()`(第 13 行附近):拒绝缺失字段、
多余字段、布尔值、非有限数值和不安全的范围。
- `parse_identification_config_csv()`:解析 `parameter,value` 两列,并将
`levels` 的逗号分隔值恢复为 Python 列表。
- `download_identification_config()`(第 79 行附近):调用云函数,
获取临时 URL,下载 CSV,并在客户端再次校验。
2. `ui/main_window.py`
- `_Bridge.identification_config_loaded`(第 46 行附近):后台下载完成后,
将结果安全地送回 Qt 主线程。
- `_on_identify_start()`(第 555 行附近):点击辨识后启动后台下载线程,
不阻塞界面,也不读取原有 UI 参数。
- `_on_identification_config_loaded()`(第 578 行附近):同步
`PcControl``xa_full`,再执行:
```python
self.ident_mgr.start_identification(
conn_mgr=self.conn_mgr,
running_flag_check=lambda: self.engine.is_running,
**config,
)
```
- `_on_identify_stop()`(第 597 行附近):停止辨识并使尚未完成的云端请求失效;
即使旧请求稍后返回,也不会再启动设备。
- `closeEvent()`(第 632 行附近):关闭软件时同样取消待处理请求并停止辨识。
3. `core/identification.py`
- `start_identification()`(第 274 行附近)的接口和 9 个业务参数保持不变。
- 第 320 行附近仍先运行 `_run_initial_travel_scan()`,随后第 324 行附近
调用原始 `collect_data_with_prbs()`PRBS 调节方式没有替换。
4. `setup.py`
-`core/identification_config.py``core/identification_feedback.py`
`core/volume_config.py` 加入 Cython 核心模块清单,正式构建时不需要向
客户交付这些模块的 Python 源码。
客户端完整流程:
```text
点击开始辨识
-> 后台调用 getIdentificationConfig(deviceId=许可证客户名称)
-> 获取临时 URL 并下载 identification_config.csv
-> 解析 parameter,value 两列
-> 严格校验 9 个参数
-> start_identification(conn_mgr, running_flag_check, **config)
-> 1000 到 0 的稳态预扫描
-> 原始 PRBS 动态辨识
```
#### 3.5 公司端上传工具
- 新增 `tool/upload_identification_config.py`
- 第 41 行附近的 `upload_identification_config()` 在公司电脑上先使用与客户端
相同的规则解析和校验 CSV,再规范化为 UTF-8 CSV,并调用既有 COS 直传流程。
- 文件名和云端子目录由脚本固定,不能误传到模型目录。
- 使用方式:
```powershell
python tool/upload_identification_config.py "客户名称" "公司内部路径\identification_config.csv"
```
- 同一客户再次执行会覆盖固定云端文件,用于多轮调整;已经运行中的一轮辨识
不会被中途改参,客户下一次点击辨识才获取新版本。
#### 3.6 验证结果
- 新增 `tests/test_identification_config.py`,覆盖:合法配置归一化、缺少字段、
CSV 解析、非 2 的整数次幂序列、`t_c < dt``xa_full < 1000`、死区越界。
- 容积配置、辨识配置和预扫描输出共 16 个单元测试全部通过;其中包含云函数请求参数、
临时 URL 下载和云端拒绝响应的模拟测试,不会访问真实网络。
- 35 个 Python 文件通过 AST 语法解析。
- `git diff --check` 通过,仅有 Git 的 LF/CRLF 转换提示。
- 本机没有 Node.js,因此未运行 `node --check index.js`
- 当前 Python 环境未安装 `requests`(项目 `requirements.txt` 已声明该依赖),
因此未向真实云环境上传配置;云端流程仅使用模拟响应完成单元测试。
- 未连接 MT2-AM8 做完整硬件联调。
#### 3.7 安全边界和部署注意事项
- 客户 UI 不显示这 9 个参数,客户端本地也不需要保存配置文件;但 Python
客户端解析 CSV 后,参数会在进程内存中存在,不能等同于绝对防提取。
- `tool/identification_config.example.csv` 仅是字段模板;构建客户安装包时不要
打包 `tool` 目录,也不要把填写了真实参数的公司内部 CSV 放进项目分发目录。
- `config/identification_config.json` 仅是旧格式迁移提示,客户端不会读取;
辨识配置只使用云端固定 CSV 文件。
- 云函数返回的是有有效期的临时下载 URL,但源 CSV 会持续保存在云存储中;
当前实现是“同路径覆盖”,不是“客户端下载后销毁”。
- 当前 HTTP 云函数仅按 `deviceId` 查找文件,没有请求签名或设备身份认证。
知道接口和其他客户名称的人理论上可能越权请求,因此正式发布前必须增加
服务端许可证签名/设备令牌校验,不能只依赖 UI 隐藏。
- 修改后的 `index.js` 必须重新部署到当前腾讯云环境,否则客户端会收到
“无效的 type 字段”。
### 4. 容积测试通过请求指令获取本次云端 8 参数 JSON
- 客户点击“测试”后,客户端只调用一次 `createVolumeConfigRequest`,在云端创建
一条带 `requestId` 的请求指令;请求有效期为 5 分钟。
- 客户端随后每 2 秒调用 `getVolumeConfigRequest` 查询同一个 `requestId` 的状态。
这些调用只是监听该请求是否已有文件,不会重复创建请求,也不会重复要求公司端上传。
- 云端使用 `volume_config_requests` 集合保存等待上传、文件就绪和过期状态;创建新请求时
会清理该客户遗留的旧请求及其临时 JSON,避免客户端读取旧参数。
- 公司端工具调用 `getPendingVolumeConfigRequest` 等待客户请求,检测到请求后才校验并上传
8 参数 JSON,再调用 `submitVolumeConfigFile` 把文件与本次 `requestId` 关联:
```powershell
python tool/upload_volume_config.py "客户名称" "公司内部路径\volume.json" --wait-seconds 300
```
- 云端只接受位于
`{客户名称}/volume_config_requests/{requestId}/volume_measurement.json` 的上传记录,
并检查上传时间处于本次请求的创建时间和过期时间之间;其他请求或旧目录中的文件不能关联。
- 客户端检测到本次文件就绪后下载 JSON,严格校验 8 个字段,再执行一次
`start_volume_measurement(conn_mgr, running_flag_check, **config)`
- 客户端加载完成、用户停止或请求超时后调用 `ackVolumeConfigRequest`,及时删除云端临时 JSON、
`file_records` 记录和请求记录。测量期间不再监听参数变化,也不会自动开始新一轮测量。
- 本地 `config/volume_measurement.json` 不提供业务参数,只保留迁移提示;公司端示例位于
`tool/volume_measurement.example.json`
- 客户端要求 `q_in_val > 0`,避免容积计算除零;其他 7 个参数继续按原有范围严格校验。
- 当前共 23 个单元测试,38 个 Python 文件通过 AST 语法解析;未连接真实云端和 MT2-AM8
完成端到端联调。
- 更新后的 `index.js` 必须重新部署,新的请求指令接口才会生效。
### 5. 辨识 CSV 的 0/1 审核与自动重测闭环
- `collect_data_with_prbs()` 生成的 `csv_data``.csv` 文件名现在直接上传到
`{客户名称}/ind_data`,不再重新包装为辨识结果 JSON。
- CSV 上传成功后,客户端调用 `registerIdentificationResult` 登记本轮文件名
作为 `runId`,然后每 2 秒调用 `getIdentificationFeedback` 查询审核结果。
- 云端使用 `identification_reviews` 集合;每个客户只保留当前一条待审核记录,
新一轮登记会覆盖旧记录并删除重复项。
- 审核结果严格使用数字:`1` 表示通过,`0` 表示未通过。其他值会被服务器和
客户端拒绝,布尔值也不会被当作数字接受。
- 客户端调试页新增持久状态显示:`正在辨识``等待反馈``已通过``未通过`
`上传失败` 等。
- 收到 `1` 后显示“已通过”,停止反馈轮询并结束辨识流程。
- 收到 `0` 后显示“未通过”,每 2 秒重新下载云端
`identification_config.csv`;如果仍是本轮旧参数则继续等待,检测到 9 参数
内容变化后才重新调用 `start_identification()`,防止旧参数重复执行。
- 客户端消费 `0/1` 后调用 `ackIdentificationFeedback` 删除当前审核记录,避免
旧反馈被下一轮误用。
- 公司端或审核算法可调用 `setIdentificationFeedback`;人工测试命令为:
```powershell
python tool/submit_identification_feedback.py "客户名称" 1
python tool/submit_identification_feedback.py "客户名称" 0
```
- 新增 `tests/test_identification_feedback.py`,并补充辨识管理器 CSV 直传测试;
当前 20 个单元测试全部通过,38 个 Python 文件通过 AST 语法解析。
- 尚未对真实云函数、审核程序和 MT2-AM8 进行端到端联调;更新后的 `index.js`
必须重新部署。
- [x] 明确容积测试的云端 JSON 参数格式和传输流程。
- [x] 明确辨识功能的云端 CSV 参数格式和传输流程。
- [x] 明确绝对行程扫描与 PRBS 辨识的当前执行顺序。
- [x] 隐藏客户调试页中的容积和辨识参数控件。
- [x] 明确测试结果上传、公司端审核和多轮反馈流程。
- [ ] 完成真实 MT2-AM8 硬件联调。
</details>