Skip to content

About

Dynamic Home Assistant Media Source integration for OpenDisplay Studio

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

OpenDisplay Studio

Design e-paper screens inside Home Assistant. Drag shapes, text, icons and live widgets onto a canvas that is exactly the size of your display, bind any property to Home Assistant data, and send the result to an OpenDisplay device, or serve it as an image that any display can fetch.

Open this integration in HACS Add OpenDisplay Studio to Home Assistant

The OpenDisplay Studio editor with a weather widget selected

What you get

  • A real WYSIWYG editor. The picture on the canvas is rendered by the same engine that produces the final image, so what you see is what the display shows: same fonts, same palette, same pixels.
  • Every OpenDisplay drawing type: text, multiline text, lines, rectangles, patterns, polygons, circles, ellipses, arcs, icons, icon rows, images, QR codes, progress bars, history plots and a debug grid.
  • Turn anything. Drag the round handle above any element to rotate it, or type an angle; the preview follows at once.
  • Your own fonts. Open Settings in the list of dashboards, drop in any .ttf or .otf and pick it for any text or widget, previewed in its own letters. Removing a font that dashboards use asks first, and nothing breaks if it is gone.
  • Live widgets: Sensor card, Sensor list, Sensor chart, Gauge, Thermometer, Calendar, Agenda, School timetable, Waste collection, Battery and Weather read your entities, calendars and forecasts. Write your own widget as a small Python package (see docs/widget-sdk.md). Every widget is described, with its options and pictures, in docs/widgets.
  • Your data in any property. Switch the {} toggle next to a field and type a Home Assistant template. The panel re-renders when the entities it reads change.
  • Made for e-paper. Pick the colours of your display (black/white, red, yellow, Spectra 6, grayscale…); the colour pickers only offer what the panel can show.

Start from the display you own

Create a dashboard from a display Home Assistant already knows, from a list of common panels, or at any custom size. Rotation is part of the dashboard, so a portrait display just works.

The new dashboard dialog, starting from a device

All your dashboards live in one list, with their size, colours and state (Draft or Ready). Ready dashboards get a stable image address; send them to a device with one click.

The list of dashboards

Shapes you can shape

Select a polygon and drag its points. Click the + on an edge to add a point, double-click a point to remove it. A line has a handle on each end. Everything snaps to the grid and to the edges and centres of its neighbours, and guides with equal-gap badges show you when things line up. Hold Ctrl to turn snapping off, press Esc to cancel a drag.

Editing the points of a polygon

Turn anything

Every element except the debug grid can be turned. Select one and drag the round handle above its frame, or type an angle under Layout → Rotation. The frame turns with the element, about the point the renderer turns it about, so what you see is what the display shows. Hold Shift to turn in steps of 15°, Esc to cancel; the whole turn is one step of the history. Text, icons, lines, shapes, QR codes and charts all turn, and a design made before keeps its look until you turn something. While an element is turned its frame has no resize handles; set the rotation back to 0 to resize it.

A text, a rectangle, an icon, a QR code, a gauge, an arc and a line, each turned, with the text selected and its rotate handle above it

Charts, gauges, codes and patterns

The more advanced drawing types are as easy to use as a rectangle. A history plot draws the recorded history of up to four entities, each with its own colour, line width and smoothing, optional axes and labels, and a multiplier for values that need scaling. Pick the entity of every series from the usual Home Assistant entity picker. Progress bars, arcs, QR codes, repeating patterns, rows of icons and multiline text sit next to them in the library.

Editing a history plot with two series

Progress bars, an arc, a pattern, a QR code and multiline text

One panel for every element

Primitives, widgets and containers are edited with the same compact controls: numbers with units, segmented choices, colour swatches limited to your display's palette, a searchable picker for every Material Design icon, an image picker, and an entity picker for each series of a history plot. Sections show a dot when something differs from the defaults and a reset link puts it back in one step; rarely needed fields wait under Advanced.

The property panel of a rounded rectangle

Widgets

Widgets decide how to lay out your data; you decide what to show. Pick the entities, calendars or weather source, choose the options, and resize the frame. The layout adapts to the size you give it. Every widget can be drawn without its frame and background, or in white on black. The widgets page lists each widget with its sources, options and pictures.

The widgets that come with Studio:

Sensor card
Sensor card
The value of one entity as a tile whose layout follows the shape of its frame: wide, square or tall.
Sensor list
Sensor list
The values of several entities, one line each, with alerts above or below a threshold.
Sensor chart
Sensor chart
The value of one entity with its history as a line chart.
Calendar
Calendar
Events of one or more calendars as upcoming days, an agenda or a grid of weeks.
Agenda
Agenda
Upcoming events from several calendars on one list.
School timetable
School timetable
A school week of one calendar as a table of days and lesson slots, with the lesson in progress marked.
Waste collection
Waste collection
When each of up to four bins is collected, with the nearest dates highlighted in a color of the display.
Weather
Weather
Current conditions and a daily or hourly forecast of a weather entity.
Battery
Battery
The charge of a battery as a battery that fills up, with its percentage beside it or inside, and a color for a low charge.
Gauge
Gauge
The value of a sensor on a half dial, with a marker or a filled arc, and as many colored ranges as you want, as for the load of a processor.
Thermometer
Thermometer
A temperature on a classic round dial with a scale, a needle and colored ranges: outdoor, a boiler, a hot water tank, a processor.

The properties of a sensor card widget

Undo, redo and a safety net

Every change is one undo step: moving, resizing, typing a value, ordering, grouping, pasting. Drag and nudge bursts are grouped sensibly, and Esc abandons a gesture without leaving a trace.

Undo and redo in the toolbar after moving an element

See the code

The Code view shows the clean, flat ODL YAML that is generated from the dashboard: absolute coordinates, only valid fields, nothing else. Copy it into an automation if you prefer to drive a display yourself.

The generated ODL YAML

Move a design between dashboards

Export saves the open dashboard as a JSON file; Import replaces the elements of the open dashboard with those of such a file, keeping its name, id and display settings. If the file was made for a display with more colours than yours, the import lists the colours your palette lacks and lets you pick a colour of your own for each; colours both displays have are kept. An import is one undo step and is not saved until you save.

Working with the canvas

Do this To get this
Mouse wheel Pan
Ctrl / ⌘ + wheel Zoom toward the pointer
Middle button, or Space + drag Move the view
Shift or Ctrl / ⌘ + click Add to the selection; click an element again to take it out
Arrow keys, Shift + arrow Nudge by 1 px, or by the grid size
Ctrl + G Group the selection
Ctrl + D, Ctrl + C / V Duplicate, copy and paste
Ctrl + Z / Y Undo and redo
Drag the round handle above a selection, with Shift Turn it, in steps of 15°

Commands

Every action is one command, and the toolbar buttons, the keyboard, the two context menus and the shortcut list (?) all use the same ones.

Command Shortcut What it does
Undo, Redo Ctrl + Z, Ctrl + Shift + Z or Ctrl + Y Step through the history; every change is one step
Copy, Cut, Paste Ctrl + C / X / V Use the clipboard of the panel
Paste here context menu of the empty canvas Paste at the place that was clicked
Duplicate Ctrl + D Copy the selection 8 px to the side
Delete Del Remove the selection, after asking
Rename F2 Rename a layer
Hide, Lock tree buttons, context menu of the tree Hide an element from the picture, or keep it from being moved
Make group, Ungroup Ctrl + G, Ctrl + Shift + G Turn the selection into a group, or dissolve one
Enter group, Exit group Enter or double-click, Esc Select the members of a group one by one
Bring to front, Move up, Move down, Send to back arrange bar, context menus Change the drawing order; the last element is on top
Align arrange bar Put the edges or the middles of the selection on one line
Space out evenly arrange bar Make the gaps between the elements equal
Nudge arrow keys, Shift + arrow keys Move by 1 px, or by the snap size
Save Ctrl + S Save the dashboard
Design / Code Ctrl + E Switch between the canvas and the generated YAML
Zoom in, out, reset Ctrl + = / - / 0 Change the view
Keyboard shortcuts ? List every shortcut

Context menus

Right-click an element on the canvas or a layer in the tree. The two menus offer what suits where you are: the canvas menu has Duplicate and the drawing order, the tree menu has Move up and down, Hide, Lock and Rename. Commands that cannot run now are dimmed.

The context menu of an element on the canvas    The context menu of a layer in the tree

Align and space out

The bar under the canvas toolbar is always there, and a button is dimmed until enough is selected. Select elements with Shift or Ctrl / ⌘ and a click (the second click takes an element out again), or drag a box around them.

The arrange bar with three elements selected

Buttons Need Result
Align left edges, centers horizontally, right edges 2 elements The edges or the middles sit on one vertical line, that of the selection's box
Align top edges, centers vertically, bottom edges 2 elements The same on a horizontal line
Space out evenly, left to right / top to bottom 3 elements The outer two stay; the ones between are moved so that every gap is equal
Bring to front, Move up, Move down, Send to back 1 element Change the drawing order

Two buttons beside them choose what the others measure against. Align to the selection is the default. Align to the container or the working area puts each element against the box it lives in, so one element is enough to align, and two are enough to space out: the first goes to one edge of the box, the last to the other.

For three entity widgets of one size: select them, centre them vertically, then space them out left to right. For a grid of nine, do that for each row, then align and space out each column. Locked elements and elements whose position comes from an expression are left where they are, and an element inside a selected container moves with it. Gaps that cannot be equal in whole pixels differ by at most one. Every press is one undo step, and a press that would change nothing does not add one.

Press ? in the editor for the complete list. Elements may hang out of the canvas; the renderer simply draws what is in view.

How it works

Home Assistant data
        ↓
dashboard (a tree of shapes, containers and widgets)
        ↓
ODL elements with absolute coordinates
        ↓
odl-renderer
        ↓
exact-size PNG
        ↓
editor preview, Media Source, or your device

The integration embeds odl-renderer: no add-on, no browser, no extra service. The editor preview and the image your display receives come from the same code path.

Every Ready dashboard has a stable address:

media-source://opendisplay_studio/<dashboard-id>

Fonts

Text uses the two fonts that ship with the renderer. To use your own, put .ttf or .otf files in /config/opendisplay_studio/fonts/; they appear in the font lists of the editor.

Installation

  1. Click Open this integration in HACS, download OpenDisplay Studio, and restart Home Assistant when requested.
  2. Click Add OpenDisplay Studio to Home Assistant.
  3. Open OpenDisplay Studio in the Home Assistant sidebar.

It works on Home Assistant OS, Supervised, Container and Core.

Troubleshooting: cannot import name 'TextMetrics' from 'odl_renderer'

Studio and the OpenDisplay integration from HACS both use the odl-renderer package, and Home Assistant keeps only one copy of it. Studio needs 0.5.13 or newer, while the released OpenDisplay 3.1.0 and older pin 0.5.12. (The OpenDisplay integration that ships with Home Assistant does not use odl-renderer.) Until the HACS OpenDisplay is released with odl-renderer 0.5.13 or newer, which its development branch already has, the two cannot be installed together, and the log says so. Update OpenDisplay to such a version, then restart Home Assistant. A restart is always needed after a package changes.

Development

python -m pip install -r requirements_test.txt
python -m ruff check .
python -m ruff format --check .
python -m mypy custom_components/opendisplay_studio scripts
python -m pytest

cd frontend-src
npm ci
npm test
npm run build
npm run test:e2e

See ARCHITECTURE.md for the render boundary, WIDGET_CONTRACT.md for the widget contract and ROADMAP.md for what is done and what is next.

License

MIT

About

Dynamic Home Assistant Media Source integration for OpenDisplay Studio

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages