tesserae-opendisplay
A bridge that pushes Tesserae-rendered dashboards to OpenDisplay BLE e-paper tags.
Tesserae renders your dashboards on the server; OpenDisplay tags are driven over Bluetooth LE. This bridge sits between them: it polls Tesserae's frame endpoint for each tag over the network, and when a frame changes it pushes the image to the tag over BLE with the py-opendisplay SDK, which dithers for whatever panel the tag advertises. One bridge drives many tags, and you can run several bridges (one per BLE cluster) against the same Tesserae server.
Requirements
- A running Tesserae server reachable over the network.
- A machine near your tags with a Bluetooth LE adapter (a Pi, a mini PC, an HA box) to run the bridge on.
- Bluetooth (BlueZ) running on that machine. On Linux the bridge talks to the adapter through BlueZ, so it needs to be installed and running:
sudo apt install bluez sudo systemctl enable --now bluetooth sudo rfkill unblock bluetooth bluetoothctl list # should show a controller
A container or VM has no Bluetooth unless a real adapter is passed through, so run the bridge on the host (or a host with a USB dongle). - Python 3.11+.
Install
pip install tesserae-opendisplay
Configure in a browser
The quickest way to set up: run the config web UI, then point a browser at the host on port 8080.
tesserae-opendisplay web # then open http://<bridge-host>:8080/
It lets you point the bridge at your Tesserae server, scan for OpenDisplay tags over Bluetooth (reading each panel size), add them, and remove them, writing config.toml for you. Prefer the command line? Skip to Find your tags.
Find your tags
tesserae-opendisplay discover
This scans for tags in range and prints a [[tags]] stub for each, including the panel size it reads off the tag, so you can paste it straight into your config.
Configure
Create config.toml:
server_url = "http://tesserae.local:8000"
poll_interval_s = 300 # fallback cadence; the server can override per tag
[[tags]]
device_id = "kitchen" # the Tesserae device id (you choose it)
ble = "AA:BB:CC:DD:EE:FF" # tag BLE MAC (or a device name to auto-scan)
width = 800 # the tag's panel, from `discover`
height = 480
pairing_code = "AB12CD" # optional: a Tesserae pairing code to register this tag once
# token = "..." # or a device token you already hold
# rotate = 0 # optional 0 / 90 / 180 / 270
# fit = "contain" # optional contain / cover / stretch / crop
# dither = "burkes" # optional dither mode
# refresh = "full" # optional full / partial
[[tags]]
device_id = "hall"
ble = "OpenDisplay-A1"
width = 400
height = 300
pairing_code = "AB12CD"
Generate a pairing code in Tesserae under Settings → Devices. The bridge registers each tag with that code on first run, then caches the token in config.toml.state.json so later runs skip registration. After a tag is registered it shows up in Tesserae like any other device: bind a dashboard, add it to a rotation, schedule it.
Run
tesserae-opendisplay --config config.toml
Each cycle the bridge asks Tesserae for every tag's frame (sending the last ETag, so unchanged frames cost nothing), and only pushes over BLE when a frame actually changed. BLE uploads happen one tag at a time (Bluetooth is serial), so a change to many tags refreshes them in sequence. Run it under systemd / an init supervisor for an always-on setup, or --once for a single pass (a cron-driven refresh).
Scaling to many tags
- One bridge cycles its tags sequentially. Fine for a wall that updates on an e-paper cadence.
- Multiple bridges, each on its own BLE adapter near its cluster of tags, all point at the same
server_url. That's how you cover more tags or more rooms: shard the tags across bridges by location.
How it fits together
Tesserae server ──HTTP /frame──► bridge (this) ──BLE upload──► OpenDisplay tag
renders polls + pushes displays
Tesserae renders each tag's dashboard as a full-colour PNG (the opendisplay device kind uses the pi_png renderer); the bridge hands that PNG to the OpenDisplay SDK, which does the panel-specific dithering. Nothing about the tag's geometry lives on the server beyond the panel size you register it with.
License
AGPL-3.0-or-later.
Metadata
Release files for tesserae-opendisplay 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tesserae_opendisplay-0.2.0.tar.gz | 35.9 kB | With provenance | Details for tesserae_opendisplay-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tesserae_opendisplay-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for tesserae_opendisplay-0.2.0-py3-none-any.whl |
Total release size: 69.0 kB
Release files / tesserae_opendisplay-0.2.0.tar.gz
| Download URL | tesserae_opendisplay-0.2.0.tar.gz |
|---|---|
| Size | 35.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
64c3b4ea198e3e459d8396311079e344fbd08fbb5946d996f314b9bc9ba13140
|
|
BLAKE2b-256 checksum How to use checksums |
8289dc9346a30bebaaf5e128f11120c3fdc93c5ea0be515a10507a513cd356d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logRelease files / tesserae_opendisplay-0.2.0-py3-none-any.whl
| Download URL | tesserae_opendisplay-0.2.0-py3-none-any.whl |
|---|---|
| Size | 33.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3ba475761e54ed8cb8e103137b478a6550b7aa1f1f17ea95f9299a33e3c65f91
|
|
BLAKE2b-256 checksum How to use checksums |
a34fc3f3ef9bf23eaf91c709ae2aae88f37386be15cd74302c4eaaea3226e4e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logSecurity for tesserae-opendisplay 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tesserae_opendisplay-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.