返回

M5Stack Basic 上的 Claude 用量仪表盘——桌面上的套餐限额与 API 花费

放在笔记本电脑键盘上的 M5Stack Basic 正显示着仪表盘——一个 Claude Max 账户的每周限额已用 88%,5 小时会话已用 30%,今日已用 142M token

我每天都用 Claude,而我最常问的问题并不是关于代码。而是”我这周还剩多少额度?“Claude Code 的 /usage 界面能回答,但前提是我得停下来手动输入。我希望答案就摆在桌上,就像时钟显示时间那样。

M5Stack Basic 很合适。它是一台成品设备:2 英寸 320×240 屏幕、三个按键、一块电池,以及封装在 54 mm 外壳里的 ESP32。无需面包板,无需焊接。

本文介绍这个仪表盘:它显示什么、数据如何从 Claude 传到屏幕、设备如何免配置连接,以及自己动手搭建的步骤。UI 是在 Velxio 中的 M5Stack Core 上设计完成的,之后才接触真实硬件——如果你想自己做一个,我也推荐这条路线。你也可以在浏览器中运行这个固件,使用演示数据,无需设备。

设备上的仪表盘:在 YouTube 上观看。

所有代码——固件和 PC 桥接程序——都以 MIT 许可证发布在 GitHub 上:velxio/m5claude。下文”逐部分解读代码”一节会逐一说明每个文件的作用。

硬件

M5Stack Basic v2.7——一块 ESP32,配备 2 英寸 320x240 IPS 屏幕、三个按键、USB-C、microSD 卡槽和 110 mAh 电池

这块板子是 M5Stack Basic Core IoT Development Kit v2.7:

不需要其他东西:仪表盘只用外壳里已有的部件。这块板子没有 IMU、麦克风、LED 或实时时钟,所以仪表盘用上了其余的一切:屏幕和按键、用于提醒的扬声器、用于省电的背光,以及用于显示电量的电源芯片。

屏幕上显示什么

这个仪表盘支持两类 Claude 账户,而且每类都可以有多个:

对两类账户,它都会显示最近一周的每日 token 数,拆分为输入、输出、缓存读取和缓存写入,并按模型分类。

共有四个视图。B 切换到下一个视图,A 和 C 在账户之间切换,长按 B 向 PC 请求最新数据,长按 C 打开设置。下面是所有屏幕,以及每个视图打开时播放的动画:

所有屏幕的动画导览:包含三个账户的总览、限额、token 和明细视图、一个 API 组织、单账户总览、电池充电、英文和西班牙文设置、审批提示以及等待屏幕

总览。 每个账户一张卡片。布局会根据账户数量自适应:一个账户铺满屏幕,两个账户使用更高的卡片并多出一行今日用量,三个或更多则变成可滚动的列表。

只有一个 Claude Max 账户的总览:每周限额显示为圆环,右侧是 5 小时会话和按模型的限额,下方是今日 token 和七日图表

两个 Max 账户和一个 API 组织的总览:每周百分比、5 小时和 7 天进度条、重置时间,以及 API 账户的七日花费

限额。 每周限额显示为圆环,旁边是会话和按模型的限额。模型名称直接来自 Claude 本身,所以这些行会跟随你套餐实际拥有的限额。颜色在 60%(琥珀色)和 85%(红色)时变化。

限额视图:67% 的每周圆环、42% 的 5 小时会话,以及 Opus 和 Sonnet 的每周限额

Token。 今天、最近七天和美元金额,然后是每日 token 数,并用虚线标出平均值。对于订阅账户,美元金额是同样多的 token 按 API 标价计算的花费。它不是实际扣费,但能让你直观看到自己使用套餐的强度。

Token 视图:今日 2.84M token、七日 20.8M、API 价值 $84.20,以及每日 token 柱状图

设备上的 Token 视图:今日 142M token,七日 296M

明细。 本周 token 按类型和按模型的分布。使用 Claude Code 时,缓存读取通常占总量的大部分。

明细视图:输入、输出、缓存读取和缓存写入 token 的堆叠条形图,以及各模型的占比

设备上的明细视图:一周 296M token 中几乎全部是缓存读取,分布在 Opus 和 Fable 之间

时钟旁的小圆点表示连接状态:数据新鲜时为绿色,过期时为琥珀色,没有 PC 连接时为红色。照片显示的是我自己的账户。截图使用的是演示账户。

电池、声音与设置

时钟旁边是电池,画法与手机一致:电量,以及充电时不断上升的闪电填充。IP5306 电源芯片只报告四档(25、50、75 和 100%),所以数字以 25 为步进变化。

