Files
STM32F4-Base/docs/任务规划/UI补齐.md
T
super_agent_bot 3a2f9b21fb
CI / 静态门禁 (pre-commit) (push) Failing after 43s
CI / 主机侧单测 (MSVC) (push) Failing after 45s
CI / 静态门禁 (pre-commit) (pull_request) Failing after 45s
CI / 主机侧单测 (MSVC) (pull_request) Failing after 45s
refactor(time_sync)!: 退役 TCP :8888 对时任务,timeSyncTask 转纯 SNTP 校时节拍宿主(#78)
SNTP 客户端已随 #73/PR #77 上线合入(merge 2b848c4a),用户裁定
8888 对时任务退出历史舞台(gitea:77 线程原话,跟踪 Issue #78)。

生产侧(App/sync/time_sync.c v2.0,任务入口名不变,freertos.c 零改动):
- 删除 :8888 监听、TIME 包重组、sys_clock 写入、OPER 落痕、
  net_drop_conn 队头自救整条链(TIME_SYNC_PORT 宏随退役删除)
- 任务体收敛为:就绪屏障(100ms 分片、osFlagsNoClear)→
  200ms 校时节拍 task_wd_beat → time_sntp_run(net_get_generation())
  → 分片延时;喂狗节奏(TASK_WD_TIMESYNC=5,required_mask)不变
- 时钟写入口自此 = SNTP / UI 手工 / 104 C_CS,双写竞态(后写者赢)
  随之消失(墙钟说明 §15 退役公告、§16 现势口径)

工具与测试:
- 删除 test/host/time_sync_server.py(对时源)与 e02_probe.py
  (队头阻塞探针,载体随监听退役;判据脚本 v5_log_gap_report.py
  保留供旧日志解读)
- time_sync 主机单测重写 v2.0:33 断言覆盖分片延时 / 屏障 /
  SNTP 节拍与网络代次当轮交接 / 未出网守门;stub 的
  net_socket.h 裁剪至 net_get_generation 作编译期绊线
- 覆盖率基线 --update-baseline 收口(time_sync.c 101→20 行为刻意
  缩减,全仓 48/48 套绿)

文档与图:墙钟说明 §15 改退役公告(教训保留:CH395F FIN 丢未读
缓冲)、§16 单一网络来源;产品需求 FR-TIME-2 退役注记、§6.3 重写;
架构总览 / 软件架构规格 / 网络配置 / 网络自愈 §9.3 / BSD 指南 /
看门狗说明心跳与白名单行 / 实机测试指南 / 部署环境 / 继保规划 /
UI补齐时基口径 / 页面补齐规划 SNTP 页行 / 任务规划 README 叶数与
暂缓项行(SNTP 叶已绑、UI_PAGE_MAP_COUNT=31 口径)等约 30 处现势
口径同步;arch / net_stack 两图生成器与 SVG 同笔重跑。

台账:ram_baseline --update + check_mem_numbers --write + 体积凭证
(Code 254,648→253,428,−1,220 B)。静态链复测发现 timeSyncTask
1,904 B / iec104Task 1,600 B 低于 ISR 硬线:master 2b848c4a 同判据
timeSyncTask 即 2,056 B(本 PR 只减不增,−152 B 旧任务自身帧),
双 FAIL 为 #74/#77 后既有债;抬栈属 Ask-first 未擅自执行,登记簿
新增「静态链硬线双 FAIL」待台架复采,复测快照入 docs/内存管理/data。

验证:keil-build 0 错 0 警;time_sync/sntp 主机单测绿;
ci_local 全绿;doc-links --all 0。
2026-11-04 18:07:03 +08:00

11 KiB
Raw Blame History

当前任务: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,不另写一套计数逻辑,免得与生成物脱钩):

& '.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 的新源文件注册按双端注册规则处理。

时基口径已裁定,勿顺手改语义:口径 = 「先本地为准,内部真源是本地钟面」(用户裁定 2026-10-27, ../子系统设计/系统墙钟时间维护说明.md §1.1);当时冲突双方「面板时钟页 vs 8888 对时 vs 104 C_CS 写 UTC」中的 8888 已于 2026-11-04 退役(写入口现为 SNTP / UI 手工 / 104 C_CS,一律先换算成本地钟面再落库)。唯一待决的是 104 上行 CP56Time2a 是否转 UTC(送检前单独定,前引 ../子系统设计/系统墙钟时间维护说明.md §1.1 末)。裁定前不要改动 RTC/epoch 语义,也不要把 时钟设置页的「回读 RTC」判据改成按某一时区补偿——那等于替产品做掉一个未定的决定。

保护闭锁必须可见:整定页可以修改定值,但当前产品在 UA/UN/IA 未标定时保护判据闭锁。 页面应显示该状态,不能让用户误以为“修改定值后保护就会动作”。口径见 docs/任务规划/数据可信.md §4.3。


5. 当前不做

项目 不做原因 重开条件
遥信类型 / 防抖 / 双点 3 页 V0.1 无开入硬件,配置没有消费者 开入固件立项后,与开入开出一起做
net 层与其他结构债 当前只做 UI,避免两条主线互相拖慢 UI 当前清单完成后,按 README §2 切换
104 上行 UTC 换算(原「RTC 时基统一」) 内部口径已由用户裁定(2026-10-27:本地钟面为真源,各写入口先换算再落库,见 §4 注),「恒差 8 小时」的后写者赢阶段已结束;剩下的只是 104 上行是否按标准转 UTC,动了要改 104 上行语义 送检/第三方主站验收方向定下来后,作为跨模块变更单独立项(墙钟说明 §1.1 末)
主站地址白名单 CH395F 单连接 socket 上「拒绝即 close+重 listen」等于给扫描风暴开门,且该值现在没有任何既有消费点 有真实消费场景或多连接后端立项时再评