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}}

          '
