13 KiB
13 KiB
Modbus 新协议后端改造说明
Summary
本次改造目标是让后端完全按 显示界面modbus协议寄存器定义.md 的新版协议工作,并取消 backend/config 作为配置真值来源的角色。
本次计划确认的边界如下:
- 只调整后端代码,不修改前端代码。
- 配置页面首次加载时,后端需先从下位机通过 Modbus 读取参数并返回。
- 界面保存配置时,后端只动态写入下位机,不再把配置写入
backend/config下的device.json、channel.json、setting.json。 - 协议文档中没有定义寄存器的现有配置接口,本次先保留,并继续沿用原本地配置逻辑作为过渡。
- 先生成本地说明文档,用户确认后再开始改代码。
Current State Analysis
1. 当前接口层现状
当前配置接口集中在 backend/app/api/routes/config.py:
- 保留协议可能覆盖的接口:
GET/POST /api/config/channelGET/POST /api/config/line_alarm_settingGET/POST /api/config/ai_alarm_settingGET/POST /api/config/system
- 当前存在但新版协议未覆盖的接口:
GET/POST /api/config/devicePOST /api/config/device/passwordGET/POST /api/config/device/netGET/POST /api/config/device/uart
根据用户本轮决策,上述“协议未定义寄存器”的配置接口在本次后端改造先保留,并继续沿用原有本地配置文件逻辑。
2. 当前业务层现状
当前业务主要集中在 backend/app/services/platform_service.py,存在两个关键问题:
- 配置读取默认来自本地 JSON:
get_device_config()get_channel_config()get_line_alarm_setting()get_ai_alarm_setting()get_system_config()
- 配置保存采用“先写本地 JSON,再下发设备”的双写模式:
save_device_config()save_channel_config()save_line_alarm_setting()save_ai_alarm_setting()save_system_config()
这与“首次从下位机读取显示、保存时只写下位机、不再落本地配置文件”的新需求直接冲突。
此外,实时数据一次值计算当前仍依赖 setting.json -> line_alarm_setting[].transformer_change[] 中的 PT/CT 变比;如果配置文件取消真值角色,则这部分变比来源也必须切到设备回读数据。
3. 当前设备适配层现状
真实 Modbus 设备适配集中在 backend/app/adapters/device_client.py,当前实现与新版协议的差异点如下:
- 已符合或基本可复用:
- 四路实时数据输入寄存器读取
- AI 输入
0x00D0 ~ 0x00DE - B 码对时
0x00E0 ~ 0x00E2 - 开入读取
0x00E3 - 开出线圈写
0x0F - 系统时间同步
0x0000
- 明显不符合新版协议:
- 当前事件总寄存器仍按旧逻辑读取
0x00E4,新版应为0x00E5 - 当前“读事件”按旧逻辑读保持寄存器
0x0000 ~ 0x0003,新版应改为读输入寄存器0x0100,长度5 * n - 当前 AI/AO/AI 报警写入地址仍是旧版:
- AI 通道:
0x004C,新版应为0x0054 - AO 通道:
0x006A,新版应为0x0072 - AI 报警:
0x0088,新版应为0x0090
- AI 通道:
- 当前线路定值写入长度按 14 寄存器/每路处理,未包含 2 个变比参数;新版总长度为 64,并明确包含变比参数
- 当前没有“参数区回读”能力,只有写寄存器,没有从设备读取参数区并还原为 API 返回结构
- 当前事件总寄存器仍按旧逻辑读取
4. 当前配置仓储现状
backend/app/repositories/json_config_repo.py 目前负责:
- 写
device.json - 写
channel.json - 写
setting.json - 读上述 JSON 作为配置真值
按照本次需求,backend/config 中的配置文件不再承担运行期配置真值角色;对应仓储将不再被配置接口和业务服务依赖,只能保留给极少数非配置场景,或在后续整理中弱化/下线。
5. 当前测试现状
backend/tests/test_api.py大量依赖本地 JSON 写入与读取断言backend/tests/test_modbus_client.py使用 FakeTransport 验证旧版寄存器地址、旧版事件读取方式和旧版参数写入地址
这些测试在本次改造后会大面积失效,必须同步调整。
Proposed Changes
1. 调整配置接口边界
文件
backend/app/api/routes/config.py
改动内容
- 保留并继续支持的接口分为两类:
- 按新版协议改造为纯 Modbus 真值:
GET/POST /api/config/channelGET/POST /api/config/line_alarm_settingGET/POST /api/config/ai_alarm_settingGET/POST /api/config/system
- 协议未定义寄存器、先保留原本地逻辑:
GET/POST /api/config/devicePOST /api/config/device/passwordGET/POST /api/config/device/netGET/POST /api/config/device/uart
- 按新版协议改造为纯 Modbus 真值:
原因
- 新协议文档已覆盖的配置项,需切换为“设备寄存器即真值”
- 新协议文档未覆盖的配置项,用户明确要求先保留接口,避免立即影响现有前端调用
- 这些未定义项本轮继续沿用本地配置文件逻辑,待后续协议补齐后再迁移
2. 配置读取改为“首次从下位机读”
文件
backend/app/services/platform_service.pybackend/app/adapters/device_client.py
改动内容
- 移除
get_channel_config()对channel.json的依赖,改为调用设备侧“参数区回读”能力 - 移除
get_line_alarm_setting()对setting.json的依赖,改为读取线路定值寄存器并按line_no解析 - 移除
get_ai_alarm_setting()对setting.json的依赖,改为读取 AI 报警寄存器并还原 API 结构 - 移除
get_system_config()对setting.json的依赖,改为从设备读取可回读的系统参数 - PT/CT 变比不再从
setting.json读取,而改为从线路定值寄存器回读结果中提取
原因
- 配置页面首次加载必须从下位机读取显示
backend/config不再保存配置真值
3. 配置保存改为“只写下位机,不写本地 JSON”
文件
backend/app/services/platform_service.pybackend/app/repositories/json_config_repo.py
改动内容
- 删除以下方法中的本地 JSON 写入逻辑:
save_channel_config()save_line_alarm_setting()save_ai_alarm_setting()save_system_config()
- 返回值改为仅描述 Modbus 写入结果,不再返回本地
save_path - 业务层不再把配置结果回写
channel.json/setting.json JsonConfigRepository不再作为上述“协议已定义项”的运行期依赖device/device password/device net/device uart相关接口暂不纳入此调整,仍继续使用本地配置文件逻辑
原因
- 用户已明确要求取消本地配置文件落盘
- 配置应以设备当前寄存器值为唯一真值
4. 按新版协议更新寄存器地址和事件机制
文件
backend/app/adapters/device_client.py
改动内容
- 更新常量地址:
- 事件总寄存器:由旧值改为
0x00E5 - 读事件起始地址:改为
0x0100 - AI 通道写入起始地址:改为
0x0054 - AO 通道写入起始地址:改为
0x0072 - AI 报警写入起始地址:改为
0x0090
- 事件总寄存器:由旧值改为
- 新增/修改事件读取实现:
- 先读
0x00E5 - 若值为
n > 0,按0x04 + 0x0100 + 5*n读取输入寄存器 - 解析事件结构:时间戳、毫秒、线路号、事件类型、事件代码、动作值
- 读完后通过
0x03 + 0x0100 + n发送“读事件成功回复”
- 先读
- 新增/修改事件映射逻辑:
- 保护类
- 动作类
- 报警类
- 操作类
- AI 越限类
原因
- 当前事件实现仍停留在旧协议,和最新文档不一致
5. 补齐参数区回读能力
文件
backend/app/adapters/device_client.pybackend/app/services/platform_service.pybackend/app/schemas/platform.py
改动内容
- 在
device_client.py中新增参数回读方法,例如:- 读取串口设置寄存器块
- 读取线路定值设置寄存器块
- 读取 AI 通道设置寄存器块
- 读取 AO 通道设置寄存器块
- 读取 AI 报警设置寄存器块
- 读取系统设置寄存器块(仅限协议已定义项)
- 将回读寄存器块解析成后端当前接口使用的结构:
ChannelConfigInLineAlarmSettingInAiAlarmSettingInSystemConfigIn的可支持子集
- 根据新版协议更新线路定值寄存器长度与解析方式:
- 从原先 7 类规则扩展到包含 2 个变比参数
- PT/CT 变比参与一次值换算
原因
- 没有回读能力,就无法满足“参数页首次加载先从下位机读取显示”
6. 处理不再受协议支持的字段
文件
backend/app/schemas/platform.pybackend/app/services/platform_service.pybackend/app/api/routes/config.py
改动内容
- 识别协议未覆盖字段并做“分层处理”
- 对
SystemConfigIn中协议未定义的字段(如brightness、screen_saver)进行重新评估:- 若协议无寄存器,则从“纯 Modbus 真值范围”中剥离
GET/POST /config/system需按协议实际可支持字段精简或拆分
- 对历史仅本地保存的密码、网卡、版本号等结构:
- 本轮不从后端 API 中移除
- 继续保留 schema 与接口
- 继续沿用本地配置文件逻辑作为兼容过渡
- 在计划与代码实现中明确区分两类配置:
- 协议已定义项:首次回读设备、保存只写设备、不落本地
- 协议未定义项:接口先保留,继续本地逻辑
原因
- 用户已确认:协议未定义寄存器的配置接口先保留,不直接移除,并继续沿用原本地配置逻辑
7. 重写测试,验证“纯设备真值”模式
文件
backend/tests/test_modbus_client.pybackend/tests/test_api.py
改动内容
- 更新
test_modbus_client.py:- 使用新版地址与长度断言
- 验证事件总寄存器
0x00E5 - 验证“读事件内容
0x0100+ 成功回复0x0100”完整链路 - 验证 AI/AO/AI报警新地址
- 验证线路定值包含变比参数
- 更新
test_api.py:- 删除“协议已定义项”对本地 JSON 写入/读取的依赖型断言
- 改成 Mock/Stub 设备回读数据断言
- 增加“首次 GET 来自设备回读、POST 只触发设备写入”的测试
- 保留“协议未定义接口”的现有本地逻辑测试,或按兼容过渡方式调整断言
原因
- 当前测试体系大量基于本地 JSON 真值,必须同步迁移
Assumptions & Decisions
已确认决策
- 只修改后端,前端本次不动
- 按新版协议文档改后端 Modbus 行为
backend/config不再保存配置参数真值- 参数页面首次加载时,后端先从下位机读取显示
- 配置保存时,后端只动态写入下位机
- 协议未定义寄存器的现有配置接口,本次先保留
- 协议未定义寄存器的现有配置接口,本次继续沿用原本地配置逻辑
当前计划中的实现假设
line_alarm_setting中的 2 个变比参数可映射到现有transformer_change结构,或需在 schema 中进一步显式化为 PT/CT 变比字段。system配置若协议只定义时间同步,则该接口最终可能会缩减为仅时间设置相关能力。- 实时数据一次值计算仍由后端负责,但 PT/CT 变比来源将变更为设备回读参数,而非本地 JSON。
json_config_repo.py会退出“协议已定义项”的配置主链路,但仍保留给协议未定义接口使用。
Verification Steps
-
代码层验证
- 协议已定义项的配置 GET 接口都不再访问
backend/config/*.json - 协议已定义项的配置 POST 接口都不再写本地 JSON
device_client.py的寄存器常量与新版文档一致
- 协议已定义项的配置 GET 接口都不再访问
-
自动化测试验证
backend/tests/test_modbus_client.py通过backend/tests/test_api.py通过- 删除或更新“协议已定义项”依赖本地配置文件真值的旧断言
- 保留或改造“协议未定义项”的本地逻辑断言
-
联调验证
- 手工调用协议已定义项的配置 GET 接口时,能从下位机回读数据
- 手工调用协议已定义项的配置 POST 接口时,只触发 Modbus 写,不产生本地配置文件变更
- 手工调用协议未定义项接口时,仍保持当前本地逻辑可用
- 事件轮询流程符合:
- 轮询
0x00E5 - 读
0x0100 - 成功回复
0x0100
- 轮询
-
回归验证
- 实时数据、设备状态、报警历史、开出控制功能不因本次改造而退化
- WebSocket 轮询链路仍能持续推送数据