Skip to content

IEC61850 客户端模型发现进度条修复

版本: 1.0
日期: 2026-06-29
状态: 已实施

1. 问题背景

IEC61850 客户端在执行“发现模型”时,前端进度条偶发出现显示异常,主要表现为:

现象触发场景影响
进度条偶尔不显示模型发现接口较快返回,或状态轮询尚未拿到后端任务态用户无法确认发现任务是否已启动
进度卡在 0%前端先启动展示,但后端仍返回旧的空闲状态或粗粒度进度容易误判为任务卡死
进度条在动但秒数不一致本地计时器与后端任务状态各自推进,连接阶段又会中断轮询展示信息不可信
自动连接后进度提前消失未连接状态下触发发现模型,后端先连接再发现发现阶段仍在运行,但前端认为连接成功后即可停止

本次修复目标是让 IEC61850 客户端模型发现进度在“连接 + 发现 + 后处理”的完整链路中保持稳定、可恢复、可解释。

2. 根因分析

2.1 前端先轮询,后端任务状态尚未建立

发现模型按钮点击后,前端会立即启动进度展示和轮询,但后端状态可能还停留在上一次任务的 idle/done。如果前端过早采信旧状态,就会把刚启动的进度条停止或维持在 0%。

2.2 连接进度与发现进度共用状态,缺少操作类型区分

原实现只暴露 progress/status 等粗粒度字段,没有明确当前是 connect 还是 discover。当发现模型需要先自动连接时,前端无法判断当前进度属于连接阶段还是模型发现阶段。

2.3 连接成功会打断发现进度轮询

fetchDeviceStatus() 在检测到 IEC61850 服务状态变为已连接后,会停止连接进度轮询。对于“未连接时点击发现模型”的场景,连接成功只是发现流程的前置阶段,后续远程模型发现仍在继续,前端却提前停止了进度更新。

2.4 后端发现过程进度粒度过粗

后端原先主要返回 10%、50%、100% 等少量节点,真实发现过程中缺少按逻辑设备、构建模型、读取描述等阶段的连续反馈。大模型或网络较慢时,前端容易长时间停在某一个百分比。

2.5 前端本地秒数与后端任务时间不同步

前端使用本地定时器显示秒数,但后端任务已经运行的时间没有纳入恢复逻辑。切换页面、重新拉取设备状态或轮询重入时,秒数可能重置,导致同一条进度展示里秒数前后不一致。

3. 修复方案

3.1 后端新增统一进度快照

在 IEC61850 客户端处理器中增加任务级进度快照,统一描述当前进度任务:

字段说明
active当前是否有连接或发现任务正在运行
operation当前操作类型,取值为 connectdiscover
operation_id本次任务唯一标识,用于前端过滤旧状态
progress任务进度百分比
statusidle/running/done/failed 等状态
message当前阶段说明
elapsed_seconds后端统计的任务耗时

对应新增 _begin_progress()_update_progress()_finish_progress() 三个内部方法,连接和发现流程都通过同一套快照更新状态。

3.2 发现模型流程拆分为明确阶段

remote_discover_model() 现在会按阶段持续更新进度:

阶段进度范围说明
初始化10% ~ 20%创建发现任务;必要时先建立连接
远程发现20% ~ 70%按逻辑设备发现模型,并通过回调持续推进
构建模型75%生成统一模型结构
读取描述80% ~ 85%补充 dU 等描述信息
数据整理88% ~ 96%生成前端需要的模型、测点和统计数据
完成100%写入最终结果并结束任务

如果发现过程抛出异常,后端会将快照置为 failed,并保留失败消息,避免前端一直停留在运行态。

3.3 前端按操作类型恢复和过滤进度

前端进度轮询增加 mode 参数,明确当前轮询的是连接还是发现:

  • 发现模型时只接受当前 operation=discover 的活动任务。
  • 通过 operation_id 过滤旧任务状态,避免上一轮 done/idle 把新进度打断。
  • 页面重新拉取设备信息时,如果后端仍有 IEC61850 任务活动,会按 operation 自动恢复对应进度展示。
  • 轮询请求增加重入保护,避免上一次轮询未返回时下一次轮询又发起,造成状态乱序。

3.4 避免连接成功误停发现进度

