Files
STM32F4-Base/docs/门禁说明/setview-check.md
T
wandering1 fa80b17d5f docs(门禁说明): 补 bom-guard 与 setview-check 两篇详解
票面:task-20 合入后 README 索引上挂着我名的两篇(Lead 指定挂批 4 MR)。按本目录八段结构写,
「拦下过什么真事」一栏用同日实测,作者自己的也算。

- bom-guard.md:立项依据是 2026-10-25 一天内 5 次(道E 4 次 + 道B 1 次);症状 #870-D / #8 /
  #274 一类**假语法错**,位置不指向真因;MSVC 与既有钩子全照不出来;"人工逐文件比 HEAD"只防得
  住记得做的人。两条刻意不报的边界(新文件无 BOM、反向加 BOM)+ 一条刻意不做(不自动补,整文件
  重写会把可修的丢 BOM 变成不可修的 U+FFFD)+ 三处互指防漂移,各写清理由。也记了本门禁自己的
  立项提交被 gitlint 拦过(正文一行 92>80,量出来仍按了提交)——这一栏只挑别人的事写就等于暗示
  写门禁的人不需要门禁。
- setview-check.md:立论点是"分层边界制造的物理盲区"——BSP 不得 include App 头,行表 id 只能是
  裸数字 + 注名,编译期无法自证;像素断言又只看可见 8 行,40 项分 5 页,错位一行时第 1 页可能
  看着完全正常。另收两条脚本自身实测坑:\w+ 吃不下带引号的单位导致**整行静默跳过**(故加行数
  硬闸)、打印中文时 CP936 半路崩(门禁脚本崩在半路 = 一条都没检查)。退出码 1 与 2 分开:把
  "我没读懂"报成"你写错了"是检查类脚本最坏的一种失败。
- README.md:索引加两行;"那 46 个钩子" → 48、"40 个 hook → 23 篇" → 42 → 25 篇(不同步就是在
  让索引说谎)。AGENTS 里"两篇待补"那句已过期,但 AGENTS 是单写者文件,留给 Lead 收。

跳过的门禁(三条同族):mem-numbers / mem-budget / size-gate(L0c),与本笔无关,等台账回填。
2026-10-25 15:33:46 +08:00

6.9 KiB
Raw Blame History

setview-check — 定值查看行表与 prot_set 枚举序 / 上下限一致性

一句话:UI 侧四张定值视图表(Drivers/BSP/UI/ui_w_setview.c)与算法侧的定值定义 (App/algo/prot_set.h 枚举序 + App/algo/prot_set.c 的 g_prot_set_meta)之间有一条 编译期照不到的对齐关系——本门禁从外面把它钉住。

1. 它在查什么

脚本用正则读出三份事实,再逐条比对(tools/setview_check/check_setview_limits.py):

  1. 四张视图表的 id 合起来恰好覆盖 0..39 各一次(不多、不少、不重);
  2. 每个数值行的 min/max 等于 g_prot_set_meta 的 Q10 上下限按该行小数位换算后的整数;
  3. 行 kind(数值 / 二态串表)与 g_prot_set_meta[].is_ctl 一致;
  4. 单位串只允许 ASCII(V/A/ms/Hz/NULL)——中文字不进子集字体,见 font-charset.md;
  5. 小数位查表 s_dec[] 与行表 decimals 对同一个 id 取值一致(组件 get 只收到 id, 两处不一致就会显示错位数字)。

退出码:0 一致;1 不一致(打印具体行与期望值);2 解析锚点丢失——这是结构漂移, 说明 C 侧写法变了、脚本要跟着改,不是"数据错了"。1 与 2 必须分开:把"我没读懂"报成"你写错了" 是检查类脚本最坏的一种失败。

2. 为什么要它(这不是"多一道保险")

  • 分层边界制造的物理盲区:layer-deps 钩子禁止 Drivers/BSP/** include App/** 的头, 所以视图表里的 id 只能是裸数字 + 行尾注名(/* PS_OC1_EN */)。这条对应关系在编译期 无法自证:写错一个数字、少写一行、上下限抄错一位小数,编译器与 cppcheck 全都不会响。
  • 像素断言只覆盖可见部分:一页只有 8 行进入黄金参考,40 项定值分 5 页;行表整体错位一行时, 第 1 页可能看起来完全正常(名字和值都是"某个真定值"),要翻到第 2、3 页才可能被人看出来, 而人真去翻的时候往往已经太晚——那时基线已经按错的图刷新过了。
  • 也就是说:分层是对的,代价必须有人补。这条门禁就是补的那一步(同类补法见 registration-check.md 用反向校验补"新文件双端注册",ui-golden.md 补"改了就画错")。

3. 触发面

