feat(sntp): 板端 SNTP 校时接入——coreSNTP 序列化器 + [sntp] 段 + 设置页(#73)
CI / 静态门禁 (pre-commit) (push) Failing after 7m28s
CI / 主机侧单测 (MSVC) (push) Successful in 29s
CI / 静态门禁 (pre-commit) (pull_request) Has been cancelled
CI / 主机侧单测 (MSVC) (pull_request) Has been cancelled

- 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)
This commit is contained in:
2026-11-04 15:27:41 +08:00
parent c1beec50e7
commit 912c16b757
73 changed files with 4676 additions and 281 deletions
+2
View File
@@ -126,6 +126,7 @@ set(UI_SOURCES
${UI_DIR}/ui_page_yk.c
${UI_DIR}/ui_page_wave_manual.c
${UI_DIR}/ui_page_wave_play.c
${UI_DIR}/ui_page_sntp.c
)
# 运行/自检记录引擎(双端共享核心 + 平台存储后端;MCU 端编 sys_log_mcu.c,见 Keil 工程)
@@ -137,6 +138,7 @@ set(SYSLOG_SOURCES
set(NETCFG_SOURCES
${NETCFG_DIR}/net_cfg.c
${NETCFG_DIR}/ftp_cfg.c
${NETCFG_DIR}/sntp_cfg.c
${PROJECT_ROOT}/App/cfg/cfg_file.c
sim/cfg_file_store_sim.c
)
+2 -2
View File
@@ -53,7 +53,7 @@ simulator/
| `build_sim.bat` / `build_sim.ps1` | 一键构建入口:vswhere 探测本机 VS 大版本(16=2019 / 17=2022 / 18=2026,取已装最高)→ 映射 CMake 生成器;`build/` 缓存生成器与本机不符(换机/升级 VS)时自动删除重建(带重试,抗文件锁)。**构建入口一律走它,文档/命令中勿写死生成器版本**;`.bat` 仅负责绕过 PowerShell 执行策略并转交 `.ps1` |
| `CMakeLists.txt` | 收集 LVGL 源码(`../Lib/lvgl`)+ 共享 UI 源码(`../Drivers/BSP/UI`)+ 通用配置文件引擎(`../App/cfg_file.c`、`../Drivers/BSP/NETCFG` 的 net_cfg;`net_cfg_legacy` 已于 2026-10-10 删除)+ `sim/` 平台层,链接预编译 SDL2,产出 `lvgl_sim.exe` |
| `i1_to_png.py` | 把 `--screenshot` 产出的 I1(1bpp) 原始位图转成 PNG,便于离线比对设计稿。详见 §3.5 |
| `tests/` | 无头回归脚本(菜单 8 状态像素回归 + 内容页 66 张:文本断言 / 反向断言 / 黄金参考逐字节比对);`ref/shot_*.bin` **随仓库入库**(判据本体,改动等于改判据,评审须逐页过目),`ref/*.png` 是本地派生的目检图(`.gitignore` 挡掉)。详见 §3.6 |
| `tests/` | 无头回归脚本(菜单 8 状态像素回归 + 内容页 74 张:文本断言 / 反向断言 / 黄金参考逐字节比对);`ref/shot_*.bin` **随仓库入库**(判据本体,改动等于改判据,评审须逐页过目),`ref/*.png` 是本地派生的目检图(`.gitignore` 挡掉)。详见 §3.6 |
> **共享代码不复制**:`ui_menu.c` / `ui_font_cn_12.c` / `ui_net_sink.c` 直接引用 `Drivers/BSP/UI/` 下的原件,
> MCU 与 PC 两端永远同步。**不要**在本目录内复制 UI 源码。
@@ -222,7 +222,7 @@ UI 改动的自动化门禁脚本(完整流程见 `docs/UI设计/UI_自动化
| 脚本 | 原理 | 失败输出 |
|------|------|----------|
| `check_menu_rows.py` | 键序注入(u/d/e/s)跑 8 个菜单状态,断言选中行白带、非选行黑底白字、框体边框、往返状态逐像素一致;MENU-STATE-00 池水位须等于脚本内 `MENU_POOL_BASELINE` | 未过断言清单 + 保留临时截图 |
| `check_content_pages.py` | ① 文本断言(解析字体字形,在截图 y 带内精确匹配期望串,不依赖 `ref/`)② **反向断言**(`ABSENT` 表:某串**不该**出现,如查看页/只读态不得出现「未标定」徽标与「保存」行——像素参考会被 `--update` 刷成"自证正确",反向断言不依赖参考图)③ **66 张**无头截图与 `tests/ref/shot_*.bin` **逐字节**比对(含 2026-10-26 新增的整定 9 态:进页 / 保存行 / 只读态 / 编辑态 / 越界 / 保存 OK / 落定后可读 / 二态回绕);另校验开页-关页往返池水位 = `POOL_AFTER_ROUNDTRIP` | 文本未命中项 / 反向断言被命中 / 差异像素数 + 双方 ink runs 对照 |
| `check_content_pages.py` | ① 文本断言(解析字体字形,在截图 y 带内精确匹配期望串,不依赖 `ref/`)② **反向断言**(`ABSENT` 表:某串**不该**出现,如查看页/只读态不得出现「未标定」徽标与「保存」行——像素参考会被 `--update` 刷成"自证正确",反向断言不依赖参考图)③ **74 张**无头截图与 `tests/ref/shot_*.bin` **逐字节**比对(含 2026-10-26 新增的整定 9 态:进页 / 保存行 / 只读态 / 编辑态 / 越界 / 保存 OK / 落定后可读 / 二态回绕);另校验开页-关页往返池水位 = `POOL_AFTER_ROUNDTRIP` | 文本未命中项 / 反向断言被命中 / 差异像素数 + 双方 ink runs 对照 |
| `check_remo_sink.py` | 启动**窗口**模拟器(非无头,`CREATE_NEW_PROCESS_GROUP` 防管道阻塞),经 TCP 7003 发 LCDMEM 取 1bpp 帧;断言首帧=LCDMEM(无 INIT 污染)/位图 3200 字节/非平凡;复用 `i1_to_png` 出目检 PNG;与无头参考(`lvgl_sim --screenshot`)逐位比对 <2% 判 MATCH。守护"INIT 污染 / 快照卡死"两个历史缺陷 | 各判据失败原因 + `sim_err.txt` 尾部 + 保留 PNG(默认不删,`--clean` 才删) |
- **黄金参考与目检 PNG**(`ref/*.bin` **入库**、`ref/*.png` 本地派生不入库):换机或想目检时——
+1 -1
View File
@@ -11,7 +11,7 @@
| `check_content_pages.py` | **内容页回归**:各内容页渲染比对 |
| `check_remo_sink.py` | **推流(RemoDispBus)回归**:接收端渲染比对 |
| `regen_ref_png.py` | 由 `ref/*.bin` 批量出**目检 PNG**(不产生基准;基准由 `check_content_pages.py --update` 刷) |
| `ref/*.bin` | **像素黄金参考(入库)**:66 张 × 3200 B,160×160 单色打包(2026-10-29 录波 UI 道 +6 张) |
| `ref/*.bin` | **像素黄金参考(入库)**:74 张 × 3200 B,160×160 单色打包(2026-10-29 录波 UI 道 +6 张;2026-11-04 SNTP 设置页 +8 张) |
## 使用方式
+62 -2
View File
@@ -114,6 +114,17 @@ PAGES = [
("netcfg_ro", "ddddde de e"), # 查看密码 000 → 只读态
("netcfg_edit", "ddddde de uruuruuue e"), # 编辑模式:IP 首字节光标反显
("netcfg_save", "ddddde de uruuruuue dddd e"), # 保存行 ENTER → 值列 OK
# ---- SNTP 设置页(node 31,通讯参数下第 3 项,#P 叶;[sntp] 工厂默认:
# enable=0 / 主备服务器 0.0.0.0 / 周期 60 分,见 Drivers/BSP/NETCFG/sntp_cfg.c)
# 导航同网口设置(ddddde 落通讯参数),再 dd 选到第 3 叶 SNTP设置。
("sntp", "ddddde dde uruuruuue"), # 首屏:工厂默认 + 保存行 ENTER
("sntp_ro", "ddddde dde e"), # 查看密码 000 → 只读态
("sntp_edit", "ddddde dde uruuruuue d e"), # 主服务器编辑:首段字节光标反显
("sntp_oct", "ddddde dde uruuruuue d e r u e"), # 光标右移 + 段值 +1 → 000.001.000.000
("sntp_en", "ddddde dde uruuruuue e"), # 启用行 ENTER → 开启(开关行无编辑态)
("sntp_poll", "ddddde dde uruuruuue ddd e"), # 周期行编辑:整值反显
("sntp_poll_big", "ddddde dde uruuruuue ddd e r e"), # ←→ ±60 粗调:60 → 120 分
("sntp_save", "ddddde dde uruuruuue e dddd e"), # 开启 + 保存行 ENTER → 值列 OK
# ---- 道F task-3 装置维护三页(根菜单第 5 项 = 4 下;子项 0/1/3 = 时钟/复归/清除)
# 键序读法与上面同源:e 进子菜单后再 e 打开叶子(叶子带 #P → 先落密码页),
# "uruuruuue" = 修改口令 123(可编辑态),单一个 e = 查看口令 000(只读态)。
@@ -178,7 +189,7 @@ PAGES = [
# 计数范围/复位原因/主站接入 + 范围标签"本次开机",第 2 页钉 104 另外三枚(发送帧数
# 128 / 发送失败 0 / 接收字节 4096)与页脚真实页码 2/2。四枚假数据值互不相同是刻意的:
# 行错位/串行只有"像素 + 逐行文本断言"两把尺子同时才照得出来(Lead 裁定 2026-10-28,
# 因此当时用例是 53+7=60 张,不是 53+6=59;现集合 66 张,见 PAGES 表)。
# 因此当时用例是 53+7=60 张,不是 53+6=59;现集合 74 张,见 PAGES 表)。
("runreport", "dddddde dddddddd e"),
("runreport_p2", "dddddde dddddddd e dddddddd"), # 页内再 8 下 → 第 2 页(选中落 r0=发送帧数)
# ── 故障录波 UI 道(2026-10-29):手动录波三态 + 回放三态(真实波形/空态/坏段)──
@@ -532,6 +543,55 @@ TEXTS = {
("r1名", "子网掩码", (38, 52), False),
("r4名", "保存", (80, 95), False),
],
# ---- SNTP 设置页:工厂默认 关闭 / 000.000.000.000 ×2 / 60 / ENTER。
# 地址行为 net_cfg_fmt_ipv4 定长 15 字符(%03u 补零,与网口设置页同真源);
# 周期行是纯十进制(无补零);字节光标 = 黑底白字小段,编辑态文本断言
# 只钉"名 + 选中带",被光标覆盖的段值改在退出编辑后的 sntp_oct 上钉全串。
"sntp": [
("标题", "SNTP设置", (0, 24), False),
("r0名", "启用", (24, 38), True), ("r0值", "关闭", (24, 38), True),
("r1名", "主服务器", (38, 52), False), ("r1值", "000.000.000.000", (38, 52), False),
("r2名", "备服务器", (52, 66), False), ("r2值", "000.000.000.000", (52, 66), False),
("r3名", "周期(分)", (66, 80), False), ("r3值", "60", (66, 80), False),
("r4名", "保存", (80, 95), False), ("r4值", "ENTER", (80, 95), False),
("页脚", "第 1 页,共 1 页", (140, 160), False),
],
"sntp_ro": [
("标题", "SNTP设置", (0, 24), False),
("r0名", "启用", (24, 38), True), ("r0值", "关闭", (24, 38), True),
("r1名", "主服务器", (38, 52), False), ("r1值", "000.000.000.000", (38, 52), False),
("r3名", "周期(分)", (66, 80), False), ("r3值", "60", (66, 80), False),
("r4名", "保存", (80, 95), False),
("页脚", "第 1 页,共 1 页", (140, 160), False),
],
"sntp_edit": [
("标题", "SNTP设置", (0, 24), False),
("r1名", "主服务器", (38, 52), True), # 选中带落到 r1
("r0名", "启用", (24, 38), False),
("r2名", "备服务器", (52, 66), False), ("r2值", "000.000.000.000", (52, 66), False),
("r4名", "保存", (80, 95), False),
],
"sntp_oct": [
("r1值改后", "000.001.000.000", (38, 52), True), # 退出编辑后选中带仍停在 r1
("r2值未动", "000.000.000.000", (52, 66), False),
("r0值未动", "关闭", (24, 38), False),
],
"sntp_en": [
("r0名", "启用", (24, 38), True), ("r0值切后", "开启", (24, 38), True),
("r4名", "保存", (80, 95), False),
],
"sntp_poll": [
("r3名", "周期(分)", (66, 80), True), # 选中带 = 编辑行
("r0名", "启用", (24, 38), False),
],
"sntp_poll_big": [
("r3值粗调后", "120", (66, 80), True), # +60 钳带步进;退出编辑后选中带仍停在 r3
("r3名", "周期(分)", (66, 80), True),
],
"sntp_save": [
("r0值", "开启", (24, 38), False),
("r4名", "保存", (80, 95), True), ("r4值", "OK", (80, 95), True),
],
# ── 道F task-2:整定 4 页文本级断言 ─────────────────────────────────────────
# 值全部来自 simulator/main.c 的固定帧(prot_set 出厂默认 + cal_block 恒 1),
# 每条断言都是"某个具体事实":徽标在不在、保存行在第几页、越界提示、改值后落没落。
@@ -909,7 +969,7 @@ EXTRA = {
# sim_oper.log 已经攒了 3 条(192 B = 3×64 B)→ "操作记录"页读到的是真记录,
# 空态判据(第 0 行"无记录")根本拍不到。**判据本身没错,错在跑它的环境被前面的写路径
# 污染了**,所以给这 5 页各开一个空目录 = 现场"这些日志文件还不存在"的确定态;
# 其余 55 页环境一字不变(对当时存量 53 张黄金零影响,实测逐字节零漂移;当时集合 60 张,现集合 66 张)。
# 其余 55 页环境一字不变(对当时存量 53 张黄金零影响,实测逐字节零漂移;当时集合 60 张,现集合 74 张)。
FRESH_CWD = ("accident", "oper", "alarm", "start", "yk")
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.