充电时的顶栏:75% 电量,带闪电图标和绿色电池,旁边是连接圆点和时钟

扬声器用于提醒。当会话或每周限额超过 90%(如果你选择,也可以是 80%)时,设备会播放一段简短的双音提示,并显示是哪个账户、哪项限额。限额重置时,它会播放一段上扬的提示音。来自新电脑的审批请求也会发出声音。按键点击音是可选的。

长按 C 打开设置。A 和 C 移动,B 修改数值,长按 B 关闭屏幕。设置保存在设备上。

设置屏幕:语言、亮度、声音、提醒阈值、电池供电时息屏、夜间调暗、已配对电脑和固件版本

同样的屏幕,西班牙文版:设置和总览

西班牙文版总览

让 110 mAh 撑得更久

最初的固件在不到一小时内就耗尽了电池。CPU 运行在 240 MHz,屏幕每秒重绘,无线电以全功率发射,连接间隔为 15–30 ms。而显示一个每分钟才变化一次的数字,根本不需要这些。在电池供电时,固件现在会这样做:

如果要在离开桌面的情况下全天使用,可以把 Battery Module 13.2 叠在 Basic 下面,增加 1500 mAh。

工作原理

数据从 Claude Code 的登录信息和会话记录、以及 Admin API 流入 Python 桥接程序,再经 USB 或蓝牙 LE 传到 M5Stack,设备只绘制收到的内容

设计原则是设备本身一无所知。它不保存任何 Claude 凭据,也没有 Wi-Fi 设置。PC 上的一个小程序——桥接程序——负责收集所有数据,并把一份快照发给设备去绘制。这样密钥就不会落在摆在桌上的设备里,而且更换电脑或网络也无需重新配置。

数据来源

桥接程序约 1,100 行 Python,只有两个依赖(pyserial 和 bleak)。它读取三个来源:

  1. 套餐限额,来自 Claude Code 的登录信息。 每个 Claude Code 配置目录(~/.claude、~/.claude-work 等)保存着一个账户的登录信息。桥接程序会找到所有这些目录,并用各自的 token 读取 Claude Code 的 /usage 界面所显示的同一份限额。它只读取 token,从不刷新,因为刷新会轮换 token,导致 Claude Code 被登出。
  2. Token,来自 Claude Code 的会话记录。 Claude Code 收到的每个响应都会写入 projects/ 下的一个 JSONL 文件,其中包含 token 用量和模型。桥接程序按天累加这些数据,去除重复项(恢复的会话会把先前的消息复制到新文件中),并用 API 价格表计算费用。
  3. API 组织的花费,来自 Usage and Cost Admin API。 usage_report/messages 提供按天和按模型的 token 数。cost_report 提供真实花费。两者都需要 Admin API 密钥(sk-ant-admin01-...)。

在真实账户上运行后得到的两点经验:

快照

每次刷新都会生成一行约 600 字节的 JSON:

{"v":1,"ts":1792770195,"tz":3600,"acc":[
 {"n":"Personal","p":"Max 20x","k":"sub","ok":1,
  "s":[42,1792778235],"w":[67,1793037195],"x":[["Opus",54,1793037195],["Sonnet",31,1793037195]],
  "td":2840000,"tk":[2310000,1480000,15900000,1120000],"c":84.2,"ct":11.35,
  "d":[1900000,3400000,2600000,4100000,3300000,2670000,2840000],"m":[["Opus",61],["Sonnet",34],["Haiku",5]]}]}

s、w 和 x 分别是会话、每周和按模型的限额,格式为 [百分比, 重置时间]。d 是每日 token 数。ts 和 tz 是 PC 的时钟和 UTC 偏移。M5Stack Basic 没有实时时钟,也没有时区数据库,所以设备从快照中获取这两者,并从那里开始计秒。这足以显示“2 小时 14 分钟后重置”和“周二 04:00”。

无需配置的连接

我希望完全不需要设置。在只有三个按钮的设备上输入 Wi-Fi 密码很不愉快。在设备上保存 PC 的 IP 地址,一旦更换电脑就会失效。所以设备支持两种连接方式,都不需要任何设置。

USB。 插上数据线即可。桥接程序会查找 USB 芯片为 M5Stack 所用型号(CH9102 或 CP2104)的串口。它在打开端口时不切换 DTR 和 RTS,因此 ESP32 不会复位,然后等待问候消息。固件每两秒发送一次 {"hello":"m5claude",...},直到收到数据。如果几秒内没有收到问候消息,桥接程序会释放端口并在一段时间内不再碰它,这样其他 ESP32 开发板和烧录工具就不会受到影响。

