You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
26 KiB
485 lines
26 KiB
######################################################################
|
|
# @CCOSTAN - Follow Me on X
|
|
# For more info visit https://www.vcloudinfo.com/click-here
|
|
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
|
|
# -------------------------------------------------------------------
|
|
# Speech Briefing Macros - TTS prompt helpers for daily briefings
|
|
# Generates macro prompts for weather, reminders, and AI-driven speech routines.
|
|
# -------------------------------------------------------------------
|
|
# Weather, responsibilities, holidays, air quality, and fact prompts parsed by speech_processing/speech_engine.
|
|
# Notes: Dorm zones are away from Bear Stone; only person state `home`
|
|
# means someone is physically home at this house.
|
|
# Notes: Previous broadcast text is stale context only; current sensor data
|
|
# stays authoritative for entry point and action wording.
|
|
# Notes: Weather context is gated by call_outside_weather or safety thresholds
|
|
# so narrow alerts stay action-first.
|
|
# Notes: Household context macros stay quiet unless current state adds action
|
|
# or abnormal status worth announcing.
|
|
######################################################################
|
|
|
|
|
|
>-
|
|
{%- macro dark_outside() -%}
|
|
[Because the sun has set, outside lights have been turned on]
|
|
{%- endmacro -%}
|
|
|
|
{%- macro garbage_day() -%}
|
|
{% set day_of_week = now().strftime('%a') %}
|
|
{% if day_of_week in ['Wed', 'Sun'] %}
|
|
Today is garbage day.
|
|
{% if day_of_week == 'Wed' %}
|
|
Both Recycling and regular Garbage goes out.
|
|
{% endif %}
|
|
{% endif %}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro inside_weather() -%}
|
|
{% set temp = state_attr('climate.downstairs', 'current_temperature') | default('unknown') %}
|
|
{% set humidity = states('sensor.downstairs_thermostat_humidity') %}
|
|
Inside the house, it is {{ temp }} degrees{% if humidity not in ['unknown','unavailable','none'] %} with {{ humidity }} percent humidity{% endif %}. [Only mention humidity if it seems unusually high]
|
|
{%- endmacro -%}
|
|
|
|
{% macro outside_weather() %}
|
|
[Here is the current weather outside]
|
|
{% set aq_description = state_attr('sensor.bear_stone_common_air_quality_index', 'description') | default('') %}
|
|
{% set aq_index = states('sensor.bear_stone_common_air_quality_index') | int(0) %}
|
|
{% if aq_index >= 50 %}
|
|
[Air Quality: {{ aq_description }}]
|
|
{% endif %}
|
|
{% set pirateweather_metrics = states.sensor
|
|
| selectattr('entity_id','search','pirateweather')
|
|
| rejectattr('state','in',['0','0.0','none','unknown','unavailable'])
|
|
| list %}
|
|
{% for entity in pirateweather_metrics %}
|
|
{% set value = entity.state %}
|
|
{% set unit = entity.attributes.unit_of_measurement | default('') %}
|
|
{% set base_name = entity.attributes.friendly_name | default(entity.entity_id) %}
|
|
{% set friendly_name = ' '.join(base_name.split(' ')[1:]) or base_name %}
|
|
{% set numeric = value | float(0) %}
|
|
{% set include = (
|
|
'Temperature' in friendly_name
|
|
or 'Minutely' in friendly_name
|
|
or 'Precip' in friendly_name
|
|
or ('Wind Speed' in friendly_name and numeric > 15)
|
|
or ('Cloud Coverage' in friendly_name and numeric > 75)
|
|
or ('Humidity' in friendly_name and (numeric < 50 or numeric > 85))
|
|
or ('Nearest Storm Distance' in friendly_name and numeric <= 10)
|
|
) %}
|
|
{% if include and 'UV Index' not in friendly_name %}
|
|
{{ friendly_name }}: {{ value }} {{ unit }}
|
|
{% endif %}
|
|
{%- endfor %}
|
|
|
|
{% set uv_index = states('sensor.pirateweather_uv_index') | float(0) %}
|
|
{% if uv_index >= 6 %}
|
|
UV index is {{ uv_index }}.
|
|
[Give a helpful suggestion based on the current UV index or weather conditions]
|
|
{% endif %}
|
|
|
|
{%- if states('sensor.nws_alerts') | int(0) > 0 -%}
|
|
{%- set alert_description = state_attr('sensor.nws_alerts', 'Alerts') | default('') %}
|
|
[Summarize the included weather alert and give overall details on any storms relevant to the residents of the home. Use the Situation Overview Section to best understand what is going on - Be sure to highlight any impacts to Seminole County or Tallahassee]
|
|
{{ alert_description }}
|
|
[END of Weather Alert]
|
|
{%- endif %}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro lightning() -%}
|
|
There have been {{ states('sensor.blitzortung_lightning_counter') }} lightning strikes detected within {{(states('sensor.blitzortung_lightning_distance') | int(9999)/ 1.69) | round (1, 'floor')}} Miles of our House.
|
|
Nearest Storm Distance : {{states('sensor.pirateweather_nearest_storm_distance')}} Miles.
|
|
{%- endmacro -%}
|
|
|
|
{%- macro fridge() -%}
|
|
{% set freezer = states('sensor.refrigerator_freezer_temp') %}
|
|
{% set fridge = states('sensor.refrigerator_fridge_temp') %}
|
|
{% set blink_temp = states('sensor.blink_blink1_temperature') %}
|
|
{% if blink_temp not in ['unknown', 'unavailable', 'none', ''] %}
|
|
The internal temperature of the refrigerator is currently {{ blink_temp }} degrees.
|
|
{% endif %}
|
|
{% if freezer not in ['unknown', 'unavailable', 'none', ''] and fridge not in ['unknown', 'unavailable', 'none', ''] %}
|
|
The freezer temperature is {{ freezer }} degrees and the fridge temperature is {{ fridge }} degrees.
|
|
{% endif %}
|
|
{% set door = states.binary_sensor.refrigerator_door_open %}
|
|
{% set door_open = states('binary_sensor.refrigerator_door_open') == 'on' and door is not none and (as_timestamp(now()) - as_timestamp(door.last_changed)) > 360 %}
|
|
{% if door_open %}The fridge door is currently open.{% endif %}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro window_check() -%}
|
|
{% set open_entries = states.binary_sensor
|
|
| selectattr('state', 'eq', 'on')
|
|
| selectattr('attributes.device_class', 'eq', 'opening')
|
|
| map(attribute='attributes.friendly_name')
|
|
| list %}
|
|
{% set entry_count = open_entries | length %}
|
|
{% if entry_count > 0 -%}
|
|
[Current entry point state: {{ open_entries | join(', ') }} {{ 'is' if entry_count == 1 else 'are' }} still open and {{ 'needs' if entry_count == 1 else 'need' }} to be closed manually. Do not say any physical window or door was closed unless current sensor data says it is closed.]
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro lock_check() -%}
|
|
{% if states.group.locks.state !='locked' -%}
|
|
The
|
|
{%- for state in states.lock -%}
|
|
{%- endfor %}
|
|
{% for group in states.lock|groupby('state') -%}
|
|
{%- for entity in group.list if entity.state == 'unlocked' -%}
|
|
{{ ' and' if loop.last and not loop.first }}
|
|
{{ entity.attributes.friendly_name }}
|
|
{%- endfor -%}
|
|
{%- endfor %}
|
|
needs to be locked.
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro garage_check() -%}
|
|
{% if states.group.garage_doors.state !='closed' -%}
|
|
The
|
|
{%- for state in states.cover -%}
|
|
{%- endfor %}
|
|
{% for group in states.cover|groupby('state') -%}
|
|
{%- for entity in group.list if entity.state == 'open' and entity.attributes.device_class == 'garage' -%}
|
|
{{ ' and' if loop.last and not loop.first }}
|
|
{{ entity.attributes.friendly_name }}
|
|
{%- endfor -%}
|
|
{%- endfor %}
|
|
need to be closed.
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro front_door_packages() -%}
|
|
{% if is_state('binary_sensor.front_door_packages_present', 'on') -%}
|
|
There appears to be a package waiting at the front door.
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro medicine() -%}
|
|
{% if is_state('input_boolean.medicine', 'off') -%}
|
|
It looks like Carlo has not taken his medicine yet. Please make sure Carlo takes his medicine now.
|
|
{% endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro tesla_charge_context() -%}
|
|
{% set battery = states('sensor.spaceship_battery_level') | float(none) %}
|
|
{% set snooze_until = as_timestamp(states('input_datetime.tesla_model_y_plug_in_snooze_until'), 0) %}
|
|
{% set last_garage_close = as_timestamp(states('input_datetime.tesla_model_y_last_garage_close'), 0) %}
|
|
{% set recent_arrival = last_garage_close > 0 and (as_timestamp(now()) - last_garage_close) < 43200 %}
|
|
{% if battery is not none
|
|
and battery < 50
|
|
and is_state('switch.spaceship_charge', 'off')
|
|
and is_state('person.carlo', 'home')
|
|
and is_state('person.stacey', 'home')
|
|
and as_timestamp(now()) >= snooze_until
|
|
and (recent_arrival or now().hour >= 17) -%}
|
|
Model Y battery is {{ battery | round(0) | int }} percent and it is not charging. Plug it in.
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro energy_context() -%}
|
|
{% set powerwall_charge = states('sensor.powerwall_charge') | float(none) %}
|
|
{% set house_load = states('sensor.powerwall_load_power') | float(none) %}
|
|
{% if is_state('binary_sensor.powerwall_grid_status', 'off') -%}
|
|
Power is out{% if powerwall_charge is not none %}. Powerwall is at {{ powerwall_charge | round(0) | int }} percent{% endif %}. {% if house_load is not none and house_load > 5 %}House load is high; reduce large appliances.{% elif powerwall_charge is none or powerwall_charge < 75 %}Keep high-load devices off.{% else %}Stay aware of backup power until the grid returns.{% endif %}
|
|
{% elif powerwall_charge is not none and powerwall_charge < 50 -%}
|
|
Powerwall is at {{ powerwall_charge | round(0) | int }} percent while the grid is online. Keep backup charge in mind before running high-load devices.
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro water_context() -%}
|
|
{% set valve_state = states('valve.phyn_shutoff_valve') %}
|
|
{% set hot_water = states('sensor.rheem_wh_available_hot_water') | float(none) %}
|
|
{% set compressor_health = states('sensor.rheem_wh_compressor_health') | float(none) %}
|
|
{% set tank_health = states('sensor.rheem_wh_tank_health') | float(none) %}
|
|
{% if valve_state == 'closed' and not is_state('binary_sensor.phyn_leak_test_running', 'on') -%}
|
|
Main water is shut off. Check for leaks before restoring water.
|
|
{% elif valve_state not in ['open', 'unknown', 'unavailable', 'none', ''] -%}
|
|
Main water valve is {{ valve_state }}. Check water status before using fixtures.
|
|
{%- endif %}
|
|
{% if hot_water is not none and hot_water < 30 -%}
|
|
Hot water is at {{ hot_water | round(0) | int }} percent. Keep showers short or wait for recovery.
|
|
{%- endif %}
|
|
{% if (compressor_health is not none and compressor_health < 90) or (tank_health is not none and tank_health < 90) -%}
|
|
Water heater health needs attention.
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro comfort_context() -%}
|
|
{% set downstairs_current = state_attr('climate.downstairs', 'current_temperature') | float(none) %}
|
|
{% set downstairs_target = state_attr('climate.downstairs', 'temperature') | float(none) %}
|
|
{% set upstairs_current = state_attr('climate.upstairs', 'current_temperature') | float(none) %}
|
|
{% set upstairs_target = state_attr('climate.upstairs', 'temperature') | float(none) %}
|
|
{% set downstairs_humidity = states('sensor.downstairs_thermostat_humidity') | float(none) %}
|
|
{% if downstairs_humidity is none %}
|
|
{% set downstairs_humidity = state_attr('climate.downstairs', 'current_humidity') | float(none) %}
|
|
{% endif %}
|
|
{% if downstairs_current is not none and downstairs_target is not none and downstairs_current >= downstairs_target + 3 and is_state('binary_sensor.downstairs_ac_is_cooling', 'on') -%}
|
|
Downstairs is {{ downstairs_current | round(0) | int }} degrees and cooling toward {{ downstairs_target | round(0) | int }}.
|
|
{% elif downstairs_current is not none and downstairs_target is not none and downstairs_current >= downstairs_target + 4 and not is_state('climate.downstairs', 'off') -%}
|
|
Downstairs is {{ downstairs_current | round(0) | int }} degrees, above the {{ downstairs_target | round(0) | int }} degree target. Check the thermostat if it feels too warm.
|
|
{%- endif %}
|
|
{% if upstairs_current is not none and upstairs_target is not none and upstairs_current >= upstairs_target + 3 and is_state('binary_sensor.upstairs_ac_is_cooling', 'on') -%}
|
|
Upstairs is {{ upstairs_current | round(0) | int }} degrees and cooling toward {{ upstairs_target | round(0) | int }}.
|
|
{% elif upstairs_current is not none and upstairs_target is not none and upstairs_current >= upstairs_target + 4 and not is_state('climate.upstairs', 'off') -%}
|
|
Upstairs is {{ upstairs_current | round(0) | int }} degrees, above the {{ upstairs_target | round(0) | int }} degree target. Check the thermostat if it feels too warm.
|
|
{%- endif %}
|
|
{% if downstairs_humidity is not none and downstairs_humidity > 60 -%}
|
|
Downstairs humidity is {{ downstairs_humidity | round(0) | int }} percent. The house may feel warmer than the thermostat suggests.
|
|
{%- endif -%}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro vacuum_context() -%}
|
|
{% set vac_state = states('vacuum.l10s_vacuum') %}
|
|
{% set vac_error = states('sensor.l10s_vacuum_error') %}
|
|
{% set room = states('sensor.l10s_vacuum_current_room') %}
|
|
{% set task_status = states('sensor.l10s_vacuum_task_status') %}
|
|
{% set phase = states('input_select.l10s_vacuum_phase') %}
|
|
{% set queue = states('input_text.l10s_vacuum_room_queue') | default('', true) | string | trim %}
|
|
{% set cleaned = states('input_text.l10s_vacuum_rooms_cleaned_today') | default('', true) | string | trim %}
|
|
{% set queue_count = queue | regex_findall('[0-9]+') | length %}
|
|
{% set valid_room = room not in ['unknown', 'unavailable', 'none', ''] %}
|
|
{% if vac_state == 'error' or vac_error not in ['no_error', 'unknown', 'unavailable', 'none', ''] -%}
|
|
Vacuum needs help{% if valid_room %} in {{ room }}{% endif %}. Error is {{ vac_error | replace('_', ' ') }}.
|
|
{% elif vac_state in ['cleaning', 'returning', 'paused'] -%}
|
|
Vacuum is {{ vac_state | replace('_', ' ') }}{% if valid_room %} near {{ room }}{% endif %}{% if queue_count > 0 %} with {{ queue_count }} rooms left{% elif task_status not in ['unknown', 'unavailable', 'none', ''] %}; task status is {{ task_status | replace('_', ' ') }}{% endif %}.
|
|
{% elif is_state('input_boolean.l10s_vacuum_on_demand', 'on') and queue_count > 0 -%}
|
|
Vacuum has {{ queue_count }} rooms queued for {{ phase | replace('_', ' ') }}.
|
|
{% elif cleaned not in ['unknown', 'unavailable', 'none', ''] -%}
|
|
Vacuum cleaned today: {{ cleaned }}.
|
|
{% endif %}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro moon() -%}
|
|
{% if (now().hour == 17) %}
|
|
Current Moon phase: {{ states('sensor.moon') }} [Give a fact and mention today's phase]
|
|
{% endif %}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro uv() -%}
|
|
{# UV details are now included in outside_weather with a threshold gate #}
|
|
{%- endmacro -%}
|
|
|
|
{%- macro holiday() -%}
|
|
{% if states.sensor.holiday.state != '' %}
|
|
Today is {{ states.sensor.holiday.state }}.
|
|
{% endif %}
|
|
{%- endmacro -%}
|
|
|
|
{# YOUTUBE VIDEO ********* https://www.vcloudinfo.com/2019/11/adding-days-until-sensor-to-my-home-assistant-speech-routines.html #}
|
|
{%- macro days_until() -%}
|
|
{%- if states('sensor.mothers_countdown') | int(9999)< 20 -%}
|
|
and don't forget, there is only {{ states.sensor.mothers_countdown.state }} days until Mothers day!
|
|
{%- elif states('sensor.fathers_countdown') | int(9999)< 20 -%}
|
|
and don't forget, there are {{ states.sensor.fathers_countdown.state }} days until Fathers day!
|
|
{%- elif states('sensor.easter_countdown') | int(9999)< 15 -%}
|
|
and don't forget, there are {{ states.sensor.easter_countdown.state }} colorful days until Easter Sunday!
|
|
{%- elif states('sensor.thanksgiving_day_countdown') | int(9999)< 10 and states('sensor.thanksgiving_day_countdown') | int(9999)> 0 -%}
|
|
and don't forget, there are {{ states.sensor.thanksgiving_day_countdown.state }} thankful days until Thanksgiving
|
|
{%- elif states('sensor.thanksgiving_day_countdown') | int(9999)< 1 -%}
|
|
and don't forget, Thanksgiving is tomorrow!
|
|
{%- elif states('sensor.halloween_countdown') | int(9999)< 30 and states('sensor.halloween_countdown') | int(9999)> 0 -%}
|
|
and don't forget, there are {{ states.sensor.halloween_countdown.state }} Spooky days until Halloween!
|
|
{%- elif states('sensor.halloween_countdown') | int(9999)< 1 -%}
|
|
and don't forget, Tomorrow is Halloween!
|
|
{%- elif states('sensor.chanukkah_countdown') | int(9999)< 15 -%}
|
|
and don't forget, there are {{ states.sensor.chanukkah_countdown.state }} days until Chanukkah!
|
|
{%- elif states('sensor.christmas_countdown') | int(9999)< 30 and states('sensor.christmas_countdown') | int(9999)> 0 -%}
|
|
and don't forget, there are {{ states.sensor.christmas_countdown.state }} Merry days until Christmas!
|
|
{%- elif states('sensor.christmas_countdown') | int(9999)< 1 -%}
|
|
and don't forget, Santa Claus is coming tomorrow!
|
|
{% endif %}
|
|
{%- endmacro -%}
|
|
|
|
{# friendly duration/location helper #}
|
|
{% macro friendly_location(person_id, place_sensor_id, name) %}
|
|
{% set person = states[person_id] %}
|
|
{% if not person %}
|
|
{{ name }}: Away
|
|
{% else %}
|
|
{% set person_state = states(person_id) %}
|
|
{% set place_state = states(place_sensor_id) if place_sensor_id in states else 'unknown' %}
|
|
{% set location_label = place_state if place_state not in ['unknown','unavailable','','none'] else person_state %}
|
|
{% set location_label = 'Away' if location_label in ['unknown','unavailable','','none'] else location_label %}
|
|
{% set at_bear_stone = person_state == 'home' %}
|
|
{% set at_dorm = 'Dorm' in location_label %}
|
|
{% set last_changed = as_timestamp(person.last_changed) %}
|
|
{% set seconds = (as_timestamp(now()) - last_changed) | int(0) if last_changed else 0 %}
|
|
{% set hours = (seconds // 3600) | int %}
|
|
{% set minutes = ((seconds % 3600) // 60) | int %}
|
|
{% set duration = (hours ~ ' hours') if hours >= 1 else (minutes ~ ' minutes') %}
|
|
{% if person_state == 'driving' %}
|
|
{% set driving_label = location_label if location_label != 'Away' else '' %}
|
|
{{ name }}: driving{% if driving_label %} near {{ driving_label }}{% endif %}{% if seconds >= 60 %} for {{ duration }}{% endif %}
|
|
{% elif at_bear_stone %}
|
|
{{ name }}: at Bear Stone home{% if seconds >= 60 %} for {{ duration }}{% endif %}
|
|
{% elif at_dorm %}
|
|
{{ name }}: away at {{ location_label }}{% if seconds >= 60 %} for {{ duration }}{% endif %}
|
|
{% else %}
|
|
{{ name }}: away at {{ location_label }}{% if seconds >= 60 %} for {{ duration }}{% endif %}
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endmacro %}
|
|
|
|
{# a macro that removes all newline characters, empty spaces, and returns formatted text and replaces underscores with spaces #}
|
|
{%- macro cleanup(data) -%}
|
|
{%- for item in data.split("\n") if item | trim != "" -%}
|
|
{{ item | trim | replace("_", " ") }} {% endfor -%}
|
|
{%- endmacro -%}
|
|
|
|
{# ********************************************* #}
|
|
{# ******** Start the Speech routines ******** #}
|
|
{# ********************************************* #}
|
|
|
|
{# a macro to call all macros :) #}
|
|
{%- macro mother_of_all_macros() -%}
|
|
|
|
{# Augmenting the System Prompt for OpenAI #}
|
|
{% set current_date = now() %}
|
|
{% set month = current_date.strftime('%B') %}
|
|
{% set day_of_week = now().strftime('%a') %}
|
|
{% set hour = now().hour %}
|
|
{% set minute = now().minute %}
|
|
{% set day = current_date.strftime('%d') %}
|
|
{% set year = current_date.strftime('%Y') %}
|
|
{% set time = current_date.strftime('%I:%M %p') %}
|
|
{% set call_no_announcement_flag = call_no_announcement | default(0) | int(0) %}
|
|
{% set call_inside_weather_flag = call_inside_weather | default(0) | int(0) %}
|
|
{% set call_outside_weather_flag = call_outside_weather | default(0) | int(0) %}
|
|
{% set call_dark_outside_flag = call_dark_outside | default(0) | int(0) %}
|
|
{% set call_garage_check_flag = call_garage_check | default(0) | int(0) %}
|
|
{% set call_window_check_flag = call_window_check | default(0) | int(0) %}
|
|
{% set call_garbage_day_flag = call_garbage_day | default(0) | int(0) %}
|
|
{% set no_fridge_flag = no_fridge | default(0) | int(0) %}
|
|
{% set lightning_close = states('sensor.blitzortung_lightning_counter') | int(0) > 0 and (states('sensor.blitzortung_lightning_distance') | float(9999) / 1.69) <= 10 %}
|
|
{% set weather_safety_context = (
|
|
states('sensor.nws_alerts') | int(0) > 0
|
|
or states('sensor.pirateweather_wind_speed') | float(0) >= 30
|
|
or states('sensor.bear_stone_common_air_quality_index') | int(0) >= 100
|
|
or lightning_close
|
|
) %}
|
|
[Current date time: {{ month }} {{ day }}, {{ year }} {{ time }}]
|
|
|
|
[Presence rule: Bear Stone home means a resident's person state is exactly `home`.
|
|
Justin Dorm and Paige Dorm are away-from-Bear-Stone locations, not home for this house.
|
|
Do not welcome or address residents at dorm zones as being home here.]
|
|
|
|
[LLM speech contract:
|
|
- Write a useful spoken household announcement, not a sensor report.
|
|
- Priority order: safety or action needed, useful implication, relevant context, then one optional human touch.
|
|
- Lead with the main thing that matters now. For urgent or narrow alerts, skip greetings and side notes.
|
|
- Translate sensor data into household meaning. Mention raw numbers only when they explain severity or change the action.
|
|
- Do not announce normal states just because they are available in context.
|
|
- Vary wording, sentence structure, openings, and closings so the house does not sound repetitive.
|
|
- Avoid robotic phrases like "currently", "detected", "please be advised", "sensor data", and "as an AI" unless needed for clarity.
|
|
- Add at most one small seasonal note, insight, or personality line, and only when no urgent action exists.
|
|
- Sound calm, practical, and natural. Do not joke during safety, security, water, appliance, or maintenance alerts.
|
|
]
|
|
|
|
[Resident: Location:
|
|
- {{ friendly_location('person.carlo', 'sensor.carlo_place', 'Carlo') }}
|
|
- {{ friendly_location('person.stacey', 'sensor.stacey_place', 'Stacey') }}
|
|
- {{ friendly_location('person.justin', 'sensor.justin_place', 'Justin') }}
|
|
- {{ friendly_location('person.paige', 'sensor.paige_place', 'Paige') }}
|
|
{% if range(1, 100) | random <= 25 %}
|
|
Cat Molly: Always home.
|
|
{% endif %}
|
|
]
|
|
|
|
[Primary event/requested action:
|
|
{{ personarriving | default('', true) }}
|
|
{{ NestStatus | default('', true) }}
|
|
{{ DoorOpened | default('', true) }}
|
|
{{ DoorClosed | default('', true) }}
|
|
{{ DoorLocked | default('', true) }}
|
|
{{ DoorUnLocked | default('', true) }}
|
|
{{ NewDevice | default('', true) }}
|
|
{% set primary_value = value1 | default('', true) | trim %}
|
|
{% if primary_value %}
|
|
{{ primary_value }}
|
|
{% endif %}
|
|
]
|
|
|
|
[Optional greeting seed:
|
|
{% if call_no_announcement_flag != 1 %}
|
|
{% if now().strftime('%H')|int(9999)< 12 and now().strftime('%H')|int(9999)> 6 %}
|
|
Good morning. [if there is only one person home, address them specifically]
|
|
{% elif now().strftime('%H')|int(9999)>= 12 and now().strftime('%H')|int(9999)< 17 %}
|
|
Good afternoon. [if there is only one person home, address them specifically]
|
|
{% else %}
|
|
Good evening. [if there is only one person home, address them specifically]
|
|
{% endif %}
|
|
{% endif %}
|
|
Use this only if it improves flow. Skip it for repeated, urgent, narrow, or very short announcements.
|
|
]
|
|
|
|
[Context data:
|
|
{% if call_inside_weather_flag == 1 %}
|
|
{{ inside_weather() }}
|
|
{% endif %}
|
|
|
|
{% if call_outside_weather_flag == 1 or weather_safety_context %}
|
|
{{ outside_weather() }}
|
|
{% endif %}
|
|
|
|
{% if (states('sensor.blitzortung_lightning_counter')|int(0)) > 0 and (call_outside_weather_flag == 1 or lightning_close) %}
|
|
{{ lightning() }}
|
|
{% endif %}
|
|
|
|
{% set blink_temp = states('sensor.blink_blink1_temperature') | float(none) %}
|
|
{% set freezer_temp = states('sensor.refrigerator_freezer_temp') | float(none) %}
|
|
{% set fridge_temp = states('sensor.refrigerator_fridge_temp') | float(none) %}
|
|
{% set fridge_door = states.binary_sensor.refrigerator_door_open %}
|
|
{% set fridge_door_open = states('binary_sensor.refrigerator_door_open') == 'on' and fridge_door is not none and (as_timestamp(now()) - as_timestamp(fridge_door.last_changed)) > 360 %}
|
|
{% if ((blink_temp is not none and blink_temp > 55) or (freezer_temp is not none and freezer_temp > 5) or (fridge_temp is not none and fridge_temp > 50) or fridge_door_open) and no_fridge_flag != 1 %}
|
|
{{ fridge() }}
|
|
{% endif %}
|
|
|
|
{{ lock_check() }}
|
|
|
|
{% if call_dark_outside_flag == 1 %}
|
|
{{ dark_outside() }}
|
|
{% endif %}
|
|
|
|
{% if call_garage_check_flag == 1 or is_state('sun.sun', 'below_horizon') %}
|
|
{{ garage_check() }}
|
|
{% endif %}
|
|
|
|
{% if (call_window_check_flag == 1 or is_state('sun.sun', 'below_horizon')) or is_state('group.entry_points', 'on') %}
|
|
{{ window_check() }}
|
|
{% endif %}
|
|
|
|
{{ front_door_packages() }}
|
|
|
|
{{ tesla_charge_context() }}
|
|
|
|
{{ energy_context() }}
|
|
|
|
{{ water_context() }}
|
|
|
|
{{ comfort_context() }}
|
|
|
|
{% if call_garbage_day_flag == 1 %}
|
|
{{ garbage_day() }}
|
|
{% endif %}
|
|
|
|
{% if now().strftime('%H')|int(0) > 21 %}
|
|
{{ medicine() }}
|
|
{% endif %}
|
|
|
|
{{ vacuum_context() }}
|
|
|
|
{{ holiday() }}
|
|
|
|
{# call a Random fact about the house or inspiration quote #}
|
|
{{ ([moon, holiday, days_until ]|random)() }}
|
|
]
|
|
[Previous broadcast rule:
|
|
The previous broadcast is stale context for repetition avoidance only.
|
|
Do not quote it, continue it, summarize it, trust it as current state, or repeat its exact phrasing.
|
|
If the same issue is still active, restate it from current Sensor Data with fresh wording.
|
|
Do not repeat prior claims that a window, door, lock, garage door, light, appliance, or weather condition changed unless current Sensor Data supports that claim.
|
|
If current Sensor Data says an entry point is still open and needs closure, say it is still open or needs attention, not that it is closed.
|
|
]
|
|
[Previous broadcast for context: "{{ state_attr('sensor.openai_response', 'response') }}" ]
|
|
|
|
{%- endmacro -%}
|
|
{{- cleanup(mother_of_all_macros()) -}}
|