feat(ui+记录): 整定写路径与四类页落地,五类记录写入方补齐
UI 面:ui_data 增加深度 4 参数写队列(请求 168 B、队列 .bss 672 B)与状态机 OK/ERR_RANGE/ERR_LOCKED/ERR_BUSY,ui_data_feed 出队后按注入 ops 走「闭锁 → 整批 预检 → 逐项 prot_set_set_sealed」,只提交改动位图;par 帧尾追加 cal_block (口径 = UA/UN/IA 三路 ADC_CAL_F_VALID,与 protect_task 判据同构,不用 rt.eng 反推,V0.1 下 eng 恒 0)、UI_DATA_VER 升到 2。参数/定值/控制字/软压板四叶绑定 内容页(UI_PAGE_MAP_COUNT 12→16,复用四个查看模块,零新增 .c),编辑态按 is_editable 分派,LOCK(写不进去)与「未标定」(仍可改值)两源两通道两词。 记录面:syslog_request_clear/state/apply 三段式删除 API(UI 只发请求,落地在 defaultTask 的 drain 尾部且必须后置,卷锁一律 try,幂等只认 FR_NO_FILE); 事故/告警/启动/操作/遥控五类各有一个真实写入点,记录类型 = 日志 ID 本身 (一类一个 /log 严格 8.3 文件;64B 定长体没有类型字段位,塞字段会砸掉既有读者)。 为守 protectTask 872 B 静态最坏链另拆 syslog_post_quiet()(无 DBG 的投递核, 丢弃留痕挪到 drain 侧差值补发),syslog_post 对外语义逐字不变。 为什么两道合成一笔而不是各一笔(实测,不是省事):simulator/main.c 同时消费 两道新增 API(整定 pump 与 logtest 清除用例),按道切文件会让中间提交编不过; RAM 受管快照与体积同码凭证描述的是合并后的 .map,拆开必落在「台账与 .map 不同 码」这条红线上。pre-commit 跑钩子前会 stash 未 staged 部分,这类耦合没法绕。 实测:@build 0 错误 0 警告;Code 228,260 / RO 24,960 / RW 1,440 / ZI 135,976 B; RW_IRAM1 79,992 B = 61.0%、RW_CCM 87.9%(阈值 92%);九个任务静态最坏链全 PASS, protectTask 872 B / 57% 改前后逐字节不变(记录投递没垫栈)。主机单测 ui_data 82→ 164、sys_log_mcu 106→137、prot_elm 47→60、iec104 141→154、iec104_serv 28→34, 既有断言零删改;48 个钩子 --all-files 全绿;编号门禁可判定 86.34%(基线 86.0%)、 不可判定 1,153 处低于上限 1,166;doc-links 无法判定 0;UI 黄金 18 页扩到 27 页 连跑两次逐字节一致;字库 diff 空。 顺手修掉三处既有缺陷(都是本轮第一个消费者才暴露):sim_syslog.c 的 s_paths 行宽 16 而 "sim_selftest.log" 正好 16 字符没有 NUL 位(stat/remove 读越过数组尾,此前 靠后面 .rodata 碰巧为 0);ui_w_setlist 二态行 ENTER 不回绕(控制字与软压板出厂值 全在最后一项,按了像没反应而叠层里已是越界值);生成物 ui_menu_tab.h 与 gen_menu.py 模板漂移(上一笔改了模板没重跑生成器),现随生成器输出对齐。 未收口(不算完成):保存后重启值保持与主站 C_RD 读回两条只能上板,台架窗口执行; LOCK 屏显与越界反显的页面侧在模拟器造不出来(模拟器不跑定值自检、无 NAND), 已由生成侧单测与代码注释点名差距;同类页数与钩子数陈述残留另立待办。
This commit is contained in:
@@ -54,9 +54,30 @@ PAGES = [
|
||||
("vset", "ddedede"),
|
||||
("vword", "ddededde"),
|
||||
("vplate", "ddededdde"),
|
||||
# ── 道F task-2:整定 4 页(参数定值 → 整定 → *,#P 叶,123=修改密码可编辑)──
|
||||
# 导航公共前缀:dd 进"参数定值"→ e 进(选中"整定")→ e 进整定子框(选中"参数")
|
||||
# → e 进密码页;密码 123 = "uruuruuue"(三框各 +1、两次右移、确认,与 netcfg 同串法);
|
||||
# 000(直接 e)= 查看密码 → 只读。定值/控制字/软压板 在整定子框里多按 d 选到该行再 e。
|
||||
# 保存行在第 (行数) 行:参数 9 行 = 2 页 → 8×d 落到保存行;定值 19 行 = 3 页。
|
||||
("sparam_p2", "ddeee uruuruuue dddddddd"), # 参数整定第 2 页:保存行 ENTER
|
||||
("sparam_ro", "ddeee e"), # 000 只读:无保存行、无徽标
|
||||
("sparam_edit", "ddeee uruuruuue d e"), # PT二次 进编辑(值列是编辑串,无单位)
|
||||
("sparam_oob", "ddeee uruuruuue d e l l d e"), # 编到 0(< min=1)→ ENTER 拒退 + 越界
|
||||
("sparam_save", "ddeee uruuruuue e u e dddddddd e"), # PT一次 +1 → 保存行 ENTER → OK
|
||||
("sparam_landed", "ddeee uruuruuue e u e dddddddd e u"), # 保存后回首屏:新值 10001V 已在帧里
|
||||
("sset", "ddeed e uruuruuue"), # 定值整定首屏(18 项 + 保存 = 3 页)
|
||||
("sword_cycle", "ddeedde uruuruuue e"), # 控制字 二态行 ENTER:跳闸 → 告警
|
||||
("splate", "ddeeddde uruuruuue"), # 软压板整定首屏(10 项 + 保存 = 2 页)
|
||||
("pwd", "ddeee"), # 密码页初始态:3 框 000、光标首框
|
||||
("pwe", "ddeee uru"), # 密码页调值+移光标:110、光标第 2 框
|
||||
("pwk", "ddeee uruuruuue"), # 密码页输 123:u / r / u,u / r / u,u,u / e → 关页进空白终点框(菜单屏)
|
||||
# 密码页输 123:u / r / u,u / r / u,u,u / e → 关页并按授权"续做进入"。
|
||||
# ⚠ **道F task-2 起这张图的落点变了**(黄金参考已 --update 刷新,属有意改判据):
|
||||
# 整定 4 叶绑定内容页之前,123 确认后走 menu_password_ok 的"无内容页 → 压空白
|
||||
# 终点框"分支(屏上是 4 框菜单,整定叶本身是个死叶子);绑定之后走
|
||||
# "有内容页 → ui_content_page_open(page, UI_PERM_MODIFY)"分支,落在**整定-参数页**。
|
||||
# 也就是说这张图现在同时钉住两件事:密码页授权链正确 + 123 真的能开可编辑整定页。
|
||||
# 旧图并非"错",是那条分支从此不再可达——留档见 2026-10-26 提交正文。
|
||||
("pwk", "ddeee uruuruuue"),
|
||||
("pwc", "ddeee ue"), # 密码页 100 不一致 → 清空重输(回到 000 初始态像素)
|
||||
# 网口设置(node 30,通讯参数下第 2 项,需密码):
|
||||
# dddddd = 根框下移 5 至通讯参数;e 进框;d 选中网口设置;e 进密码页
|
||||
@@ -272,6 +293,79 @@ TEXTS = {
|
||||
("r1名", "子网掩码", (38, 52), False),
|
||||
("r4名", "保存", (80, 95), False),
|
||||
],
|
||||
# ── 道F task-2:整定 4 页文本级断言 ─────────────────────────────────────────
|
||||
# 值全部来自 simulator/main.c 的固定帧(prot_set 出厂默认 + cal_block 恒 1),
|
||||
# 每条断言都是"某个具体事实":徽标在不在、保存行在第几页、越界提示、改值后落没落。
|
||||
# ⚠ 编辑态的值列**没有单位后缀**(ui_w_setlist_refresh 编辑分支走
|
||||
# ui_w_editor_format,非编辑分支才拼 unit)——所以 sparam_edit 断 "100" 而不是
|
||||
# "100V":这条差异本身就是"这一行正在编辑"的像素证据,别把它"顺手统一"掉。
|
||||
"pwk": [
|
||||
("标题", "参数", (0, 24), False),
|
||||
("徽标", "未标定", (0, 24), False), # cal_block=1:整定页必须看得见
|
||||
("r0名", "PT一次", (24, 38), True), ("r0值", "10000V", (24, 38), True),
|
||||
("r4名", "过量返回", (80, 94), False), ("r4值", "0.95", (80, 94), False),
|
||||
("r7名", "低频返回", (122, 136), False), ("r7值", "1.01", (122, 136), False),
|
||||
("页脚", "第 1 页,共 2 页", (140, 160), False), # 8 项 + 保存行 = 9 行 → 2 页
|
||||
],
|
||||
"sparam_p2": [
|
||||
("徽标", "未标定", (0, 24), False),
|
||||
("保存名", "保存", (24, 38), True),
|
||||
("保存值", "ENTER", (24, 38), True), # 从未投递 → IDLE
|
||||
("页脚", "第 2 页,共 2 页", (140, 160), False),
|
||||
],
|
||||
"sparam_ro": [
|
||||
# 000 查看密码:同一份描述符的只读分支——有行、无保存行、无徽标(见 ABSENT)
|
||||
("标题", "参数", (0, 24), False),
|
||||
("r0名", "PT一次", (24, 38), True), ("r0值", "10000V", (24, 38), True),
|
||||
("r7名", "低频返回", (122, 136), False),
|
||||
("页脚", "第 1 页,共 1 页", (140, 160), False), # 无保存行 → 8 行正好 1 页
|
||||
],
|
||||
"sparam_edit": [
|
||||
# 编辑态的可见特征:选中带反显(白底黑字)+ 值列**没有单位后缀**(见 ABSENT)
|
||||
("r1名", "PT二次", (38, 52), True),
|
||||
("r0名", "PT一次", (24, 38), False), ("r0值", "10000V", (24, 38), False),
|
||||
("r3名", "CT二次", (66, 80), False), ("r3值", "5A", (66, 80), False),
|
||||
],
|
||||
"sparam_oob": [
|
||||
# PT二次 下限 1:把百位从 1 调到 0 → 0 < min → ENTER 被拒、留在编辑态并打"越界"
|
||||
("越界提示", "越界", (38, 52), True),
|
||||
("r1名", "PT二次", (38, 52), True),
|
||||
("r0值未变", "10000V", (24, 38), False), # 别的行不受影响(编辑只作用选中行)
|
||||
],
|
||||
"sparam_save": [
|
||||
("保存名", "保存", (24, 38), True),
|
||||
("保存值", "OK", (24, 38), True), # 投递 → drain 落定 → 终态 OK
|
||||
("页脚", "第 2 页,共 2 页", (140, 160), False),
|
||||
],
|
||||
"sparam_landed": [
|
||||
# 保存后再按一次上移回到首屏:新值必须已在参数帧里(写路径的完整闭环)
|
||||
("r0值新", "10001V", (24, 38), False),
|
||||
("r1值旧", "100V", (38, 52), False), # 只提交改动行:没动的行还是旧值
|
||||
("页脚", "第 1 页,共 2 页", (140, 160), False),
|
||||
],
|
||||
"sset": [
|
||||
("标题", "定值", (0, 24), False),
|
||||
("徽标", "未标定", (0, 24), False),
|
||||
("r0名", "Ⅰ段电流", (24, 38), True), ("r0值", "10.00A", (24, 38), True),
|
||||
("r7名", "过负荷延时", (122, 136), False), ("r7值", "10000ms", (122, 136), False),
|
||||
("页脚", "第 1 页,共 3 页", (140, 160), False), # 18 项 + 保存行 = 19 行 → 3 页
|
||||
],
|
||||
"sword_cycle": [
|
||||
# 二态行 ENTER:跳闸(1) → **回绕到 告警(0)**;未动的行保持 跳闸(只提交改动 id)
|
||||
("标题", "控制字", (0, 24), False),
|
||||
("r0名", "Ⅰ段跳闸", (24, 38), True), ("r0值", "告警", (24, 38), True),
|
||||
("r1名", "Ⅱ段跳闸", (38, 52), False), ("r1值", "跳闸", (38, 52), False),
|
||||
("r3名", "过负荷跳闸", (66, 80), False), ("r3值", "告警", (66, 80), False),
|
||||
("保存名", "保存", (80, 95), False), ("保存值", "ENTER", (80, 95), False),
|
||||
("页脚", "第 1 页,共 1 页", (140, 160), False),
|
||||
],
|
||||
"splate": [
|
||||
("标题", "软压板", (0, 24), False),
|
||||
("徽标", "未标定", (0, 24), False),
|
||||
("r0名", "Ⅰ段投入", (24, 38), True), ("r0值", "投入", (24, 38), True),
|
||||
("r7名", "过频投入", (122, 136), False), ("r7值", "投入", (122, 136), False),
|
||||
("页脚", "第 1 页,共 2 页", (140, 160), False), # 10 项 + 保存行 = 11 行 → 2 页
|
||||
],
|
||||
"netcfg_save": [
|
||||
("标题", "网口设置", (0, 24), False),
|
||||
("r0名", "IP地址", (24, 38), False), ("r0值", "192.168.001.100", (24, 38), False),
|
||||
@@ -280,6 +374,36 @@ TEXTS = {
|
||||
],
|
||||
}
|
||||
|
||||
# 反向文本断言表:页名 -> [(名称, 期望**不出现**的串, y 带, 是否反显态)]
|
||||
# ⚠ inv 必须与"这一行本来会怎么画"一致,否则反向断言恒真、形同没写:
|
||||
# 选中/编辑行是白底黑字 → inv=True;普通行黑底白字 → inv=False。
|
||||
# 为什么需要"不该出现"这一侧:像素参考能钉住整张图,但参考图是按当前实现刷出来的
|
||||
# ——如果"未标定"徽标哪天在两处都画了(整定 attach 判据失效 + 顺手 --update 刷参考),
|
||||
# 像素比对会"一致"而事实已经错了。反向断言不依赖参考图,钉的是"这条规矩本身":
|
||||
# · 徽标只属于整定态(可改值但判据停走),不属于只读态,也不属于四个查看页;
|
||||
# · 只读态没有"保存"这件事(无 commit → 组件不画保存行)。
|
||||
ABSENT = {
|
||||
"sparam_ro": [
|
||||
("只读页无未标定徽标", "未标定", (0, 24), False),
|
||||
("只读页无保存行", "保存", (0, 140), False),
|
||||
],
|
||||
# 查看 4 页:task-2 给同一批描述符绑了 key_cb / edit_capable,像素必须零变化;
|
||||
# 徽标与保存行都不该出现在它们身上(出现 = 整定 attach 漏判了权限)
|
||||
"vparam": [("查看页无未标定徽标", "未标定", (0, 24), False),
|
||||
("查看页无保存行", "保存", (0, 140), False)],
|
||||
"vset": [("查看页无未标定徽标", "未标定", (0, 24), False),
|
||||
("查看页无保存行", "保存", (0, 140), False)],
|
||||
"vword": [("查看页无未标定徽标", "未标定", (0, 24), False),
|
||||
("查看页无保存行", "保存", (0, 140), False)],
|
||||
"vplate": [("查看页无未标定徽标", "未标定", (0, 24), False),
|
||||
("查看页无保存行", "保存", (0, 140), False)],
|
||||
# 编辑态的值列由 ui_w_editor_format 生成(**不拼单位**),非编辑态才拼:
|
||||
# 所以"100V 不在这一行"就是"这一行确实在编辑中"的证据。
|
||||
# 反过来正向断言"100"是没有意义的——它是"100V"甚至"10000V"的子串,
|
||||
# 字形匹配器只保证 bbox 内干净、不检查词边界(实测在上一行的 10000V 上命中)
|
||||
"sparam_edit": [("编辑态不打单位后缀", "100V", (38, 52), True)],
|
||||
}
|
||||
|
||||
W = H = 160
|
||||
STRIDE = W // 8 # I1:20 字节/行
|
||||
|
||||
@@ -468,16 +592,26 @@ def main():
|
||||
run_sim(seq, shot, tmp)
|
||||
shots[name] = open(shot, "rb").read()
|
||||
|
||||
n_pos = 0
|
||||
for name, _seq in PAGES:
|
||||
for tname, text, band, inv in TEXTS.get(name, []):
|
||||
n_pos += 1
|
||||
if not _match_text(shots[name], text, band, inv):
|
||||
ok = False
|
||||
print("[%s] FAIL 文本断言未命中:%s = %r(y 带 %s 反显=%s)"
|
||||
% (name, tname, text, band, inv))
|
||||
n_abs = 0
|
||||
for name, _seq in PAGES:
|
||||
for tname, text, band, inv in ABSENT.get(name, []):
|
||||
n_abs += 1
|
||||
if _match_text(shots[name], text, band, inv):
|
||||
ok = False
|
||||
print("[%s] FAIL 反向断言被命中:%s 不该出现却出现了(y 带 %s)"
|
||||
% (name, tname, band))
|
||||
if not ok:
|
||||
print("FAIL: 文本级断言未通过(缺字/错标签);中止像素比对(现场保留在 %s)" % tmp)
|
||||
return 1
|
||||
print("文本级断言:%d 条全部命中" % sum(len(TEXTS.get(n, [])) for n, _ in PAGES))
|
||||
print("文本级断言:%d 条命中 + %d 条反向(不该出现)全部通过" % (n_pos, n_abs))
|
||||
|
||||
# 2) 像素黄金参考比对 / 刷新
|
||||
for name, seq in PAGES:
|
||||
|
||||
Reference in New Issue
Block a user