fetchDeviceStatus() 只在当前进度模式为 connect 时,才会因连接状态变更而停止轮询。当前模式为 discover 时,即使服务端已经连上,也会继续等待发现流程返回最终状态。

3.5 统一秒数来源和展示节奏

前端计时逻辑改为基于任务开始时间计算,并吸收后端返回的 elapsed_seconds

  • 本地展示使用时间戳差值,不再依赖定时器累计次数。
  • 后端返回耗时更大时,前端会向后对齐,避免秒数倒退。
  • 进度文本只在一个位置显示秒数,避免阶段文本和进度文本各自显示不同耗时。

3.6 保证快速任务也能被用户看见

发现模型前端在发起 HTTP 请求前,先等待一次 Vue 渲染和浏览器帧,让初始进度行有机会真正绘制出来。任务结束后也保留一个很短的收尾展示时间,避免快速完成时进度条一闪而过。

4. 修改文件清单

文件改动说明
front/src/views/Device.vue重构 IEC61850 连接/发现进度轮询、秒数同步、旧状态过滤和快速任务展示
front/src/api/deviceApi.ts扩展 IEC61850 进度接口类型,增加 active/operation/operation_id/elapsed_seconds/message
src/device/protocol/iec61850_handler.py增加进度快照、任务互斥、发现阶段进度和失败收尾
src/device/core/device.py更新 IEC61850 进度查询接口说明
src/proto/iec61850/iec61850_client.py将发现进度回调传入模型发现服务,并补充构建/描述读取阶段
src/proto/iec61850/model/discovery.py按逻辑设备发现进度回调,提升长耗时发现过程的可见性
src/tests/iec61850/test_discovery_progress.py新增覆盖发现进度阶段、失败收尾和任务互斥
src/tests/iec61850/test_remote_discovery_refresh.py适配新增的发现进度回调参数

5. 修复后的行为

模型发现

  • 点击发现模型后,进度条会稳定显示,不再依赖后端第一次轮询是否已经进入运行态。
  • 未连接时触发发现模型,会显示连接和发现的连续进度,不会在连接成功后提前消失。
  • 大模型发现时,进度会随逻辑设备发现、模型构建、描述读取等阶段逐步推进。
  • 发现失败时,进度状态会进入失败态并展示失败原因。

秒数显示

  • 秒数只显示一份,避免同一条进度中出现多个不同耗时。
  • 页面刷新或设备状态重新拉取后,如果后端任务仍在运行,秒数会按后端任务耗时恢复。
  • 轮询乱序或重入不会导致秒数回退。

任务互斥

  • 连接任务和发现任务都纳入同一进度任务管理。
  • 当已有 IEC61850 连接/发现任务运行时,新任务会被拒绝,避免多个后台任务抢占同一个进度状态。

6. 验证结果

6.1 后端测试

text
python -m pytest -q src/tests/iec61850/test_discovery_progress.py src/tests/iec61850/test_remote_discovery_refresh.py
6 passed

python -m pytest -q src/tests/iec61850
98 passed, 25 skipped, 1 warning

新增测试覆盖:

  • 远程发现模型时按阶段推进进度,并在完成后进入 done/100%
  • 发现异常时进入 failed,并释放活动任务状态。
  • 已有发现任务运行时,第二个任务会被拒绝。

6.2 代码质量与前端构建

text
ruff check src/device/core/device.py src/device/protocol/iec61850_handler.py src/proto/iec61850/iec61850_client.py src/proto/iec61850/model/discovery.py src/tests/iec61850/test_discovery_progress.py src/tests/iec61850/test_remote_discovery_refresh.py
passed

ruff format --check src/device/core/device.py src/device/protocol/iec61850_handler.py src/proto/iec61850/iec61850_client.py src/proto/iec61850/model/discovery.py src/tests/iec61850/test_discovery_progress.py src/tests/iec61850/test_remote_discovery_refresh.py
passed

npm run type-check
passed

npm run build-only
passed

7. 后续建议

  1. 在 IEC61850 客户端页面增加可选的阶段明细日志,方便现场定位具体卡在哪个 LD 或哪个读取阶段。
  2. 如果后续模型发现还要支持取消任务,可以复用本次新增的 operation_id 作为取消目标。
  3. 对前端其他长耗时操作复用同样的“后端快照 + 操作类型 + 任务 ID + 后端耗时”模式,避免类似进度展示问题重复出现。

Released under the Apache 2.0 License.