Files
STM32F4-Base/docs/任务规划/UI补齐.md
T
super_agent_bot ad7338365c
CI / 静态门禁 (pre-commit) (push) Failing after 6m14s
CI / 主机侧单测 (MSVC) (push) Successful in 54s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 4m35s
CI / 主机侧单测 (MSVC) (pull_request) Successful in 47s
feat(sntp): 板端 SNTP 校时接入——coreSNTP 序列化器 + [sntp] 段 + 设置页(#73)
- vendored coreSNTP v2.0.0 序列化器(MIT,仅 serializer+LICENSE,零堆),
  48 字节报文编解码在库,节奏与准入判据在本方(RFC 4330 §10 调研口径)
- App/sync/time_sntp.c 挂 timeSyncTask 的 8888 事件循环,等待切片 ≤50 ms,
  不饿任务狗与 IWDG;懒建 UDP socket,代际变化/禁用/死错误码即关闭归还
- 防伪 = OriginTimestamp 逐位等于发出时 T1(含低 16 位随机小数位);
  mode/stratum/闰秒指示/KoD 按 RFC 拒收;DENY·RSTR 换服务器、RATE 只退避
- 主备轮换 + 失败指数退避(5 s 起、60 s 封顶)+ 首轮 1~5 分钟随机错峰;
  成功恢复 poll_min 周期(1~1440 分,出厂默认 60,默认不启用不发包)
- 钟面 = 本地时间:UTC+8 固定偏移落 sys_clock_set_unix(§1.1 时基裁定,
  第三个写入口,装置仍不存时区);|offset|<2 s 只记日志不步进,冷启动或
  更大偏差步进并回写 SD2506,留痕 [SNTP] step 与 syslog OPER
- 首个校验通过的同步置 SYS_EVT_TIMESYNC_READY(就绪位,消费方按需 NoClear)
- [sntp] 配置段(enable/server1/server2/poll_min)属主 sntp_cfg.c,
  注册在 net_cfg_load();UI 页 31「SNTP 设置」(密码叶):启用开关 +
  主/备服务器 octet 编辑 + 周期(分) + 保存,复用 net_cfg_save_request 链
- 测试与门禁:test/host/sntp 新套件(报文/防伪/KoD/退避周期/阶跃域/配置
  注册表)、net_cfg 与 time_sync 套件补 fake、黄金参考 66→74 张零漂移、
  字符集 228 字、Keil 0 错 0 警(RO +5,848 B 含字体)、覆盖率基线回填
- 文档:墙钟维护说明 §16、网络配置说明 [sntp] 节、配置文件设计说明变更记录、
  产品需求 FR-TIME-3 与 8.3/9.1.2 台账、UI 补齐规划/UI补齐 31 叶口径、
  登记簿销项并登记「SNTP 校时真机判据」等台架(PC 时间源 192.168.31.161/.13)
2026-11-04 16:20:22 +08:00

120 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 当前任务:UI 补齐
> **执行清单已清空(2026-10-28)**:记录 5 页与运行报告页已落地、绑页并纳入像素黄金回归。
> **2026-10-29 录波 UI 道**:「手动录波」由不做转落地(绑操作页),新增「录波回放」叶(节点 43);
> 叶数口径同步为 43/34/30/4(下方逐项)。
> 本文件保留为 UI 补齐的**范围与判据口径**(§1 叶数、§4 每页统一动作、§5 不做的取舍);
> 下一顺位见 docs/任务规划/README.md §2.0(换主线待用户点头),上板待复核项见 docs/任务规划/登记簿.md §7。
## 1. 目标与范围
菜单树共 **34 叶**(节点行合计 43,缩进即层级):按行内 `#page=` 实测**已绑 31 叶、未绑 3 叶**,
页面映射表 `UI_PAGE_MAP_COUNT` = 31(与已绑叶数一致)。未绑 3 叶 = §5 明确不做的 **遥信 3 叶**,
与下面分类表逐项对得上;2026-10-29 录波 UI 道把「手动录波」从不做转为
落地并新增「录波回放」叶,绑 +2(手动转绑 + 新叶);2026-11-04 SNTP 客户端立项(Issue #57 拍板
选型、#73 拍板节奏),SNTP 设置叶转绑定(+1);2026-10-28 记录 5 页与运行报告页落地后,
原「需补配置或写入方」的 6 叶缺口清零并按销项删行(该行内容见本节末与 §3)。
| 分类 | 数量 | 当前怎么处理 |
|---|---:|---|
| 无开入硬件 | 3 | 不做:遥信类型、遥信防抖、双点遥信 |
(原「缺独立模块或产品定义:SNTP 设置」行已于 2026-11-04 随 SNTP 客户端立项转绑定销项;手动录波更早,2026-10-29 随故障录波 UI 道转绑。)
现有基础:`ui_w_editor` / `ui_w_setlist` / `ui_page_action` 已就绪;`ui_data` 已扩到**四通道**
(rt / par / info + 遥测死区与系数用的第四张注入表);像素黄金用例与字符集门禁已存在,内容页黄金
现有 **74 张**(菜单 8 状态另计;2026-10-29 录波 UI 道 +6 张:手动录波 3 态 + 录波回放 3 态;2026-11-04 SNTP 设置页 +8 张)。**装置维护 3 页、遥测死区/系数 2 页、通讯设置页、SNTP 设置页、记录 5 页与
运行报告页都是把这套基础接上真实消费者做出来的,不另发明一套机制。**
逐页形态见 `docs/UI设计/页面补齐规划.md`;数据契约见
`docs/UI设计/UI_数据供给设计说明.md`。本文件保留范围、完成判据与不做的取舍口径(执行清单已于 2026-10-28 清空)。
### 叶数判定与复核(2026-10-28 复核)
1. **节点行** = `ui_menu_tree.txt` 里非空、非 `#` 开头的行(当前 **43** 行,含根「主界面」)。
2. **缩进即层级**(每级 2 空格;Tab 会被 `gen_menu.py` 直接拒绝):某节点行之后再没有更深缩进的行 = **叶**
(当前 **34** 叶);有更深缩进后继者 = 菜单节点(当前 **9** 个)。等价于生成物口径 `ui_menu_tab_has_children(node) == false`。
3. **绑定**:叶行行尾带 ` #page=` = 已绑(当前 **31** 叶);不带的 = 未绑(当前 **3** 叶)。
4. **闭合**:`未绑 = 待做 + 不做` —— 当前待做 **0**(§2 清单已清空)+ 不做 **3**(遥信 3)= **3**,
与上面的分类表、§5「当前不做」表逐项对得上。
5. **别拿 `grep -c '#page='` 当已绑叶数**:2026-10-28 实测它得 **29**,比真值多 1 —— 文件头第 5 行是规则说明里的
` #page=<模块名>` 示例行(不是节点行),必须先剔注释/示例行;剔完的数才等于生成物 `UI_PAGE_MAP_COUNT`(现 31)。
复核命令(复用生成器自己的解析器 `tools/menu_gen/gen_menu.py` 的 `parse_tree`,不另写一套计数逻辑,免得与生成物脱钩):
```bash
& '.venv\Scripts\python.exe' -c "import io,sys; sys.path.insert(0,'tools/menu_gen'); import gen_menu as g; n,_=g.parse_tree(io.open('ui_menu_tree.txt',encoding='utf-8').read()); leaf=[i for i,x in enumerate(n) if all(y[0]!=i for y in n)]; b=sum(1 for i in leaf if n[i][4]); print('nodes=%d leaves=%d bound=%d unbound=%d' % (len(n),len(leaf),b,len(leaf)-b))"
```
输出 `nodes=43 leaves=34 bound=30 unbound=4`(2026-10-29 录波 UI 道落地后实测);交叉核对生成物:`ui_menu_tab.h` 的 `UI_MENU_TAB_COUNT` = 43(节点行数)、
`ui_page_registry.h` 的 `UI_PAGE_MAP_COUNT` = 30(已绑叶数)——一对 43、一对 30,与上面逐项对得上。
三个已踩过的错算法(每种都同时给**当时**与**2026-10-28 重跑**的产物——错法不会自己失效,只是错数跟着已绑叶数一起漂):
**把 42 个节点行当叶子**(多算 9 个菜单节点:当时已绑 21 叶 → 得「未绑 21」,2026-10-28 同一错法得「未绑 14」= 42 − 28);
**`grep -c '#page='` 当时得 23**(当时已绑 22 叶,多的那 1 正是文件头注释第 5 行的 `#page=<模块名>` 示例字样,必须先剔注释行;
2026-10-28 同一命令得 29 = 当时已绑 28 + 该示例行 1;2026-10-29 当时值 31 = 已绑 30 + 示例行 1;2026-11-04 现值 32 = 已绑 31 + 示例行 1);**按叶子名去重得 29**(`参数`/`定值`/`控制字`/`软压板` 在「整定」「查看」下各一份,
4 对同名不能合并;2026-10-28 重跑仍是 29 = 33 叶 − 4 对同名)。
(21 / 23 两个错数分属 2026-10-27「已绑 21 叶」与「已绑 22 叶」两个时点的实测,只用来说明错法,不代表现值;
去重 29 与上面 grep 现值 29 **只是撞号**:一个是「合并同名叶」、一个是「不剔注释行」,都与真值 30(2026-10-29 现值)无关。)
---
## 2. 执行清单
> 状态只在这里维护。完成一项就删除对应行,并同步调整后续顺序;不要在本文件留完成史。
> 当前无待做项:最后两项(记录 5 页、运行报告)已于 2026-10-28 落地并销项删行。
> 下一批 UI 页面开工时在本节重新起表;完成一项就删除对应行,本文件不留完成史。
### 依赖关系
- 各项虽可独立开发,但当前仍按表序单道执行(菜单树、页面注册表与字库都是生成物)。
- **不允许用静态演示数据充数**:记录 5 页与运行报告页都是先有真实写入方 / 真实计数器(道F task-10、道G task-12),再补页面(2026-10-28 交付口径),下一批沿用。
- 历史教训(已完成的装置维护 3 页留下的口径,后续项沿用):**执行类页面不得做成「点了个按钮但没效果」**——清除记录必须按 `syslog_clear_state()` 出真反馈;遥测死区/系数两页的三态用
`run_par_dirty_peek()` 区分「已受理」与「已落盘」,且黄金必须出 WAIT 与 OK 两张(假件保留脏位、只由
headless pump 清),否则真机的 WAIT 态永远不会被像素回归覆盖。
---
## 3. 数据源对照
| 页面 | 现有数据源 | 还缺什么 |
|---|---|---|
| 通讯设置 | 页面与六态黄金已随 `728d6067` 入库;`[comm]` 段与端口真源在 `App/protocol/iec104/iec104_comm.{c,h}` | 「改后重启即生效」真机判据、配置段数与键数上限核对(台架窗口统一补做并留证) |
| 记录 5 页 | 五类记录 ID / 文件 / 写入点已齐(docs/任务规划/登记簿.md §7 与 App/log/README.md §五类记录);reader 注入两端已映射 7 个记录源 | 页面已交付;只剩真机判据(真记录翻页、掉电保持、清除后归零),见 docs/任务规划/登记簿.md §7 |
| 录波两页 | 手动录波操作页 + 录波回放页已落地绑页(2026-10-29 录波 UI 道);数据源 = `App/algo/wave_ring`/`wave_store` 真实现经 `ui_data_wave_ops_t` 注入,回放读盘走 `vol_lock` try 锁小窗口 | 页面已交付;真机判据归台架(真实触发落盘的段号连续性、削徽标真值、切段切道实测毫秒与卷锁忙「本轮无段」行为,见 `docs/子系统设计/故障录波设计说明.md` §10 台架判据) |
| 运行报告 | boot_stats(SD2506 用户 SRAM 上电次数 + 本次复位原因快照,道G task-12)、iec104_serv 四个只读观测计数、现成 uptime_s | 页面已交付;**跨开机累计不做**(用户裁定只报本次开机)。真机待复核 SRAM 自增与四态判定,见 docs/测试说明/专项验证/模拟器差距清单.md §2.3 |
---
## 4. 每页的统一完成动作
1. 新增 `ui_page_xxx.c/.h`,优先复用现有组件。
2. 在 `ui_menu_tree.txt` 对应叶子增加 ` #page=xxx`。
3. 运行 `& '.venv\Scripts\python.exe' tools/menu_gen/gen_menu.py`,检查生成物差异(该脚本只用标准库,但入口统一走 `.venv`;
新增文案后还要跑字库链,那条**依赖 fontTools** ⇒ 见 `font-regen` skill 与 `docs/环境与部署/本地工具路径环境变量方案.md`)。
4. 新文案先过字符集提取和字库生成,不能显示方块。
5. 加像素黄金用例与必要的主机单测。
6. 涉及保存、重启、主站读回的项目,台架可用后统一补做实机判据并留证。
**单写者约束**:`ui_menu_tree.txt`、页面注册表、字库生成物不得由多个分支同时修改。
`MDK-ARM/*.uvprojx` 的新源文件注册按双端注册规则处理。
**时基口径未定,勿顺手统一**:面板时钟页与 8888 对时把「本地钟面当 epoch」写入,而 104 `C_CS` 按 CP56Time2a 的
UTC 写入,后写者赢 ⇒ 装置墙钟与主机本地时刻恒差 8 小时。用户裁定前**不要改动 RTC/epoch 语义**,也不要把
时钟设置页的「回读 RTC」判据改成按某一时区补偿——那等于替产品做掉一个未定的决定。
**保护闭锁必须可见**:整定页可以修改定值,但当前产品在 UA/UN/IA 未标定时保护判据闭锁。
页面应显示该状态,不能让用户误以为“修改定值后保护就会动作”。口径见
`docs/任务规划/数据可信.md` §4.3。
---
## 5. 当前不做
| 项目 | 不做原因 | 重开条件 |
|---|---|---|
| 遥信类型 / 防抖 / 双点 3 页 | V0.1 无开入硬件,配置没有消费者 | 开入固件立项后,与开入开出一起做 |
| net 层与其他结构债 | 当前只做 UI,避免两条主线互相拖慢 | UI 当前清单完成后,按 README §2 切换 |
| RTC 时基统一 | 两套写入口径并存(面板与 8888 写本地钟面、104 写 UTC),恒差 8 小时;统一任一侧都要动 104 上行语义或 UI 判据 | 用户裁定时基方向后,作为跨模块变更单独立项 |
| 主站地址白名单 | CH395F 单连接 socket 上「拒绝即 close+重 listen」等于给扫描风暴开门,且该值现在没有任何既有消费点 | 有真实消费场景或多连接后端立项时再评 |