编制日期:2026-06-17 · 里程碑:M5 · 对应需求 7 / 9 / 10(兼顾 12)· 决策 🔶D8(配置分层边界)/ 🔶D10(实时指标) · 风险 R8(配置迁移)/ R9(实时通讯) 父需求:
../00-需求总览.md§3(需求 7/9/10)、§5(🔶D8/🔶D10)、§6(R8/R9) · 方案权威:../需求文档/06-参数配置统一管理.md、../需求文档/05-实时通讯与服务监控.md改造对象工程:ivf_tl_operate_2.0/ivf_tl_Operate/(合并后主进程,前台 UI + 设置页)、ivf_tl_control_2.0/ivf_tl_Control/、ivf_tl_control_2.0/ivf_tl_ServicesImpl/(后台托管服务,监控数据来源)
把当前「配置散落四处、明文密码、operate/control 各存一份、运维只能改 XML、断线无 UI 提示、心跳被屏蔽」的状态,改造为:
passWord / MQTT 凭据 / 硬编码 tl13579 纳入治理),原"只能改 XML"的项搬到界面可编辑。return; 屏蔽的 MQTT 保活心跳、链路健康可视化(服务器/MQTT/上报队列/最后成功通讯时间)、断线显著提示(不"假装实时")、图片补传机制补强(落盘队列 + 去重 + 断网累积兜底)。配置统一只动「读写来源 + 入口聚合 + 加密」,不改既有业务参数语义;监控页只读不写;通讯改造只补强保活/提示/补传,不改 MQTT 主题与上报报文结构。 既有设置项(HEPA/保养时间、对焦时间、帧率、抠图数、舱室/对焦/调试入口、密码校验语义)一律保留(00-需求总览.md §8「既有设置项不删只增统一入口」)。
| 来源 | 精确位置 | 内容 | 问题 |
|---|---|---|---|
operate 本地 App.config |
ivf_tl_operate_2.0/ivf_tl_Operate/App.config:3-29 |
autoFocus(实为烧录换气)/outInter/userName/passWord(明文123456)/tlNum/urlIp/urlPort/mqttIp/mqttPort/houseEnabled/Language |
手改 XML;明文密码;键名词不符义 |
control 本地 App.config |
ivf_tl_control_2.0/ivf_tl_ControlTest/App.config:3-46 |
CCDError/csTime/gbTime/VentNum/VentPre/VentWaitTimeB/D/AutoWaitTime/CCDAutoWaitTime/CCDFailedWaitTime/CCDFailedNumber/QueuAir/StopPro/userName/passWord(明文123456)/cacheDisk/urlIp/urlPort/kfkaIP/kfkaPort/mqttIp/mqttPort/Language |
同名键与 operate 重复且默认值不一致(operate urlIp=192.168.1.92 vs control 192.168.0.91;mqttIp 同样不一致) |
数据库 TLSetting(服务器下发) |
operate SettingPageView.xaml.cs:52 SettingCommonApi、:116 CommonUpdateApi;字段见 tLSettingCommon.autoFocusTime/videoFps/cropNum/heapDate/keepDate/cleanSurfaceData/tmpDir |
对焦时间/帧率/抠图数/换气/HEPA/保养/清理天数/缓存盘 等 | 部分现场可改(设置页),但与本地配置来源割裂 |
| 硬编码口令 | SettingPageView.xaml.cs:109 MiMa():textBox.Password.Trim() == "tl13579" |
全设备统一明文工程师口令,7 处入口共用(:167/190/213/237/256/291/323) |
明文、不可改、无权限分级 |
下位机 EEPROM / calibration.json |
见 03 / M2 计划 | well 水平位/Z 零点/灯光/阀门时间;自动对焦标定 | 本计划只纳入只读展示,写入归 03/M2,不在 M5 动 |
配置读取方式(核对到的精确调用点):
| 键 | 读取点 | 写回点 |
|---|---|---|
operate urlIp/urlPort/mqttIp/mqttPort/outInter |
ivf_tl_operate_2.0/ivf_tl_Operate/AppData.cs:79-82 构造函数 |
— |
operate userName/passWord/tlNum |
LoginWindow.xaml.cs:36-38(回填登录框) |
AppData.cs:159-167 SetApp(...)(OpenExeConfiguration) + :169-197 setAppConfig(...)(直接改 ivf_tl_Operate.dll.config XML) |
operate Language |
App.xaml.cs:57 |
— |
operate cacheDisk(合并后) |
MainWindow.xaml.cs:96 启动托管 control 时读 → PathHelper.pan |
— |
control 全部业务参数 + urlIp/kfkaIP/mqttIp/mqttPort |
ivf_tl_control_2.0/ivf_tl_Control/AppData.cs:49-74 构造函数(ConfigurationManager.AppSettings[...]) |
— |
control userName/passWord/cacheDisk |
ivf_tl_ControlTest/Window1.xaml.cs:53-55,91-92(原 control 登录窗,M1 已去 UI;合并后由 MainWindow.xaml.cs:96 单登录透传) |
— |
去重关键:M1 合并后两进程变一进程,
ConfigurationManager.AppSettings实际只读主进程(operate)的ivf_tl_Operate.dll.config——controlAppData.cs:49-74在同进程内读到的将是 operate 的 config,control 那份ControlTest/App.config在合并后不再生效。因此「去重」不是手工比对两文件,而是:把 control 独有键并入 operate config(单一文件),并补回 control 需要、operate config 现在缺的键(kfkaIP/kfkaPort/csTime/gbTime/VentNum/...等约 16 个),否则int.Parse/.ToString()会 NPE(R8「改一处漏一处导致服务起不来」的具体形态)。
| 关注点 | 现状(核对到的精确位置) | M5 处理 |
|---|---|---|
| MQTT 保活心跳 | ivf_tl_control_2.0/ivf_tl_ServicesImpl/MqttServices/MqttService.cs:79-80:Task.Run(ClientMqtt); return;——return; 后的 TryPingAsync 保活循环(:81-113)整段死代码不执行 |
M5-04:恢复保活心跳 |
| 断线补连 | MqttService.cs:197-208 _mqttClient_DisconnectedAsync 已在断开回调里 ClientMqtt() 重连;但 :65 WithCleanSession() 断线期间漏发不补 |
M5-04:保留重连 + 评估 CleanSession(标 D10/M7) |
| 断线 UI 提示 | 断线仅 MqttAlarm?.Invoke(...) 写日志(:202-203),operate/control 均无 UI 失联提示 |
M5-03/04:链路健康卡片 + 显著失联提示 |
| 在线态来源割裂 | operate MainPageViewModel.StartThread:741-773 HTTP 5s 轮询 TlInfoTimeApi(运行/保养/HEPA) + 报警计数;舱室态走 MQTT RecMqttMessage:512。broker 掉线 HTTP 仍正常 → 显"在线"但数据停更 |
M5-03:链路健康同页区分两源 + 最后通讯时间 |
| control 实时上报线程 | ivf_tl_Control/AppData.cs:273 StartUpLoadImage(图片)、:316 StartSendMqttMsg(舱室态1s)、:372 StartSendHistoryMsg、:435 StartPushMessageThread;均 StartAsync():221 内拉起 |
监控数据来源(只读取状态,不改逻辑) |
| 图片补传现状 | AppData.cs:273-311 StartUpLoadImage:每 5s 扫描落盘目录 *.jpg 调 KafkaUploadImageAsync;:1258-1345:成功才 File.Delete(:1313-1317),失败 KafkaAlarm 保留文件下轮重扫;imageDTO 为空则 File.Move 到 error 目录(:1290-1293) |
M5-04:已具「失败保留+重扫重试」雏形,但无显式队列/无去重防重传/无断网累积上限——补强为落盘队列可视化 + 去重 + 兜底(05 §2.5「无明确补传队列」) |
| 监控取数桥 | M1 已在 operate 进程内托管 control:MainWindow.xaml.cs:103-125 new StartMain().StartRun();ivf_tl_Control.AppData.Instance 单例同进程可直接访问 |
M5-02:监控页直接读 ivf_tl_Control.AppData.Instance 暴露的只读状态 |
| 监控可用数据源(control 内存/事件,已核对存在) | AppData.cs:1461 GetDiskInfo(磁盘)、MqttService.cs:263 MqttIsConnected()(MQTT)、AppData.cs:759 HouseBin_GetCCDServiceEvent/:652 HouseBinPhotoStateEvent(CCD/拍照)、:164 ImageDTODic+扫目录(上传队列)、各 HouseBin*/BufferBottleBin(温度/气体态)、:172 HttpService(服务器通信) |
M5-02:聚合为只读监控快照 |
来源割裂的本质(05 §1):HTTP
online与 MQTT 舱室态两条链独立,任一断、另一未断时界面"假装实时"。M5 不合并两源,而是在链路健康页把两源的「最后成功通讯时间 + 连接态」并排显式呈现,让运维一眼看出哪条断了。
System.Configuration.ConfigurationManager(沿用现有读取链,仅扩键 + 集中封装);写回沿用 OpenExeConfiguration + RefreshSection(已存在于 AppData.cs:159-205)System.Security.Cryptography.ProtectedData(DPAPI,LocalMachine 作用域,零外部依赖、与本机绑定,契合「本机凭据」语义)——存储时加密、读取时解密、界面脱敏显示UserControl + ViewModel + DispatcherTimer 轮询 ivf_tl_Control.AppData.Instance 只读快照(不订阅写事件、不持有可写引用)MQTTnet TryPingAsync/ConnectAsync、现有落盘扫描线程,只补强(解屏蔽 + 队列状态 + 去重标记)urlIp/urlPort/mqttIp/mqttPort/kfkaIP/kfkaPort、cacheDisk、Language、outInter、tlNum、userName/passWord(加密)、houseEnabled。TLSetting 的 autoFocusTime/videoFps/cropNum/heapDate/keepDate/cleanSurfaceData 等保持数据库来源。csTime/gbTime/VentNum/VentPre/VentWaitTime*/AutoWaitTime/CCDAutoWaitTime/CCDFailedNumber/CCDFailedWaitTime/QueuAir/StopPro)——06 §2 建议这些进数据库,但现状在 control App.config。M5 先原样保留在本地层并集中展示,迁移到数据库登记为 [D8] 待确认项,不在 M5 强行搬迁(避免 R8 起不来)。get 状态、不 set、不下发指令、不新增控制按钮。代码上监控 ViewModel 只接受 AppData.Instance 的只读快照 DTO,不持有可调用控制方法的引用。SettingPageView 现有 7 个入口与业务项全部保留,M5 只新增「统一配置」与「服务监控」两个入口,不改既有 MiMa() 校验语义、不改既有 UpdataTlSetting() 流程。TL/House/surface/{tlSn}、TL/House/collecting-data)、上报报文结构、Kafka topic 一律不动;M5 只补强保活/提示/补传可靠性。每步产出登记到统一清单(沿用 M1 的 V-xxx,本计划用 V-M5-xx)。需运行/服务/网络/broker/断网恢复的项标 [M7];依赖 D8 配置分层拍板的标 [D8];依赖 D10 指标拍板的标 [D10]。
| 任务 | 主题 | 需求 | 步骤数 |
|---|---|---|---|
| M5-01 | 配置统一:去重合并(两份 App.config → 单一来源)+ 集中读写封装 | 9 | 5 |
| M5-02 | 配置统一:密码/口令加密 + 设置页统一配置入口(界面化)+ 旧值迁移 | 9 | 5 |
| M5-03 | 只读服务监控页 + 链路健康可视化(服务/连接/队列/磁盘 + 最后通讯时间) | 7/10 | 5 |
| M5-04 | 通讯稳定:恢复 MQTT 保活心跳 + 断线显著提示 + 图片补传补强 | 10 | 4 |
共 4 子任务 / 19 步骤。建议执行序:M5-01 → M5-02 → M5-04 → M5-03(先把配置单一化与加密落定,再补强通讯可靠性,最后做监控页——监控页要展示心跳/补传状态,依赖 M5-04 暴露的状态字段)。M5-03 与 M5-04 状态字段对齐后可并行细化。
目标:合并后单进程只有 operate 一份 App.config 生效,把 control 独有键并入,消除「operate/control 各存一份、默认值不一致」;新增统一读取封装类,杜绝 AppSettings[...] 散落直读。
ivf_tl_operate_2.0/ivf_tl_Operate/App.config:3-29(目标合并文件);参照 ivf_tl_control_2.0/ivf_tl_ControlTest/App.config:3-46(来源)App.config 的 <appSettings> 内补入 control 现有、operate 缺失的键(保留注释说明,纠正词不符义):CCDError/csTime/gbTime/VentNum/VentPre/VentWaitTimeB/VentWaitTimeD/AutoWaitTime/CCDAutoWaitTime/CCDFailedWaitTime/CCDFailedNumber/QueuAir/StopPro/cacheDisk/kfkaIP/kfkaPort。同名键(userName/passWord/urlIp/urlPort/mqttIp/mqttPort/Language)只保留 operate 一份,值以 operate 为准(IP 默认值统一为现场实际值,登记 [M7] 现场核对)。ConfigurationManager.AppSettings 只读主进程 config,control AppData.cs:49-74 同进程读到的是 operate config;不补全键,control 构造函数 int.Parse/.ToString() 立刻 NPE(R8)。这是「去重 = 单一数据源」的落地形态,不是手工比对两文件。ControlTest/App.config 合并后不再生效,标注其为历史文件(保留只读供迁移比对,见 M5-02-5)。ivf_tl_operate_2.0/ivf_tl_Operate/Helpers/AppConfigHelper.cs(命名沿用 operate 现有 Converts/、Helpers/ 风格,若无 Helpers/ 目录则新建)GetString(key, default)/GetInt(key, default)/GetEncrypted(key)),内部仍走 ConfigurationManager.AppSettings,但集中容错(键缺失返回默认值而非 NPE)+ 分层标注(注释每键属本地层/数据库层/待 D8)。预留 Save(key,value) 走现有 OpenExeConfiguration+RefreshSection(沿用 AppData.cs:159-167 写法)。AppSettings[...] 散落 14 文件直读(见 Architecture A),易漏改、易 NPE。集中封装是去重与后续加密的单一接管点。ivf_tl_control_2.0/ivf_tl_Control/AppData.cs:49-74ConfigurationManager.AppSettings["xxx"].ToString() 直读(:51-52 mqttIp/mqttPort、:49-50 urlIp/kfkaIP)改为经 AppConfigHelper(或就地加 ?? 默认值 容错),消除「键缺失 → .ToString() NPE」。:54-74 的 int.TryParse 已容错,保留。:51 AppSettings["mqttIp"].ToString() 直接崩,control 后台线程起不来(R8)。ivf_tl_operate_2.0/ivf_tl_Operate/AppData.cs:79-82、App.xaml.cs:57、MainWindow.xaml.cs:96、Windows/LoginWindow.xaml.cs:36-38AppSettings["xxx"].ToString() 直读,缺键会崩。逐点改为 AppConfigHelper 容错读取(语义不变)。LoginWindow:36-38 回填登录框的 userName/passWord/tlNum 改走解密读取(接 M5-02-2)。App.config 注释(ivf_tl_operate_2.0/ivf_tl_Operate/App.config)目标:明文密码/凭据加密存储 + 界面脱敏;把"只能改 XML"的本地项搬到设置页统一配置页;硬编码 tl13579 纳入治理;旧明文值平滑迁移。
ivf_tl_operate_2.0/ivf_tl_Operate/Helpers/CryptoHelper.csEncrypt(plain)/Decrypt(cipher)/IsEncrypted(value) 基于 System.Security.Cryptography.ProtectedData(DPAPI,DataProtectionScope.LocalMachine),密文 Base64 存 config;IsEncrypted 用前缀标记(如 enc:)区分明文/密文,支持「读时若为明文则视为旧值待迁移」。ivf_tl_operate_2.0/ivf_tl_Operate/App.config(passWord 项);读取 Windows/LoginWindow.xaml.cs:37、AppData.cs(MQTT 凭据);写回 AppData.cs:159-167 SetApp / :169-197 setAppConfigpassWord 调 CryptoHelper.Encrypt;读取(LoginWindow:37 回填、登录透传)先 IsEncrypted 判断——密文解密、明文(旧值)直接用并触发一次「读后回写为密文」迁移。MQTT 凭据(control AppData.cs:156-157 现为硬编码 aivfo/aivfo,operate MqttUserName/MqttPassword 字段)若纳入 config 则同样加密。ivf_tl_operate_2.0/ivf_tl_Operate/View/SettingPageView.xaml.cs:106-112 MiMa()(口令源 :109)"tl13579" 比对改为读取加密存储的工程师口令(config 新增 engineerPwd 本地层键,CryptoHelper 加密;首次无值则回退默认 tl13579 并提示迁移)。保留 MiMa(PasswordBox) 方法签名与 7 处调用点不变(:167/190/213/237/256/291/323),只换口令来源。tl13579 纳入治理(加密 + 可改);签名不变 = 不触碰既有入口(00-需求总览.md §8)。ivf_tl_operate_2.0/ivf_tl_Operate/View/SettingPageView.xaml(新增入口控件,与现有 7 入口同构)+ SettingPageView.xaml.cs(新增 UnifiedConfig_MouseUp 事件,仿 :211 HouseSetting_MouseUp 走 MiMa 进入);新增 View/UnifiedConfigView.xaml(.cs) + ViewModel/UnifiedConfigViewModel.csAppConfigHelper.Save + 加密项经 CryptoHelper;每组带说明文案(纠正词不符义,如 autoFocus 注明"实为烧录换气开关")+ 改后生效提示(沿用现有 MessagePrompt)。数据库层项(对焦时间/帧率/抠图数等)维持现有 SettingPageView 的 TLSetting 编辑路径,统一配置页对其做「只读引用+跳转」,不重复写入口。AppConfigHelper(或一次性 ConfigMigrator 静态方法,operate 启动 App.xaml.cs 调用一次);比对来源 ivf_tl_control_2.0/ivf_tl_ControlTest/App.config(历史只读)passWord/engineerPwd 明文→密文回写;(b) 若 operate config 缺 control 独有键,从历史 ControlTest/App.config 导入默认值(保证 M5-01-1 未手填的键有兜底);(c) 同名键不一致时以 operate 为准并写日志(去重比对留痕)。迁移幂等(已迁移则跳过)。目标:设置页新增纯只读"服务运行监控"页,从托管的 control 内存/事件取只读快照,展示各服务/连接/队列/磁盘 + 链路健康(服务器/MQTT/上报队列/最后成功通讯时间)+ 断线显著提示。不新增任何控制。
ivf_tl_control_2.0/ivf_tl_Control/MonitorSnapshot.cs(只读 DTO)+ ivf_tl_Control/AppData.cs 新增 GetMonitorSnapshot() 只读方法MqttService.cs:263 MqttIsConnected() / :23 IsConnected)、服务器通信态(HttpService 最近调用成功标记,新增只读字段)、CCD/拍照态(HouseBin_GetCCDServiceEvent/HouseBinPhotoStateEvent 已有的 CCD 状态字段聚合)、上传队列长度(ImageDTODic.Count + 落盘目录 *.jpg 待传数)、磁盘(GetDiskInfo(PathHelper.pan),AppData.cs:1461)、各舱温度/气体态(HouseBin*/BufferBottleBin 只读字段)、各链路「最后成功通讯时间」(新增只读时间戳字段,见 M5-03-2)。ivf_tl_control_2.0/ivf_tl_Control/AppData.cs(StartSendMqttMsg:316-367 MQTT 上报成功后、KafkaUploadImageAsync:1298-1312 Kafka 上传成功后、HttpService 调用成功后)LastMqttOkAt/LastKafkaOkAt/LastHttpOkAt),供 DTO 与链路健康呈现「最后成功通讯时间」、判定"过期/失联"。ivf_tl_operate_2.0/ivf_tl_Operate/View/ServiceMonitorView.xaml(.cs) + ViewModel/ServiceMonitorViewModel.csDispatcherTimer(默认 2s,阈值占位 [D10])调 ivf_tl_Control.AppData.Instance.GetMonitorSnapshot() 刷新;页面无任何按钮/输入/下发控件(约束 4)。AppData.Instance(MainWindow.xaml.cs:103 已托管);触控/自适应套 M4 框架。ServiceMonitorView.xaml(.cs) + ServiceMonitorViewModel.cs(同 M5-03-3)online 与 MQTT 舱室态两源(解决 05 §1 来源割裂"假装实时")。提示为只读呈现(变色/图标/文案),不弹可操作控件。ivf_tl_operate_2.0/ivf_tl_Operate/View/SettingPageView.xaml(新增入口控件)+ SettingPageView.xaml.cs(新增 ServiceMonitor_MouseUp,加载 ServiceMonitorView):337 About_MouseUp(无密码、直接 LoadPage)新增只读入口——服务监控只读、无需工程师口令亦可,或按 [D8] 权限分级决定是否要口令;进入即 LoadPage(new ServiceMonitorView(...))。目标:恢复被 return; 屏蔽的保活心跳、断线写入失联状态供监控页显示、图片补传由"裸扫目录"补强为有去重/有累积兜底的可靠补传。
ivf_tl_control_2.0/ivf_tl_ServicesImpl/MqttServices/MqttService.cs:79-80:79 Task.Run(() => ClientMqtt()); 之后的 :80 return; 是把 :81-113 的 TryPingAsync 保活循环整段屏蔽成死代码。改为保活心跳与首连接并存——保留 ClientMqtt() 首连,删除/绕过 :80 return; 使 :81-113 保活循环生效(循环内 TryPingAsync 失败则 ConnectAsync 重连,10s 间隔)。注意避免与 :206 _mqttClient_DisconnectedAsync 的重连重复并发——以 IsConnected/IsDispose 做幂等护栏。ivf_tl_control_2.0/ivf_tl_ServicesImpl/MqttServices/MqttService.cs:65 WithCleanSession()WithCleanSession()(改持久会话 + QoS≥1)以减少断线期间漏发;因涉及 broker 端会话与重复投递语义,M5 不直接改默认行为,仅记录评估结论与改法,留 M7 真机/broker 验证后定。当前舱室态走 1s 周期重发(StartSendMqttMsg:359),漏一帧影响小;临床图片走 Kafka 独立链(M5-04-3),故 CleanSession 风险主要在状态类。ivf_tl_control_2.0/ivf_tl_Control/AppData.cs:273-311 StartUpLoadImage、:1258-1345 KafkaUploadImageAsync:1313-1317 删、:1301-1305 失败保留)——补强三点:(a) 去重防重传:上传中文件加 in-flight 集合标记,避免 5s 重扫期间同名文件并发重传(现 ImageDTODic lock 仅护 DTO 缓存,未护"正在上传");(b) 断网累积兜底:MQTT/Kafka 断时落盘目录会持续累积,新增待传数与磁盘水位联动告警(接 M5-03 队列长度 + GetDiskInfo),超阈值([D10])显著提示,不静默堆积;(c) 补传可见:待传队列长度、最后成功上传时间纳入监控快照(M5-03-1/2)。保留"落盘即不丢、成功才删"的现有不丢语义,不引入新的删图风险。PathHelper.GetAutoFocusSaveDirectory/GetEmbryoPicSaveDirectory)。ivf_tl_operate_2.0/ivf_tl_Operate/ViewModel/MainPageViewModel.cs:741-773 StartThread(HTTP 5s 轮询)TlInfoTimeApi(:754) 成功/失败时记录 operate 侧「最后成功 HTTP 通讯时间」与连接态(新增只读字段),供链路健康页区分「HTTP online 链」与「MQTT 舱室态链」——解决 05 §1「broker 掉线 HTTP 正常仍显在线」的来源割裂。失败时 :755 if (a == null) continue; 现状静默跳过,补一处只读失联标记(不改轮询节奏)。Init() 刷新逻辑,只加只读状态标记。| 编号 | 内容 | 标签 |
|---|---|---|
| V-M5-01 | 合并 config 真机启动 control 全键解析无 NPE;IP/端口与现场一致 | [M7] |
| V-M5-02 | AppConfigHelper 缺键取默认容错 | [M7] |
| V-M5-03 | control 构造函数缺键降级不崩 | [M7] |
| V-M5-04 | operate 启动直读点容错 + 登录回填正常 | [M7] |
| V-M5-05 | 配置分层归属定稿(换气/CCD 入库?无网兜底?权限分级?) | [D8] |
| V-M5-06 | DPAPI 加解密往返一致;是否需跨机密钥 | [M7][D8] |
| V-M5-07 | 明文 config 自动迁移密文 + 登录成功;密文登录成功 | [M7] |
| V-M5-08 | engineerPwd 改后 7 入口校验生效;权限分级是否实装 | [M7][D8] |
| V-M5-09 | 统一配置页改本地项落盘密文重启生效;既有项不受影响 | [M7] |
| V-M5-10 | 旧值导入+去重比对+缺键兜底;无网只读副本是否需要 | [M7][D8] |
| V-M5-11 | 监控快照各字段运行时取值正确 | [M7] |
| V-M5-12 | 各链路最后成功通讯时间断链停更、其他续 | [M7] |
| V-M5-13 | 监控页只读刷新;确认无写控件 | [M7] |
| V-M5-14 | 断 MQTT/HTTP/Kafka 任一显失联+阈值上色;阈值具体值 | [M7][D10] |
| V-M5-15 | 设置页服务监控入口可进;是否需口令/权限 | [M7][D8] |
| V-M5-16 | MQTT 心跳断后检出重连、无连接风暴 | [M7] |
| V-M5-17 | CleanSession 持久会话方案 broker 验证后定 | [M7] |
| V-M5-18 | 断网图片累积不丢、恢复全补传、无重复、无并发重传 | [M7] |
| V-M5-19 | HTTP 断时 operate 失联标记置位、监控可见 | [M7] |
MainWindow.xaml.cs:103-125,ivf_tl_Control.AppData.Instance 同进程可访问)。配置去重依赖 M1 合并后单一 config 生效的事实。calibration.json/EEPROM 标定为只读纳入展示,写入归 M2/03,不在 M5 改。