蓝牙 LE。 固件广播一个 GATT 服务,包含两个特征:一个供 PC 写入数据行,另一个供设备发送通知。桥接程序扫描该服务 UUID 并连接。没有 Windows 配对对话框,也不需要从列表中选择任何东西。

由于范围内的任何电脑都能发现该设备,每台新 PC 都需要在设备上批准一次:

批准提示:“New computer, DESKTOP-STUDIO. Allow it to send usage data?”(新电脑 DESKTOP-STUDIO,允许它发送用量数据吗?),按钮 A 为 Deny(拒绝),按钮 C 为 Allow(允许)

配对交互过程:设备发出问候,桥接程序发送 PC 名称和稳定 id,等待应答,屏幕提示,然后返回 ok,请求刷新并发送快照

桥接程序在 ~/.m5claude/pc_id 中保存一个随机 id。设备在 NVS 中最多存储四台已批准 PC 的 id。已知的 PC 会立即被接受,开机时按住 A 会忘记所有已批准的 PC。已经通过 USB 连接的设备会跳过蓝牙,因此不会要求同一台 PC 批准两次。

在桥接程序运行之前,设备会显示该怎么做:

等待界面:“Waiting for your PC. Run m5claude-bridge on your computer. It connects over USB or Bluetooth automatically.”(正在等待你的 PC。在电脑上运行 m5claude-bridge。它会通过 USB 或蓝牙自动连接。)

固件

固件是一个 Arduino sketch,使用 arduino-cli 在 arduino-esp32 2.0 核心上构建。它使用三个库:

UI 代码不依赖硬件。它绘制到一个 LovyanGFX 目标中,并读取三个按钮。所有与开发板相关的内容(面板、USB、BLE、NVS)都在 sketch 中。

一些让它看起来像产品而非演示的细节:

在没有 PSRAM 的情况下绘制,以及斜条纹

16 位色的完整 320×240 帧为 150 KB。在蓝牙运行的情况下,ESP32 最大的空闲内存块比这更小。因此 UI 每帧分四次绘制到一个 320×60 的条带(38 KB)中。每一遍都按条带的偏移量向上平移绘制所有内容,超出条带的部分会被裁剪。

第一次在开发板上运行时,屏幕显示斜条纹,批准提示的按钮出现了两次,分别在顶部和底部。我首先怀疑的是面板配置。我根据 M5Stack 的文档手工重写了它,但没有任何变化。原因在别处:

使用单个缓冲区时,下一个条带会在 DMA 仍在发送当前条带时被绘制到同一缓冲区中。使用两个缓冲区时,一个在绘制的同时另一个在发送,CPU 在复用缓冲区之前等待传输完成

LovyanGFX 通过 DMA 在后台把 sprite 发送到面板。我的循环在上一个条带仍在发送时就开始把下一个条带绘制到同一个缓冲区,于是面板收到了一半来自一个条带、一半来自下一个条带的内容。修复方法是轮流使用两个缓冲区,并在推送前等待上一次传输完成:

for (int y = 0, k = 0; y < 240; y += 60, k ^= 1) {
  LGFX_Sprite& band = bands[k];
  band.fillScreen(BG);
  draw_ui(band, /*offset_y=*/y);   // runs while the other buffer is still being sent
  lcd.waitDMA();                    // the other buffer's transfer has finished
  band.pushSprite(&lcd, 0, y);      // starts this buffer's transfer
}
lcd.waitDMA();

代价是多用一个 38 KB 的缓冲区,而空闲 RAM 总共约 275 KB。

代码,逐部分讲解

用 git clone https://github.com/velxio/m5claude.git 下载代码,或从仓库的 Code 按钮下载 ZIP。它由两半组成,除了协议之外互不共享:bridge/ 在 PC 上运行,firmware/ 和 src/ 在 M5Stack 上运行。

在 M5Stack 上

firmware/m5claude/m5claude.ino:所有与开发板相关的内容。

src/app/app.cpp:协议,与链路无关。

src/model/:数据。

src/ui/:屏幕。

在 PC 上

桥接程序位于 bridge/m5claude_bridge/。它唯一的依赖是 pyserial 和 bleak。HTTPS 调用使用标准库。

__main__.py:命令行和主循环。

autostart.py 注册桥接程序在登录时无窗口启动:Windows 上是带 pythonw 的 Run 注册表项,macOS 上是 LaunchAgent,Linux 上是 systemd 用户单元。

config.py:账户。

sources/:每个数据源一个文件。

pricing.py 保存按模型系列划分的 API 标价。它估算订阅用量的价值。

snapshot.py:构建快照。

hub.py 保留最新的快照并将其提供给每个已连接的设备。慢速链路只会拿到最新的那一份,绝不会积压。

