v0.4.0 - Claude usage zone + always-on settings page
Claude usage bars on the clock screen, and an always-on settings page for updating the
token/timezone without the BOOT-button dance.
New: Claude usage zone. Three bars (5-hour, 7-day, 7-day-Sonnet) shown beneath the
clock, polling Anthropic's usage endpoint every 5 minutes. Getting this reliable took real
diagnosis on real hardware: TLS handshakes were failing from heap fragmentation (not
total free memory - the board reported 50KB+ free at the same moments it failed). Fixed by
measuring and shrinking an over-provisioned LVGL memory pool (40KB -> 20KB, only ~13KB was
ever used), pausing BLE scanning during each fetch attempt, and checking available
contiguous memory before even trying instead of blocking on a doomed connect. Two more real
bugs found once the fetch was reliable: percentages were 100x too large (API returns them
already as a percentage, not a 0-1 fraction), and the bar fill had a visible gradient
banding/stripe artifact that two different fixes (dithering, gradient caching) failed to
resolve - solved by dropping the gradient for a flat per-state color instead.
Security note, explicit and deliberate: the OAuth token is entered and stored on the
device itself (masked input, NVS storage), not kept off-device via a safer bridge-script
design that was offered and declined. This is a real tradeoff, not an oversight - see the
firmware README's "Claude usage zone" section for the full writeup.
New: always-on settings page at http://pinecyd.local/ (reachable whenever the clock
screen is showing) for updating the token or timezone without needing the WiFi captive
portal - useful since the token isn't refreshed and needs periodic re-entry. The
BOOT-button-forced portal is also now non-destructive (no longer wipes WiFi credentials
just to edit a different field).
Known limitation: flash headroom is tight (~94% of the OTA partition slot) after this
release's added dependencies (ArduinoJson, HTTPClient, WiFiClientSecure).