Elaborate Starting Template for TTS General Status Notification

Hello Home Assistant Community!

I’m excited to share a comprehensive Morning Status Notification (that can serve as a status update any time of day as well - with conditional handling to make it make sense) script that I’ve been working on. Initially, I sought the perfect morning summary to inform me about the weather and upcoming birthdays. However, with the help of ChatGPT, I found myself expanding its capabilities to include a variety of health metrics and other insightful notifications. Almost the entire script was generated by ChatGPT and then meticulously fine-tuned by me to better fit my needs.

Key Features:

  • Comprehensive Daily Summary:
    • Current Time & Date: Always stay updated with the exact time and date.
    • Appointments & Events: Get a rundown of your day’s schedule, including appointments and important events.
    • Birthdays & Holidays: Never miss celebrating a loved one’s birthday or a significant holiday.
    • Weather Conditions & Alerts: Receive detailed weather forecasts along with any active weather alerts.
  • Health Metrics Monitoring:
    • Heart Rate Changes: Notifications if your average heart rate deviates from the weekly norm.
    • Blood Oxygen Levels: Alerts based on your weekly oxygen saturation averages.
    • Blood Glucose Levels: Stay informed about any significant changes in your blood glucose.
    • Heart Points & Steps: Track your heart points and daily steps against your weekly averages.
  • Additional Insights:
    • Sleep Quality: Insights into your sleep score to help you improve rest.
    • Battery Checks: Notifications if your phone or watch batteries are running low.
    • Air Quality: Updates on local outdoor air quality with health recommendations.
    • Zodiac Signs & Moon Phases: Fun additions like your current zodiac sign and moon phase.
    • Motivational Quotes: Start your day with an encouraging thought.

Implementation Details:

To implement this script on your Home Assistant setup, follow these steps:

  1. Prerequisites:
  • Integrations Needed:
    • Weatheralerts: For receiving weather-related notifications.
    • Google Conversational AI: To refine and generate the spoken notifications.
    • Additional Integrations: Ensure you have integrations for calendars, health metrics sensors, and to-do lists as referenced in the script. All the required sensors are either in the drop-in configuration.yml code or defined at the top of the script.
  1. Configuration Setup:
  • Edit configuration.yml:
    • Insert the sensor configurations provided at the top of the script into your configuration.yml.
    • Important: After restarting Home Assistant, remove the two lines that say {%- else %} and {{ states('sensor.brian_z_steps') }}. Restart again to finalize the setup.
    • Sensor Customization: Replace the sensor entities with your own sensors to match your setup.
  1. Script Creation:
  • Home Assistant UI:
    • Navigate to the Scripts section in the Home Assistant UI.
    • Create a new script and switch to the YAML editor.
    • Paste the provided script into the editor.
  • Customization:
    • Ensure you update the sensor names and entities to align with your Home Assistant configuration.
  1. Execution:
  • Once set up, you can trigger the script manually or automate it to run at your desired time each morning.
  • The script will generate a spoken summary through your designated media player (e.g., media_player.living_room).

Final Thoughts:

This script has transformed my mornings by providing a wealth of information in a concise and easily digestible format. Whether it’s keeping track of health metrics or staying informed about the day’s events, it has become an invaluable part of my daily routine. I hope it proves to be just as useful for you!

Feel free to customize and expand upon it to better suit your personal needs. I’d love to hear your feedback and any enhancements you make!

The script code is provided in the next post and configuration.yml code is posted in the post after due to character limits. After everything is set up, when you run it, you’ll get a message that packs a lot of hidden features that only are reported if absolutely necessary. Anyway, here’s the example I just got by running it which is spoken through a speaker:

      Good morning!


      Today is Wednesday, December 18, 2024. It's 6:28 AM.


      No scheduled events are currently planned.


      Happy birthday to Jazzy Votz!


      Your sleep score was 49 last night; consider prioritizing more rest
      tonight for improved well-being.  Your phone battery is at 40%; please
      charge it.


      Currently, it's 33°F with 88% humidity.  The high today will be around
      49°F, and the low will be near 32°F. High humidity may make it feel cooler
      than the temperature suggests; light clothing is recommended.  Expect
      variable conditions and gentle breezes, with a chance of light,
      intermittent precipitation.  It's a cool and rainy day—don't forget your
      jacket and waterproof shoes! Sunset is at 4:33 PM.


      You have 5 tasks on your to-do list.


      Embrace the moment and shine!
