From 0fe104668ee7c2f9a4d4908abb73c58f47581ef3 Mon Sep 17 00:00:00 2001 From: Carlo Costanzo Date: Sat, 11 Jul 2026 23:09:38 -0400 Subject: [PATCH] fix: clarify household presence locations --- .../overview/partials/home_sections.yaml | 34 +++++++++---------- config/templates/speech/briefing.yaml | 26 +++++++------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/config/dashboards/overview/partials/home_sections.yaml b/config/dashboards/overview/partials/home_sections.yaml index 37bb79f3..c88a0fd7 100644 --- a/config/dashboards/overview/partials/home_sections.yaml +++ b/config/dashboards/overview/partials/home_sections.yaml @@ -22,6 +22,8 @@ state_filter: home: none not_home: grayscale(100%) opacity(50%) + Justin Dorm: grayscale(10%) opacity(50%) + Paige Home: grayscale(10%) opacity(50%) driving: grayscale(100%) opacity(50%) - type: picture-entity entity: person.stacey @@ -31,6 +33,8 @@ state_filter: home: none not_home: grayscale(100%) opacity(50%) + Justin Dorm: grayscale(10%) opacity(50%) + Paige Home: grayscale(10%) opacity(50%) gym: grayscale(100%) opacity(50%) driving: grayscale(100%) opacity(50%) - type: picture-entity @@ -42,6 +46,7 @@ home: none not_home: grayscale(100%) opacity(50%) Justin Dorm: grayscale(10%) opacity(50%) + Paige Home: grayscale(10%) opacity(50%) gym: grayscale(100%) opacity(50%) driving: grayscale(100%) opacity(50%) - type: picture-entity @@ -54,6 +59,7 @@ not_home: grayscale(100%) opacity(50%) paige_work: grayscale(100%) opacity(50%) Justin Dorm: grayscale(10%) opacity(50%) + Paige Home: grayscale(10%) opacity(50%) gym: grayscale(100%) opacity(50%) driving: grayscale(100%) opacity(50%) columns: 4 @@ -100,14 +106,14 @@ action: none layout: horizontal fill_container: true + # Core map cards are required to show each person's location history. - type: map entities: - person.justin - - person.paige hours_to_show: 48 aspect_ratio: '4:3' theme_mode: auto - card_mod: + card_mod: &person_location_map_style style: null ha-map $ ha-entity-marker $: ".marker { \n /* Style person marker & adjust position to avoid blocking waypoints */\ \ \n border: 3px solid var(\u2014state-person) !important; \n border-radius: 50% 50% 50% 0px !important; \n transform:\ @@ -123,6 +129,13 @@ \ [\u2018home\u2019, \u2018not_home\u2019, \u2018unknown\u2019]) %} \n var(\u2014state-person-{{ states(config.entities[0].entity)\ \ | replace(\u2018_\u2019, \u2018-\u2018) }}) \n {% else %} \n var(\u2014state-person-zone) \n {% endif\ \ %}; \n}\n" + - type: map + entities: + - person.paige + hours_to_show: 48 + aspect_ratio: '4:3' + theme_mode: auto + card_mod: *person_location_map_style - type: map entities: - person.carlo @@ -130,22 +143,7 @@ hours_to_show: 48 aspect_ratio: '4:3' theme_mode: auto - card_mod: - style: null - ha-map $ ha-entity-marker $: ".marker { \n /* Style person marker & adjust position to avoid blocking waypoints */\ - \ \n border: 3px solid var(\u2014state-person) !important; \n border-radius: 50% 50% 50% 0px !important; \n transform:\ - \ rotate(-45deg) translate(50%, -50%); \n overflow: visible !important;\n} \n.entity-picture { \n /* Correct orientation\ - \ of person avatar / \n transform: rotate(45deg); \n border-radius: 50%; \n} \n" - ha-map $: "path:first-child { \n / Style accuracy radius / \n stroke: var(\u2014state-person); \n fill: color-mix(in\ - \ srgb, var(\u2014state-person) 50%, transparent); \n stroke-width: 0px; } \npath:nth-child(even) { \n / Styling\ - \ for waypoints / \n stroke: var(\u2014purple-color); \n stroke-width: 4px; \n} \npath:nth-child(odd):not(:first-child)\ - \ { \n / Styling for lines */ \n stroke: var(\u2014purple-color); \n stroke-width: 4px; \n}\n:host { \n /* Define\ - \ Person State colors. Can be added to theme / \n \u2014state-person-home: var(\u2014green-color); \n \u2014state-person-not-home:\ - \ var(\u2014red-color); \n \u2014state-person-zone: var(\u2014blue-color); \n \u2014state-person-unknown: var(\u2014\ - grey-color); \n / Set person state color */ \n \u2014state-person: \n {% if is_state(config.entities[0].entity,\ - \ [\u2018home\u2019, \u2018not_home\u2019, \u2018unknown\u2019]) %} \n var(\u2014state-person-{{ states(config.entities[0].entity)\ - \ | replace(\u2018_\u2019, \u2018-\u2018) }}) \n {% else %} \n var(\u2014state-person-zone) \n {% endif\ - \ %}; \n}\n" + card_mod: *person_location_map_style column_span: 1 - cards: - type: custom:mushroom-vacuum-card diff --git a/config/templates/speech/briefing.yaml b/config/templates/speech/briefing.yaml index 1e85ebf4..b104372b 100755 --- a/config/templates/speech/briefing.yaml +++ b/config/templates/speech/briefing.yaml @@ -7,8 +7,8 @@ # 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: Justin Dorm is away from Bear Stone; only person state `home` -# means someone is physically home at this house. +# Notes: Person state `home` means someone is physically at Bear Stone. +# Paige Home and Justin Dorm are spoken as home only for their respective child. # Notes: Previous broadcast text is stale context only; current sensor data # stays authoritative for entry point and action wording. # Notes: Weather context is included during the useful daytime window, when @@ -292,15 +292,15 @@ {% macro friendly_location(person_id, place_sensor_id, name) %} {% set person = states[person_id] %} {% if not person %} - {{ name }}: Away + {{ name }}: location unavailable {% 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 location_label = 'Away' if name == 'Paige' and 'Dorm' in location_label else location_label %} {% set at_bear_stone = person_state == 'home' %} - {% set at_dorm = 'Dorm' in location_label %} + {% set location_key = location_label | lower %} + {% set at_personal_home = (name == 'Paige' and location_key == 'paige home') or (name == 'Justin' and location_key == 'justin dorm') %} {% 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 %} @@ -311,12 +311,12 @@ {{ 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 %} + {% elif at_personal_home %} + {{ name }}: home at {{ location_label }}{% if seconds >= 60 %} for {{ duration }}{% endif %} {% elif location_label == 'Away' %} - {{ name }}: away{% if seconds >= 60 %} for {{ duration }}{% endif %} + {{ name }}: location unavailable{% if seconds >= 60 %} for {{ duration }}{% endif %} {% else %} - {{ name }}: away at {{ location_label }}{% if seconds >= 60 %} for {{ duration }}{% endif %} + {{ name }}: at {{ location_label }}{% if seconds >= 60 %} for {{ duration }}{% endif %} {% endif %} {% endif %} {% endmacro %} @@ -362,9 +362,11 @@ ) %} [Current date time: {{ month }} {{ day }}, {{ year }} {{ time }}] - [Presence rule: Bear Stone home means a resident's person state is exactly `home`. - Justin Dorm is an away-from-Bear-Stone location, not home for this house. - Do not welcome or address residents at dorm zones as being home here.] + [Presence and location rule: + - Bear Stone home means a resident's person state is exactly `home`. + - When a presence update is useful, name each resident's known location instead of saying only that they are away. + - Paige at Paige Home and Justin at Justin Dorm are each home at their own home. Do not describe either as away, and do not welcome them as being at Bear Stone. + - Other named places are off-site locations. Use "location unavailable" only when no current location label exists.] [LLM speech contract: - Write a useful spoken household announcement, not a sensor report.