Update Home Assistant repo instructions

This commit is contained in:
Carlo Costanzo
2026-05-03 15:52:51 -04:00
parent 8ea8fcd7f3
commit 8670d3892e
8 changed files with 216 additions and 39 deletions

View File

@@ -9,6 +9,7 @@
# Related Issue: n/a
# Notes: Uses color temperature only to avoid inherited color scenes.
# TV playback keeps the sink off so media time does not re-light it.
# Notes: Office lamp switch off-gates the sink while active PC work is in progress.
######################################################################
- alias: "Kitchen Sink Circadian Daylight"
@@ -35,6 +36,10 @@
entity_id: media_player.living_room_ultra
to: "playing"
id: tv_playing
- platform: state
entity_id: switch.office_lamp_switch
to: "on"
id: working
- platform: sun
event: sunrise
offset: "-00:30:00"
@@ -75,6 +80,8 @@
{% set stacey_awake = is_state('person.stacey', 'home')
and is_state('binary_sensor.sleepnumber_carlo_stacey_is_in_bed', 'off') %}
{{ carlo_awake or stacey_awake }}
working_active: >-
{{ is_state('switch.office_lamp_switch', 'on') }}
target_kelvin: >-
{% set elevation = state_attr('sun.sun', 'elevation') | float(-90) %}
{% if elevation <= -2 %}
@@ -102,12 +109,13 @@
{{ is_state('group.family', 'home')
and is_state('input_boolean.guest_mode', 'off')
and not (tv_active | bool)
and not (working_active | bool)
and ((awake_home | bool) or is_state('light.sink', 'on'))
and (is_state('light.sink', 'on') or now().hour >= 4) }}
- choose:
- conditions:
- condition: template
value_template: "{{ tv_active | bool }}"
value_template: "{{ tv_active | bool or working_active | bool }}"
sequence:
- service: light.turn_off
target:

View File

@@ -59,7 +59,7 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this
| [telegram_bot.yaml](telegram_bot.yaml) | Legacy Telegram transport marker for BearClaw; the shared `joanna_send_telegram` helper now forwards through the codex_appliance direct Telegram API. | `rest_command.bearclaw_telegram_send`, `script.joanna_send_telegram` |
| [phynplus.yaml](phynplus.yaml) | Phyn shutoff automations with push + Activity feed + Repairs issues for leak events. | `valve.phyn_shutoff_valve`, `binary_sensor.phyn_leak_test_running`, `repairs.create` |
| [water_delivery.yaml](water_delivery.yaml) | ReadyRefresh delivery date helper with night-before + garage door Alexa reminders, plus helper-change audit logging and Telegram confirmations. | `input_datetime.water_delivery_date`, `script.send_to_logbook`, `script.joanna_send_telegram`, `notify.alexa_media_garage` |
| [vacation_mode.yaml](vacation_mode.yaml) | Auto-enable vacation mode after 24 hours away or no bed use, track sitter analytics/secure-house checks, and deliver Chromecast-first vacation briefings with a garage Alexa welcome. | `input_boolean.vacation_mode`, `input_boolean.house_sitter_present`, `sensor.vacation_house_sitter_*`, `group.garage_doors`, `lock.front_door`, `script.notify_engine`, `script.joanna_send_telegram` |
| [vacation_mode.yaml](vacation_mode.yaml) | Auto-enable vacation mode after 24 hours away or no bed use, track sitter analytics/secure-house checks, and deliver exact sitter-facing briefings with garage Alexa support. | `input_boolean.vacation_mode`, `input_boolean.house_sitter_present`, `input_datetime.vacation_house_sitter_*`, `sensor.vacation_house_sitter_*`, `group.garage_doors`, `lock.front_door`, `script.notify_engine`, `script.joanna_send_telegram` |
| [maintenance_log.yaml](maintenance_log.yaml) | Joanna maintenance webhook ingest for water softener salt with idempotent event handling, Activity feed logging, and recorder-backed helper history for long-term graphing. | `automation.maintenance_log_joanna_webhook_ingest`, `input_number.water_softener_salt_total_added_lb`, `counter.water_softener_salt_event_count`, `sensor.water_softener_salt_days_since_last_add` |
| [powerwall.yaml](powerwall.yaml) | Track Tesla Powerwall grid status, push live outage tracking to mobile targets, and shed loads automatically when off-grid (alerts include Activity feed + Repairs). | `binary_sensor.powerwall_grid_status`, `sensor.powerwall_*`, `script.notify_live_activity`, `repairs.create` |
| [tesla_model_y.yaml](tesla_model_y.yaml) | Remind the garage and parents to plug in the Model Y after low-battery arrivals and after 8 PM when it is home but not charging. | `sensor.spaceship_battery_level`, `switch.spaceship_charge`, `notify.alexa_media_garage`, `script.notify_engine` |

View File

@@ -137,10 +137,15 @@ switch:
- switch.pihole_secondary_container_2
- switch.poker_tracker_container
- switch.poker_tracker_container_2
- switch.portainer_agent_container
- switch.portainer_agent_container_2
- switch.portainer_container
- switch.portainer_container_2
- switch.postgres_webhooks_backup_container
- switch.postgres_webhooks_engine_container
- switch.postgres_webhooks_engine_container_2
- switch.rc_price_checker_container
- switch.rc_price_checker_container_2
- switch.redis_webhooks_engine_container
- switch.redis_webhooks_engine_container_2
- switch.rvtools_ppt_web_container
@@ -155,6 +160,7 @@ switch:
- switch.unifi_container_2
- switch.webhooks_engine_container
- switch.webhooks_engine_container_2
- switch.wordpress_db_backup_container
- switch.wordpress_db_container
- switch.wordpress_db_container_2
- switch.wordpress_wp_container

View File

@@ -9,7 +9,8 @@
# Related Issue: 793
# Notes: Vacation mode auto-enables after 24 hours of family absence or 24 hours without bed use while the family is away.
# Notes: General vacation speech uses Chromecast only; the garage Alexa welcome is the one local-device exception.
# Notes: Visit analytics come from native entity attributes plus recorder-backed sensors instead of extra helper entities.
# Notes: Visit analytics use recorder-backed visit counts plus arrival/departure helpers for accurate durations.
# Notes: Dorm zones are reported as away locations, not Bear Stone home.
######################################################################
input_boolean:
@@ -22,6 +23,25 @@ input_boolean:
icon: mdi:account-key
initial: off
input_datetime:
vacation_house_sitter_last_arrival:
name: Vacation House Sitter Last Arrival
has_date: true
has_time: true
vacation_house_sitter_last_departure:
name: Vacation House Sitter Last Departure
has_date: true
has_time: true
input_number:
vacation_house_sitter_last_visit_minutes:
name: Vacation House Sitter Last Visit Minutes
min: 0
max: 1440
step: 0.1
mode: box
unit_of_measurement: min
sensor:
- platform: history_stats
name: Vacation House Sitter Visit Count
@@ -51,38 +71,35 @@ template:
{% endif %}
last_arrival_at: >-
{% set vacation_start = as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) %}
{% set raw = state_attr('automation.vacation_mode_house_sitter_arrival', 'last_triggered') %}
{% set raw = states('input_datetime.vacation_house_sitter_last_arrival') %}
{% set ts = as_timestamp(raw, 0) %}
{% if ts >= vacation_start and ts > 0 %}
{{ as_local(raw).isoformat() }}
{% if is_state('input_boolean.vacation_mode', 'on') and ts >= vacation_start and ts > 0 %}
{{ as_local(as_datetime(raw)).isoformat() }}
{% else %}
none
{% endif %}
last_departure_at: >-
{% set vacation_start = as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) %}
{% set raw = state_attr('automation.vacation_mode_house_sitter_departure', 'last_triggered') %}
{% set raw = states('input_datetime.vacation_house_sitter_last_departure') %}
{% set ts = as_timestamp(raw, 0) %}
{% if ts >= vacation_start and ts > 0 %}
{{ as_local(raw).isoformat() }}
{% if is_state('input_boolean.vacation_mode', 'on') and ts >= vacation_start and ts > 0 %}
{{ as_local(as_datetime(raw)).isoformat() }}
{% else %}
none
{% endif %}
last_visit_minutes: >-
{% set vacation_start = as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) %}
{% set arrival = state_attr('automation.vacation_mode_house_sitter_arrival', 'last_triggered') %}
{% set departure = state_attr('automation.vacation_mode_house_sitter_departure', 'last_triggered') %}
{% set arrival_ts = as_timestamp(arrival, 0) %}
{% set departure_ts = as_timestamp(departure, 0) %}
{% if arrival_ts >= vacation_start and departure_ts >= arrival_ts %}
{{ ((departure_ts - arrival_ts) / 60) | round(1) }}
{% set departure_ts = as_timestamp(states('input_datetime.vacation_house_sitter_last_departure'), 0) %}
{% if is_state('input_boolean.vacation_mode', 'on') and departure_ts >= vacation_start %}
{{ states('input_number.vacation_house_sitter_last_visit_minutes') | float(0) }}
{% else %}
0
{% endif %}
hours_since_last_visit: >-
{% set vacation_start = as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) %}
{% set departure = state_attr('automation.vacation_mode_house_sitter_departure', 'last_triggered') %}
{% set departure = states('input_datetime.vacation_house_sitter_last_departure') %}
{% set departure_ts = as_timestamp(departure, 0) %}
{% if departure_ts >= vacation_start %}
{% if is_state('input_boolean.vacation_mode', 'on') and departure_ts >= vacation_start %}
{{ ((as_timestamp(now()) - departure_ts) / 3600) | round(1) }}
{% else %}
0
@@ -160,6 +177,7 @@ automation:
- platform: state
entity_id: group.family
to: 'home'
for: "00:02:00"
condition:
- condition: template
@@ -255,7 +273,7 @@ automation:
entry_delay: >-
{{ '00:05:00' if trigger.id == 'garage' else '00:02:00' }}
vacation_start_ts: "{{ as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) }}"
last_departure_raw: "{{ state_attr('automation.vacation_mode_house_sitter_departure', 'last_triggered') }}"
last_departure_raw: "{{ states('input_datetime.vacation_house_sitter_last_departure') }}"
last_departure_ts: "{{ as_timestamp(last_departure_raw, 0) }}"
visit_number: "{{ (states('sensor.vacation_house_sitter_visit_count') | int(0)) + 1 }}"
away_duration: >-
@@ -286,17 +304,57 @@ automation:
This is the first house-sitter visit for this vacation.
{% endif %}
carlo_location: >-
{% set person_state = states('person.carlo') %}
{% set place = states('sensor.carlo_place') %}
{{ place if place not in ['unknown', 'unavailable', 'none', ''] else states('person.carlo') }}
{% set label = place if place not in ['unknown', 'unavailable', 'none', ''] else person_state %}
{% if person_state == 'driving' or label.startswith('Driving') %}
driving near {{ label | replace('Driving near ', '') | replace('Driving', '') | trim }}
{% elif person_state == 'home' %}
at Bear Stone home
{% elif 'Dorm' in label %}
away at {{ label }}
{% else %}
at {{ label }}
{% endif %}
stacey_location: >-
{% set person_state = states('person.stacey') %}
{% set place = states('sensor.stacey_place') %}
{{ place if place not in ['unknown', 'unavailable', 'none', ''] else states('person.stacey') }}
{% set label = place if place not in ['unknown', 'unavailable', 'none', ''] else person_state %}
{% if person_state == 'driving' or label.startswith('Driving') %}
driving near {{ label | replace('Driving near ', '') | replace('Driving', '') | trim }}
{% elif person_state == 'home' %}
at Bear Stone home
{% elif 'Dorm' in label %}
away at {{ label }}
{% else %}
at {{ label }}
{% endif %}
justin_location: >-
{% set person_state = states('person.justin') %}
{% set place = states('sensor.justin_place') %}
{{ place if place not in ['unknown', 'unavailable', 'none', ''] else states('person.justin') }}
{% set label = place if place not in ['unknown', 'unavailable', 'none', ''] else person_state %}
{% if person_state == 'driving' or label.startswith('Driving') %}
driving near {{ label | replace('Driving near ', '') | replace('Driving', '') | trim }}
{% elif person_state == 'home' %}
at Bear Stone home
{% elif 'Dorm' in label %}
away at {{ label }}
{% else %}
at {{ label }}
{% endif %}
paige_location: >-
{% set person_state = states('person.paige') %}
{% set place = states('sensor.paige_place') %}
{{ place if place not in ['unknown', 'unavailable', 'none', ''] else states('person.paige') }}
{% set label = place if place not in ['unknown', 'unavailable', 'none', ''] else person_state %}
{% if person_state == 'driving' or label.startswith('Driving') %}
driving near {{ label | replace('Driving near ', '') | replace('Driving', '') | trim }}
{% elif person_state == 'home' %}
at Bear Stone home
{% elif 'Dorm' in label %}
away at {{ label }}
{% else %}
at {{ label }}
{% endif %}
garbage_message: >-
{% set day = now().strftime('%a') %}
{% if day in ['Tue', 'Sat'] %}
@@ -316,8 +374,8 @@ automation:
House sitter arrival detected through the {{ entry_label }}.
The family was last home {{ away_duration }} ago.
{{ visit_context }}
Carlo is at {{ carlo_location }}. Stacey is at {{ stacey_location }}.
Justin is at {{ justin_location }}. Paige is at {{ paige_location }}.
Carlo is {{ carlo_location }}. Stacey is {{ stacey_location }}.
Justin is {{ justin_location }}. Paige is {{ paige_location }}.
Please check Molly's food, water, and litter box.
{{ package_message }}
{{ garbage_message }}
@@ -341,6 +399,12 @@ automation:
entity_id:
- input_boolean.house_sitter_present
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.vacation_house_sitter_last_arrival
data:
timestamp: "{{ now().timestamp() }}"
- service: automation.trigger
target:
entity_id: automation.late_night_helper
@@ -376,6 +440,7 @@ automation:
- service: script.speech_processing
data:
media_player: media_player.livingroomcc
speech_direct: true
speech_message: "{{ arrival_message }}"
- alias: 'Vacation Mode Sitter Checklist Follow-Up'
@@ -411,6 +476,7 @@ automation:
- service: script.speech_processing
data:
media_player: media_player.livingroomcc
speech_direct: true
speech_message: "{{ checklist_message }}"
- alias: 'Vacation Mode House Sitter Departure'
@@ -442,12 +508,27 @@ automation:
exit_label: >-
{{ 'garage door' if trigger.id == 'garage' else 'front door' }}
visit_count: "{{ states('sensor.vacation_house_sitter_visit_count') | int(0) }}"
visit_minutes_numeric: >-
{% set seconds = (as_timestamp(now()) - as_timestamp(states.input_boolean.house_sitter_present.last_changed, 0)) | int(0) %}
{{ (seconds / 60) | round(1) }}
visit_duration: >-
{% set seconds = (as_timestamp(now()) - as_timestamp(states.input_boolean.house_sitter_present.last_changed, 0)) | int(0) %}
{% set minutes = (seconds // 60) | int(0) %}
{% set remainder = (seconds % 60) | int(0) %}
{{ minutes }} minute{{ 's' if minutes != 1 else '' }}{% if remainder > 0 %} and {{ remainder }} second{{ 's' if remainder != 1 else '' }}{% endif %}
- service: input_number.set_value
target:
entity_id: input_number.vacation_house_sitter_last_visit_minutes
data:
value: "{{ visit_minutes_numeric }}"
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.vacation_house_sitter_last_departure
data:
timestamp: "{{ now().timestamp() }}"
- service: homeassistant.turn_off
target:
entity_id: input_boolean.house_sitter_present
@@ -553,7 +634,7 @@ automation:
- condition: template
value_template: >-
{% set vacation_start = as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) %}
{% set last_departure = as_timestamp(state_attr('automation.vacation_mode_house_sitter_departure', 'last_triggered'), 0) %}
{% set last_departure = as_timestamp(states('input_datetime.vacation_house_sitter_last_departure'), 0) %}
{% set baseline = last_departure if last_departure >= vacation_start else vacation_start %}
{{ is_state('input_boolean.vacation_mode', 'on')
and is_state('input_boolean.house_sitter_present', 'off')
@@ -567,7 +648,7 @@ automation:
- variables:
visit_count: "{{ states('sensor.vacation_house_sitter_visit_count') | int(0) }}"
vacation_start: "{{ as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) }}"
last_departure: "{{ as_timestamp(state_attr('automation.vacation_mode_house_sitter_departure', 'last_triggered'), 0) }}"
last_departure: "{{ as_timestamp(states('input_datetime.vacation_house_sitter_last_departure'), 0) }}"
baseline: >-
{{ last_departure if (last_departure | float(0)) >= (vacation_start | float(0)) else vacation_start }}
hours_since: "{{ ((as_timestamp(now()) - (baseline | float(0))) / 3600) | round(1) }}"
@@ -677,6 +758,7 @@ automation:
- service: script.speech_processing
data:
media_player: media_player.livingroomcc
speech_direct: true
speech_message: "{{ hint_message }}"
- delay: "00:20:00"

View File

@@ -6,7 +6,7 @@
# Recorder Configuration - database retention and exclusions
# Stores HA history while purging noise and controlling DB size.
# -------------------------------------------------------------------
# Notes: Keeps 180 days (1/2 year); excludes vcloudinfo pings, noisy connectivity telemetry, countdown-style alarm helpers, MariaDB snapshot helpers, raw Glances host telemetry, and other high-churn entities; MariaDB via recorder_db_url.
# Notes: Keeps 180 days (1/2 year); excludes vcloudinfo pings, noisy connectivity telemetry, countdown-style alarm helpers, low-value script/button/scene history, MariaDB snapshot helpers, raw Docker/Proxmox/Glances host telemetry, PoE live power, and other high-churn entities; MariaDB via recorder_db_url.
######################################################################
db_url: !secret recorder_db_url
purge_keep_days: 180
@@ -14,6 +14,7 @@ auto_purge: true
commit_interval: 30
exclude:
domains:
- button
- camera
- device_tracker
- event
@@ -21,6 +22,8 @@ exclude:
- image
- media_player
- persistent_notification
- scene
- script
- sun
- update
- zone
@@ -57,12 +60,68 @@ exclude:
- sensor.*_wifi_signal
- sensor.*_wifi_signal_strength
- sensor.*_wake_alarm_minutes
- sensor.*_cpu_usage_total*
- sensor.*_memory_usage*
- sensor.*_temperature_state
- sensor.*_humidity_state
- sensor.*_last_seen*
- sensor.192_168_10_17_*
- sensor.docker14_*
- sensor.docker69_*
- sensor.alarm_panel_*_free_memory
- sensor.alarm_panel_*_internal_storage_free_space
- sensor.joanna_minutes_since_*
- sensor.node_proxmox*_containers_running
- sensor.node_proxmox*_cpu_used
- sensor.node_proxmox*_disk_used_percentage
- sensor.node_proxmox*_memory_free
- sensor.node_proxmox*_memory_used
- sensor.node_proxmox*_memory_used_percentage
- sensor.node_proxmox*_total_updates
- sensor.node_proxmox*_virtual_machines_running
- sensor.poe_*_poe_power
- sensor.proxmox1_cpu_load
- sensor.proxmox1_cpu_usage
- sensor.proxmox1_disk_free
- sensor.proxmox1_disk_usage
- sensor.proxmox1_disk_used
- sensor.proxmox1_*_disk_read
- sensor.proxmox1_*_disk_write
- sensor.proxmox1_*_rx
- sensor.proxmox1_*_tx
- sensor.proxmox1_memory_free
- sensor.proxmox1_memory_usage
- sensor.proxmox1_memory_use
- sensor.proxmox1_processor_fan_*
- sensor.proxmox1_running
- sensor.proxmox1_sleeping
- sensor.proxmox1_swap_*
- sensor.proxmox1_threads
- sensor.proxmox1_total
- sensor.proxmox2_cpu_load
- sensor.proxmox2_cpu_usage
- sensor.proxmox2_disk_free
- sensor.proxmox2_disk_usage
- sensor.proxmox2_disk_used
- sensor.proxmox2_*_disk_read
- sensor.proxmox2_*_disk_write
- sensor.proxmox2_*_rx
- sensor.proxmox2_*_tx
- sensor.proxmox2_memory_free
- sensor.proxmox2_memory_usage
- sensor.proxmox2_memory_use
- sensor.proxmox2_processor_fan_*
- sensor.proxmox2_running
- sensor.proxmox2_sleeping
- sensor.proxmox2_swap_*
- sensor.proxmox2_threads
- sensor.proxmox2_total
- sensor.qemu_*_cpu_used
- sensor.qemu_*_disk_used_percentage
- sensor.qemu_*_memory_free
- sensor.qemu_*_memory_used
- sensor.qemu_*_memory_used_percentage
- sensor.storage_proxmox*_*_disk_used_percentage
- switch.*_do_not_disturb_*
- switch.*_repeat_switch
- input_text.l10s_vacuum_*

View File

@@ -31,7 +31,7 @@ Reusable scripts that other automations call for notifications, lighting, safety
| [notify_live_activity.yaml](notify_live_activity.yaml) | Shared helper for tagged live activity/live update pushes and clear commands. |
| [send_to_logbook.yaml](send_to_logbook.yaml) | Generic `logbook.log` helper for Activity feed entries (Issue #1550). |
| [joanna_dispatch.yaml](joanna_dispatch.yaml) | Shared AGENT engineer dispatch contract that routes HA-detected issues into Joanna/BearClaw remediation. |
| [speech_engine.yaml](speech_engine.yaml) | TTS/announcement orchestration with templated speech; speech processing also routes garage Echo announcements and office Echo announcements when the office lamp switch indicates active PC work. |
| [speech_engine.yaml](speech_engine.yaml) | TTS/announcement orchestration with templated speech; speech processing can bypass LLM rewriting for exact messages and also routes garage/office Echo announcements. |
| [monthly_color_scene.yaml](monthly_color_scene.yaml) | Seasonal lighting scenes used across automations. |
| [interior_off.yaml](interior_off.yaml) | One-call "all interior lights off" helper. |

View File

@@ -9,6 +9,7 @@
# Related Issue: 798
# Notes: Operates only when family/guest/vacation and speech notification
# guards allow it, with time-aware volume.
# Notes: Set `speech_direct: true` for exact visitor-facing announcements that should not be rewritten by the LLM.
# Notes: Garage Echo is an always-on announcement target. Office Echo is
# added when switch.office_lamp_switch is on, which tracks active PC work.
######################################################################
@@ -20,6 +21,11 @@ speech_processing:
- event: openai_instructions_sent
event_data:
instructions: "{{ speech_message | striptags }}"
- variables:
direct_speech: "{{ speech_direct | default(false) | bool }}"
routed_media_players: "{{ media_player | string | lower }}"
speech_response: "{{ speech_message | striptags | trim }}"
- condition: and
conditions:
@@ -67,16 +73,20 @@ speech_processing:
0.2
{% endif %}
- service: conversation.process
data:
agent_id: conversation.openai_conversation
text: >-
{{ speech_message }}
response_variable: agent
- choose:
- conditions:
- condition: template
value_template: "{{ not direct_speech }}"
sequence:
- service: conversation.process
data:
agent_id: conversation.openai_conversation
text: >-
{{ speech_message }}
response_variable: agent
- variables:
speech_response: "{{ agent.response.speech.plain.speech }}"
routed_media_players: "{{ media_player | string | lower }}"
- variables:
speech_response: "{{ agent.response.speech.plain.speech }}"
- service: tts.cloud_say
data:

View File

@@ -7,6 +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: Dorm zones are away from Bear Stone; only person state `home`
# means someone is physically home at this house.
######################################################################
@@ -201,6 +203,8 @@
{% 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 %}
@@ -208,9 +212,13 @@
{% 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 %}
{{ 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 }}: {{ location_label }}{% if seconds >= 60 %} for {{ duration }}{% endif %}
{{ name }}: away at {{ location_label }}{% if seconds >= 60 %} for {{ duration }}{% endif %}
{% endif %}
{% endif %}
{% endmacro %}
@@ -239,6 +247,10 @@
{% set time = current_date.strftime('%I:%M %p') %}
[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.]
[Resident: Location:
- {{ friendly_location('person.carlo', 'sensor.carlo_place', 'Carlo') }}
- {{ friendly_location('person.stacey', 'sensor.stacey_place', 'Stacey') }}