ESP32 动态网页仪表盘用 Mongoose Wizard 生成之后,手动在 mongoose_glue.c 里加了 0~100 循环,串口监视器里 g_dynamic_value 明明每 100ms 在变,浏览器上的数值卡片却要按 F5 才更新——这个排障场景最容易被误判成 mongoose_poll 没跑。先把 TaoToken 的 Key 和 Codex 通道配通,让 Codex 对照 glue_get_state 的覆盖顺序和向导里的 Auto-refresh 设置,比盲目重生成代码省事。打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content= 创建 YOUR_API_KEY,把 Codex 的 Base URL 填成 https://taotoken.net/api,后面按原文第四部分把 Polling interval 补上。TaoToken 在这里只负责 Key 和兼容通道,不参与 ESP32 代码修改,编译上传仍然在你的 Arduino IDE 里完成。
这个问题的坑点在于两个地方都会“看起来正常”:串口里更新函数在跑,浏览器里页面也能打开,WiFi 和 mongoose_poll 都没断。真正断掉的是“数据从 mcu 到前端”的那条链:glue_get_state 有没有把动态值塞进 state 结构体,以及前端有没有按间隔去请求 state 端点。只改 loop 不配向导里的轮询,网页就不会自动刷新;只配轮询但 glue_get_state 还在返回静态 s_state,数值就会卡住不动。下面按排障顺序,把 Codex 接进 TaoToken 兼容通道,再回到 mongoose_glue.c、mongoose_glue.h、wizard.ino 和 Wizard 属性面板逐项对照。
1. 数字只在手动刷新时变:先分清 glue_get_state 和 Auto-refresh
1.1 串口在跑、网页不动,问题不在 0~100 循环本身
当你看到串口里 g_dynamic_value 从 0 到 100 循环,第一反应往往是 update_dynamic_value 没被 loop 调用,或者 millis 判断写错了。但既然串口能打印变化,说明定时逻辑和主循环基本是活的。此时浏览器手动刷新能看到最新数字,说明 HTTP 服务、state 端点、前端渲染都没有完全断。问题被压缩到两个位置:第一,glue_get_state 返回给前端的数据里,dynamic_value 是不是每次都用 g_dynamic_value 覆盖了 s_state;第二,Wizard 生成的前端有没有定时器去重新拉取 state。
Mongoose Wizard 默认生成的页面更像一张“快照”:打开页面时请求一次 state,之后除非你手动刷新,否则不会主动再问。你后来在 mongoose_glue.c 里加了动态变量,只是让“下一次被请求时”返回新值。手动刷新会触发新请求,所以数字会跳;不刷新就没有新请求,数字自然不动。分清这一点,就不会把时间浪费在重写 0~100 循环上。
1.2 两个检查点:dynamic_value 有没有进 state,轮询间隔有没有生成到前端
第一个检查点看 C 代码。打开 src/mongoose_glue.c,找到 glue_get_state(struct state *data)。这个函数通常先把静态 s_state 整体复制给 data,然后你可以用># ~/.codex/config.toml model = "YOUR_MODEL_ID" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"
保存后,在终端里导出环境变量,再启动 Codex:
export TAOTOKEN_API_KEY=YOUR_API_KEY codex如果 Codex 启动后能正常对话,说明兼容通道已经通了。此时不要让它直接操作开发板,也不要期待它替你编译上传。Codex 的职责是读代码、对照配置、指出 glue_get_state 的赋值顺序和 Wizard 里 Auto-refresh 该设成什么。Arduino IDE 的编译、上传、串口监视器仍然由你在本地执行。
2.3 给 Codex 的排障提问:只对照文件,不代你编译上传
把下面这段提问模板粘进 Codex,它会把注意力放在文件对照上,而不是乱改工程。你可以在模板里补上自己实际看到的串口输出和浏览器现象。
我在 Mongoose Wizard 生成的 ESP32 项目里,手动加了 0~100 循环。 现象:串口里 g_dynamic_value 在变,但网页数值不自动刷新,手动刷新才变。 请只对照以下文件,不要替我编译或上传: 1. src/mongoose_glue.c 中 glue_get_state 是否先用 *data = s_state,再用>#include <Arduino.h> static int g_dynamic_value = 0; static unsigned long g_last_ms = 0; void update_dynamic_value(void) { unsigned long now = millis(); if (now - g_last_ms >= 100) { g_last_ms = now; g_dynamic_value = (g_dynamic_value + 1) % 101; } } void glue_get_state(struct state *data) { *data = s_state; >void loop() { update_dynamic_value(); mongoose_poll(); }如果 update_dynamic_value 定义在别的文件,记得在 wizard.ino 顶部包含对应头文件。编译上传后打开串口监视器,先确认没有重启循环,再访问 ESP32 的 IP。此时手动刷新页面应该能看到数字变化;如果向导里的 Auto-refresh 已经设成 1s,页面不用刷新也会跳。
5. 编译上传后仍不跳动:用 Codex 对照三处 JSON 与缓存
5.1 看浏览器 Network 里 state 返回的 JSON
打开浏览器开发者工具,切到 Network,过滤 state 或 fetch/XHR。观察两件事:请求有没有按 1s 左右重复发出;返回的 JSON 里 dynamic_value 是否每次都在变。如果请求压根没有重复,说明 Auto-refresh 没生成成功,回向导检查 Polling interval 并重新 Generate code。如果请求在重复但 JSON 里的值不变,说明 glue_get_state 没有正确覆盖,或者你上传的是旧固件。
还有一种情况:JSON 里字段名是 dynamic_value,但前端绑的是 data.dynamicValue,大小写或下划线不一致。Codex 可以帮你对照 mongoose_glue.h 的成员名和向导里组件 Key,但它看不到你浏览器里的 Network 面板。你需要把 JSON 片段贴回对话,让它根据实际字段给出修改建议。
5.2 轮询 URL 写错或组件没绑定 Data Source
有些工程里 state 端点不是默认路径,或者你在 Wizard 里改过 API 前缀。组件如果没绑定 Data Source,前端就不知道该请求哪个地址。检查向导属性面板:API Reference 是否指向 state.dynamic_value,而不是空的或者别的组件。重新生成后,前端文件里应该能看到对应的请求地址和轮询间隔。
如果轮询 URL 返回 404,浏览器 Network 里会直接标红。此时不要急着改 C 代码,先确认 mongoose 的路由注册是否包含该端点。Mongoose Wizard 生成的后端通常已经注册好,问题多出在你手动改了路径或复制了旧文件。把新生成的 src 目录和旧目录对比,优先保留新生成的路由,再迁移业务逻辑。
5.3 向导缓存与浏览器强刷:旧 Key 会骗你
Mongoose Wizard 的设计数据保存在浏览器缓存里,换浏览器、清缓存或换设备后可能看不到原设计。如果你在旧缓存里改了 Key,但重新生成时用的还是旧设计,前端字段就会和后端对不上。另一个常见坑是浏览器强缓存:ESP32 返回的 HTML 或 JS 被浏览器缓存,你上传了新固件但页面仍跑旧脚本。排障时用无痕窗口或禁用缓存刷新一次,确认不是缓存问题。
如果你已经确认 JSON 在变、请求在发、页面还是不动,把 Codex 叫回来,让它只对照 mongoose_glue.c、mongoose_glue.h 和向导导出的 JSON 配置。注意 Codex 不能直接连你的浏览器或开发板,它只能根据你贴出的片段分析。你负责在本地执行编译、上传、Network 抓包,再把结果贴回去。
6. 把 app_logic 拆出去,下次 Generate code 不再丢逻辑
6.1 app_logic.h / app_logic.cpp 最小可编译骨架
每次改 UI 都重新生成代码,然后手工搬 g_dynamic_value,很容易漏。更稳的做法是把业务逻辑放到独立文件,让 Wizard 生成的代码只做粘合。在项目根目录新建 app_logic.h 和 app_logic.cpp:
// app_logic.h #ifndef APP_LOGIC_H #define APP_LOGIC_H #include <Arduino.h> extern int g_dynamic_value; void update_dynamic_value(void); #endif// app_logic.cpp #include "app_logic.h" int g_dynamic_value = 0; static unsigned long g_last_ms = 0; void update_dynamic_value(void) { unsigned long now = millis(); if (now - g_last_ms >= 100) { g_last_ms = now; g_dynamic_value = (g_dynamic_value + 1) % 101; } }这两个文件不依赖 Wizard 生成的任何结构体,所以重新生成 UI 时不需要改它们。更新频率、上限、是否接入真实传感器,都可以在这里扩展。
6.2 mongoose_glue.c 只留粘合:include 与一行赋值
在 src/mongoose_glue.c 顶部包含 app_logic.h,然后在 glue_get_state 里用 g_dynamic_value 覆盖成员。这样 mongoose_glue.c 里只剩下向导生成的复制语句和你自己的一行赋值,迁移成本最低。
#include "app_logic.h" void glue_get_state(struct state *data) { *data = s_state; data->dynamic_value = g_dynamic_value; }wizard.ino 的 loop 仍然调用 update_dynamic_value(),但函数实现已经移到 app_logic.cpp。Arduino IDE 会自动编译同目录或 src 目录下的 cpp 文件,如果提示找不到函数,检查 include 路径和文件位置。
6.3 未来改 UI 的迁移清单:复制两个文件,恢复一行赋值
以后在 Wizard 里改布局或改 Auto-refresh,重新 Generate code 后按这个清单走:第一,解压新项目;第二,把旧的 app_logic.h 和 app_logic.cpp 复制到新项目根目录;第三,在新项目的 mongoose_glue.c 顶部加 #include "app_logic.h";第四,在 glue_get_state 里补上 data->dynamic_value = g_dynamic_value;第五,确认 wizard.ino 的 loop 调用了 update_dynamic_value();第六,编译上传并用无痕窗口验证轮询。
这个清单比每次重写整段动态逻辑更不容易错。如果向导把 struct state 成员名改了,你只需要同步改这一行赋值,业务文件不用动。排障时也让 Codex 按这个清单逐项核对,它会更容易发现“新生成代码覆盖了旧 glue_get_state”这类问题。
7. 验证 Codex 通道与 ESP32 仪表盘:最后去控制台对一下调用
7.1 模型对话里用同一把 Key 发一条测试
Codex 配置保存后,先不要直接让它分析整个工程。用同一把 YOUR_API_KEY 在 TaoToken 模型对话 里发一条简单消息,确认模型 ID 和 Base URL 没填错。如果这里能正常返回,再回到 Codex 里让它读取 src/mongoose_glue.c,列出 glue_get_state 的赋值顺序和 struct state 的成员名。这样能把“通道问题”和“ESP32 代码问题”分开。
验证 ESP32 端时,打开无痕窗口访问仪表盘 IP,观察数字是否按 1s 自动跳动;同时看串口监视器有没有异常重启。如果网页自动刷新正常,但 Codex 那边报 401 或 404,检查 ~/.codex/config.toml 里的 base_url 是不是误加了 /v1,或者环境变量名是否和 env_key 一致。不要把落地页的 utm_source 拼到 base_url 上。
7.2 看用量与创建 Key 的入口
Codex 能正常读文件后,去 控制台 API Keys 看这次调用有没有记上账,顺便确认 Key 的剩余情况。如果你准备长期用 Codex 配合 ESP32 项目做代码对照,可以打开 Coding Plan 看套餐是否够用;模型 ID 仍以 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content= 模型广场当时列表为准。配完这一轮,你的仪表盘应该已经能自动刷新,Codex 也只在需要对照 mongoose_glue.c 和 Auto-refresh 设置时出场,编译上传和硬件验证始终留在本地。