transports/:每条链路一个文件。

仓库的 README 以表格形式提供了同样的导览,外加故障排除。

自己动手做一个

我推荐的顺序是:先在 Velxio 里设计界面,然后给板子刷固件,最后连接桥接程序。

1. 在 Velxio 里运行并修改 M5Stack Core

Velxio 模拟 M5Stack Core,包括它的 320×240 屏幕、A、B、C 三个按键和电池芯片。在 2 英寸的屏幕上排版需要大量微调(标签低了两个像素、数字放不进卡片),而在浏览器里每次调整只需几秒,不必经历一轮刷写。

这个仪表盘就在 Velxio 的示例库中,源文件与仓库中的完全一致:

  1. 打开 M5Stack Core: Claude usage dashboard (m5claude) 并点击播放按钮。无需注册。它会以本文中的演示账户启动。
  2. 点击 A 和 C 选择账户,点击 B 切换视图。模拟器运行固件的速度比板子慢,所以要打开设置,请按住 C 几秒钟。
  3. 想看到你自己的数据,就在 PC 上运行 m5claude-bridge snapshot,把它打印出的那一行粘贴到串口监视器中。草图的第一条注释里有一行示例,你可以直接修改。
  4. 在 ui.cpp 中修改界面并重新运行。看起来满意后,再刷写到板子上。

与板子有两处不同:Velxio 没有蓝牙,因此这条链路被省略,串口监视器是唯一的连接方式;扬声器代码使用的是较新的 ESP32 Arduino 核心的调用。每处改动都在草图中做了标记。

想从空白屏幕开始搭建自己的仪表盘,M5Stack Core: Hello LCD + Buttons 是最小的示例。它使用 M5Stack 的 M5GFX,后者基于 LovyanGFX 构建并共享其绘图 API,因此代码可以在两者之间迁移。

2. 刷写固件

git clone https://github.com/velxio/m5claude.git && cd m5claude
arduino-cli core install esp32:esp32
arduino-cli lib install LovyanGFX NimBLE-Arduino ArduinoJson

./firmware/build.sh /dev/ttyUSB0      # Linux / macOS
.\firmware\build.ps1 -Upload          # Windows, finds the COM port by itself

这些脚本为 M5Stack Core 构建,使用的分区方案为大型应用留出了空间(PartitionScheme=no_ota)。固件大约 820 KB。有两个设置让我踩了坑:

3. 运行桥接程序

pip install -e bridge                # from the repository root; installs pyserial and bleak
m5claude-bridge accounts             # which accounts it found
m5claude-bridge autostart on         # start now, and at every login

autostart on 会注册桥接程序,使其在你登录时无窗口启动。在 Windows 上,它会在用户的 Run 注册表项下添加一个启动 pythonw 的值。在 macOS 上它会安装一个 LaunchAgent,在 Linux 上则是一个 systemd 用户服务。autostart status 会显示它是否在运行,以及日志的最后几行,日志位于 ~/.m5claude/bridge.log。同一时间只能运行一个桥接程序:第二个会争抢 USB 端口和蓝牙连接,因此它会打印一条消息后退出。单独运行 m5claude-bridge 会让它保持在前台,日志输出到终端。

Pro 和 Max 账户是从 Claude Code 的配置目录中找到的。要添加第二个订阅,请在其自己的目录下登录:

$env:CLAUDE_CONFIG_DIR = "$HOME\.claude-work"; claude    # then /login

API 组织需要一个 Admin API 密钥,可在 Claude Console 的 Settings → Admin keys 中获取:

m5claude-bridge add-api "Acme API" --key-env ACME_ADMIN_KEY

4. 连接

插上 USB 线,或者把设备放在桌上让蓝牙找到它。首次通过蓝牙连接时,在设备上按 C 来批准这台 PC。数据会在几秒内出现。

注意事项

下一步

代码在 github.com/velxio/m5claude。欢迎提交 issue 和 pull request。

感谢 M5Stack 提供了一块开箱即用的板子,也感谢 LovyanGFX、NimBLE-Arduino、ArduinoJson 和 bleak 的作者们。

本页中指向 M5Stack 商店的链接是联盟链接:如果你通过它们购买,Velxio 会获得少量佣金,对你没有额外费用,这有助于让模拟器保持免费。


分享到:
David Montero

作者

David Montero

Creator of Velxio, the open-source circuit and Arduino simulator.

GitHub velxio.dev

相关文章


上一篇
可爱的桌面机器人:ESP-VoCat 上会倾听的脸,以及浏览器中的模拟器
下一篇
浏览器中的树莓派 4 和 5:基础模式与 Linux 模式,分步指南