Skip to content

Instantly share code, notes, and snippets.

@10der
Created December 8, 2023 12:39
Show Gist options
  • Save 10der/568244e49b7709d8d9443084e4706034 to your computer and use it in GitHub Desktop.
Save 10der/568244e49b7709d8d9443084e4706034 to your computer and use it in GitHub Desktop.
awtrix_weatherflow_ad_hoc.yaml
---
blueprint:
name: AWTRIX Weather ⛈️ + Forecast + 🌕️
description: >
This is somewhat of a mega-weather blueprint with moon phase support. However for it work correctly you will need a variety of different things setup. It was initially designed to use in partnership with a personal weather station however it seems to work fine with OpenWeather as well or any other provider that offers an hourly forecast.
![](https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/docs/weather.gif)
![](https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/docs/sunset.gif)
This blueprint will publish to two separate topics. `jeef_weather` for the weather report and `jeef_weather_sun` if its near sunrise/set
## ⚠️ REQUIREMENTS ⚠️
For this blueprint to work you MUST have a few things pre-setup.
### Moon Integration 🌕️
.------.
( I MOON ) ..
`------' .' /
O / ;
o i OO
C `-. Make sure you've
| <-' enabled
( ,--. the MOON Sensor
V \_)
\ :
`._\.
The moon integration is required. You can add it via the [moon](https://www.home-assistant.io/integrations/moon/) page or just by [clicking here](https://my.home-assistant.io/redirect/config_flow_start?domain=moon)
### Moon Rise/Set Sensor 🌕️ ⏲️
M
(X)
// \\ Lets use a GeoLocation to find
// \\ out the Moon Rise / Set
// \\ TIMES
// \\
/ \
As Home Assistant doesn't _currently_ provide moon rise/set times you will need to get this from some api.
You can use the [ipgeolocation](https://app.ipgeolocation.io) API.
To do so you will need to create an account and extract your `API_KEY`. Additionally you need your `LAT` and `LON`.
Then you can add a [REST](https://www.home-assistant.io/integrations/sensor.rest/) sensor to your `configuraiton.yaml` file like the one here:
resource: https://api.ipgeolocation.io/astronomy?lat=<LAT>&long=<LON>&apiKey=<API_KEY>
name: ip_geo_location
scan_interval: 300
value_template: "OK"
json_attributes:
- moonrise
- moonset
- moon_altitude
### Icons
You can call my custom script which will prompt you for an Awtrix device and then upload the required icons:
(If you have windows I don't know if this will work)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/icons/upload_icon.sh)"
_This blueprint ~will~ may be updated as new features_
![](https://www.gravatar.com/avatar/3b9968835eb719e5d78a04ba7a2bafbd?s=64)
https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/blueprints/automation/awtrix_weatherflow.yaml
domain: automation
input:
awtrix:
name: AWTRIX Device
description: Select the Awtrix light
selector:
device:
integration: mqtt
manufacturer: Blueforcer
model: AWTRIX Light
multiple: true
forecast_var:
name: Hourly Forecast
description: >
Select a sensor that provides an Hourly forecast (not a daily one)
This integration has been tested with:
- HACS [Weatherflow](https://github.com/briis/hass-weatherflow) integration
- HomeAssistant [Openweather](https://www.home-assistant.io/integrations/openweathermap/)
selector:
entity:
filter:
domain:
- weather
multiple: false
hours_to_show:
name: Forecast Hours to Show
description: >
How many hours of forecast do you wish to show along the bottom of the display
selector:
number:
max: 24
min: 0
unit_of_measurement: "hours"
mode: box
default: 12
forecast_temp_field:
name: Temperature Attributes
description: >
Once you've selected your hourly forecast you will need to identify which attributes in the forecast provides a temperature value.
- If you are using [Weatherflow](https://github.com/briis/hass-weatherflow) you may be able to select from either `feels_like` or `temperature`
- In [Openweather](https://www.home-assistant.io/integrations/openweathermap/) you only have access to `temperature`
selector:
text:
default: "feels_like"
temp_digits:
name: Temp Digits
description: >
By default we will round the temp to the nearest whole-number. If you want percisions you can change this to 1 or 2 in order to see more decimalm places.
selector:
number:
min: 0
max: 2
step: 1
mode: box
unit_of_measurement: "Decimal places"
default: 0
temp_suffix:
name: Temperature suffix
description: >-
How do you want to display the temperature
If you live in a country with the following flags:
🇺🇸️🇵🇷️🇵🇼️🇧🇿️🇰🇾️🇫🇲️🇲🇭️🇻🇮️🇬🇺️
You probbaly use Farenheit.
Everybody else in the 🗺️ seems to rock the Metric System
selector:
select:
options:
- label: None
value: ""
- label: "°"
value: "°"
- label: °F
value: "°F"
- label: °C
value: "°C"
- label: F
value: "F"
- label: C
value: "C"
default: "°"
current_temp_var:
name: The current outside temperature
description: >
Select a sensor either from a PWS or a forecast that provides the current outside temperature you wish to display:
- `sensor.openweathermap_feels_like_temperature`
selector:
entity:
domain:
- sensor
multiple: false
default: sensor.weatherflow_air_temperature
color_matrix_json:
name: Color Matrix
description: >
The `Color Matrix` will control colors map to temperature ranges on the display. The format of this map is **JSON**
Here you can enter a temperature to color mapping.
> Please note the format is *JSON*,
Some possible mappings are:
#### USA: Farenheit 0-100 (Based on NOAA scale from 0-100)
{"0": "#FEC4FF","10": "#D977DF","20": "#9545BC","30": "#4B379C","40": "#31B8DB","50": "#31DB8B","60": "#6ED228","70": "#FFFF28","80": "#F87E27","90": "#CF3927","100": "#A12527"}
#### EURO: -12°c to -38°c based on USA NOAA Colors
{"-12": "#D977DF","-6": "#9545BC","-1": "#4B379C","0": "#FEC4FF","4": "#31B8DB","10": "#31DB8B","15": "#6ED228","21": "#FFFF28","27": "#F87E27","32": "#CF3927","38": "#A12527"}
selector:
text:
multiline: true
default: >
{
"0": "#FEC4FF",
"10": "#D977DF",
"20": "#9545BC",
"30": "#4B379C",
"40": "#31B8DB",
"50": "#31DB8B",
"60": "#6ED228",
"70": "#FFFF28",
"80": "#F87E27",
"90": "#CF3927",
"100": "#A12527"
}
# -------------
# Moon Stuff
# -------------
moon:
name: Moon Phase Sensor
description: >
🌑️🌒️🌓️🌔️🌖️🌗️🌘️
To setup a moon sensor see here: https://www.home-assistant.io/integrations/moon/
or just [clicking here](https://my.home-assistant.io/redirect/config_flow_start?domain=moon)
selector:
entity:
multiple: false
filter:
integration: moon
moon_rise_set:
name: Moon Riese/Set Sensor
description: >
As Home Assistant doesn't provide moon rise/set times you will need to get this from some api. In my personal setup I use [ipgeolocation](https://app.ipgeolocation.io) as my api.
You can create a custom REST sensor as follows:
```
sensor:
- platform: rest
resource: https://api.ipgeolocation.io/astronomy?lat=<LAT>&long=-<LON>&apiKey=<API_KEY>
name: ip_geo_location
scan_interval: 300
value_template: "OK"
json_attributes:
- moonrise
- moonset
- moon_altitude
```
selector:
entity:
multiple: false
filter:
integration: rest
when_show_moon:
name: When should the moon be displayed
description: >
Some people are really into the moon 🐺️ and they are called Wearwolves or maybe Astronomers.
Please select how and when you want the moon displayed
By selecting `Always show moon` the moon will always be drawn to the right of the display. Otherwise the moon will only be drawn if its risen depending on the option selected.
### NOTE:
At Brightness values less than 29 the greys of the moon will render green on the clock.
selector:
select:
options:
- label: Never show moon
value: never
- label: Always show moon
value: always
- label: Only show moon if its risen
value: risen
- label: Only show moon if risen + night
value: night
default: "night"
use_moon_clear_night:
name: Swap Clear Night for Moon
description: >-
The default case is for the moon to be drawn to the right-side of the clock, however, you have the option if this is selected to repalce the `clear_night` icon with the moon icon. This will only swap icons if the moon is currently being displayed.
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2314_icon_thumb.png?v=1) - `full_moon`
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2315_icon_thumb.png?v=1) - `waning_gibbous`
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2316_icon_thumb.png?v=1) - `last_quarter`
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2317_icon_thumb.png?v=1) - `waning_crescent`
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2318_icon_thumb.png?v=1) - `new_moon`
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2319_icon_thumb.png?v=1) - `waxing_crescent`
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2320_icon_thumb.png?v=1) - `first_quarter`
- ![](https://developer.lametric.com/content/apps/icon_thumbs/2321_icon_thumb.png?v=1) - `waxing_gibbous`
If you wish to use a different icon please enter its text in the box to the right
selector:
boolean:
default: True
use_moon_sunny_night:
name: Swap Sunny + Night for the Moon
description: >-
Some weather integrations may not correctly implement the `clear-night` weather state. In that case you can use
this option to automatically swap out the moon for if you have night + sunny
selector:
boolean:
default: True
#----------------------------------------
# Sunrise Sunset Times :)
#----------------------------------------
show_sun_rise_set:
name: ☀️ Show Sunrise/Sunset
description: >
Prior to both sunrise and sunset times offer a message about pending sun transitional state.
:
`. ; .'
`. .-'''-. .'
;' __ _;'
/ '_ _`\ TURN ME ON!
| _( a ( a |
''''| (_) > |``````
\ \ / /
`. `--'.'
.' `-,,,-' `.
.' : `.
:
_You can change the icons for sun rise/set way down below._
selector:
boolean:
default: True
sun_event_minute_threshold:
name: Sun Time Prior 🕰️
description: >-
This value controls when to show sunrise/set notifications.
If the sunrise will occur in `50` minutes and this value is set to `60` it will show, however if this value is only `30` it won't show.
selector:
number:
min: 5
max: 1440
unit_of_measurement: "min"
default: 30
sun_time_type:
name: Sun Time Type
description: >
When showing a notification about sun rise/set it can offer 3 different time formats:
- Relative Time: `12 min`
- Actual Time: `8:31 pm` or `22:31`
selector:
select:
options:
- Relative
- Actual
default: "Actual"
sun_time_format:
name: Actual Time Format
description: >
If you are using actual time you can enter a STRFTIME format string here for the time. Some options would be:
- `%H%M` which would render `0529`
- `%-I%M%p` which woudl render `529AM`
- `%-I%:M%p` which woudl render `5:29AM`
For details see https://strftime.org/
selector:
text:
type: text
default: "%-I%M%p"
message_duration_forecast:
name: Forecast Duration ⏱️
description: >-
How long should the forecast message remain on the screen(in seconds). *If you select `0` it will use the Global App Time*
selector:
number:
min: 0
max: 300
unit_of_measurement: "sec"
default: 30
message_duration_riseset:
name: Sun Rise/Set Duration ⏱️
description: >-
How long should the sunrise sunset message remain on the screen(in seconds). *If you select `0` it will use the Global App Time*
selector:
number:
min: 0
max: 300
unit_of_measurement: "sec"
default: 30
#-----------------------------------------
# This was really annoying to generate :)
#-----------------------------------------
icon_clear_night:
name: Icon for clear-night
description: >
The default clear_night icon is:
![](https://developer.lametric.com/content/apps/icon_thumbs/53383_icon_thumb.gif?v=2) - `53383`
selector:
text:
default: "w-clear-night"
icon_cloudy:
name: Icon for cloudy
description: >
This is the icon ID which maps to the weather state: `cloudy`
![](https://developer.lametric.com/content/apps/icon_thumbs/53384_icon_thumb.gif?v=1)
selector:
text:
default: "w-cloudy"
icon_exceptional:
name: Icon for exceptional
description: >
This is the icon ID which maps to the weather state: `exceptional`
![](https://developer.lametric.com/content/apps/icon_thumbs/36637_icon_thumb.gif?v=1)
selector:
text:
default: "w-exceptional"
icon_fog:
name: Icon for fog
description: >
This is the icon ID which maps to the weather state: `fog`
![](https://developer.lametric.com/content/apps/icon_thumbs/17055_icon_thumb.gif?v=1)
selector:
text:
default: "w-fog"
icon_hail:
name: Icon for hail
description: >
This is the icon ID which maps to the weather state: `hail` (IF YOU HAVE A BETTER ONE PLEASE LET ME KNOW)
![](https://developer.lametric.com/content/apps/icon_thumbs/53385_icon_thumb.gif?v=1)
selector:
text:
default: "w-hail"
icon_lightning:
name: Icon for lightning
description: >
This is the icon ID which maps to the weather state: `lightning`
![](https://developer.lametric.com/content/apps/icon_thumbs/29839_icon_thumb.gif?v=1)
selector:
text:
default: "w-lightning"
icon_lightning_rainy:
name: Icon for lightning-rainy
description: >
This is the icon ID which maps to the weather state: `lightning-rainy`
![](https://developer.lametric.com/content/apps/icon_thumbs/49299_icon_thumb.gif?v=4)
selector:
text:
default: "w-lightning-rainy"
icon_partlycloudy:
name: Icon for partlycloudy
description: >
This is the icon ID which maps to the weather state: `partlycloudy`
![](https://developer.lametric.com/content/apps/icon_thumbs/2286_icon_thumb.gif?v=1)
selector:
text:
default: "w-partlycloudy"
icon_pouring:
name: Icon for pouring
description: >
This is the default icon which maps to the weather state: `pouring`
![](https://developer.lametric.com/content/apps/icon_thumbs/49300_icon_thumb.gif?v=1)
selector:
text:
default: "w-pouring"
icon_rainy:
name: Icon for rainy
description: >
This is the default icon which maps to the weather state: `rainy`
![](https://developer.lametric.com/content/apps/icon_thumbs/2720_icon_thumb.gif?v=1)
selector:
text:
default: "w-rainy"
icon_snowy:
name: Icon for snowy
description: >
This is the icon ID which maps to the weather state: `snowy`
![](https://developer.lametric.com/content/apps/icon_thumbs/2289_icon_thumb.gif?v=1)
selector:
text:
default: "w-snowy"
icon_snowy_rainy:
name: Icon for snowy-rainy
description: >
This is the icon ID which maps to the weather state: `snowy-rainy`
![](https://developer.lametric.com/content/apps/icon_thumbs/49301_icon_thumb.gif?v=2)
selector:
text:
default: "w-snowy-rainy"
icon_sunny:
name: Icon for sunny
description: >
This is the icon ID which maps to the weather state: `sunny`
![](https://developer.lametric.com/content/apps/icon_thumbs/53386_icon_thumb.gif?v=1)
selector:
text:
default: "w-sunny"
icon_windy:
name: Icon for windy
description: >
This is the icon ID which maps to the weather state: `windy`
![](https://developer.lametric.com/content/apps/icon_thumbs/3363_icon_thumb.gif?v=1)
selector:
text:
default: "w-windy"
icon_windy_variant:
name: Icon for windy-variant
description: >
This is the icon ID which maps to the weather state: `windy-variant`
![](https://developer.lametric.com/content/apps/icon_thumbs/3363_icon_thumb.gif?v=1)
selector:
text:
default: "w-windy-variant"
icon_sunrise:
name: Icon for sunrise
description: >
This is the icon ID which maps to the `sunrise`
![](https://developer.lametric.com/content/apps/icon_thumbs/53418_icon_thumb.gif?v=1)
selector:
text:
default: "w-sunrise"
icon_sunset:
name: Icon for sunset
description: >
This is the icon ID which maps to the `sunset`
![](https://developer.lametric.com/content/apps/icon_thumbs/53417_icon_thumb.gif?v=1)
selector:
text:
default: "w-sunset"
mode: restart
variables:
device_ids: !input awtrix
app_topic: jeef_weather
devices_topics: >-
{%- macro get_device_topic(device_id) %}
{{ states((device_entities(device_id) | select('search','device_topic') | list)[0]) }}
{%- endmacro %}
{%- set ns = namespace(devices=[]) %}
{%- for device_id in device_ids %}
{%- set device=get_device_topic(device_id)|replace(' ','') %}
{% set ns.devices = ns.devices + [ device ~ '/custom/' ~ app_topic] %}
{%- endfor %}
{{ ns.devices | reject('match','unavailable') | list}}
forecast_var: !input forecast_var
forecast: "{{state_attr(forecast_var,'forecast')}}"
weather: "{{states(forecast_var)}}"
hours_to_show: !input hours_to_show
#---------------------------------
# Moon Stuff
#---------------------------------
moon: !input moon
moon_phase: "{{states(moon)}}"
moon_times: !input moon_rise_set
moon_rise: "{{state_attr(moon_times,'moonrise')}}"
moon_set: "{{state_attr(moon_times,'moonset')}}"
moon_alt: "{{state_attr(moon_times,'moon_altitude')}}"
moon_risen: "{{moon_alt > 0}}"
when_show_moon: !input when_show_moon
show_moon: >-
{%- if when_show_moon == 'always' %}
True
{%- elif when_show_moon == 'never' %}
False
{%- elif when_show_moon == 'risen' %}
{{moon_risen}}
{%- else %}
{{state_attr('sun.sun', 'elevation') < 0 and moon_risen}}
{%- endif %}
#----------------
# Temp & Text
# --------------
message_duration: !input message_duration_forecast
message_duration_riseset: !input message_duration_riseset
current_temp_var: !input current_temp_var
temp_digits: !input temp_digits
temp_suffix: !input temp_suffix
current_temp: "{{states(current_temp_var)}}"
temp_text: >-
{%- macro round_and_set_temp(temp_var, temp_suffix, digits=0) -%}
{%- if has_value(temp_var) -%}
{{ states(temp_var) | round(digits) ~ temp_suffix}}
{%- else -%}
??
{%- endif -%}
{%- endmacro -%}
{{ round_and_set_temp(current_temp_var, temp_suffix, temp_digits)}}
forecast_temp_field: !input forecast_temp_field
text_available_width: >
{%- if show_moon %}16{%- else %}24{%- endif %}
text_len: >-
{%- macro get_text_len(string) %}
{%- set length = namespace(value=0) %}
{%- for char in string %}
{%- if char.isdigit() %}
{%- set length.value = length.value + 3 %}
{%- elif char == '°' %}
{%- set length.value = length.value + 2 %}
{%- elif char == '.' %}
{%- set length.value = length.value + 1 %}
{%- elif char in ['-','C','F'] %}
{%- set length.value = length.value + 3 %}
{%- else %}
{%- set length.value = length.value + 1 %}
{%- endif %}
{%- if not loop.last %}
{%- set length.value = length.value + 1 %}{%- endif -%}
{%- endfor -%}
{{ length.value }}
{%- endmacro %}
{{get_text_len(temp_text)}}
text_x: >-
{{8 + ((text_available_width - text_len)/2)}}
# ------------------------------
# SUN THINGS
# ------------------------------
sun_event_minute_threshold: !input sun_event_minute_threshold
sun_time_type: !input sun_time_type
sun_time_format: !input sun_time_format
icon_sunrise: !input icon_sunrise
icon_sunset: !input icon_sunset
show_sun_rise_set: !input show_sun_rise_set
sun_next_event: >-
{%- set rise = state_attr('sun.sun','next_rising') %}
{%- set set = state_attr('sun.sun','next_setting') %}
{%- set ts_rise = rise |as_timestamp %}
{%- set ts_set = set |as_timestamp %}
{{ iif(ts_set < ts_rise,'sunset','sunrise') }}
sun_min_until_next_event: >-
{%- set rise = state_attr('sun.sun','next_rising') %}
{%- set set = state_attr('sun.sun','next_setting') %}
{%- set ts_rise = rise |as_timestamp %}
{%- set ts_set = set |as_timestamp %}
{{ iif(sun_next_event == 'sunrise',(ts_rise - utcnow()|as_timestamp) / 60,(ts_set - utcnow()|as_timestamp) / 60) | round(0) }}
sun_next_str: >-
{%- set rise = state_attr('sun.sun','next_rising') %}
{%- set set = state_attr('sun.sun','next_setting') %}
{%- set ts_rise = rise |as_timestamp %}
{%- set ts_set = set |as_timestamp %}
{%- if sun_time_type == 'Actual' %}
{{ iif(sun_next_event == 'sunrise',(ts_rise | as_datetime | as_local).strftime(sun_time_format), (ts_set | as_datetime | as_local).strftime(sun_time_format)) }}
{%- else %}
{#- relative time #}
{% set hours = sun_min_until_next_event // 60 %}
{% set remaining_minutes = sun_min_until_next_event % 60 %}
{% if hours == 0 %}
{{ remaining_minutes }} min
{% else %}
[
{"t":"{{hours}}", "c":"#ffffff"},
{"t":"h", "c":"#9c9d97"},
{"t":"{{remaining_minutes}}", "c":"#ffffff"},
{"t":"m", "c":"#9c9d97"}
]
{% endif %}
{%- endif %}
sun_event_icon: >-
{{ iif(sun_next_event == 'sunrise', icon_sunrise, icon_sunset) }}
sun_event_payload: >-
{"icon":"{{sun_event_icon}}", "text":"{{sun_next_str}}", "duration": {{message_duration_riseset}}}
sun_payload: >-
{%- if show_sun_rise_set %}
{{ iif(sun_event_minute_threshold >= sun_min_until_next_event, sun_event_payload, "{}") }}
{%- else %}
{}
{%- endif %}
icon_clear_night: !input icon_clear_night
use_moon_clear_night: !input use_moon_clear_night
use_moon_sunny_night: !input use_moon_sunny_night
icon_cloudy: !input icon_cloudy
icon_exceptional: !input icon_exceptional
icon_fog: !input icon_fog
icon_hail: !input icon_hail
icon_lightning: !input icon_lightning
icon_lightning_rainy: !input icon_lightning_rainy
icon_partlycloudy: !input icon_partlycloudy
icon_pouring: !input icon_pouring
icon_rainy: !input icon_rainy
icon_snowy: !input icon_snowy
icon_snowy_rainy: !input icon_snowy_rainy
icon_sunny: !input icon_sunny
icon_windy: !input icon_windy
icon_windy_variant: !input icon_windy_variant
clear_night_dict: >-
{{ dict({
'full_moon': '2314',
'waning_gibbous': '2315',
'last_quarter': '2316',
'waning_crescent': '2317',
'new_moon': '2318',
'waxing_crescent': '2319',
'first_quarter': '2320',
'waxing_gibbous': '2321'}) }}
color_matrix_json: !input color_matrix_json
color_dict: >-
{%
set color_matrix_json_fix_me = {
"-12": "#D977DF",
"-6": "#9545BC",
"-1": "#4B379C",
"0": "#FEC4FF",
"4": "#31B8DB",
"10": "#31DB8B",
"15": "#6ED228",
"21": "#FFFF28",
"27": "#F87E27",
"32": "#CF3927",
"38": "#A12527"
}
%}
{% set b = color_matrix_json_fix_me %}
{%- set ns = namespace(tuples=[]) %}
{%- for k,v in b | items -%}
{%- set key = k|float -%}
{%- set ns.tuples = ns.tuples + [(key,v)] %}
{% endfor %}
{{ dict.from_keys(ns.tuples) }}
icon_dict: >-
{{ dict({'clear-night': icon_clear_night,
'cloudy': icon_cloudy,
'exceptional': icon_exceptional,
'fog': icon_fog,
'hail': icon_hail,
'lightning': icon_lightning,
'lightning-rainy': icon_lightning_rainy,
'partlycloudy': icon_partlycloudy,
'pouring': icon_pouring,
'rainy': icon_rainy,
'snowy': icon_snowy,
'snowy-rainy': icon_snowy_rainy,
'sunny': icon_sunny,
'windy': icon_windy,
'windy-variant': icon_windy_variant})}}
icon: >
{%- if ((weather == 'clear_night') and use_moon_clear_night) %}
{{clear_night_dict[moon_phase]}}
{%- elif (sun_next_event == 'sunrise') and use_moon_sunny_night and (weather == 'sunny') -%}
{%- else %}
{{ icon_dict[weather] }}
{%- endif %}
moon_data: >
{%- macro draw_moon(phase,x=22,y=0) %}
{%- if phase == 'first_quarter' %}
{"db":[{{x}},{{y}},8,8,[0,0,3355443,3355443,14079702,14079702,0,0,0,3355443,3355443,3355443,15790320,14079702,14079702,0,3355443,3355443,3355443,3355443,13355979,13355979,14079702,14079702,3355443,3355443,1644825,3355443,13355979,15790320,15790320,14079702,3355443,3355443,1644825,3355443,15790320,15790320,15790320,14079702,3355443,3355443,3355443,3355443,15790320,13355979,14079702,14079702,0,3355443,3355443,3355443,15790320,14079702,14079702,0,0,0,3355443,3355443,14079702,14079702,0,0]]}
{%- endif %}
{%- if phase == 'full_moon' %}
{"db":[{{x}},{{y}},8,8,[0,0,14079702,14079702,14079702,14079702,0,0,0,14079702,14079702,15790320,15790320,14079702,14079702,0,14079702,14079702,15790320,15790320,11974326,11974326,14079702,14079702,14079702,15790320,11974326,15790320,11974326,15790320,15790320,14079702,14079702,15790320,11974326,15790320,15790320,15790320,15790320,14079702,14079702,14079702,15790320,15790320,15790320,11974326,14079702,14079702,0,14079702,14079702,11974326,15790320,14079702,14079702,0,0,0,14079702,14079702,14079702,14079702,0,0]]}
{%- endif %}
{%- if phase == 'last_quarter' %}
{"db":[{{x}},{{y}},8,8,[0,0,14079702,14079702,3487029,3487029,0,0,0,14079702,14079702,15790320,3487029,3487029,3487029,0,14079702,14079702,15790320,15790320,1907997,1907997,3487029,3487029,14079702,15790320,13553358,15790320,1907997,3487029,3487029,3487029,14079702,15790320,13553358,15790320,3487029,3487029,3487029,3487029,14079702,14079702,15790320,15790320,3487029,1907997,3487029,3487029,0,14079702,14079702,13553358,3487029,3487029,3487029,0,0,0,14079702,14079702,3487029,3487029,0,0]]}
{%- endif %}
{%- if phase == 'new_moon' %}
{"db":[{{x}},{{y}},8,8,[0,0,2763306,2763306,2763306,2763306,0,0,0,2763306,2763306,2763306,2763306,2763306,2763306,0,2763306,2763306,2763306,2763306,1842204,1842204,2763306,2763306,2763306,2763306,1842204,2763306,1842204,2763306,2763306,2763306,2763306,2763306,1842204,2763306,2763306,2763306,2763306,2763306,2763306,2763306,2763306,2763306,2763306,1842204,2763306,2763306,0,2763306,2763306,1842204,2763306,2763306,2763306,0,0,0,2763306,2763306,2763306,2763306,0,0]]}
{%- endif %}
{%- if phase == 'waning_crescent' %}
{"db":[{{x}},{{y}},8,8,[0,0,14079702,14079702,2763306,2763306,0,0,0,14079702,14079702,2763306,2763306,2763306,2763306,0,14079702,14079702,2763306,2763306,1842204,1842204,2763306,2763306,14079702,15790320,1842204,2763306,1842204,2763306,2763306,2763306,14079702,15790320,1842204,2763306,2763306,2763306,2763306,2763306,14079702,14079702,2763306,2763306,2763306,1842204,2763306,2763306,0,14079702,14079702,1842204,2763306,2763306,2763306,0,0,0,14079702,14079702,2763306,2763306,0,0]]}
{%- endif %}
{%- if phase == 'waning_gibbous' %}
{"db":[{{x}},{{y}},8,8,[0,0,14079702,14079702,3552822,3552822,0,0,0,14079702,14079702,15790320,15790320,3552822,3552822,0,14079702,14079702,15790320,15790320,13421772,13421772,3552822,3552822,14079702,15790320,13421772,15790320,13421772,15790320,3552822,3552822,14079702,15790320,13421772,15790320,15790320,15790320,3552822,3552822,14079702,14079702,15790320,15790320,15790320,13421772,3552822,3552822,0,14079702,14079702,13421772,15790320,3552822,3552822,0,0,0,14079702,14079702,3552822,3552822,0,0]]}
{%- endif %}
{%- if phase == 'waxing_crescent' %}
{"db":[{{x}},{{y}},8,8,[0,0,3355443,3355443,14079702,14079702,0,0,0,3355443,3355443,3355443,3355443,14079702,14079702,0,3355443,3355443,3355443,3355443,1644825,1644825,14079702,14079702,3355443,3355443,1644825,3355443,1644825,3355443,15790320,14079702,3355443,3355443,1644825,3355443,3355443,3355443,15790320,14079702,3355443,3355443,3355443,3355443,3355443,1644825,14079702,14079702,0,3355443,3355443,3355443,3355443,14079702,14079702,0,0,0,3355443,3355443,14079702,14079702,0,0]]}
{%- endif %}
{%- if phase == 'waxing_gibbous' %}
{"db":[{{x}},{{y}},8,8,[0,0,3355443,3355443,14079702,14079702,0,0,0,3355443,3355443,14079702,15790320,14079702,14079702,0,3355443,3355443,15790320,15790320,12763842,12763842,14079702,14079702,3355443,3355443,12763842,15790320,12763842,15790320,15790320,14079702,3355443,3355443,12763842,15790320,15790320,15790320,15790320,14079702,3355443,3355443,15790320,15790320,15790320,12763842,14079702,14079702,0,3355443,3355443,12763842,15790320,14079702,14079702,0,0,0,3355443,3355443,14079702,14079702,0,0]]}
{%- endif %}
{%- endmacro %}
{%- if weather == 'clear-night' and use_moon_clear_night -%}
{{draw_moon(moon_phase,0,0)}}
{%- elif(sun_next_event == 'sunrise') and use_moon_sunny_night and (weather == 'sunny') -%}
{{draw_moon(moon_phase,0,0)}}
{%- else -%}
{{draw_moon(moon_phase,23,0)}}
{%- endif -%}
payload: >
{%- macro interpolate(dictionary, x) -%}
{%- set sorted_keys = dictionary|dictsort -%}
{%- set above = sorted_keys|selectattr('0', 'gt', x)|map(attribute='0')|list|first -%}
{%- set below = sorted_keys|selectattr('0', 'lt', x)|map(attribute='0')|list|last -%}
{#- Key matches x exactly -#}
{%- if above is defined and dictionary[above] == x -%}
{%- set value = dictionary[above] -%}
{{ value }}
{%- elif below is defined and dictionary[below] == x -%}
{%- set value = dictionary[below] -%}
{{ value }}
{#- Interpolation between two values -#}
{%- elif below is defined and above is defined -%}
{%- set lower_value = dictionary[below] -%}
{%- set upper_value = dictionary[above] -%}
{%- set lower_rgb = lower_value[1:] -%}
{%- set upper_rgb = upper_value[1:] -%}
{%- set lower_r = lower_rgb[0:2]|int(base=16) -%}
{%- set lower_g = lower_rgb[2:4]|int(base=16) -%}
{%- set lower_b = lower_rgb[4:6]|int(base=16) -%}
{%- set upper_r = upper_rgb[0:2]|int(base=16) -%}
{%- set upper_g = upper_rgb[2:4]|int(base=16) -%}
{%- set upper_b = upper_rgb[4:6]|int(base=16) -%}
{%- set interpolation_factor = (x - below) / (above - below) -%}
{%- set interpolated_r = ((1 - interpolation_factor) * lower_r + interpolation_factor * upper_r)|int -%}
{%- set interpolated_g = ((1 - interpolation_factor) * lower_g + interpolation_factor * upper_g)|int -%}
{%- set interpolated_b = ((1 - interpolation_factor) * lower_b + interpolation_factor * upper_b)|int -%}
{%- set interpolated_hex = '#' ~ '%02X' % interpolated_r ~ '%02X' % interpolated_g ~ '%02X' % interpolated_b -%}
{{ interpolated_hex }}
{#- Only below key available -#}
{%- elif below is defined -%}
{%- set value = dictionary[below] -%}
{{ value }}
{#- Only above key available -#}
{%- elif above is defined -%}
{%- set value = dictionary[above] -%}
{{ value }}
{#- No matching keys available -#}
{%- else -%}
No matching key found.
{%- endif -%}
{%- endmacro -%}
{#- Define macro to get length of the forecast}
{%- macro str_len(str) %}
{%- if '.' in str %}
{%- set char_count = (str | length) -1 %}{{char_count * 3 + 1 + char_count}}
{%- else %}
{%- set char_count = (str | length) %}{{char_count * 3 + (char_count - 1)}}
{%- endif %}
{%- endmacro %}
{#- Define a macro to draw out the forecast lines#}
{%- macro draw_forecast_lines(x,hours,height) %}
{%- for hour in range(hours) %}
{%- if height == 0 %}
{"dp": [{{x+hour}},7,"{{interpolate(color_dict, forecast[hour][forecast_temp_field]) }}"]}
{%- else %}
{"dl": [{{x+hour}},7,{{x+hour}},{{7 - height}},"{{interpolate(color_dict, forecast[hour][forecast_temp_field]) }}"]}
{%- endif %}
{%- if hour+1 != hours %},{%endif%}
{%- endfor %}
{%- endmacro %}
{# Define the color mapping dictionary #}
{
"draw": [
{%- if hours_to_show > 0 %}
{{draw_forecast_lines(8,hours_to_show,0)}}
{%- endif %}
{%- if current_temp != 'unavailable' -%}
,{"dt":[{{text_x}},1,"{{temp_text}}","{{interpolate(color_dict, current_temp | float)}}"]}
{%- else -%}
{"dt":"err"}
{%- endif -%}
{% if show_moon %}
,{{moon_data}}
{% endif %}
],
"icon": "{{icon}}",
"duration": {{message_duration}},
"pushIcon": 2,
"lifetime": 120,
"lifetimeMode":1,
"weather": "{{weather}}"
}
trigger:
- platform: time_pattern
seconds: /5
- platform: state
entity_id: !input forecast_var
id: Changes
enabled: true
condition: []
action:
- repeat:
for_each: "{{ devices_topics }}"
sequence:
- service: mqtt.publish
data:
qos: 0
retain: false
topic: "{{ repeat.item }}"
payload: >
{{payload}}
- service: mqtt.publish
data:
qos: 0
retain: false
topic: "{{ repeat.item ~ '_sun'}} "
payload: >
{{sun_payload}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment