Skip to content

feat: OpenCode Go usage on a third screen - #154

Open
gbrein wants to merge 5 commits into
HermannBjorgvin:mainfrom
gbrein:opencode-go-screen
Open

feat: OpenCode Go usage on a third screen#154
gbrein wants to merge 5 commits into
HermannBjorgvin:mainfrom
gbrein:opencode-go-screen

Conversation

@gbrein

@gbrein gbrein commented Aug 12, 2026

Copy link
Copy Markdown

Adds an OpenCode screen next to the Anthropic one, with the same two-gauge layout, because the data has the same shape: OpenCode Go exposes rolling / weekly / monthly windows, each with a percent and a reset.

Daemon (daemon/opencode_usage.py, shared by all three daemons):

  • Gauges from GET https://opencode.ai/zen/go/v1/usage, authenticated with the key OpenCode already stores in auth.json. Undocumented endpoint, found by probing; the Zen docs list none.
  • The User-Agent header is load-bearing: Cloudflare fronts opencode.ai and 403s urllib's default Python-urllib/3.x with error code 1010.
  • Today's tokens from a read-only sqlite3 query against opencode.db. Not ccusage: that parses the storage/message/*.json layout current OpenCode versions no longer write, so it silently reports nothing.
  • urllib, not httpx, since the bash daemon runs this under the host's python3.
  • Every failure path omits the fields, so the screen reads "No data" rather than a fabricated 0%. Free-ride on the stored key, never refreshed.

Firmware:

  • Screens now cycle in enum order (splash -> usage -> opencode) instead of the old two-way toggle; prev_non_splash_screen goes away.
  • OpenCode's official mark takes the corner slot on its own screen, sized to match clawd_still.h so both marks carry the same visual weight.

Also here, both prerequisites for verifying the above on Windows:

  • boards/sim/shim: strlcpy + gmtime_r under _WIN32. Pre-existing gap; the sim had never been built with mingw, which has neither.
  • tools/package.json: png_to_lvgl.js needs pngjs and never declared it.
  • flash-mac.sh only probed /dev/cu.usbmodem*, missing every USB-UART bridge board (CH9102 enumerates as cu.wchusbserial*).

main.cpp and ui.cpp also carry a few in-flight hunks from the board-port work that interactive staging was unavailable to separate.

Claude-Session: https://claude.ai/code/session_015vSCPLyj5rcQssERdM6iy5

gbrein and others added 5 commits August 12, 2026 20:43
Adds an OpenCode screen next to the Anthropic one, with the same two-gauge
layout, because the data has the same shape: OpenCode Go exposes rolling /
weekly / monthly windows, each with a percent and a reset.

Daemon (daemon/opencode_usage.py, shared by all three daemons):
- Gauges from GET https://opencode.ai/zen/go/v1/usage, authenticated with the
  key OpenCode already stores in auth.json. Undocumented endpoint, found by
  probing; the Zen docs list none.
- The User-Agent header is load-bearing: Cloudflare fronts opencode.ai and
  403s urllib's default Python-urllib/3.x with error code 1010.
- Today's tokens from a read-only sqlite3 query against opencode.db. Not
  ccusage: that parses the storage/message/*.json layout current OpenCode
  versions no longer write, so it silently reports nothing.
- urllib, not httpx, since the bash daemon runs this under the host's python3.
- Every failure path omits the fields, so the screen reads "No data" rather
  than a fabricated 0%. Free-ride on the stored key, never refreshed.

Firmware:
- Screens now cycle in enum order (splash -> usage -> opencode) instead of the
  old two-way toggle; prev_non_splash_screen goes away.
- OpenCode's official mark takes the corner slot on its own screen, sized to
  match clawd_still.h so both marks carry the same visual weight.

Also here, both prerequisites for verifying the above on Windows:
- boards/sim/shim: strlcpy + gmtime_r under _WIN32. Pre-existing gap; the sim
  had never been built with mingw, which has neither.
- tools/package.json: png_to_lvgl.js needs pngjs and never declared it.
- flash-mac.sh only probed /dev/cu.usbmodem*, missing every USB-UART bridge
  board (CH9102 enumerates as cu.wchusbserial*).

main.cpp and ui.cpp also carry a few in-flight hunks from the board-port work
that interactive staging was unavailable to separate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015vSCPLyj5rcQssERdM6iy5
Touchless boards had no way to leave the splash: the tap-to-toggle gesture
is the only thing that advances screens, so a display-only port sat on the
splash forever. caps.has_touch lets main.cpp hand that job to the PWR-role
short press instead, at the cost of animation/brightness cycling there.
… T-Display

Both are Xtensa LX6 with no PSRAM and no native USB, so they take UART0
Serial and huge_app.csv partitions, and both are touchless, so the PWR-role
button carries screen cycling. The T-Display's 240x135 is the smallest panel
in the tree: the splash stage lands at 2 px per cell.

Its pin map and GRAM offsets were confirmed with a throwaway probe on the
real board rather than from a wiki. LCD_PANEL_W/H stays separate from
LCD_WIDTH/HEIGHT there on purpose: the constructor wants the native 135x240,
LVGL wants the rotated 240x135, and conflating them draws the UI into a
135-wide window on a 240-wide screen.
… boards

Two things kept the script from working outside the original setup. It shelled
out to ffmpeg for the RGB565 -> PNG conversion, its only external dependency,
now done with zlib and struct from the stdlib. And it opened the port with DTR
and RTS asserted, which on boards whose serial goes through a CH9102/CP2102/
CH340 bridge is wired to EN/IO0 -- so opening the port reset the chip and a
rebooting device answered the screenshot command, i.e. never.

Also adds the pio Scripts/python.exe fallback for Windows, where python3 is
usually the Store stub, and a clearer message for LV_USE_SNAPSHOT=0 builds.
The env comment says CH9102, so the macOS device path is cu.wchusbserial*,
not the cu.usbserial-* a CP210x gets. Older T-Display units do ship the
CP2104, hence both.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant