Skip to content

Instantly share code, notes, and snippets.

@g4bri3lDev
Last active October 2, 2025 20:18
Show Gist options
  • Select an option

  • Save g4bri3lDev/0463318d5e3688703182eabe8435cd45 to your computer and use it in GitHub Desktop.

Select an option

Save g4bri3lDev/0463318d5e3688703182eabe8435cd45 to your computer and use it in GitHub Desktop.
blueprint:
name: Waste Collection Display (2.9")
description: >
# OpenEPaperLink Waste Collection Display (2.9")
## Requirements
- [OpenEPaperLink Integration](https://github.com/jonasniesner/open_epaper_link_homeassistant) installed
- [Waste Collection Schedule Integration](https://github.com/mampfes/hacs_waste_collection_schedule) configured
- At least one waste collection sensor
- 2.9" e-paper display (296x128 pixels)
## Sensor Configuration
This blueprint works with any value template configuration. It automatically extracts
the number of days from your sensor state, whether configured as:
- `"3"` (just a number)
- `"in 3 days"` (with text)
- `"3 days remaining"` (custom format)
The display automatically updates once per day at 00:10 (10 minutes after midnight).
author: g4bri3lDev
source_url: https://gist.githubusercontent.com/g4bri3lDev/0463318d5e3688703182eabe8435cd45/raw
domain: automation
input:
displays:
name: E-Paper Display(s)
description: >
Select one or more 2.9" OpenEPaperLink displays to show the waste collection
schedule. All selected displays will show the same content.
selector:
device:
multiple: true
filter:
integration: open_epaper_link
trash:
name: Waste Collection Sensors
description: >
Select your waste collection sensors to display.
**With sorting enabled:** Select all your sensors, and the display will
automatically show the 4 soonest upcoming collections.
**With sorting disabled (default):** Only the first 4 selected sensors will be shown in the
order you selected them (top-left, top-right, bottom-left, bottom-right).
selector:
entity:
multiple: true
filter:
integration: waste_collection_schedule
language:
name: Language
description: >
Choose the language for date labels (Today, Tomorrow, in X days). This only
affects the display text, not your sensor names.
default: "en"
selector:
select:
options:
- label: "English"
value: "en"
- label: "German"
value: "de"
- label: "Dutch"
value: "nl"
- label: "French"
value: "fr"
- label: "Spanish"
value: "es"
- label: "Polish"
value: "pl"
- label: "Croatian"
value: "hr"
- label: "Swedish"
value: "sv"
- label: "Italian"
value: "it"
- label: "Danish"
value: "da"
- label: "Norwegian"
value: "no"
sort_by_date:
name: Sort by Next Collection
description: >
When enabled, automatically shows the 4 soonest collections regardless of
which sensors are selected. Useful when there are more than 4 sensors.
default: false
selector:
boolean: {}
font_file:
name: Font file
description: >
Font file to use for all text on the display. The font must be available in
your Home Assistant font directories. For best results, use a bold, rounded
font like `GothamRnd-Bold.ttf`. The default `ppb.ttf` works
well for most displays.
default: ppb.ttf
selector:
text: {}
variables:
font_file: !input font_file
trash_raw: !input trash
sort_by_date: !input sort_by_date
trash: >
{%- if sort_by_date -%}
{%- set days_list = trash_raw | map('states') | map('regex_findall', '\\d+') | map('first') | map('int') | list -%}
{{ zip(trash_raw, days_list) | list | sort(attribute='1') | map(attribute='0') | list | list }}
{%- else -%}
{{ trash_raw[:4] }}
{%- endif -%}
language: !input language
language_map: >
{% set map = {
"en": {
"today": "Today",
"tomorrow": "Tomorrow",
"in": "in",
"days": "days",
"day": "day"
},
"de": {
"today": "Heute",
"tomorrow": "Morgen",
"in": "in",
"days": "Tagen",
"day": "Tag"
},
"nl": {
"today": "Vandaag",
"tomorrow": "Morgen",
"in": "over",
"days": "dagen",
"day": "dag"
},
"fr": {
"today": "Aujourd'hui",
"tomorrow": "Demain",
"in": "dans",
"days": "jours",
"day": "jour"
},
"es": {
"today": "Hoy",
"tomorrow": "Mañana",
"in": "en",
"days": "días",
"day": "día"
},
"pl": {
"today": "Dzisiaj",
"tomorrow": "Jutro",
"in": "za",
"days": "dni",
"day": "dzień"
},
"hr": {
"today": "Danas",
"tomorrow": "Sutra",
"in": "za",
"days": "dana",
"day": "dan"
},
"sv": {
"today": "Idag",
"tomorrow": "Imorgon",
"in": "om",
"days": "dagar",
"day": "dag"
},
"it": {
"today": "Oggi",
"tomorrow": "Domani",
"in": "tra",
"days": "giorni",
"day": "giorno"
},
"da": {
"today": "I dag",
"tomorrow": "I morgen",
"in": "om",
"days": "dage",
"day": "dag"
},
"no": {
"today": "I dag",
"tomorrow": "I morgen",
"in": "om",
"days": "dager",
"day": "dag"
}
} %}
{{ map }}
trigger:
- trigger: time
at:
- "00:10:00"
action:
- action: open_epaper_link.drawcustom
target:
device_id: !input displays
data:
background: white
rotate: 0
dry-run: false
payload: >
[
{
"type": "line",
"x_start": 4,
"x_end": 292,
"y_start": 64,
"y_end": 64,
"color": "accent",
"width": 3,
},
{
"type": "line",
"x_start": 148,
"x_end": 148,
"y_start": 4,
"y_end": 124,
"color": "accent",
"width": 3,
},
{% for i in range(trash|length) if i < 4 %}
{% set days_until = states(trash[i]) | regex_findall('\\d+') | first | int %}
{
"type": "rectangle",
"x_start": {{ 4 + (i % 2) * 148}},
"y_start": {{ 4 + (i // 2) * 64 }},
"x_end": {{ 144 + (i % 2) * 148 }},
"y_end": {{ 60 + (i // 2) * 64 }},
"fill": "{% if days_until == 0 %}accent{% elif days_until == 1 %}half_accent{% else %}white{% endif %}",
"outline": "white",
"width": 1
},
{
"type": "text",
"value": "{{ state_attr(trash[i], 'friendly_name') }}",
"font": "{{ font_file }}",
"x": {{ (10 + (i % 2) * 148) if (i % 2) == 0 else (138 + (i % 2) * 148) }},
"y": {{ 22 + (i // 2) * 64 }},
"size": 16,
"color": "{{ iif(days_until == 0, 'white', 'black') }}",
"anchor": "{{ 'lm' if (i % 2) == 0 else 'rm' }}"
},
{
"type": "text",
"value": "{% if days_until == 0%}{{ language_map[language]['today'] }}{% elif days_until == 1 %}{{ language_map[language]['tomorrow'] }}{% else %}{{ language_map[language]['in'] }} {{ days_until}} {{ language_map[language]['days'] }}{% endif %}",
"font": "{{ font_file }}",
"x": {{ (10 + (i % 2) * 148) if (i % 2) == 0 else (138 + (i % 2) * 148) }},
"y": {{ 42 + (i // 2) * 64 }},
"size": 16,
"color": "{{ iif(days_until == 0, 'white', 'black') }}",
"anchor": "{{ 'lm' if (i % 2) == 0 else 'rm' }}"
},
{% endfor %}
{
"type": "circle",
"x": 148,
"y": 64,
"radius": 32,
"fill": "white",
"outline": "white",
"width": 1,
},
{
"type": "icon",
"value": "mdi:delete",
"x": 148,
"y": 64,
"size": 48,
"color": "accent",
"anchor": "mm",
},
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment