Files
ReinLoopTest/ReinLoop/features.md
T
2026-07-30 11:12:31 +08:00

157 lines
11 KiB
Markdown

# ReinLoop 功能与接口
本文档描述 `ReinLoop/` Python 客户端当前提供的运行时功能与接口。
## 约定
- 业务服务端地址由 `REINLOOP_API_URL` 指定,未设置时使用
`REINLOOP_SERVER_URL + /api`
- 新许可证的设备标识为 `<company_code>/<production_line_code>`,在代码中通过
`api.the_folder` 使用。旧许可证才回退到 `REINLOOP_DEVICE_ID`
- 所有服务端业务请求均使用 `POST /api`,通过请求体的 `type` 字段分发。
- 公司、产线、许可证签发/撤销、模型删除、审核反馈及配置提交均为
ControlPanel 管理端能力,客户端不提供对应的管理接口。旧微信云函数和其管理脚本
已移除。
## 应用与设备连接
| 功能 | 接口 | 返回或行为 |
| --- | --- | --- |
| 启动桌面程序 | `main.main()` | 初始化 PySide6 主窗口、全局日志及异常处理。 |
| 连接 MT2-AM8 | `ConnectionManager.connect(tcp_ip, tcp_port, pressure_addr, motor_addr, flowmeter_addr, pressure_range=400, flow_range=100)` | 返回 `bool`。建立 Modbus TCP 连接并保存模拟量通道配置。 |
| 断开设备 | `ConnectionManager.disconnect()` | 关闭连接并通知状态回调。 |
| 查询连接状态 | `ConnectionManager.is_connected()` | 返回 `bool`。 |
| 读取压力 | `ConnectionManager.read_pressure()` | 返回压力值 `kPa`,失败时为 `None`。 |
| 读取流量 | `ConnectionManager.read_flow()` | 返回流量 `L/min`;未配置流量计或失败时为 `None`。 |
| 设置电机位置 | `ConnectionManager.set_motor_position(xa)` | 将目标行程写入模拟量输出,返回 `bool`。 |
| 日志和连接回调 | `set_log_callback(callback)``set_status_callback(callback)` | 回调签名分别为 `callback(message)``callback(connected, status_text)`。 |
主运行路径使用 `ConnectionManager`。底层调试或独立脚本还可使用
`PcControl.py` 中的 `MT2AM8Client``Easy521ModbusClient`
`MotorModbusRTUClient``PressureModbusRTUClient`
## 压力控制
| 功能 | 接口 | 返回或行为 |
| --- | --- | --- |
| 创建控制器 | `ControlEngine(pid)` | `pid``IncrementalPID` 实例。 |
| 注入依赖 | `set_connection_manager(mgr)``set_model_manager(mgr)``set_data_collector(collector)` | 配置设备、RL 模型和数据采集服务。 |
| 启动控制 | `ControlEngine.start()` | 要求设备已连接;RL 模式还要求模型已加载。 |
| 执行一个周期 | `ControlEngine.control_tick()` | 读取压力、执行 PID/RL/手动控制、写入电机并更新显示。由 GUI 的 QTimer 调用。 |
| 停止控制 | `ControlEngine.stop()` | 停止循环,并触发 `DataCollector.finalize_and_upload()`。 |
| 查询运行状态 | `ControlEngine.is_running` | 只读属性,返回 `bool`。 |
| 切换模式 | `engine.mode = "PID" / "RL" / "MANUAL"` | PID 闭环、RL 调参增强闭环或直接设置阀门开度。 |
| 更新 PID 参数 | `IncrementalPID.update_parameters(kp, ki, kd)` | 重算增量 PID 系数。 |
| 执行 PID 单步 | `IncrementalPID.update_pressure_values(current, target)``update(du_max=None)` | `update()` 返回受限后的阀门开度百分比。 |
| 重置 PID 状态 | `IncrementalPID.reset()` | 清除误差历史与输出状态。 |
| 设置单步限幅 | `IncrementalPID.set_du_max(value)` | 设置 PID 输出增量上限。 |
`ControlEngine` 的常用配置字段包括 `target_pressure``flow``volume`
`manual_valve``collect_data``dz``motor_max``xa_full`
`pressure_alpha`
## RL 模型管理
| 功能 | 接口 | 服务端请求 |
| --- | --- | --- |
| 刷新模型列表 | `ModelManager.scan_models()` | `listModels`,目录为 `<deviceId>/model_config`。异步执行。 |
| 加载 SAC 模型 | `ModelManager.load_model(model_name)` | `downloadModel` 获取临时 URL,再下载并以 `SAC.load()` 加载。 |
| 检查模型状态 | `ModelManager.is_model_loaded()` | 返回 `bool`。 |
| 回调注册 | `set_models_loaded_callback(callback)``set_load_complete_callback(callback)` | 回调签名分别为 `callback(file_names)``callback(success, message)`。 |
RL 模式下,`ControlEngine` 使用模型根据流量、当前压力和压力误差预测 `Kp/Ki`,随后继续使用 PID 计算阀门开度。
## 控制过程数据采集与上传
| 功能 | 接口 | 返回或行为 |
| --- | --- | --- |
| 初始化一轮采集 | `DataCollector.reset()` | 清空 Episode 缓存。 |
| 记录控制点 | `DataCollector.record_step(cycle_count, current_pressure, target_pressure, valve_opening, kp, ki, kd, q_in, v)` | 目标压力变化时自动切分 Episode。 |
| 停止后异步上传 | `DataCollector.finalize_and_upload(flow, vol)` | 分片上传 Pickle 数据和 manifest 到 `<deviceId>/data_record/...`。 |
| 上传凭证与直传 | `DataCollector._upload_to_cos(data_bytes, filename, folder)` | 内部接口;先请求上传凭证,再将对象直传。 |
上传地址通过服务端 `uploadDataFile` 获取。单个 Episode 数据文件超过约 5 MB 时会自动拆分。
## 系统辨识
| 功能 | 接口 | 返回或行为 |
| --- | --- | --- |
| 下载辨识配置 | `download_identification_config(timeout=20)` | 下载并返回已校验的九参数配置字典。 |
| 校验配置对象 | `validate_identification_config(config)` | 规范化后返回字典,非法参数抛出 `ValueError`。 |
| 解析配置 CSV | `parse_identification_config_csv(csv_text)` | 解析 `parameter,value` 两列 CSV 并完成校验。 |
| 启动辨识 | `IdentificationManager.start_identification(conn_mgr=..., running_flag_check=..., q_in_val=..., dt=..., n_order=..., t_c=..., levels=..., dead_area=..., xa_full=..., V_val=..., repeat=2)` | 返回 `bool`;后台依次执行行程预扫描、PRBS 采集并上传 CSV。 |
| 停止辨识 | `IdentificationManager.stop()` | 请求正在运行的辨识/容积任务停止。 |
| 查询任务状态 | `IdentificationManager.is_running` | 返回 `bool`。 |
| 生成 PRBS | `generate_prbs(n_order=7, low_val=40, high_val=60, samples_per_bit=20, levels=None)` | 返回 NumPy 激励序列。 |
| 生成复合激励 | `generate_composite_sequence(dt, n_order, t_c, levels)` | 返回闭阀、全开和多电平 PRBS 组合序列。 |
| 执行 PRBS 采集 | `collect_data_with_prbs(conn_mgr, q_in_val, dt=0.05, n_order=7, t_c=1.0, levels=None, dead_area=240, xa_full=1062.5, V_val=None, should_stop=None, log=print, on_sample=None, repeat=2)` | 返回含 `t``u``p``csv_data``filename``samples``success` 的字典。 |
辨识流程会先按 `1000``0` 的行程档位扫描稳定压力,将结果上传到
`<deviceId>/ind_data`;随后上传 PRBS CSV 到同一目录。
### 辨识审核反馈
| 功能 | 接口 | 服务端请求 | 返回 |
| --- | --- | --- | --- |
| 登记结果 | `register_identification_result(run_id, timeout=10)` | `registerIdentificationResult` | 成功时返回 `None`。 |
| 查询审核 | `get_identification_feedback(run_id, timeout=10)` | `getIdentificationFeedback` | 未就绪返回 `None`;就绪返回 `0``1`。 |
| 确认清理 | `acknowledge_identification_feedback(run_id, timeout=10)` | `ackIdentificationFeedback` | 成功时返回 `None`。 |
## 容积测量
| 功能 | 接口 | 返回或行为 |
| --- | --- | --- |
| 读取本地配置 | `load_volume_config(path=None)` | 读取 JSON 并返回八参数配置。 |
| 校验配置 | `validate_volume_config(config)` | 返回规范化配置;错误时抛出 `ValueError`。 |
| 执行单次测量 | `measure_volume(conn_mgr, q_in_slm=50.0, dt=0.1, xa=1000, p_max=200.0, fit_low=50.0, fit_high=150.0, T_delta=30.0, should_stop=None, log=print, on_sample=None)` | 返回拟合斜率、截距、`c1``volume_L`、原始压力曲线和 `success`。 |
| 启动多次测量 | `IdentificationManager.start_volume_measurement(conn_mgr=..., running_flag_check=..., q_in_val=..., dt=..., p_max=..., fit_low=..., fit_high=..., T_delta=..., xa_full=1000, num_runs=3)` | 返回 `bool`;后台多次测量、计算平均值并上传 JSON。 |
| 创建配置请求 | `create_volume_config_request(timeout=10)` | 返回 `{"request_id", "expires_at_ms"}`。 |
| 查询配置请求 | `poll_volume_config_request(request_id, timeout=10)` | 返回 `{"ready", "expired"}`;就绪时额外包含 `config`。 |
| 确认配置请求 | `acknowledge_volume_config_request(request_id, timeout=10)` | 成功时返回 `None`。 |
容积测量汇总结果上传到 `<deviceId>/V_config`。容积参数请求与确认是客户端和 ControlPanel 的一次性协作流程。
## 许可证与设备标识
| 功能 | 接口 | 返回或行为 |
| --- | --- | --- |
| 本地验签 | `verify_license(lic_path=None)` | 验证 RSA-PSS/SHA-256 签名、载荷和有效期,返回许可证载荷。 |
| 启动许可证检查 | `check_license(lic_path=None)` | 本地校验、在线校验并启动唯一的后台巡检线程;失败时退出程序。 |
| 获取已验证载荷 | `get_verified_license()` | 返回缓存载荷副本,未验证时返回 `None`。 |
| 在线校验 | `validate_license_online(payload)` | 调用 `validateLicense`;明确无效时抛出 `ExpiredError`。 |
| 启动后台巡检 | `start_license_watchdog(interval_minutes=5)` | 幂等启动,最短巡检间隔为 5 分钟。 |
| 注册生命周期回调 | `set_on_expired(callback)``set_on_grace(callback)``set_on_log(callback)` | 接收失效信息、宽限期小时数或许可证日志。 |
新许可证必须包含 `license_id``company_id``production_line_id`
`device_id``device_id` 必须是两个安全路径段组成的
`<company>/<production-line>`。旧许可证仍可本地验签,但不支持在线撤销。
网络故障不会立即中断控制;离线时限由 `REINLOOP_LICENSE_OFFLINE_HOURS` 配置,默认 72 小时。
## 客户端服务端协议
所有业务请求都发送至 `POST /api`。业务成功响应应至少包含 `success: true`
| `type` | 请求关键字段 | 用途 |
| --- | --- | --- |
| `validateLicense` | `licenseId`, `deviceId` | 校验许可证是否为 `active` 状态。 |
| `listModels` | `folder` | 列出 `<deviceId>/model_config` 中的模型。 |
| `downloadModel` | `fileID` | 获取模型临时下载 URL。 |
| `uploadDataFile` | `fileName`, `folder` | 获取对象存储直传凭证。 |
| `getIdentificationConfig` | `deviceId` | 获取九项辨识参数 CSV 的下载 URL。 |
| `registerIdentificationResult` | `deviceId`, `runId`, `fileName` | 登记待审核的辨识 CSV。 |
| `getIdentificationFeedback` | `deviceId`, `runId` | 查询辨识审核结果。 |
| `ackIdentificationFeedback` | `deviceId`, `runId` | 确认并清理已消费的审核结果。 |
| `createVolumeConfigRequest` | `deviceId` | 创建一次性容积配置请求。 |
| `getVolumeConfigRequest` | `deviceId`, `requestId` | 查询请求状态;就绪时取得配置下载 URL。 |
| `ackVolumeConfigRequest` | `deviceId`, `requestId` | 确认或清理容积配置请求。 |
## 配置环境变量
| 变量 | 用途 |
| --- | --- |
| `REINLOOP_SERVER_URL` | 服务端根地址。 |
| `REINLOOP_API_URL` | 完整 API 地址,优先级高于根地址。 |
| `REINLOOP_DEVICE_ID` | 旧许可证或开发测试设备标识;新许可证中必须与 `device_id` 一致。 |
| `REINLOOP_LICENSE_OFFLINE_HOURS` | 许可证在线校验的最大离线时长,默认 `72`。 |
| `REINLOOP_VOLUME_CONFIG` | 本地容积配置 JSON 的覆盖路径。 |