Install a client¶
The Tesserae server publishes frames; a client on the other end paints your panel. Four reference clients live in their own repos, pick whichever matches your hardware. Three of them subscribe to MQTT (Pi + ESP32); the fourth (TRMNL / KOReader-on-Kindle) polls the server over HTTP. All four use the same device-registration flow described in Set up a device.
| Client | Transport | Default id | Best for |
|---|---|---|---|
tesserae-esp32-bin-client |
MQTT | esp32 |
Battery-powered Waveshare 13.3" Spectra 6 |
tesserae-pi-bin-client |
MQTT | pi_bin |
Plugged-in Pimoroni Inky Impression (fastest path) |
tesserae-pi-png-client |
MQTT | pi_png |
Any inky-supported panel (2/3/6/7 colour) |
tesserae-trmnl-client |
HTTP-pull | trmnl |
TRMNL hardware + KOReader-on-Kindle |
See Screens & compatibility for which renderer feeds each client and what's been tested on real hardware.
tesserae-esp32-bin-client¶
dmellok/tesserae-esp32-bin-client
· pairs with the esp32_bin renderer · default id esp32
Battery-powered ESP32-S3-WROOM-2 firmware for the Waveshare 13.3" Spectra 6
panel. It deep-sleeps between wakes, subscribes to the retained
tesserae/<device_id>/frame/bin topic, and skips the download when the frame
hash hasn't changed. Months of battery life from a single Li-Po; the refresh
cadence is set by sleep_interval_s on tesserae/<device_id>/config. Device id
and Wi-Fi are configured through a captive portal (reachable afterward on the
LAN at tesserae-<id>.local).
This is the maintainer's daily driver
The ESP32 + Waveshare 13.3" path runs in production daily. All three clients are confirmed on real hardware.
tesserae-pi-bin-client¶
dmellok/tesserae-pi-bin-client
· pairs with the pi_bin renderer · default id pi_bin
A Raspberry-Pi-side Python daemon. It subscribes to
tesserae/<device_id>/frame/bin and writes the server's already-packed 4-bpp
buffer straight into the inky library's
internal _buf, no PIL on the Pi paint path. This is the fastest path on a
Pimoroni Inky Impression (Spectra 6 / Waveshare E6, any of the four sizes,
auto-detected via the HAT EEPROM). The trade-off is a private-API dependency:
the inky version is pinned exactly.
tesserae-pi-png-client¶
dmellok/tesserae-pi-png-client
· pairs with the pi_png renderer · default id pi_png
The same Pi-side daemon shape, but it subscribes to
tesserae/<device_id>/frame/png and hands incoming PNGs to inky's high-level
set_image(). That makes it work on every panel the inky library supports -
pHAT, wHAT, Impression 4"/5.7"/7.3"/13.3", in 2/3/6/7 colour. Quantising on the
Pi every frame makes it the slower of the two Pi paths, but it stays
wire-compatible with the inky-dash v3/v4 listener protocol.
TRMNL / KOReader (HTTP-pull)¶
dmellok/tesserae-trmnl-client
· pairs with the trmnl_png renderer · default id trmnl
For TRMNL hardware and Kindle e-readers running KOReader's
trmnl-display plugin. Instead of subscribing to MQTT, the device polls
GET /api/display on a schedule (the response carries the next frame
URL and the next-poll interval). No broker required, handy when you
want a panel that "just talks to the internet".
Pairing flow: the device reads its MAC, hits /api/setup, and the
server prints a short 5-character access token on the admin's
Settings → Devices → Add device → TRMNL card. Type the token into
the device once and it's paired; from there it polls /api/display
authenticated via the token. Errors / battery / RSSI heartbeat back
via POST /api/log and surface on the device card.
The trmnl_png renderer fits your composition PNG to the device's
panel size and quantises to 1-bit black/white with the dither of
your choice (Floyd-Steinberg, Atkinson, Jarvis, Stucki, Bayer 8×8,
halftone, crosshatch, or none). Dither + contrast live on the device
card so you can tune for the specific panel (Kindle Paperwhite 2,
native TRMNL panel, etc.).
After flashing / pairing¶
On first run, a client publishes a heartbeat on tesserae/<device-id>/status
(MQTT clients) or calls /api/setup then /api/display (TRMNL).
Head to Set up a device to register it, calibrate the
panel orientation, and bind a dashboard.
Running more than one panel? Flash / pair each with a distinct
device-id, every client gets its own topics or HTTP token, panel
size, and orientation.