# 实时故障显示需求说明 日期:2026-07-23 来源:`新需求.png` ## 需求目标 当前故障需要在实时监控页即时、准确、明确地显示出来,不能再依赖 10 分钟一次的历史扫描后才出现在报警预览中。 本次需求涉及四块: 1. 0x17 回路分控器参数解析调整 2. 实时监控页新增当前故障显示 3. 报警预览历史记录即时写入 4. 未定义回路不参与轮询 ## 当前问题 ### 实时监控页没有故障信息 当前实时监控页只展示回路开关状态、电压、电流、功率、调光值等信息,没有展示当前故障条目。 结果是:即使设备已经返回故障,用户也无法在实时监控页直接看到。 ### 报警预览显示太慢 后台当前通过 `ScanM9z` 定时扫描故障,定时周期是 10 分钟: ```go AddTaskByFunc("ScanM9z", "ScanM9z", "@every 10m", m9zTtyApi.ScanM9z) ``` 所以用户看到“十几分钟后报警预览才有故障内容”,和当前代码行为一致。 ### 故障文案不够准确 当前故障文案包含: ```text 欠压/短路故障 过压/开路故障 电源故障 未知异常 ``` 新需求要求按实际故障类型显示,不再混用“欠压/过压”描述。 ### 回路电流解析需要调整 当前 0x17 解析中,回路总电流按 `0.1A` 处理。 新需求示例: ```text 01 BF = 0.447A ``` 也就是 `0x01BF = 447`,应按 `0.001A` 解析。 ## 当前故障显示区域 “当前故障显示区域”指实时监控页上一块专门展示当前故障的区域。 它不是历史报警列表,也不是报警预览页,而是当前设备正在发生的故障提示。 建议位置: ```text 实时监控页右上方空白区域 或实时监控页底部空白区域 ``` 建议显示内容: ```text 当前故障: 回路1短路故障 回路2开路故障 回路3设备1/2电源故障 ``` 没有故障时显示: ```text 当前无故障 ``` 建议在该区域增加一个手动刷新按钮: ```text 刷新当前故障 ``` 按钮用途: 1. 现场人员可以立即重新读取当前故障,不必等待下一次自动刷新 2. 调试和验收时可以快速确认故障是否已恢复 3. 当通信短暂异常或页面刚恢复时,可以主动刷新当前状态 交互建议: 1. 点击后调用实时监控接口重新读取当前故障 2. 按钮请求期间显示 loading 或禁用,避免连续点击造成串口请求堆积 3. 刷新成功后更新当前故障区域 4. 刷新失败时提示“当前故障刷新失败”或保留原状态并显示错误提示 每条故障建议包含: | 字段 | 说明 | | --- | --- | | 回路号 | 例如:回路1、回路2 | | 故障类型 | 短路故障、开路故障、电源故障 | | 设备号 | 仅电源故障需要显示,例如:设备1、设备2 | | 故障码 | 可选显示,例如:01、02、04 01、04 03 | ## 故障码解析规则 0x17 返回的故障码按以下规则解析: | 故障码 | 含义 | 显示文案 | | --- | --- | --- | | `0x01` | 短路故障 | 回路n短路故障 | | `0x02` | 开路故障 | 回路n开路故障 | | `0x04 + 设备掩码` | 电源故障 | 回路n设备x电源故障 | 电源故障示例: | 故障码 | 含义 | 显示文案 | | --- | --- | --- | | `04 01` | 设备1电源故障 | 回路n设备1电源故障 | | `04 02` | 设备2电源故障 | 回路n设备2电源故障 | | `04 03` | 设备1/2电源故障 | 回路n设备1/2电源故障 | 如果同一回路同时存在多类故障,应拆成多条故障显示,或合并为一条清晰文案。 ## 收到故障无需确认 “收到故障无需确认”指设备返回故障数据后,系统直接显示并记录,不弹窗询问用户是否确认。 正确流程: ```text 设备返回故障 -> 后端解析 -> 实时监控显示 -> 写入报警历史 ``` 不需要: ```text 设备返回故障 -> 弹窗问用户是否确认 -> 用户确认后才显示/记录 ``` 报警预览页里“批量删除”的确认弹窗可以保留,因为它属于用户删除操作确认,不属于故障进入系统前的确认。 ## 未定义设备不轮询 当前代码固定轮询 10 个回路: ```go for i := 0; i < 10; i++ { // read 0x17 } ``` 新需求要求未定义设备不参与轮询。 建议行为: ```text 配置了 4 路:只轮询 0~3 配置了 8 路:只轮询 0~7 配置了 10 路:轮询 0~9 ``` 好处: 1. 减少串口请求 2. 避免无效设备超时 3. 提升实时监控响应速度 4. 报警预览可以更快出现有效故障 如果暂时没有回路数量配置,建议新增配置项,例如: ```json { "deviceInfo": { "loopCount": 10 } } ``` 没有配置时默认 `10`,但现场可以按实际回路数量调整。 后端实时接口需要返回当前实际参与扫描的设备数,便于前端展示和现场核对当前扫描范围。 建议字段: ```json { "scan_device_count": 4 } ``` 字段含义: | 字段 | 说明 | | --- | --- | | `scan_device_count` | 本次按配置实际参与 0x17 轮询的设备/回路数量 | 如果后续需要区分“参与扫描数量”和“成功读取数量”,可以再增加: ```json { "scan_device_count": 4, "scan_success_count": 3 } ``` ## 后端改动点 ### 1. 调整 0x17 数据解析 文件: ```text internal/library/m9z/m9z_SubLoopParameters.go ``` 改动: 1. 回路总电流从 `0.1A` 比例调整为 `0.001A` 2. 保留 `AlarmStatus` 和 `AlarmCode` 3. 增加结构化故障列表,例如 `Faults []LoopFault` 建议结构: ```go type LoopFault struct { LoopIdx uint `json:"loop_idx"` DeviceIdx uint `json:"device_idx,omitempty"` Type string `json:"type"` Message string `json:"message"` Code string `json:"code"` } ``` ### 2. 统一故障文案生成 建议新增公共函数,供实时接口和历史扫描共用: ```go func BuildLoopFaults(loopIdx uint, alarmStatus uint16, alarmCode string) []LoopFault ``` 输出示例: ```text 回路1短路故障 回路2开路故障 回路3设备1/2电源故障 ``` ### 3. 实时接口返回故障字段 文件: ```text internal/module/m9zTtyApi/read.go ``` 接口: ```text /m9z/getDeviceStatus2 ``` 每个回路建议增加字段: ```json { "scan_device_count": 4, "Loops": [ { "has_fault": true, "fault_msg": "回路1短路故障", "fault_code": "01", "faults": [] } ] } ``` 其中每个回路对象包含: ```json { "has_fault": true, "fault_msg": "回路1短路故障", "fault_code": "01", "faults": [] } ``` 顶层 `scan_device_count` 表示当前后端实际参与扫描的设备/回路数量。 同时把实时监控中的回路电流改为直接使用 0x17 的回路总电流字段,不再累加子模块电流。 ### 4. 实时写入报警历史 文件: ```text internal/module/m9zTtyApi/cron.go ``` 当前历史报警只由 `ScanM9z` 10 分钟扫描写入。新需求应改为: ```text 实时接口读到故障 -> 立即写入 data/data.json ``` 同时需要做去重,避免实时接口每次刷新都重复插入同一条故障。 建议去重维度: ```text comm_uid + loop_idx + fault_code + fault_msg + 未处理状态 ``` ### 5. 轮询数量配置化 把以下固定循环: ```go for i := 0; i < 10; i++ { } ``` 改成: ```go for i := 0; i < loopCount; i++ { } ``` `loopCount` 从配置读取,未配置默认 10。 实时接口返回值需要带上当前扫描数量: ```json { "scan_device_count": 10 } ``` 涉及位置: ```text internal/module/m9zTtyApi/read.go internal/module/m9zTtyApi/cron.go ``` ## 前端改动点 ### 1. 实时监控页增加当前故障区域 页面: ```text 实时监控 ``` 展示: ```text 当前故障: 回路1短路故障 回路2开路故障 ``` 无故障时: ```text 当前无故障 ``` 当前故障区域需要提供手动刷新按钮: ```text 刷新当前故障 ``` 点击后重新调用 `/m9z/getDeviceStatus2`,只刷新实时监控状态和当前故障显示,不需要弹确认框。 按钮请求期间应显示 loading 或禁用,避免连续点击造成重复串口请求。 ### 2. 适配实时接口字段 调用接口: ```text /m9z/getDeviceStatus2 ``` 读取字段: ```text scan_device_count Loops[].has_fault Loops[].fault_msg Loops[].fault_code Loops[].faults ``` 前端可在当前故障区域或调试信息中展示当前扫描数量,例如: ```text 当前扫描设备数:4 ``` ### 3. 报警预览保持历史列表 页面: ```text 报警预览 ``` 接口继续使用: ```text /m9z/fault/list ``` 后端实时写入后,用户刷新报警预览即可更快看到记录。 ### 4. 删除确认保留 报警预览页的批量删除确认弹窗可以保留。 “收到故障无需确认”只针对故障进入系统,不针对删除操作。 ## 建议实施顺序 1. 后端先完成 0x17 解析和故障文案统一 2. 后端改 `/m9z/getDeviceStatus2` 返回当前故障 3. 后端增加实时写入历史和去重 4. 后端增加 `loopCount` 配置 5. 前端实时监控页增加当前故障区域和“刷新当前故障”按钮 6. 前端适配接口字段 7. 联调真实 0x17 报文:`01`、`02`、`04 01`、`04 02`、`04 03` ## 待确认点 1. `loopCount` 放在哪个配置节点:建议放在 `deviceInfo.loopCount` 2. 电源故障的设备掩码最大支持几个设备:目前图片只展示设备1、设备2 3. 同一回路多故障时前端展示为多行,还是合并为一行