Skip to main content

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tesserae_opendisplay-0.2.0.tar.gz (35.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tesserae_opendisplay-0.2.0-py3-none-any.whl (33.1 kB view details)

Uploaded Python 3

File details

Details for the file tesserae_opendisplay-0.2.0.tar.gz.

File metadata

  • Download URL: tesserae_opendisplay-0.2.0.tar.gz
  • Upload date:
  • Size: 35.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tesserae_opendisplay-0.2.0.tar.gz
Algorithm Hash digest
SHA256 64c3b4ea198e3e459d8396311079e344fbd08fbb5946d996f314b9bc9ba13140
MD5 1e6d51e164d1431caca2953cd9dd31e7
BLAKE2b-256 8289dc9346a30bebaaf5e128f11120c3fdc93c5ea0be515a10507a513cd356d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for tesserae_opendisplay-0.2.0.tar.gz:

Publisher: publish.yml on dmellok/tesserae-opendisplay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tesserae_opendisplay-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for tesserae_opendisplay-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3ba475761e54ed8cb8e103137b478a6550b7aa1f1f17ea95f9299a33e3c65f91
MD5 128d5fd2e1e7db032457bfc2b92c8acd
BLAKE2b-256 a34fc3f3ef9bf23eaf91c709ae2aae88f37386be15cd74302c4eaaea3226e4e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for tesserae_opendisplay-0.2.0-py3-none-any.whl:

Publisher: publish.yml on dmellok/tesserae-opendisplay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page