alias: TTS Status Notification
description: >
  This script provides a comprehensive spoken summary of important information
  at any time of day—current time, appointments, birthdays, holidays, sleep
  quality, weather conditions, battery checks, health metrics, tasks, and more.
  It integrates with multiple Home Assistant sensors, calendars, and a to-do
  entity. It then refines the message via ChatGPT to improve grammar, style, and
  context-based reminders.

  Prior to running this, you need to place the following code in your
  configuration.yml:
  

Due to max character limits, its provided in the next post. But here’s the drop-in code for the script you can paste into a script made with the web UI:

mode: restart
sequence:
- action: weather.get_forecasts
  data:
    type: hourly
  target:
    entity_id: weather.forecast_home
  response_variable: weather_forecast_hourly
- action: calendar.get_events
  data:
    duration:
      hours: 24
      minutes: 0
      seconds: 0
  target:
    entity_id:
      - calendar.facebook_birthdays
  response_variable: birthday_calendars
- action: calendar.get_events
  data:
    duration:
      hours: 24
      minutes: 0
      seconds: 0
  target:
    entity_id:
      - calendar.christian_holidays
      - calendar.hindu_holidays
      - calendar.holidays_in_united_states
      - calendar.jewish_holidays
      - calendar.muslim_holidays
  response_variable: holiday_calendars
- action: calendar.get_events
  data:
    duration:
      hours: 24
      minutes: 0
      seconds: 0
  target:
    entity_id:
      - calendar.blzalewski_gmail_com
  response_variable: appointment_calendars
- choose:
    - conditions:
        - condition: template
          value_template: >-
            {{ states('sensor.morris') is not none and
            states('sensor.morris')|int >= 1 }}
      sequence:
        - action: google_generative_ai_conversation.generate_content
          data:
            prompt: >
              The weather alert sensor shows the following JSON {{
              state_attr('sensor.martin', 'alerts') }}. Please provide an
              extremely short, concise summary of the weather alerts in simple
              terms.
          response_variable: chatgpt_alert_summary
- variables:
    features: |
      {% set f = {
        'include_greeting_and_time': True,
        'include_appointments': True,
        'include_holidays': True,
        'include_birthdays': True,
        'include_sleep_score': True,
        'include_battery_checks': True,
        'include_weather_alerts': True,
        'include_weather': True,
        'include_zodiac': True,
        'include_full_moon': True,
        'include_sunday_reminder': True,
        'include_motivational_quotes': True,
        'include_tasks': True,
        'include_smart_predictions': True,
        'include_air_quality': True,
        'night_mode': now().hour|int >= 21 or now().hour <= 4
      } %} {{ f }}
- variables:
    current_hour: "{{ now().hour }}"
    current_day_str: "{{ now().strftime('%A, %B %-d, %Y') }}"
    current_time_str: "{{ now().strftime('%-I:%M %p') }}"
    weekday: "{{ now().strftime('%A') }}"
    is_weekend: "{{ now().strftime('%A') in ['Saturday','Sunday'] }}"
    today_str: "{{ now().strftime('%Y-%m-%d') }}"
    tomorrow_str: "{{ (now() + timedelta(days=1)).strftime('%Y-%m-%d') }}"
    day_after_tomorrow_str: "{{ (now() + timedelta(days=2)).strftime('%Y-%m-%d') }}"
    sleep_score_sensor: "{{ states('sensor.withings_sleep_score') }}"
    phone_battery_sensor: "{{ states('sensor.pixel_8_pro_battery_level') }}"
    watch_battery_sensor: "{{ states('sensor.google_pixel_watch_3_battery_level') }}"
    morris_sensor: "{{ states('sensor.morris') }}"
    moon_phase_sensor: "{{ states('sensor.moon_phase') }}"
    zodiac_today_sensor: "{{ states('sensor.zodiac')|default('unknown') }}"
    zodiac_yesterday_sensor: "{{ states('sensor.yesterdays_zodiac')|default('unknown') }}"
    local_air_quality_sensor: "{{ states('sensor.local_outdoor_air_quality') }}"
    today_steps: "{{ states('sensor.brian_z_steps')|int }}"
    avg_steps: "{{ states('sensor.weekly_average_steps') | int(default=0) }}"
    today_hr: "{{ states('sensor.heart_rate')|int }}"
    avg_hr: "{{ states('sensor.weekly_average_heart_rate')|int }}"
    today_resting_hr: "{{ states('sensor.resting_heart_rate')|int }}"
    avg_resting_hr: "{{ states('sensor.weekly_average_resting_heart_rate')|int }}"
    today_oxygen: "{{ states('sensor.oxygen_saturation')|float }}"
    avg_oxygen: "{{ states('sensor.weekly_average_oxygen_saturation')|float }}"
    today_bglucose: "{{ states('sensor.blood_glucose')|float(default=0) }}"
    avg_bglucose: "{{ states('sensor.weekly_average_blood_glucose')|float(default=0) }}"
    today_heart_points: "{{ states('sensor.heart_points_daily')|int }}"
    avg_heart_points: "{{ states('sensor.weekly_average_heart_points')|int }}"
    tasks_list_raw: >-
      {{ states('todo.blzalewski_s_list') if states('todo.blzalewski_s_list')
      != 'unknown' else '' }}
    tasks_list: >
      {% set raw = states('todo.blzalewski_s_list') %} {% if raw is not none
      and raw != 'unknown' and raw|length > 0 %}
        {{ raw.split(',') }}
      {% else %}
        []
      {% endif %}
    weather_entity: weather.forecast_home
    weather_obj: >-
      {{ states(weather_entity) if states.weather.forecast_home is defined
      else None }}
    weather_forecast: >-
      {{ weather_forecast_hourly['weather.forecast_home'].forecast if
      weather_forecast_hourly['weather.forecast_home'] is defined else None }}
    birthdays_start_date: |
      {% set f=features %} {% if f.night_mode and now().hour|int < 24 %}
        {{ tomorrow_str }}
      {% else %}
        {{ today_str }}
      {% endif %}
    birthdays_end_date: |
      {% set f=features %} {% if f.night_mode and now().hour|int < 24 %}
        {{ day_after_tomorrow_str }}
      {% else %}
        {{ tomorrow_str }}
      {% endif %}
    holidays_start_date: |
      {% set f=features %} {% if f.night_mode and now().hour|int < 24 %}
        {{ tomorrow_str }}
      {% else %}
        {{ today_str }}
      {% endif %}
    holidays_end_date: |
      {% set f=features %} {% if f.night_mode and now().hour|int < 24 %}
        {{ day_after_tomorrow_str }}
      {% else %}
        {{ tomorrow_str }}
      {% endif %}
