homeassistant-config/blueprints/automation/jeeftor/awtrix_weatherflow.yaml

678 lines
35 KiB
YAML
Raw Permalink Normal View History

blueprint:
name: "AWTRIX Weather ⛈️ + Forecast + \U0001F315"
description: "\nThis 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.\n\n\n![](https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/docs/weather.gif)\n\n![](https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/docs/sunset.gif)\nThis
blueprint will publish to two separate topics. `jeef_weather` for the weather
report and `jeef_weather_sun` if its near sunrise/set\n## ⚠️ REQUIREMENTS ⚠️\nFor
this blueprint to work you MUST have a few things pre-setup. \n### Moon Integration
\U0001F315\n .------.\n ( I MOON ) ..\n `------' .' /\n O
\ / ;\n o i OO\n C `-. Make sure you've\n |
\ <-' enabled\n ( ,--. the MOON Sensor\n V
\ \\_)\n \\ :\n `._\\. \n\n\nThe 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)\n###
Moon Rise/Set Sensor \U0001F315 ⏲️\n\n M\n (X)\n // \\\\
\ Lets use a GeoLocation to find\n // \\\\ out the Moon Rise / Set\n
\ // \\\\ TIMES\n // \\\\\n / \\\n\nAs 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.\nTo do so you will need to create an account and extract your `API_KEY`.
Additionally you need your `LAT` and `LON`.\nThen you can add a [REST](https://www.home-assistant.io/integrations/sensor.rest/)
sensor to your `configuraiton.yaml` file like the one here:\n\n resource: https://api.ipgeolocation.io/astronomy?lat=<LAT>&long=<LON>&apiKey=<API_KEY>\n
\ name: ip_geo_location\n scan_interval: 300\n value_template: \"OK\"\n
\ json_attributes:\n - moonrise\n - moonset\n - moon_altitude\n\n###
Icons\nYou can call my custom script which will prompt you for an Awtrix device
and then upload the required icons:\n \n (If you have windows I don't know if
this will work)\n\n bash -c \"$(curl -fsSL https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/icons/upload_icon.sh)\"\n\n_This
blueprint ~will~ may be updated as new features_\n![](https://www.gravatar.com/avatar/3b9968835eb719e5d78a04ba7a2bafbd?s=64)
https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/blueprints/automation/awtrix_weatherflow.yaml\n"
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)\nThis integration has been tested with:\n\n - HACS [Weatherflow](https://github.com/briis/hass-weatherflow)
integration \n \n - HomeAssistant [Openweather](https://www.home-assistant.io/integrations/openweathermap/)\n"
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.0
min: 0.0
unit_of_measurement: hours
mode: box
step: 1.0
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. \n\n - If
you are using [Weatherflow](https://github.com/briis/hass-weatherflow) you
may be able to select from either `feels_like` or `temperature`\n\n - In
[Openweather](https://www.home-assistant.io/integrations/openweathermap/)
you only have access to `temperature`\n"
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.0
max: 2.0
step: 1.0
mode: box
unit_of_measurement: Decimal places
default: 0
temp_suffix:
name: Temperature suffix
description: "How do you want to display the temperature\nIf you live in a country
with the following flags:\n\U0001F1FA\U0001F1F8\U0001F1F5\U0001F1F7\U0001F1F5\U0001F1FC\U0001F1E7\U0001F1FF\U0001F1F0\U0001F1FE\U0001F1EB\U0001F1F2\U0001F1F2\U0001F1ED\U0001F1FB\U0001F1EE\U0001F1EC\U0001F1FA\nYou
probbaly use Farenheit.\nEverybody else in the \U0001F5FA 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
sort: false
custom_value: false
multiple: false
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:\n\n - `sensor.openweathermap_feels_like_temperature`\n"
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** \nHere you can enter a
temperature to color mapping. \n> Please note the format is *JSON*,\n \n\nSome
possible mappings are:\n#### USA: Farenheit 0-100 (Based on NOAA scale from
0-100)\n\n\n {\"0\": \"#FEC4FF\",\"10\": \"#D977DF\",\"20\": \"#9545BC\",\"30\":
\"#4B379C\",\"40\": \"#31B8DB\",\"50\": \"#31DB8B\",\"60\": \"#6ED228\",\"70\":
\"#FFFF28\",\"80\": \"#F87E27\",\"90\": \"#CF3927\",\"100\": \"#A12527\"}\n\n\n####
EURO: -12°c to -38°c based on USA NOAA Colors \n\n {\"-12\": \"#D977DF\",\"-6\":
\"#9545BC\",\"-1\": \"#4B379C\",\"0\": \"#FEC4FF\",\"4\": \"#31B8DB\",\"10\":
\"#31DB8B\",\"15\": \"#6ED228\",\"21\": \"#FFFF28\",\"27\": \"#F87E27\",\"32\":
\"#CF3927\",\"38\": \"#A12527\"}\n"
selector:
text:
multiline: true
default: "{\n \"0\": \"#FEC4FF\",\n \"10\": \"#D977DF\",\n \"20\": \"#9545BC\",\n
\ \"30\": \"#4B379C\",\n \"40\": \"#31B8DB\",\n \"50\": \"#31DB8B\",\n \"60\":
\"#6ED228\",\n \"70\": \"#FFFF28\",\n \"80\": \"#F87E27\",\n \"90\": \"#CF3927\",\n
\ \"100\": \"#A12527\"\n}\n"
moon:
name: Moon Phase Sensor
description: "\U0001F311\U0001F312\U0001F313\U0001F314\U0001F316\U0001F317\U0001F318\nTo
setup a moon sensor see here: https://www.home-assistant.io/integrations/moon/\nor
just [clicking here](https://my.home-assistant.io/redirect/config_flow_start?domain=moon)\n"
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.\nYou can create a custom REST sensor as follows:\n``` sensor: -
platform: rest\n resource: https://api.ipgeolocation.io/astronomy?lat=<LAT>&long=-<LON>&apiKey=<API_KEY>\n
\ name: ip_geo_location\n scan_interval: 300\n value_template: \"OK\"\n
\ json_attributes:\n - moonrise\n - moonset\n - moon_altitude\n```\n"
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 \U0001F43A and they are
called Wearwolves or maybe Astronomers. \n\nPlease select how and when you
want the moon displayed\n\nBy 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.\n### NOTE:\n\n At Brightness
values less than 29 the greys of the moon will render green on the clock.\n"
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
sort: false
custom_value: false
multiple: false
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
show_sun_rise_set:
name: ☀️ Show Sunrise/Sunset
description: "Prior to both sunrise and sunset times offer a message about pending
sun transitional state.\n\n :\n `. ; .'\n
\ `. .-'''-. .'\n ;' __ _;'\n / '_ _`\\
\ TURN ME ON!\n | _( a ( a |\n ''''| (_) > |``````\n
\ \\ \\ / /\n `. `--'.'\n .' `-,,,-' `.\n
\ .' : `.\n :\n\n\n_You can change the icons
for sun rise/set way down below._\n"
selector:
boolean: {}
default: true
sun_event_minute_threshold:
name: "Sun Time Prior \U0001F570"
description: "This value controls when to show sunrise/set notifications. \n\nIf
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.0
max: 1440.0
unit_of_measurement: min
step: 1.0
mode: slider
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:\n\n - Relative Time: `12 min`\n - Actual Time:
\ `8:31 pm` or `22:31`\n"
selector:
select:
options:
- Relative
- Actual
sort: false
custom_value: false
multiple: false
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:\n\n - `%H%M` which would render
`0529`\n \n - `%-I%M%p` which woudl render `529AM`\n - `%-I%:M%p` which
woudl render `5:29AM`\n\n\n\n For details see https://strftime.org/\n"
selector:
text:
type: text
multiline: false
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.0
max: 300.0
unit_of_measurement: sec
step: 1.0
mode: slider
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.0
max: 300.0
unit_of_measurement: sec
step: 1.0
mode: slider
default: 30
icon_clear_night:
name: Icon for clear-night
description: "\nThe default clear_night icon is: \n\n ![](https://developer.lametric.com/content/apps/icon_thumbs/53383_icon_thumb.gif?v=2)
- `53383`\n"
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`\n
\n![](https://developer.lametric.com/content/apps/icon_thumbs/2286_icon_thumb.gif?v=1)\n"
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
source_url: https://raw.githubusercontent.com/jeeftor/HomeAssistant/master/blueprints/automation/awtrix_weatherflow.yaml
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 %}\n{%- set ns =
namespace(devices=[]) %} {%- for device_id in device_ids %}\n {%- set device=get_device_topic(device_id)|replace('
','') %}\n {% set ns.devices = ns.devices + [ device ~ '/custom/' ~ app_topic]
%}\n{%- 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: !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
%}'
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) -%}\n {{ states(temp_var) | round(digits) ~ temp_suffix}}
\n{%- 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 %}\n {%- if char.isdigit() %}\n {%- set length.value
= length.value + 3 %}\n {%- elif char == '°' %}\n {%- set length.value = length.value
+ 2 %}\n {%- elif char == '.' %}\n {%- set length.value = length.value + 1
%}\n {%- elif char in ['-','C','F'] %}\n {%- set length.value = length.value
+ 3 %}\n {%- else %}\n {%- set length.value = length.value + 1 %}\n {%- endif
%}\n {%- if not loop.last %}\n {%- set length.value = length.value + 1 %}{%-
endif -%}\n{%- endfor -%} {{ length.value }} {%- endmacro %}\n{{get_text_len(temp_text)}}"
text_x: '{{8 + ((text_available_width - text_len)/2)}}'
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' %}\n
\ {{ 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)) }}\n{%- else %}
{#- relative time #}\n {% set hours = sun_min_until_next_event // 60 %}\n {%
set remaining_minutes = sun_min_until_next_event % 60 %}\n\n {% if hours == 0
%}\n {{ remaining_minutes }} min\n {% else %}\n [\n {\"t\":\"{{hours}}\",
\"c\":\"#ffffff\"},\n {\"t\":\"h\", \"c\":\"#9c9d97\"},\n {\"t\":\"{{remaining_minutes}}\",
\"c\":\"#ffffff\"},\n {\"t\":\"m\", \"c\":\"#9c9d97\"}\n ]\n {% endif
%}\n \n{%- 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({\n 'full_moon': '2314',\n 'waning_gibbous': '2315',\n
\ 'last_quarter': '2316',\n 'waning_crescent': '2317',\n 'new_moon': '2318',\n
\ 'waxing_crescent': '2319',\n 'first_quarter': '2320',\n 'waxing_gibbous':
'2321'}) }}"
color_matrix_json: !input color_matrix_json
color_dict: "{% set b = color_matrix_json | from_json %} {%- set ns = namespace(tuples=[])
%} {%- for k,v in b | items -%}\n {%- set key = k|float -%}\n {%- set ns.tuples
= ns.tuples + [(key,v)] %} \n{% 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) %}\n {{clear_night_dict[moon_phase]}}\n{%-
elif (sun_next_event == 'sunrise') and use_moon_sunny_night and (weather == 'sunny')
-%}\n \n{%- else %}\n {{ icon_dict[weather] }}\n{%- endif %}\n"
moon_data: "{%- macro draw_moon(phase,x=22,y=0) %}\n {%- if phase == 'first_quarter'
\ %}\n {\"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]]}\n
\ {%- endif %}\n {%- if phase == 'full_moon' %}\n {\"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]]}\n
\ {%- endif %}\n {%- if phase == 'last_quarter' %}\n {\"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]]}\n
\ {%- endif %}\n {%- if phase == 'new_moon' %}\n {\"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]]}\n
\ {%- endif %}\n {%- if phase == 'waning_crescent' %}\n {\"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]]}\n
\ {%- endif %}\n {%- if phase == 'waning_gibbous' %}\n {\"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]]}\n
\ {%- endif %}\n {%- if phase == 'waxing_crescent' %}\n {\"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]]}\n
\ {%- endif %}\n {%- if phase == 'waxing_gibbous' %}\n {\"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]]}\n
\ {%- endif %}\n{%- endmacro %}\n{%- 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 -%}\n"
payload: "{%- macro interpolate(dictionary, x) -%}\n \n {%- set sorted_keys =
dictionary|dictsort -%}\n {%- set above = sorted_keys|selectattr('0', 'gt', x)|map(attribute='0')|list|first
-%}\n {%- set below = sorted_keys|selectattr('0', 'lt', x)|map(attribute='0')|list|last
-%}\n\n {#- Key matches x exactly -#}\n {%- if above is defined and dictionary[above]
== x -%}\n {%- set value = dictionary[above] -%}\n {{ value }}\n {%- elif
below is defined and dictionary[below] == x -%}\n {%- set value = dictionary[below]
-%}\n {{ value }}\n {#- Interpolation between two values -#}\n {%- elif below
is defined and above is defined -%}\n {%- set lower_value = dictionary[below]
-%}\n {%- set upper_value = dictionary[above] -%}\n {%- set lower_rgb =
lower_value[1:] -%}\n {%- set upper_rgb = upper_value[1:] -%}\n\n {%- set
lower_r = lower_rgb[0:2]|int(base=16) -%}\n {%- set lower_g = lower_rgb[2:4]|int(base=16)
-%}\n {%- set lower_b = lower_rgb[4:6]|int(base=16) -%}\n\n {%- set upper_r
= upper_rgb[0:2]|int(base=16) -%}\n {%- set upper_g = upper_rgb[2:4]|int(base=16)
-%}\n {%- set upper_b = upper_rgb[4:6]|int(base=16) -%}\n\n {%- set interpolation_factor
= (x - below) / (above - below) -%}\n {%- set interpolated_r = ((1 - interpolation_factor)
* lower_r + interpolation_factor * upper_r)|int -%}\n {%- set interpolated_g
= ((1 - interpolation_factor) * lower_g + interpolation_factor * upper_g)|int
-%}\n {%- set interpolated_b = ((1 - interpolation_factor) * lower_b + interpolation_factor
* upper_b)|int -%}\n\n {%- set interpolated_hex = '#' ~ '%02X' % interpolated_r
~ '%02X' % interpolated_g ~ '%02X' % interpolated_b -%}\n {{ interpolated_hex
}}\n {#- Only below key available -#}\n {%- elif below is defined -%}\n {%-
set value = dictionary[below] -%}\n {{ value }}\n {#- Only above key available
-#}\n {%- elif above is defined -%}\n {%- set value = dictionary[above] -%}\n
\ {{ value }}\n {#- No matching keys available -#}\n {%- else -%}\n No
matching key found.\n {%- endif -%}\n{%- endmacro -%}\n{#- 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 %}\n{#- Define a macro to draw out the forecast lines#}
{%- macro draw_forecast_lines(x,hours,height) %}\n {%- for hour in range(hours)
%}\n {%- if height == 0 %}\n {\"dp\": [{{x+hour}},7,\"{{interpolate(color_dict,
forecast[hour][forecast_temp_field]) }}\"]}\n {%- else %}\n {\"dl\": [{{x+hour}},7,{{x+hour}},{{7
- height}},\"{{interpolate(color_dict, forecast[hour][forecast_temp_field]) }}\"]}\n
\ {%- endif %}\n {%- if hour+1 != hours %},{%endif%}\n {%- endfor %}\n{%-
endmacro %}\n\n{# Define the color mapping dictionary #} { \"draw\": [\n {%-
if hours_to_show > 0 %}\n {{draw_forecast_lines(8,hours_to_show,0)}}\n {%- endif
%}\n {%- if current_temp != 'unavailable' -%}\n ,{\"dt\":[{{text_x}},1,\"{{temp_text}}\",\"{{interpolate(color_dict,
current_temp | float)}}\"]}\n {%- else -%}\n {\"dt\":\"err\"}\n {%- endif -%}\n
\n {% if show_moon %}\n ,{{moon_data}}\n {% endif %}\n], \"icon\": \"{{icon}}\",
\"duration\": {{message_duration}}, \"pushIcon\": 2, \"lifetime\": 120, \"lifetimeMode\":1,
\"weather\": \"{{weather}}\" }\n"
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}}
'