你家里可能摆着一台青萍空气检测仪(CGS1),一块小屏幕,平时只显示 PM2.5、温湿度。但有人硬是把 AI 订阅额度显示到了这块屏上:Codex 和 OpenCode Go 的剩余配额、重置时间,一目了然。这不是官方功能,而是自己动手改出来的。整个过程绕了几个弯,踩了几个坑,思路很值得借鉴——尤其是“凭证只留本机,数据通过公网静态文件中转”的设计,和“设备上 CA 证书缺失导致 HTTPS 失败”的排查。
先说需求:作者订阅了 ChatGPT(通过 Codex CLI 使用)和 OpenCode Go(通过 Pi 使用),想随时知道这两个服务的额度还剩多少。额度数据不是公开 API 随便调的,得先解决“怎么拿到”。Codex CLI 本机装了 0.166.0 版本,支持 app-server(一个本地服务器模式,能通过 stdio 协议和它对话),复用登录态后调用 `account/rateLimits/read` 方法就能拿到 `usedPercent`、`windowDurationMins`、`resetsAt` 这些字段,算一下就知道剩余比例和重置时间。OpenCode Go 这边,Pi 的默认 provider 是 opencode-go,认证类型是 API key,存在 `~/.pi/agent/auth.json` 里。Mac 上的服务读取这个凭据,直接向 `https://opencode.ai/inference/go/v1/usage` 发 GET 请求,带上 Bearer token 就有额度数据。注意,这里没有去动 Pi 本身,也不用装插件,仅仅读取了它的配置文件。
拿到数据后,最初的方案是让 Mac 起一个局域网 HTTP 服务,青萍设备直接访问。但问题来了:青萍 QML 页面里要写死 Mac 的局域网 IP,而家里网络环境复杂(多路由器、DHCP 不固定 IP),根本保证不了稳定访问。于是作者换了个思路:利用已有的 VPS 做中转。流程变成:Mac 每分钟采集额度数据,通过 SSH 把 JSON 文件写到 VPS 上;VPS 用 HTTPS 域名提供这个静态文件;青萍的 QML 页面定时读取。这样凭证一直在 Mac 本地,VPS 上只放一个不敏感的 `quota.json`,结构里只包含页面展示所需字段——比如 `providers` 数组里每个订阅的状态、窗口的已用/剩余百分比、重置时间等。
这个设计有个聪明点:文件通过 SSH 原子替换,传输中断或校验失败不会留下半份 JSON;QML 页面按数组结构渲染卡片和额度条,以后新增展示条目不用改页面布局。页面取数失败时会保留上次数据并把卡片灰显,首次失败会显示连接状态。所有这些细节都写成了一个完整的工程。
但最大的坑出现在 HTTPS 访问上。当作者在青萍设备上执行 `curl https://domain/quota.json`,报错 `SSL certificate problem: unable to get local issuer certificate`。排查发现设备的 `/etc/ssl/certs` 目录是空的——系统压根没有可信任的 CA 证书。解决办法是手动下载 ISRG Root X1(Let's Encrypt 的根证书)放到 `/data` 分区,用 `curl --cacert` 能通过,但 QML 页面里的 Qt 网络模块还不认——Qt 的 TLS 后端也需要能找到可信任证书。最终在看门狗启动 SnowApp(青萍上的应用)之前,设置了 `export SSL_CERT_FILE=/data/custom/ai-quota-display/ISRG-Root-X1.pem`,并用 `mount -o bind` 把自定义证书目录绑定到 `/etc/ssl/certs`,重启设备后 QML 才能正常走 HTTPS。
这个案例的启发很直接:当你需要让一个资源受限的小屏设备(物联网设备)展示来自互联网服务的数据时,不要在设备上保存任何敏感凭证,而是让有凭证的“主力机”定时抓取,用 SSH 推送到一个公网静态文件,设备只读这个文件。数据格式要设计成可扩展的结构,保证前端渲染逻辑稳定。另外,嵌入式设备经常缺 CA 证书,遇到 HTTPS 失败先查 `/etc/ssl/certs`,该补证书就补,别在代码里绕过证书校验。整个方案的代码和配置作者放在 qingping-cgs1-ai-quota-display 仓库里,遇到类似场景可以直接参考。如果真想复刻,还得先搞明白青萍 CGS1 怎么获得外置 QML 页面入口,那又是一个独立的改造过程。
内容与图片版权归原作者所有 · 原文: https://liudon.com/posts/qingping-cgs1-ai-quota-display/