- variables:
    message: |
      ```
      {%- set hour = current_hour|int -%} {%- set f = features -%}

      {# Greeting and time #} {%- if f.include_greeting_and_time %}
        {%- if hour > 4 and hour < 12 %}
          {%- set greeting = "Good morning! " %}
        {%- elif hour >= 21 or hour <= 4 %}
          {%- set greeting = "Good night! " %}
        {%- elif hour < 18 %}
          {%- set greeting = "Good afternoon! " %}
        {%- else %}
          {%- set greeting = "Good evening! " %}
        {%- endif %}
        {{ greeting }}

        {% if not f.night_mode %}
          {{ "Today is " ~ current_day_str ~ ". The current time is " ~ current_time_str ~ ". " }}
        {% else %}
          {{ "The current time is " ~ current_time_str ~ ". " }}
        {% endif %}
      {% endif %}

      {# Appointments #} {% if f.include_appointments %}
        {%- set appointments = namespace(events=[]) -%}
        {%- for cal in appointment_calendars.values() %}
          {%- set events = cal.events
             | selectattr('start','match','^'~today_str~'T\\d{2}:\\d{2}:\\d{2}(?:[+\\-]\\d{2}:\\d{2})?$')
             | selectattr('end','match','^'~tomorrow_str~'T\\d{2}:\\d{2}:\\d{2}(?:[+\\-]\\d{2}:\\d{2})?$')
             | list -%}
          {%- set appointments.events = appointments.events + events %}
        {%- endfor -%}
        {%- set appointments.events = appointments.events|sort(attribute='start') %}
        {% if appointments.events|length > 0 %}
          {% if appointments.events|length > 1 %}
            {{ "You have " ~ (appointments.events|length) ~ " events scheduled in the next 24 hours. " }}
          {% endif %}
          {{ "Your next event starts at " ~ strptime(appointments.events[0].start, "%Y-%m-%dT%H:%M:%S%z").strftime("%-I:%M %p") ~ ". " }}
        {% else %}
          {{ "No scheduled events are found for the upcoming period. " }}
        {% endif %}
      {% endif %}

      {# Holidays #} {% if f.include_holidays %}
        {%- set holidays = namespace(list=[]) -%}
        {%- for cal in holiday_calendars.values() %}
          {%- set h = cal.events
             | selectattr('start','match','^'~holidays_start_date~'$')
             | selectattr('end','match','^'~holidays_end_date~'$')
             | map(attribute='summary')
             | list -%}
          {%- set holidays.list = holidays.list + h %}
        {%- endfor -%}
        {%- set holidays.list = holidays.list|unique|list -%}
        {% if holidays.list|length > 0 %}
          {% if holidays.list|length == 1 %}
            {% if f.night_mode and now().hour|int < 24 %}
              {{ "Tomorrow, it will be " ~ holidays.list[0] ~ ". " }}
            {% else %}
              {{ "It is " ~ holidays.list[0] ~ " today. " }}
            {% endif %}
          {% else %}
            {% if f.night_mode and now().hour|int < 24 %}
              {{ "Tomorrow, it will be " ~ holidays.list[:-1]|join(", ") ~ " and " ~ holidays.list[-1] ~ ". " }}
            {% else %}
              {{ "It is " ~ holidays.list[:-1]|join(", ") ~ " and " ~ holidays.list[-1] ~ ". " }}
            {% endif %}
          {% endif %}
        {% endif %}
      {% endif %}

      {# Birthdays #} {% if f.include_birthdays %}
        {%- set birthdays = namespace(list=[]) -%}
        {%- for cal in birthday_calendars.values() %}
          {%- set b = cal.events
             | selectattr('start','match','^'~birthdays_start_date~'$')
             | selectattr('end','match','^'~birthdays_end_date~'$')
             | map(attribute='summary')
             | list -%}
          {%- set birthdays.list = birthdays.list + b %}
        {%- endfor -%}
        {%- set birthdays.list = birthdays.list|unique|list -%}
        {% if birthdays.list|length > 0 %}
          {% if birthdays.list|length == 1 %}
            {% if f.night_mode and now().hour|int < 24 %}
              {{ "Tommorow is " ~ birthdays.list[0] ~ "'s birthday. " }}
            {% else %}
              {{ "It is " ~ birthdays.list[0] ~ "'s birthday today. Wish them a happy birthday! " }}
            {% endif %}
          {% else %}
            {% if f.night_mode and now().hour|int < 24 %}
              {{ birthdays.list[:-1]|join(", ") ~ " and " ~ birthdays.list[-1] ~ " have birthdays tomorrow. " }}
            {% else %}
              {{ "It is " ~ birthdays.list[:-1]|join(", ") ~ " and " ~ birthdays.list[-1] ~ "'s birthdays today. Wish them a happy birthday! " }}
            {% endif %}
          {% endif %}
        {% endif %}
      {% endif %}

      {# Sleep Score #} {% if f.include_sleep_score and sleep_score_sensor is
      not none and sleep_score_sensor|int >= 0 and not f.night_mode %}
        {% set s = sleep_score_sensor|int %}
        {% if s > 80 %}
          {{ "Your sleep was excellent, scoring " ~ s ~ ". " }}
        {% elif s > 70 %}
          {{ "Your sleep was decent, with a score of " ~ s ~ ". " }}
        {% elif s > 50 %}
          {{ "Your sleep scored " ~ s ~ ", there's room for improvement. " }}
        {% else %}
          {{ "Your sleep was poor, scoring only " ~ s ~ ". Consider more rest tonight. " }}
        {% endif %}
      {% elif f.include_sleep_score %}
        {{ "No sleep score data is available at this time. " }}
      {% endif %}

      {# Device Battery Checks #} {% if f.include_battery_checks and hour >=5
      and hour <=14 %}
        {% if phone_battery_sensor is not none and phone_battery_sensor|int < 50 %}
          {{ "Your phone battery is at " ~ phone_battery_sensor ~ "%. A charge is advisable. " }}
        {% endif %}
        {% if watch_battery_sensor is not none and watch_battery_sensor|int < 50 %}
          {{ "Your watch battery is at " ~ watch_battery_sensor ~ "%. Consider plugging it in. " }}
        {% endif %}
      {% endif %}

      {# Weather Alerts #} {% if f.include_weather_alerts and morris_sensor is
      not none and morris_sensor|int >= 1 %}
        {% if chatgpt_alert_summary is defined %}
          {{ "There is an active weather alert: " ~ chatgpt_alert_summary.text ~ ". " }}
        {% else %}
          {{ "A weather alert is active, but no details are provided. Stay cautious. " }}
        {% endif %}
      {% endif %}

      {# Weather Forecast #} {% if f.include_weather and weather_obj is not
      none %}
        {% set temp = state_attr(weather_entity,'temperature')|int %}
        {% set tempunit = state_attr(weather_entity,'temperature_unit')|default('°F') %}
        {% set humidity = state_attr(weather_entity,'humidity')|int %}
        {% set sunset = states('sensor.sun_next_setting')|as_timestamp|timestamp_custom('%-I:%M %p') %}
        {{ "Currently, it's " ~ temp ~ " " ~ tempunit ~ " with " ~ humidity ~ "% humidity. " }}

        {% if humidity > 80 %}
          {{ "High humidity may feel heavy—light clothing helps. " }}
        {% elif humidity < 30 %}
          {{ "The air is dry; consider moisturizer or a humidifier. " }}
        {% elif humidity > 65 and humidity <= 80 %}
          {{ "Moderate humidity may make it feel slightly warmer. " }}
        {% endif %}

        {% if weather_forecast %}
          {% set temperatures = weather_forecast|map(attribute='temperature')|list %}
          {% set temphigh = temperatures|max if temperatures else temp %}
          {% set templow = temperatures|min if temperatures else temp %}
          {% set precips = weather_forecast|map(attribute='precipitation')|select('defined')|list %}
          {% set total_precip = precips|sum if precips else 0 %}
          {% set precip_probs = weather_forecast|map(attribute='precipitation_probability')|select('defined')|list %}
          {% set max_precip_chance = precip_probs|max if precip_probs else 0 %}
          {% set conditions = weather_forecast|map(attribute='condition')|select('defined')|list %}
          {% set conditions = conditions[:12] %}
          {{ "The high may reach around " ~ temphigh ~ " " ~ tempunit ~ " and the low near " ~ templow ~ " " ~ tempunit ~ ". " }}

          {% set total_count = conditions|length %}
          {% set threshold = total_count * 0.1 %}
          {% set ns = namespace(keep=[]) %}
          {% for c in conditions|unique %}
            {% set count = (conditions|select('equalto', c)|list|length) %}
            {% if count >= threshold %}
              {% set ns.keep = ns.keep + [c] %}
            {% endif %}
          {% endfor %}
          {% set common_conditions = (conditions|select('in', ns.keep)|unique)|list %}

          {% set conditions_map = {
            'rainy': "frequent rain showers",
            'snowy': "periods of snow",
            'foggy': "occasional fog",
            'sunny': "some sunshine",
            'clear': "clear skies",
            'clear-night': "clear skies",
            'partlycloudy': "a mix of sun and clouds",
            'cloudy': "overcast skies",
            'sleet': "some sleet",
            'hail': "hail",
            'lightning': "lightning",
            'lightning-rainy': "thunderstorms",
            'pouring': "heavy rainfall",
            'snowy-rainy': "mixed snow and rain",
            'exceptional': "unusual weather"
          } %}
          {% set wind_speeds = weather_forecast|map(attribute='wind_speed')|select('defined')|list %}
          {% set max_wind_speed = wind_speeds|max if wind_speeds else 0 %}

          {% set summary_parts = [] %}
          {% for c, desc in conditions_map.items() %}
            {% if c in common_conditions %}
              {% set summary_parts = summary_parts + [desc] %}
            {% endif %}
          {% endfor %}
          {% if summary_parts|length == 0 %}
            {% set summary_parts = ["variable conditions"] %}
          {% endif %}

          {% if max_precip_chance > 50 and total_precip > 0 %}
            {% set summary_parts = summary_parts + ["some measurable precipitation"] %}
          {% elif max_precip_chance > 50 %}
            {% set summary_parts = summary_parts + ["a notable chance of precipitation"] %}
          {% endif %}

          {% if max_wind_speed > 20 %}
            {% set summary_parts = summary_parts + ["brisk winds"] %}
          {% elif max_wind_speed > 10 %}
            {% set summary_parts = summary_parts + ["gentle breezes"] %}
          {% endif %}

          {% if summary_parts|length > 1 %}
            {{ "You can anticipate " ~ summary_parts[:-1]|join(", ") ~ " and " ~ summary_parts[-1] ~ " ahead. " }}
          {% else %}
            {{ "You can expect " ~ summary_parts[0] ~ " ahead. " }}
          {% endif %}

          {% if total_precip > 0.8 %}
            {{ "Heavy precipitation is likely. " }}
          {% endif %}
          {% if 'rainy' in common_conditions and max_precip_chance > 40 %}
            {{ "Rain is quite possible—carry an umbrella. " }}
          {% endif %}
          {% if temphigh > 95 %}
            {{ "Extreme heat—stay cool and hydrated. " }}
          {% endif %}
          {% if temphigh < 30 %}
            {{ "Very cold—dress warmly if venturing out. " }}
          {% endif %}
          {% if total_precip > 0.2 and total_precip <= 0.8 %}
            {{ "Light, intermittent precipitation may occur. " }}
          {% endif %}
          {% if max_precip_chance > 70 and 'rainy' not in common_conditions and 'snowy' not in common_conditions %}
            {{ "Unusual precipitation like sleet or hail may appear—be alert. " }}
          {% endif %}
          {% if 'sunny' in common_conditions and temphigh > 85 %}
            {{ "Strong sunshine—consider sunscreen and protective gear. " }}
          {% endif %}
          {% if temphigh > 60 and temphigh < 80 and ('sunny' in common_conditions or 'partlycloudy' in common_conditions or 'cloudy' in common_conditions) %}
            {{ "Conditions are mild and comfortable, suitable for various activities. " }}
          {% endif %}
          {% if humidity > 80 and temphigh > 85 %}
            {{ "High heat and humidity—take indoor breaks and stay hydrated. " }}
          {% endif %}
          {% if 'rainy' in common_conditions and temphigh < 60 %}
            {{ "Cool and rainy—grab a jacket and waterproof footwear. " }}
          {% endif %}
          {% if 'snowy' in common_conditions and max_wind_speed > 15 %}
            {{ "Snow with moderate winds—caution on roads. " }}
          {% endif %}
          {% if temphigh < 32 %}
            {{ "Below freezing—watch for ice. " }}
          {% endif %}
          {% if temphigh < 20 %}
            {{ "Extremely cold—risk of frostbite, dress in layers. " }}
          {% endif %}
          {% if max_wind_speed > 25 %}
            {{ "Strong gusts possible—secure outdoor items. " }}
          {% endif %}
          {% if humidity < 30 and max_wind_speed > 15 %}
            {{ "Dry and breezy—use moisturizer for comfort. " }}
          {% endif %}
          {% if ('cloudy' in common_conditions or 'partlycloudy' in common_conditions) and max_precip_chance < 30 and temphigh > 50 and temphigh < 85 %}
            {{ "Cloud cover with mild temps—pleasant for most plans. " }}
          {% endif %}
          {% if humidity > 40 and humidity < 60 and max_wind_speed < 10 %}
            {{ "Balanced humidity and light winds—overall pleasant. " }}
          {% endif %}

          {{ "Sunset is around " ~ sunset ~ ". " }}
        {% else %}
          {{ "Detailed hourly forecast data isn't currently available. " }}
        {% endif %}
      {% elif f.include_weather %}
        {{ "Weather information is currently unavailable. " }}
      {% endif %}

      {# Zodiac Sign #} {% if f.include_zodiac and zodiac_today_sensor !=
      'unknown' and zodiac_yesterday_sensor != 'unknown' and
      zodiac_today_sensor != zodiac_yesterday_sensor %}
        {{ "The Zodiac sign has shifted from " ~ zodiac_yesterday_sensor ~ " to " ~ zodiac_today_sensor ~ " today. " }}
      {% endif %}

      {# Full Moon #} {% if f.include_full_moon and moon_phase_sensor ==
      'full_moon' %}
        {{ "Tonight features a full moon—take a moment to appreciate its glow. " }}
      {% endif %}

      {# Sunday Reminder #} {% if f.include_sunday_reminder and weekday ==
      'Sunday' %}
        {{ "Remember to water your plants today since it's Sunday. " }}
      {% endif %}

      {# Tasks Section #} {% if f.include_tasks %}
        {%- set tasks = tasks_list %}
        {% if tasks|length > 0 %}
          {{ "Here are the tasks on your to-do list: " }}
          {% for t in tasks %}
            {{ "- " ~ t ~ " " }}
          {% endfor %}
        {% else %}
          {{ "Your to-do list appears to be empty at the moment. " }}
        {% endif %}
      {% endif %}

      {# Air Quality #} {% if f.include_air_quality and
      local_air_quality_sensor in ['Unhealthy for sensitive groups',
      'Unhealthy', 'Very unhealthy', 'Hazardous'] %}
        {{ "Local outdoor air quality is " ~ local_air_quality_sensor ~ ", consider limiting extended outdoor activity. " }}
      {% endif %}

      {# Re-include Smart Predictions Section #} {% if
      f.include_smart_predictions %}
        {# Steps comparison #}
        {% if today_steps > 0 and avg_steps > 0 %}
          {% if today_steps < avg_steps %}
            {{ "You have fewer steps than your weekly average so far. A short walk might help. " }}
          {% else %}
            {{ "Your steps match or exceed your weekly average—keep the momentum! " }}
          {% endif %}
        {% endif %}

        {# Heart Rate comparison #}
        {% if today_hr > 0 and avg_hr > 0 %}
          {% if today_hr > avg_hr + 5 %}
            {{ "Your average heart rate is higher than usual. A calm break might be beneficial. " }}
          {% elif today_hr < avg_hr - 5 %}
            {{ "Your heart rate is lower than normal, possibly indicating good rest. " }}
          {% else %}
            {{ "Your heart rate is near your normal baseline. Stay steady. " }}
          {% endif %}
        {% endif %}

        {# Resting Heart Rate comparison #}
        {% if today_resting_hr > 0 and avg_resting_hr > 0 %}
          {% if today_resting_hr > avg_resting_hr + 5 %}
            {{ "Your resting heart rate is above average. Consider a brief relaxation technique. " }}
          {% elif today_resting_hr < avg_resting_hr - 5 %}
            {{ "Your resting heart rate is lower than usual, indicating positive recovery. " }}
          {% else %}
            {{ "Your resting heart rate is stable. Maintain your current healthy habits. " }}
          {% endif %}
        {% endif %}

        {# Oxygen Saturation comparison #}
        {% if today_oxygen > 0 and avg_oxygen > 0 %}
          {% if today_oxygen < avg_oxygen - 1.0 %}
            {{ "Your oxygen saturation is slightly lower today—consider a deep-breathing pause. " }}
          {% else %}
            {{ "Your oxygen saturation aligns with your weekly norm. " }}
          {% endif %}
        {% endif %}

        {# Blood Glucose comparison #}
        {% if today_bglucose > 0 and avg_bglucose > 0 %}
          {% if today_bglucose > avg_bglucose + 10 %}
            {{ "Your blood glucose is higher than average—monitor your intake or consider guidance. " }}
          {% elif today_bglucose < avg_bglucose - 10 %}
            {{ "Your blood glucose is lower than usual. If you feel off, a small balanced snack might help. " }}
          {% else %}
            {{ "Your blood glucose remains close to your weekly average. " }}
          {% endif %}
        {% endif %}

        {# Heart Points comparison #}
        {% if today_heart_points > 0 and avg_heart_points > 0 %}
          {% if today_heart_points < avg_heart_points %}
            {{ "Your heart points are lower than normal. Maybe add a light cardio activity today. " }}
          {% else %}
            {{ "Your heart points are at or above your usual level—great job staying active! " }}
          {% endif %}
        {% endif %}
      {% endif %}

      {# Motivational Quote at the end #} {% if f.include_motivational_quotes
      %}
        {%- set motivational_quotes = [
          "Seize your opportunities today.",
          "Each hour can bring growth and progress.",
          "Keep moving forward with hope.",
          "Every step counts toward your goals.",
          "Embrace the moment and shine."
        ] -%}
        {%- set quote = motivational_quotes|random -%}
        {{ "Here's an encouraging thought: " ~ quote }}
      {% endif %}
      ```
- action: google_generative_ai_conversation.generate_content
  data:
    prompt: >
      Please take the following daily summary message and:

      1. Improve grammar, phrasing, and style. 2. Add day-specific historical
      significance or seasonal notes only if the information is highly
      relevant (e.g., if it's a historically significant date or a leap day).
      Include this addition at the end of the response and make it as short
      and concise as possible. Unless the information is very significant or
      highly relevant, then just skip this step 3. Maintain all reported facts
      and data, following the same structure with minor adjustments to improve
      hearability 4. Provide subtle reminders about why this date may matter
      (e.g., historical events). 5. Remove all emojis prior to processing 6.
      Make it as concise and short as possible 6. Remove all astericks from
      the response

      Original Message: {{ message }}
  response_variable: refined_message
- action: tts.speak
  data:
    media_player_entity_id: media_player.living_room
    message: "{{ refined_message.text }}"
  target:
    entity_id: tts.google_cloud
sensor:
    - platform: weatheralerts
      state: NJ
      zone: 8
      county: 27
    - platform: weatheralerts
      state: IN
      zone: 69
      county: 101
    - platform: statistics
      name: "Average Outdoor PM2.5 (24h)"
      entity_id: sensor.crown_view_villas_pm2_5
      state_characteristic: mean
      max_age:
        hours: 24
    - platform: statistics
      name: "Average Outdoor PM10.0 (24h)"
      entity_id: sensor.crown_view_villas_pm10
      state_characteristic: mean
      max_age:
        hours: 24
    - platform: statistics
      name: "Heart Points Weekly Statistics"
      entity_id: sensor.heart_points_daily
      state_characteristic: mean
      max_age:
        days: 7
    - platform: statistics
      name: "Steps Weekly Statistics"
      entity_id: sensor.daily_max_steps
      state_characteristic: mean
      max_age:
        days: 7
    - platform: statistics
      name: "Blood Glucose Weekly Statistics"
      entity_id: sensor.blood_glucose
      state_characteristic: mean
      max_age:
        days: 7
    - platform: statistics
      name: "Oxygen Saturation Weekly Statistics"
      entity_id: sensor.oxygen_saturation
      state_characteristic: mean
      max_age:
        days: 7
    - platform: statistics
      name: "Resting Heart Rate Weekly Statistics"
      entity_id: sensor.resting_heart_rate
      state_characteristic: mean
      max_age:
        days: 7
    - platform: statistics
      name: "Heart Rate Weekly Statistics"
      entity_id: sensor.heart_rate
      state_characteristic: mean
      max_age:
        days: 7

  template:
    - sensor:
        - name: "Daily Max Steps"
          state: >
            {% if now().hour == 23 and now().minute == 59 -%}
              {{ states('sensor.brian_z_steps') }}
            {%- else %}
              {{ states('sensor.brian_z_steps') | int(default=0) }}
            {%- endif -%}
          unique_id: daily_max_steps

    - sensor:
        - name: "Weekly Average Steps"
          unit_of_measurement: "steps"
          state: "{{ state_attr('sensor.steps_weekly_statistics', 'mean') | int(default=0) }}"

        - name: "Weekly Average Heart Rate"
          unit_of_measurement: "bpm"
          state: "{{ state_attr('sensor.heart_rate_weekly_statistics', 'mean') | int(default=0) }}"

        - name: "Weekly Average Resting Heart Rate"
          unit_of_measurement: "bpm"
          state: "{{ state_attr('sensor.resting_heart_rate_weekly_statistics', 'mean') | int(default=0) }}"

        - name: "Weekly Average Oxygen Saturation"
          unit_of_measurement: "%"
          state: "{{ state_attr('sensor.oxygen_saturation_weekly_statistics', 'mean') | int(default=0) }}"

        - name: "Weekly Average Blood Glucose"
          unit_of_measurement: "mg/dL"
          state: "{{ state_attr('sensor.blood_glucose_weekly_statistics', 'mean') | int(default=0) }}"

        - name: "Weekly Average Heart Points"
          unit_of_measurement: "points"
          state: "{{ state_attr('sensor.heart_points_weekly_statistics', 'mean') | int(default=0) }}"
    - sensor:
        - name: "Yesterday's Zodiac sign"
          state: >
            {% if now().hour == 23 and now().minute == 59 -%}
              {{ states('sensor.zodiac') }}
            {%- else %}
              {{ states('sensor.yesterdays_zodiac') }}
            {%- endif %}
          unique_id: yesterdays_zodiac
        - name: "Local Outdoor Air Quality"
          state: >
            {% set pm2_5_avg = states("sensor.average_outdoor_pm2_5_24h") | int %}
            {% if 0 <= pm2_5_avg <= 12.0 %}
              {% set pm2_5_rating = 0 %}
            {% elif 12.0 < pm2_5_avg <= 35.4 %}
              {% set pm2_5_rating = 1 %}
            {% elif 35.4 < pm2_5_avg <= 55.4 %}
              {% set pm2_5_rating = 2 %}
            {% elif 55.4 < pm2_5_avg <= 150.4 %}
              {% set pm2_5_rating = 3 %}
            {% elif 150.4 < pm2_5_avg <= 250.4 %}
              {% set pm2_5_rating = 4 %}
            {% else %}
              {% set pm2_5_rating = 5 %}
            {% endif %}

            {% set pm10_0_avg = states("sensor.average_outdoor_pm10_0_24h") | int %}
            {% if 0 <= pm10_0_avg <= 54.0 %}
              {% set pm10_0_rating = 0 %}
            {% elif 54.0 < pm10_0_avg <= 154.0 %}
              {% set pm10_0_rating = 1 %}
            {% elif 154.0 < pm10_0_avg <= 254.0 %}
              {% set pm10_0_rating = 2 %}
            {% elif 254.0 < pm10_0_avg <= 354.0 %}
              {% set pm10_0_rating = 3 %}
            {% elif 354.0 < pm10_0_avg <= 424.0 %}
              {% set pm10_0_rating = 4 %}
            {% else %}
              {% set pm10_0_rating = 5 %}
            {% endif %}

            {% set rating = [pm2_5_rating, pm10_0_rating] | max %}
            {% if rating == 0 %}
              Good
            {% elif rating == 1 %}
              Moderate
            {% elif rating == 2 %}
              Unhealthy for sensitive groups
            {% elif rating == 3 %}
              Unhealthy
            {% elif rating == 4 %}
              Very unhealthy
            {% else %}
              Hazardous
            {% endif %}
          unique_id: local_outdoor_air_quality