diff --git a/README.md b/README.md index d8f02fe7..deeae7a3 100755 --- a/README.md +++ b/README.md @@ -18,10 +18,10 @@ Live, personal Home Assistant configuration shared for **browsing and inspiration**. This is not a turnkey clone-and-run setup; borrow ideas, adapt entity IDs/secrets, and test in your own environment. -### Latest video: Home Assistant Leak Detection Automations -[![Home Assistant Leak Detection Automations](https://www.vcloudinfo.com/wp-content/uploads/2026/06/maxresdefault.jpg)](https://youtu.be/xbhgWnomFYI) +### Latest video: Track Codex Resets in Home Assistant Before They Expire +[![Track Codex Resets in Home Assistant Before They Expire](https://www.vcloudinfo.com/wp-content/uploads/2026/06/codex-resets-home-assistant-thumbnail.png)](https://youtu.be/7wKhtrvtyiI) -This walkthrough breaks down the water-leak response loop I use in Home Assistant: a shutoff valve state, a maintenance guard, Activity Feed context, Repairs tracking, and critical phone recovery actions. [Watch the video](https://youtu.be/xbhgWnomFYI), read the [companion blog post](https://www.vcloudinfo.com/2026/06/home-assistant-leak-detection-automations.html), browse the YAML in [config/packages/phynplus.yaml](config/packages/phynplus.yaml), and see the older Phyn Plus backstory in the [original write-up](https://www.vcloudinfo.com/2020/05/phyn-plus-smart-water-shutoff-device.html). +This walkthrough shows how I track Codex reset credits in Home Assistant: a reset-credit JSON feed, REST/template sensors, a dashboard card with expiration dates, and a Repair that stays open while any reset is within 7 days of expiring. [Watch the video](https://youtu.be/7wKhtrvtyiI), read the [companion blog post](https://www.vcloudinfo.com/2026/06/track-codex-resets-home-assistant.html), browse the YAML in [config/packages/bearclaw.yaml](config/packages/bearclaw.yaml), and see the dashboard source in [config/dashboards/infrastructure](config/dashboards/infrastructure). ### Quick navigation - You are here: `/` (root repo guide) @@ -48,6 +48,7 @@ This walkthrough breaks down the water-leak response loop I use in Home Assistan - Alarm and perimeter monitoring: [config/packages/alarm.yaml](config/packages/alarm.yaml) - Garage routines and entry lighting: [config/packages/garadget.yaml](config/packages/garadget.yaml), [config/automation/garage_entry_light.yaml](config/automation/garage_entry_light.yaml), [video walkthrough](https://youtu.be/wFO0H5zgnzk) - LLM Vision package reminders: [config/packages/llmvision.yaml](config/packages/llmvision.yaml), [video walkthrough](https://youtu.be/nAhCezFetvI) +- Codex reset-credit tracking: [config/packages/bearclaw.yaml](config/packages/bearclaw.yaml), [config/dashboards/infrastructure](config/dashboards/infrastructure), [video walkthrough](https://youtu.be/7wKhtrvtyiI) - Water leak response loop: [config/packages/phynplus.yaml](config/packages/phynplus.yaml), [video walkthrough](https://youtu.be/xbhgWnomFYI) - Bedroom camera kiosk tablet: [config/packages/kiosk_tablet.yaml](config/packages/kiosk_tablet.yaml), [config/dashboards/kiosk](config/dashboards/kiosk), [video walkthrough](https://youtu.be/ChgEu0IDWzc) - Holiday/front-of-house color scenes: [config/scene/monthly_colors.yaml](config/scene/monthly_colors.yaml), [config/script/monthly_color_scene.yaml](config/script/monthly_color_scene.yaml) diff --git a/config/README.md b/config/README.md index 366f2bed..0d9b58db 100755 --- a/config/README.md +++ b/config/README.md @@ -51,7 +51,7 @@ Live view of the `config/` directory my production Home Assistant instance loads | Dashboards & Media | UI chrome, floorplans, sound bites, and automation assets. | [dashboards/kiosk](dashboards/kiosk), [www/custom_ui/floorplan/images/branding/Bear-Stone-Docker-Diagram.jpg](www/custom_ui/floorplan/images/branding/Bear-Stone-Docker-Diagram.jpg), [media/](media) | | Seasonal Audio | Cuckoo clock with Halloween and Christmas sound packs. | [automation/System/CucKoo_Clock.yaml](automation/System/CucKoo_Clock.yaml) | -The latest walkthrough shows a practical leak-detection response loop in Home Assistant: [video](https://youtu.be/xbhgWnomFYI), [companion post](https://www.vcloudinfo.com/2026/06/home-assistant-leak-detection-automations.html), YAML in [packages/phynplus.yaml](packages/phynplus.yaml), and the original Phyn Plus backstory in the [older write-up](https://www.vcloudinfo.com/2020/05/phyn-plus-smart-water-shutoff-device.html). The earlier kiosk and LLM Vision walkthroughs are still available with examples in [packages/kiosk_tablet.yaml](packages/kiosk_tablet.yaml) and [packages/llmvision.yaml](packages/llmvision.yaml). +The latest walkthrough shows Codex reset-credit tracking in Home Assistant: [video](https://youtu.be/7wKhtrvtyiI), [companion post](https://www.vcloudinfo.com/2026/06/track-codex-resets-home-assistant.html), YAML in [packages/bearclaw.yaml](packages/bearclaw.yaml), and the dashboard source in [dashboards/infrastructure](dashboards/infrastructure). The earlier leak-detection, kiosk, and LLM Vision walkthroughs are still available with examples in [packages/phynplus.yaml](packages/phynplus.yaml), [packages/kiosk_tablet.yaml](packages/kiosk_tablet.yaml), and [packages/llmvision.yaml](packages/llmvision.yaml). ### Gear tied to these automations (affiliate links) Only including devices that have active references in the files above. diff --git a/config/dashboards/infrastructure/partials/joanna_sections.yaml b/config/dashboards/infrastructure/partials/joanna_sections.yaml index 0f85cfb2..99773301 100644 --- a/config/dashboards/infrastructure/partials/joanna_sections.yaml +++ b/config/dashboards/infrastructure/partials/joanna_sections.yaml @@ -39,11 +39,6 @@ entity: sensor.codex_reset_credits_available name: Resets icon: mdi:backup-restore - - type: custom:button-card - template: bearstone_infra_kpi - entity: sensor.codex_reset_credits_expiring_soon - name: Reset Warnings - icon: mdi:alert-clock - type: custom:button-card template: bearstone_infra_kpi entity: sensor.joanna_all_dispatches_24h @@ -62,7 +57,7 @@ - type: grid column_span: 4 - columns: 2 + columns: 3 square: false cards: - type: custom:vertical-stack-in-card @@ -184,11 +179,6 @@ return `${enabled ? 'enabled' : 'disabled'} | ${age} min ago`; ]]] -- type: grid - column_span: 4 - columns: 1 - square: false - cards: - type: custom:vertical-stack-in-card card_mod: style: !include /config/dashboards/infrastructure/card_mod/infra_panel.yaml diff --git a/config/dashboards/infrastructure/views/06_joanna.yaml b/config/dashboards/infrastructure/views/06_joanna.yaml index d630f8fb..27f0af79 100644 --- a/config/dashboards/infrastructure/views/06_joanna.yaml +++ b/config/dashboards/infrastructure/views/06_joanna.yaml @@ -8,6 +8,8 @@ # ------------------------------------------------------------------- # Notes: Uses telemetry from /api/bearclaw/status ingested by bearclaw.yaml. # Notes: Shows Codex reset-credit expiry data from the codexUsage status field. +# Notes: Codex reset walkthrough: https://youtu.be/7wKhtrvtyiI +# Notes: Codex reset companion post: https://www.vcloudinfo.com/2026/06/track-codex-resets-home-assistant.html ###################################################################### type: sections diff --git a/config/packages/README.md b/config/packages/README.md index 277c3b69..9fb75687 100755 --- a/config/packages/README.md +++ b/config/packages/README.md @@ -59,11 +59,11 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this | [processmonitor.yaml](processmonitor.yaml) | Root filesystem disk-pressure monitoring with immediate digest/logbook notes at 80%, Joanna review after 10 minutes above 80%, and delayed phone alerts only if the issue stays unresolved after dispatch. | `sensor.disk_use_percent`, `repairs.create`, `script.joanna_dispatch`, `tts.clear_cache` | | [tugtainer_updates.yaml](tugtainer_updates.yaml) | Tugtainer container update notifications via webhook + persistent alerts, plus event-based Joanna dispatch when reports include `### Available:` (24h cooldown via `mode: single` + delay, no new helpers). | `persistent_notification.create`, `event: tugtainer_available_detected`, `script.joanna_dispatch`, `input_datetime.tugtainer_last_update` | | [printer.yaml](printer.yaml) | Epson ink watchdog with one-day and one-week mobile snooze actions for low-ink reminders. | `input_datetime.printer_ink_snooze_until`, `sensor.epson_*`, mobile app action events | -| [bearclaw.yaml](bearclaw.yaml) | Joanna/BearClaw bridge automations that forward Telegram commands to codex_appliance, include LLM-first routing context for freeform text, relay replies back, ingest `/api/bearclaw/status` telemetry, and expose dispatch, QMD/memory-index, plus Codex reset-credit expiry sensors and Repairs for Infrastructure dashboards. | `rest_command.bearclaw_*`, `sensor.bearclaw_status_telemetry`, `sensor.joanna_*`, `sensor.codex_reset_*`, `binary_sensor.joanna_*`, `binary_sensor.codex_reset_credit_expiring_soon`, `automation.bearclaw_*`, `automation.codex_reset_credit_expiry_repair`, `repairs.create`, `repairs.remove`, `script.send_to_logbook` | +| [bearclaw.yaml](bearclaw.yaml) | Joanna/BearClaw bridge automations that forward Telegram commands to codex_appliance, include LLM-first routing context for freeform text, relay replies back, ingest `/api/bearclaw/status` telemetry, and expose dispatch, QMD/memory-index, plus Codex reset-credit expiry sensors and Repairs for Infrastructure dashboards; see the [Codex reset tracking video](https://youtu.be/7wKhtrvtyiI) and [companion post](https://www.vcloudinfo.com/2026/06/track-codex-resets-home-assistant.html). | `rest_command.bearclaw_*`, `sensor.bearclaw_status_telemetry`, `sensor.joanna_*`, `sensor.codex_reset_*`, `binary_sensor.joanna_*`, `binary_sensor.codex_reset_credit_expiring_soon`, `automation.bearclaw_*`, `automation.codex_reset_credit_expiry_repair`, `repairs.create`, `repairs.remove`, `script.send_to_logbook` | | [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 leak-test guard, Activity Feed context, Repairs tracking, and critical push recovery when the valve closes; see the [leak detection automation video](https://youtu.be/xbhgWnomFYI). | `valve.phyn_shutoff_valve`, `binary_sensor.phyn_leak_test_running`, `script.phyn_send_actionable_leak_notification`, `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, stale-visit timeout protection, 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.vacation_house_sitter_clear_presence`, `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, stale-visit timeout protection, deliver sitter-facing briefings, and send 10 AM/10 PM house digests with Powerwall/security/backup status plus Joanna review. | `input_boolean.vacation_mode`, `input_boolean.house_sitter_present`, `input_datetime.vacation_house_sitter_*`, `input_datetime.vacation_house_status_digest_last_sent`, `sensor.vacation_house_sitter_*`, `binary_sensor.powerwall_grid_status`, `sensor.powerwall_charge`, `group.garage_doors`, `lock.front_door`, `script.vacation_house_sitter_clear_presence`, `script.vacation_house_status_digest`, `script.notify_engine`, `rest_command.bearclaw_command`, `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` | | [kiosk_tablet.yaml](kiosk_tablet.yaml) | Keeps the bedroom Fully Kiosk Fire tablet pinned to the dedicated camera kiosk dashboard when the page or foreground app drifts; normal wake events only restore brightness/focus. See the [video walkthrough](https://youtu.be/ChgEu0IDWzc). | `sensor.alarm_panel_1_current_page`, `sensor.alarm_panel_1_foreground_app`, `button.alarm_panel_1_bring_to_foreground`, `button.alarm_panel_1_load_start_url` | | [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` | @@ -99,6 +99,7 @@ When a package has a dedicated blog post or video, I link it right inside the YA | Package | Why read/watch | Deep dive links | | --- | --- | --- | +| [bearclaw.yaml](bearclaw.yaml) + [Infrastructure dashboard](../dashboards/infrastructure) | Codex reset-credit expiry tracking with REST telemetry, template sensors, dashboard cards, and Repairs that stay open until the reset clears. | [Video walkthrough](https://youtu.be/7wKhtrvtyiI) · [Companion post](https://www.vcloudinfo.com/2026/06/track-codex-resets-home-assistant.html) | | [finance.yaml](finance.yaml) | Custom Yahoo Finance integration overview and setup notes. | [Blog](https://www.vcloudinfo.com/2020/10/how-to-track-stocks-in-home-assistant-using-a-custom-component.html) | | [garadget.yaml](garadget.yaml) | Garage arrival hub with auto-open guardrails, entry prompts, wind alerts, nighttime reminders, camera context, and the older MQTT/token setup notes. | [Video walkthrough](https://youtu.be/wFO0H5zgnzk) · [Companion post](https://www.vcloudinfo.com/2026/05/home-assistant-garage-automations-arrival-alerts-tesla.html) · [Blog: Integration guide](https://www.vcloudinfo.com/2019/03/how-to-add-garadget-to-home-assistant.html) · [Blog: Token fix](https://www.vcloudinfo.com/2020/05/fixing-garadget-in-home-assistant.html) | | [garage_entry_light.yaml](../automation/garage_entry_light.yaml) | Simple door-open and door-closed hallway lighting pattern from the garage walkthrough. | [Video walkthrough](https://youtu.be/wFO0H5zgnzk) · [Companion post](https://www.vcloudinfo.com/2026/05/home-assistant-garage-automations-arrival-alerts-tesla.html) | @@ -110,7 +111,7 @@ When a package has a dedicated blog post or video, I link it right inside the YA | [lightning.yaml](lightning.yaml) | Blitzortung detector wiring, strike alerts, and snooze workflow. | [Blog](https://www.vcloudinfo.com/2020/08/adding-a-lightning-sensor-to-home-assistant.html) | | [phynplus.yaml](phynplus.yaml) | Leak-detection response loop with valve state, maintenance guard, Activity Feed context, Repairs tracking, and critical push recovery. | [Video walkthrough](https://youtu.be/xbhgWnomFYI) · [Companion post](https://www.vcloudinfo.com/2026/06/home-assistant-leak-detection-automations.html) · [Original Phyn Plus post](https://www.vcloudinfo.com/2020/05/phyn-plus-smart-water-shutoff-device.html) | | [powerwall.yaml](powerwall.yaml) | Monitoring Tesla Powerwall health + what to automate when the grid drops. | [Blog](https://www.vcloudinfo.com/2018/01/going-green-to-save-some-green-in-2018.html) | -| [vacation_mode.yaml](vacation_mode.yaml) | Sustained-away Vacation Mode, house-sitter visit tracking, reminders, missed-visit alerts, and secure-house checks. | [Video walkthrough](https://youtu.be/15kRcFaVV2Y) · [Blog](https://www.vcloudinfo.com/2026/05/home-assistant-vacation-mode-house-sitter-automation.html) | +| [vacation_mode.yaml](vacation_mode.yaml) | Sustained-away Vacation Mode, house-sitter visit tracking, reminders, missed-visit alerts, secure-house checks, and vacation house digests that keep Powerwall status visible. | [Video walkthrough](https://youtu.be/15kRcFaVV2Y) · [Blog](https://www.vcloudinfo.com/2026/05/home-assistant-vacation-mode-house-sitter-automation.html) | | [vacuum.yaml](vacuum.yaml) | Dreame away-only cleaning, room queues, sweep/mop phases, Alexa one-off room commands, and rescue notifications. | [Video walkthrough](https://youtu.be/KKOWSKuF5jA) · [Companion post](https://www.vcloudinfo.com/2026/05/home-assistant-vacuum-automations-dreame-2026.html) · [Older Neato post](https://www.vcloudinfo.com/2020/05/home-assistant-neato-vacuum-automation.html) | | [pihole_ha.yaml](pihole_ha.yaml) | Sync Pi-hole blocking state across HA DNS nodes. | | | [grafana.yaml.disabled](grafana.yaml.disabled) | Rendering Grafana dashboards to images for Lovelace and social posts. | [Blog](https://www.vcloudinfo.com/2018/01/going-green-to-save-some-green-in-2018.html) · [Blog](https://www.vcloudinfo.com/2018/09/re-installing-tesla-solar-panels-again.html) · [Video](https://youtu.be/BartadUzGOA) | diff --git a/config/packages/bearclaw.yaml b/config/packages/bearclaw.yaml index 67073783..34b29da9 100644 --- a/config/packages/bearclaw.yaml +++ b/config/packages/bearclaw.yaml @@ -14,6 +14,8 @@ # Notes: The callback webhook writes JOANNA activity entries to logbook for traceability and optional HA alerts. # Notes: Status telemetry polling expects !secret bearclaw_status_url (token header stays !secret bearclaw_token). # Notes: Codex reset-credit expiry telemetry is sourced from the appliance `codexUsage` status field. +# Notes: Codex reset walkthrough: https://youtu.be/7wKhtrvtyiI +# Notes: Codex reset companion post: https://www.vcloudinfo.com/2026/06/track-codex-resets-home-assistant.html # Notes: Nightly Duplicati verification calls a codex_appliance admin endpoint and returns structured health to HA via response_variable. # Notes: v2 intake is the primary HA contract; legacy command/ingest routes remain appliance-side shims. # Notes: Command payload supports async_only for automation-first queueing when immediate inline handling is not required. @@ -504,6 +506,25 @@ automation: topic: JOANNA message: "{{ status | upper }}: {{ logbook_message }}" - choose: + - conditions: + - condition: template + value_template: >- + {{ source == 'home_assistant_automation.vacation_house_status_digest' + and status == 'completed' }} + sequence: + - service: script.notify_engine + data: + title: Vacation digest review + value1: >- + {% set compact = (message if message | trim != '' else summary) | replace('\r', ' ') | replace('\n', ' ') | trim %} + {% if compact | length > 420 %} + {{ compact[:417] ~ '...' }} + {% else %} + {{ compact }} + {% endif %} + who: carlo + group: vacation + level: active - conditions: - condition: template value_template: "{{ severity in ['warning', 'error', 'critical'] or status in ['failed', 'canceled'] }}" diff --git a/config/packages/vacation_mode.yaml b/config/packages/vacation_mode.yaml index 2e7e2c8e..625733c1 100644 --- a/config/packages/vacation_mode.yaml +++ b/config/packages/vacation_mode.yaml @@ -7,12 +7,16 @@ # Detects long absences, tracks sitter visits, and delivers vacation-specific reminders. # ------------------------------------------------------------------- # Related Issue: 793 +# Related Issue: 1791 +# Related Issue: 1792 # 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 use recorder-backed visit counts plus arrival/departure helpers for accurate durations. # Notes: Dorm zones are reported as away locations, not Bear Stone home. # Notes: Recent-departure lockout and a 3-hour stale-visit timeout prevent missed close edges from creating inflated visit durations. # Notes: Missed sitter alerts include 2-day and 3-day snooze actions that clear after a visit. +# Notes: 10 AM and 10 PM house digests send lock-screen pushes and dispatch a richer snapshot to Joanna for vacation-mode review. +# Notes: Powerwall/grid status is always included in vacation digests because power events are high signal. # Video: https://youtu.be/15kRcFaVV2Y # Blog: https://www.vcloudinfo.com/2026/05/home-assistant-vacation-mode-house-sitter-automation.html # Snooze video: https://youtu.be/y47KSflS1aw @@ -42,6 +46,10 @@ input_datetime: name: Vacation House Sitter Missed Visit Snooze Until has_date: true has_time: true + vacation_house_status_digest_last_sent: + name: Vacation House Status Digest Last Sent + has_date: true + has_time: true input_number: vacation_house_sitter_last_visit_minutes: @@ -80,6 +88,235 @@ script: target: entity_id: input_boolean.house_sitter_present + vacation_house_status_digest: + alias: Vacation House Status Digest + mode: queued + fields: + digest_mode: + description: Digest window label, usually morning or night. + example: morning + sequence: + - variables: + digest_mode_value: "{{ digest_mode | default('morning', true) | lower }}" + - variables: + digest_label: "{{ 'Night' if digest_mode_value == 'night' else 'Morning' }}" + last_digest_ts: "{{ as_timestamp(states('input_datetime.vacation_house_status_digest_last_sent'), 0) }}" + vacation_started_ts: "{{ as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) }}" + vacation_duration: >- + {% set started = as_timestamp(states.input_boolean.vacation_mode.last_changed, 0) %} + {% if is_state('input_boolean.vacation_mode', 'on') and started > 0 %} + {% set hours = ((as_timestamp(now()) - started) / 3600) | int(0) %} + {% set days = (hours // 24) | int(0) %} + {% set remaining_hours = (hours % 24) | int(0) %} + {{ days ~ 'd ' ~ remaining_hours ~ 'h' if days > 0 else remaining_hours ~ 'h' }} + {% else %} + inactive + {% endif %} + sitter_summary: >- + {% set visit_count = states('sensor.vacation_house_sitter_visit_count') | int(0) %} + {% set hours_since = state_attr('sensor.vacation_house_sitter_analytics', 'hours_since_last_visit') | float(0) %} + {% if is_state('input_boolean.house_sitter_present', 'on') %} + Sitter is currently at the house. + {% elif visit_count > 0 %} + Sitter visits: {{ visit_count }}; last visit {{ hours_since | round(1) }}h ago. + {% else %} + No sitter visit recorded yet this vacation. + {% endif %} + powerwall_grid_label: >- + {% set grid = states('binary_sensor.powerwall_grid_status') %} + {% if grid == 'on' %} + grid up + {% elif grid == 'off' %} + GRID DOWN + {% else %} + grid {{ grid }} + {% endif %} + powerwall_charge_label: >- + {% set charge = states('sensor.powerwall_charge') %} + {% if charge in ['unknown', 'unavailable', 'none', ''] %} + battery unavailable + {% else %} + battery {{ charge | float(0) | round(0) | int(0) }}% + {% endif %} + powerwall_grid_changed_ts: >- + {% set entity = states.binary_sensor.powerwall_grid_status if states.binary_sensor.powerwall_grid_status is defined else none %} + {{ as_timestamp(entity.last_changed, 0) if entity is not none else 0 }} + powerwall_recent_event: >- + {% set changed = powerwall_grid_changed_ts | float(0) %} + {{ last_digest_ts | float(0) > 0 and changed > last_digest_ts | float(0) }} + powerwall_summary: >- + {% set summary = 'Powerwall: ' ~ powerwall_grid_label | trim ~ ', ' ~ powerwall_charge_label | trim ~ '.' %} + {% if powerwall_recent_event | bool(false) %} + {{ summary }} Grid status changed since the last digest at {{ (powerwall_grid_changed_ts | float(0)) | timestamp_custom('%H:%M', true) }}. + {% else %} + {{ summary }} + {% endif %} + powerwall_issues: >- + {% set ns = namespace(items=[]) %} + {% set charge = states('sensor.powerwall_charge') %} + {% if is_state('binary_sensor.powerwall_grid_status', 'off') %} + {% set ns.items = ns.items + ['grid is down'] %} + {% endif %} + {% if charge in ['unknown', 'unavailable', 'none', ''] %} + {% set ns.items = ns.items + ['Powerwall charge unavailable'] %} + {% elif charge | float(100) < 60 %} + {% set ns.items = ns.items + ['Powerwall charge ' ~ (charge | float(0) | round(0) | int(0)) ~ '%'] %} + {% endif %} + {{ ns.items | join('; ') if ns.items | count > 0 else 'none' }} + security_issues: >- + {% set ns = namespace(items=[]) %} + {% if states('lock.front_door') != 'locked' %} + {% set ns.items = ns.items + ['front door ' ~ states('lock.front_door')] %} + {% endif %} + {% if states('group.locks') != 'locked' %} + {% set ns.items = ns.items + ['locks ' ~ states('group.locks')] %} + {% endif %} + {% if states('group.garage_doors') not in ['closed', 'off'] %} + {% set ns.items = ns.items + ['garage ' ~ states('group.garage_doors')] %} + {% endif %} + {% if states('group.entry_points') not in ['off', 'closed'] %} + {% set ns.items = ns.items + ['entry points ' ~ states('group.entry_points')] %} + {% endif %} + {{ ns.items | join('; ') if ns.items | count > 0 else 'none' }} + security_summary: >- + {% if security_issues == 'none' %} + Secure: locks locked, garage closed, entry points closed. + {% else %} + Needs security attention: {{ security_issues }}. + {% endif %} + climate_summary: >- + {% set down_temp = state_attr('climate.downstairs', 'current_temperature') %} + {% set up_temp = state_attr('climate.upstairs', 'current_temperature') %} + Climate: downstairs {{ down_temp if down_temp is not none else states('climate.downstairs') }}, upstairs {{ up_temp if up_temp is not none else states('climate.upstairs') }}. + safety_issues: >- + {% set ns = namespace(items=[]) %} + {% set fridge = states('sensor.refrigerator_fridge_temp') %} + {% set freezer = states('sensor.refrigerator_freezer_temp') %} + {% set flow = states('sensor.phyn_water_flowing') %} + {% if states('valve.phyn_shutoff_valve') != 'open' %} + {% set ns.items = ns.items + ['Phyn valve ' ~ states('valve.phyn_shutoff_valve')] %} + {% endif %} + {% if flow in ['unknown', 'unavailable', 'none', ''] %} + {% set ns.items = ns.items + ['water telemetry ' ~ flow] %} + {% elif flow in ['on', 'true'] or flow | float(0) > 0 %} + {% set ns.items = ns.items + ['water flowing ' ~ flow] %} + {% endif %} + {% if is_state('binary_sensor.refrigerator_door_open', 'on') %} + {% set ns.items = ns.items + ['refrigerator door open'] %} + {% endif %} + {% if fridge in ['unknown', 'unavailable', 'none', ''] and freezer in ['unknown', 'unavailable', 'none', ''] %} + {% set ns.items = ns.items + ['refrigerator telemetry unavailable'] %} + {% endif %} + {% if fridge not in ['unknown', 'unavailable', 'none', ''] and fridge | float(0) > 45 %} + {% set ns.items = ns.items + ['fridge ' ~ (fridge | float(0) | round(1)) ~ 'F'] %} + {% endif %} + {% if freezer not in ['unknown', 'unavailable', 'none', ''] and freezer | float(0) > 15 %} + {% set ns.items = ns.items + ['freezer ' ~ (freezer | float(0) | round(1)) ~ 'F'] %} + {% endif %} + {% if is_state('binary_sensor.front_door_packages_present', 'on') %} + {% set ns.items = ns.items + ['package at front door'] %} + {% endif %} + {{ ns.items | join('; ') if ns.items | count > 0 else 'none' }} + infra_issues: >- + {% set ns = namespace(items=[]) %} + {% if is_state('binary_sensor.mqtt_broker_problem', 'on') %} + {% set ns.items = ns.items + ['MQTT broker problem'] %} + {% endif %} + {% if is_state('binary_sensor.infra_nebula_sync_degraded', 'on') %} + {% set ns.items = ns.items + ['Nebula Sync DNS degraded'] %} + {% endif %} + {% if is_state('binary_sensor.infra_pihole_iot_dns_degraded', 'on') %} + {% set ns.items = ns.items + ['IoT Pi-hole DNS degraded'] %} + {% endif %} + {% if is_state('input_boolean.infra_duplicati_backup_repair_active', 'on') %} + {% set ns.items = ns.items + ['Duplicati backup repair active'] %} + {% endif %} + {{ ns.items | join('; ') if ns.items | count > 0 else 'none' }} + - variables: + action_items: >- + {% set ns = namespace(items=[]) %} + {% if powerwall_issues != 'none' %} + {% set ns.items = ns.items + ['Powerwall: ' ~ powerwall_issues] %} + {% endif %} + {% if security_issues != 'none' %} + {% set ns.items = ns.items + ['Security: ' ~ security_issues] %} + {% endif %} + {% if safety_issues != 'none' %} + {% set ns.items = ns.items + ['Safety: ' ~ safety_issues] %} + {% endif %} + {% if infra_issues != 'none' %} + {% set ns.items = ns.items + ['Infra: ' ~ infra_issues] %} + {% endif %} + {{ ns.items | join(' | ') if ns.items | count > 0 else 'No material issues found.' }} + fallback_message_one: >- + {% set msg = 'Vacation ' ~ digest_label | lower ~ ' (' ~ vacation_duration | trim ~ '): ' ~ powerwall_summary | trim ~ ' ' ~ security_summary | trim ~ ' ' ~ sitter_summary | trim %} + {{ msg[:447] ~ '...' if msg | length > 450 else msg }} + fallback_message_two: >- + {% set msg = 'Actions: ' ~ action_items | trim ~ ' ' ~ climate_summary | trim %} + {{ msg[:447] ~ '...' if msg | length > 450 else msg }} + joanna_diagnostics: >- + vacation_mode={{ states('input_boolean.vacation_mode') }}; + digest={{ digest_mode_value }}; + vacation_duration={{ vacation_duration | trim }}; + last_digest_ts={{ last_digest_ts }}; + powerwall_grid={{ states('binary_sensor.powerwall_grid_status') }}; + powerwall_charge={{ states('sensor.powerwall_charge') }}; + powerwall_recent_event={{ powerwall_recent_event | trim }}; + security={{ security_issues }}; + safety={{ safety_issues }}; + infra={{ infra_issues }}; + sitter={{ sitter_summary | trim }}; + climate={{ climate_summary | trim }}; + entities=binary_sensor.powerwall_grid_status,sensor.powerwall_charge,group.locks,lock.front_door,group.garage_doors,group.entry_points,input_boolean.house_sitter_present,sensor.vacation_house_sitter_analytics,sensor.phyn_water_flowing,valve.phyn_shutoff_valve,binary_sensor.refrigerator_door_open,sensor.refrigerator_fridge_temp,sensor.refrigerator_freezer_temp,binary_sensor.front_door_packages_present,binary_sensor.mqtt_broker_problem,binary_sensor.infra_nebula_sync_degraded,binary_sensor.infra_pihole_iot_dns_degraded,input_boolean.infra_duplicati_backup_repair_active + + - service: script.notify_engine + data: + title: "Vacation {{ digest_label }} House Digest" + value1: "{{ fallback_message_one }}" + who: carlo + group: vacation + level: active + + - service: script.notify_engine + data: + title: "Vacation {{ digest_label }} Power/Issues" + value1: "{{ fallback_message_two }}" + who: carlo + group: vacation + level: active + + - service: rest_command.bearclaw_command + data: + source: home_assistant_automation.vacation_house_status_digest + user: carlo + context: "Vacation Mode {{ digest_label }} House Status Digest" + domain_hint: ops + lane_hint: joanna.ops + priority: high + async_only: true + metadata: + vacationMode: true + digestMode: "{{ digest_mode_value }}" + houseDigest: true + powerwallImportant: true + text: >- + Vacation {{ digest_label | lower }} house digest snapshot. + Fallback push 1: {{ fallback_message_one }} + Fallback push 2: {{ fallback_message_two }} + Diagnostics: {{ joanna_diagnostics }} + Request: Use the vacation-mode heavier reasoning profile. Return one concise Home Assistant push paragraph under 420 characters. Powerwall/grid status is high signal and must always be mentioned. Mention only material issues or actions; avoid Docker/AP recovery noise unless unresolved. Start with "Vacation {{ digest_label }}:". + + - service: script.send_to_logbook + data: + topic: VACATION DIGEST + message: "{{ digest_label }} vacation digest sent. {{ action_items }}" + + - service: input_datetime.set_datetime + target: + entity_id: input_datetime.vacation_house_status_digest_last_sent + data: + timestamp: "{{ now().timestamp() }}" + sensor: - platform: history_stats name: Vacation House Sitter Visit Count @@ -257,6 +494,27 @@ automation: data: datetime: "{{ (now() - timedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') }}" + - alias: 'Vacation Mode House Digest Schedule' + id: ed48b582-107f-4424-ab47-bb54cbd8ad38 + mode: single + + trigger: + - platform: time + id: morning + at: "10:00:00" + - platform: time + id: night + at: "22:00:00" + + condition: + - condition: template + value_template: "{{ is_state('input_boolean.vacation_mode', 'on') }}" + + action: + - service: script.vacation_house_status_digest + data: + digest_mode: "{{ trigger.id }}" + - alias: 'Vacation Mode Garage Welcome' id: 63ac9268-c895-4a1b-b0df-92b5bb8e9d01 mode: single