^(tools/setview_check/|Drivers/BSP/UI/ui_w_setview\.(c|h)$):改脚本自己、或改视图表所在 文件时触发。⚠ files 不命中时是 Skipped,Skipped ≠ Passed。

本钩子与实现文件是跨分支落地的(钩子配置在 task/bom-guard 分支,脚本在 task/pages-ui 分支):在脚本还没合入的树上,files 永不命中 → 钩子自然 skip,合入后自动生效,不需要任何人 再动配置。这一条写进配置注释,是为了避免下一个人以为"钩子没跑 = 配置坏了"。

4. 单独跑

# 仓库根执行(脚本按仓库根的相对路径读三个源文件,别在子目录跑)
& '.venv/Scripts/python.exe' tools/setview_check/check_setview_limits.py

正常输出只有一行:行表 40 行 / dec 40 项 / meta 40 项 -> OK。行数必须等于 40 是硬闸: 解析器少吞一行不算通过(见 §6.1)。

5. 好处

  1. 把一条"只有真机装载真定值、且人翻到第 2 页之后"才可能暴露的静默错位,提前到提交点;
  2. 让整定 4 页能安全复用同一批表:界内界外只有一份定义,不会出现"查看说合法、整定说越界" 两套边界(复用是当初把表放在 ui_w_setview.c 而不是各页面里的原因);
  3. 口径变更留下痕迹:RATIO_IDS 与文档 §3.2.2 的表注互为引用,改动必须同时解释。

6. 限制、盲区与写脚本时踩到的两个坑

脚本用正则读 C 源码,天然脆弱:换一种写法(宏生成表、初始化器拆行、结构体加字段)就可能 解析不到。以下是同日实测的两个真坑,都已固化进脚本:

6.1 \w+ 吃不下带引号的单位 → 整行静默跳过

行表项形如 { "过流Ⅰ段", 0, 1, 0, 0, "A", NULL }。最初的行正则用 \w+ 匹配"最后一个字段", 带引号的 "A" 匹配不上 → 整行不匹配 → 一条错误都不报,脚本照样打 OK。少检一行比检查错 更难发现(后者有人会去查,前者看起来像已经查过)。修法有两半:字段改用 \S+ 承接,以及加 len(rows) == 40 的硬闸——解析条数本身也要被检查,否则"没解析到"就等价于"没问题"。

6.2 打印中文 → Windows 控制台按 CP936 写 stdout 会崩在半路

门禁脚本崩在半路等于一条都没检查,而现场看到的是一串 Python traceback 而不是 FAIL。脚本开头 把 stdout/stderr 锁到 UTF-8(errors="replace")。同一条课在本仓一天里踩了两次,第二次才 写成固定动作——所以两个脚本里都有这段,且都写了为什么。

6.3 不检查的东西(别把它当万能闸)

  • 名字对不对不查:"过流Ⅰ段" 该不该叫这个名字是语义判断,脚本只核结构一致;名称口径 的真源是 docs/UI设计/页面扩充详细方案.md §3.2.2~§3.2.5 四张表;
  • 上下限本身合不合理不查:脚本只核"行表等于 meta 换算结果",如果 meta 自己就写错, 这条门禁会忠实地把错的值判成一致(真机定值核对在台架大窗里做);
  • Q10 → 显示小数位的换算函数本身由主机单测与像素断言覆盖,不在本脚本内(脚本重算一遍 换算是为了独立见证,不复用 C 侧代码)。

7. 豁免与基线

无存量豁免、无基线文件、无 --write。定值项数改变(PS_ID_COUNT ≠ 40)时必须同步:脚本里的 期望行数与 id 上界、ui_data.h 的 UI_DATA_SET_N、以及 docs/UI设计/UI_数据供给设计说明.md 的参数通道说明。

一条已修正的原口径记在这里免得被"改回去":四个返回系数按 2 位小数显示。原方案文档写 3 位, 而 Q10 存不下 0.95(0.95×1024 截成 972 → 真存 0.94921875),3 位会多打一位根本不存在的数字; §3.2.2 的表已同步改成 2 位并加 ⚠ 指向代码注释。

8. 改这个门禁本身

  • 行表写法一改(新增字段、换初始化风格),先跑脚本:退出码 2 就是"脚本要先跟上";
  • 新增校验项时同步新增一条"如果这行解析不到就 FAIL"的期望,不要让新校验继承 §6.1 的静默;
  • 想把它扩成通用"表 vs 元数据"检查器之前,先数一下真有几个这样的对象(现在只有一个)。

9. 变更记录

日期 变更
2026-10-25 首版(道E task-20 追加批;脚本与实现来自 task-15 批 3)。素材:\w+ 静默跳行、CP936 半路崩、满屏横杠与 4 字符位两条像素教训