diff --git a/config/logbook.yaml b/config/logbook.yaml index e7bc0c8b..2f0c3e13 100644 --- a/config/logbook.yaml +++ b/config/logbook.yaml @@ -17,6 +17,7 @@ # Notes: Water-softener salt helpers stay in recorder for restore/math; curated MAINTENANCE events and trend sensors are the visible signal. # Notes: Rolling maintenance days-since sensors are live-only display helpers. # Notes: TP-Link lamp voltage diagnostics stay out of Activity; recorder.yaml keeps them live-only. +# Notes: WHOIS days-until-expiration countdowns stay out of Activity; actionable domain alert changes remain visible. ###################################################################### exclude: @@ -86,6 +87,10 @@ exclude: - sensor.hvac_condenser_lines_days_since_cleaned - sensor.front_office_lamp_voltage - sensor.water_softener_salt_days_since_last_add + - sensor.fordst_com_days_until_expiration + - sensor.ipmer_com_days_until_expiration + - sensor.kingcrafthomes_com_days_until_expiration + - sensor.vcloudinfo_com_days_until_expiration - input_datetime.water_softener_salt_last_occurred_at - input_number.water_softener_salt_last_amount_lb - input_number.water_softener_salt_total_added_lb diff --git a/config/packages/README.md b/config/packages/README.md index 5e90f68e..37005497 100755 --- a/config/packages/README.md +++ b/config/packages/README.md @@ -49,7 +49,7 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this | [![YAML source: logbook_activity_feed](https://img.shields.io/static/v1?label=YAML&message=logbook_activity_feed&color=lightgrey&logo=github&logoColor=181717)](logbook_activity_feed.yaml) | Dummy `sensor.activity_feed` + helper to write clean Activity entries (Issue #1550). | `sensor.activity_feed`, `script.send_to_logbook` | | [![YAML source: mariadb_monitoring](https://img.shields.io/static/v1?label=YAML&message=mariadb_monitoring&color=lightgrey&logo=github&logoColor=181717)](mariadb_monitoring.yaml) | MariaDB health sensors and Lovelace dashboard snippet for recorder stats. | `sensor.mariadb_status`, `sensor.database_size` | | [![YAML source: llmvision](https://img.shields.io/static/v1?label=YAML&message=llmvision&color=lightgrey&logo=github&logoColor=181717)](llmvision.yaml) | Vision-backed garage-can and front-door package checks with rate-limited, downscaled OpenAI calls for package detection. [![Watch on YouTube](https://img.shields.io/badge/Watch-YouTube-FF0000?logo=youtube&logoColor=white)](https://youtu.be/nAhCezFetvI) | `input_button.llmvision_*`, `binary_sensor.front_door_packages_present`, `llmvision.stream_analyzer` | -| [![YAML source: docker_infrastructure](https://img.shields.io/static/v1?label=YAML&message=docker_infrastructure&color=lightgrey&logo=github&logoColor=181717)](docker_infrastructure.yaml) | Docker host patching telemetry, container/stack Repairs automation, retired Portainer repair cleanup, 20-minute Joanna escalation for persistent container outages including stuck `restarting`/`created` states, and weekly scheduled prune actions across docker_10/14/17/69; the dedicated codex_appliance VM is monitored through BearClaw status telemetry. [![Watch on YouTube](https://img.shields.io/badge/Watch-YouTube-FF0000?logo=youtube&logoColor=white)](https://youtu.be/aceV7ObKJVA) [![vCloudInfo Blog Post](https://img.shields.io/static/v1?label=vCloudInfo&message=Blog%20Post&color=21759B&logo=wordpress&logoColor=white)](https://www.vcloudinfo.com/2026/07/using-codex-clean-up-home-assistant-entities.html) | `sensor.docker_*_apt_status`, `binary_sensor.*_stack_status`, `sensor.docker_stacks_down_count`, `repairs.create`, `repairs.remove`, `script.joanna_dispatch` | +| [![YAML source: docker_infrastructure](https://img.shields.io/static/v1?label=YAML&message=docker_infrastructure&color=lightgrey&logo=github&logoColor=181717)](docker_infrastructure.yaml) | Docker host patching telemetry with persisted Mon/Thu maintenance deadlines, container/stack Repairs automation, retired Portainer repair cleanup, 20-minute Joanna escalation for persistent container outages including stuck `restarting`/`created` states, and weekly scheduled prune actions across docker_10/14/17/69; the dedicated codex_appliance VM is monitored through BearClaw status telemetry. [![Watch on YouTube](https://img.shields.io/badge/Watch-YouTube-FF0000?logo=youtube&logoColor=white)](https://youtu.be/aceV7ObKJVA) [![vCloudInfo Blog Post](https://img.shields.io/static/v1?label=vCloudInfo&message=Blog%20Post&color=21759B&logo=wordpress&logoColor=white)](https://www.vcloudinfo.com/2026/07/using-codex-clean-up-home-assistant-entities.html) | `sensor.docker_*_apt_status`, `input_datetime.apt_docker_*_action_due`, `binary_sensor.*_stack_status`, `sensor.docker_stacks_down_count`, `repairs.create`, `repairs.remove`, `script.joanna_dispatch` | | [![YAML source: proxmox](https://img.shields.io/static/v1?label=YAML&message=proxmox&color=lightgrey&logo=github&logoColor=181717)](proxmox.yaml) | Proxmox update detection with Repairs, 02:15 Joanna patch orchestration, final per-host HA success notifications, kernel-refresh handoff hints, runtime and disk pressure monitoring, plus nightly Frigate reboot. | `binary_sensor.node_proxmox*_updates_packages`, `sensor.node_proxmox*_total_updates`, `persistent_notification.create`, `script.joanna_dispatch`, `binary_sensor.proxmox*_runtime_healthy`, `sensor.proxmox*_disk_used_percentage`, `button.qemu_docker2_101_reboot` | | [![YAML source: synology_dsm](https://img.shields.io/static/v1?label=YAML&message=synology_dsm&color=lightgrey&logo=github&logoColor=181717)](synology_dsm.yaml) | Synology DSM integration health normalization for Carlo-NAS01 and Carlo-NVR, with outage-aware Joanna-first handling for lone post-outage volume warnings and Repairs escalation for persistent or non-outage problems. | `binary_sensor.carlo_*_synology_problem`, `sensor.carlo_*_synology_problem_summary`, `binary_sensor.powerwall_grid_status`, `repairs.create`, `script.joanna_dispatch` | | [![YAML source: infrastructure](https://img.shields.io/static/v1?label=YAML&message=infrastructure&color=lightgrey&logo=github&logoColor=181717)](infrastructure.yaml) | Normalized WAN/DNS/backup/domain/cert health, Nebula Sync and promoted IoT primary/backup Pi-hole consistency monitoring with Joanna dispatch, Glances-backed Docker host disk pressure with Joanna-only warning cleanup and critical Repairs, immediate website-down Repairs/Joanna dispatch plus uptime/latency SLO signals, nightly backup verification, and monthly Joanna HA log hygiene review with public-safe GitHub issue follow-up. [![Watch on YouTube](https://img.shields.io/badge/Watch-YouTube-FF0000?logo=youtube&logoColor=white)](https://youtu.be/aceV7ObKJVA) [![vCloudInfo Blog Post](https://img.shields.io/static/v1?label=vCloudInfo&message=Blog%20Post&color=21759B&logo=wordpress&logoColor=white)](https://www.vcloudinfo.com/2026/07/using-codex-clean-up-home-assistant-entities.html) | `sensor.infra_nebula_sync_dns_consistency`, `sensor.infra_pihole_iot_dns_consistency`, `binary_sensor.infra_nebula_sync_degraded`, `binary_sensor.infra_pihole_iot_dns_degraded`, `sensor.docker_*_disk_used_percentage`, `automation.infra_nebula_sync_health_dispatch`, `automation.infra_pihole_iot_dns_drift_dispatch`, `automation.docker_host_disk_pressure_monitor`, `automation.infra_website_down_repair_and_dispatch`, `binary_sensor.infra_website_uptime_slo_breach`, `binary_sensor.infra_website_latency_degraded`, `automation.infra_backup_nightly_verification`, `script.joanna_dispatch` | @@ -57,7 +57,7 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this | [![YAML source: mqtt_status](https://img.shields.io/static/v1?label=YAML&message=mqtt_status&color=lightgrey&logo=github&logoColor=181717)](mqtt_status.yaml) | Command-line MQTT broker reachability probe with Spook Repairs escalation and Joanna troubleshooting dispatch on outage. | `binary_sensor.mqtt_status_raw`, `binary_sensor.mqtt_broker_problem`, `repairs.create`, `rest_command.bearclaw_command` | | [![YAML source: mariadb](https://img.shields.io/static/v1?label=YAML&message=mariadb&color=lightgrey&logo=github&logoColor=181717)](mariadb.yaml) | MariaDB recorder health and capacity snapshots with hourly live metrics, weekly admin/recorder polling, and stats-ready numeric sensors. | `sensor.mariadb_status`, `sensor.database_size` | | [![YAML source: processmonitor](https://img.shields.io/static/v1?label=YAML&message=processmonitor&color=lightgrey&logo=github&logoColor=181717)](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` | -| [![YAML source: tugtainer_updates](https://img.shields.io/static/v1?label=YAML&message=tugtainer_updates&color=lightgrey&logo=github&logoColor=181717)](tugtainer_updates.yaml) | Tugtainer container update notifications via webhook + persistent alerts, plus event-based Joanna dispatch when reports include `### Available:` with Home Assistant core updates held for explicit approval, config check, and a maintenance window (24h cooldown via `mode: single` + delay, no new helpers). [![Watch on YouTube](https://img.shields.io/badge/Watch-YouTube-FF0000?logo=youtube&logoColor=white)](https://youtu.be/4NNOkXzUyYw) [![vCloudInfo Blog Post](https://img.shields.io/static/v1?label=vCloudInfo&message=Blog%20Post&color=21759B&logo=wordpress&logoColor=white)](https://www.vcloudinfo.com/2026/07/home-assistant-tugtainer-docker-updates.html) | `persistent_notification.create`, `event: tugtainer_available_detected`, `script.joanna_dispatch`, `input_datetime.tugtainer_last_update` | +| [![YAML source: tugtainer_updates](https://img.shields.io/static/v1?label=YAML&message=tugtainer_updates&color=lightgrey&logo=github&logoColor=181717)](tugtainer_updates.yaml) | Tugtainer container update notifications via webhook + persistent alerts, with immediate Joanna recovery dispatch for `### Failed:` / `### Rolled-back:` reports and event-based review dispatch for `### Available:` reports. Home Assistant core updates remain held for explicit approval, config check, and a maintenance window; the Available-report path keeps its 24h cooldown without blocking failures. [![Watch on YouTube](https://img.shields.io/badge/Watch-YouTube-FF0000?logo=youtube&logoColor=white)](https://youtu.be/4NNOkXzUyYw) [![vCloudInfo Blog Post](https://img.shields.io/static/v1?label=vCloudInfo&message=Blog%20Post&color=21759B&logo=wordpress&logoColor=white)](https://www.vcloudinfo.com/2026/07/home-assistant-tugtainer-docker-updates.html) | `persistent_notification.create`, `event: tugtainer_available_detected`, `script.joanna_dispatch`, `input_datetime.tugtainer_last_update` | | [![YAML source: printer](https://img.shields.io/static/v1?label=YAML&message=printer&color=lightgrey&logo=github&logoColor=181717)](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 | | [![YAML source: bearclaw](https://img.shields.io/static/v1?label=YAML&message=bearclaw&color=lightgrey&logo=github&logoColor=181717)](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. [![Watch on YouTube](https://img.shields.io/badge/Watch-YouTube-FF0000?logo=youtube&logoColor=white)](https://youtu.be/7wKhtrvtyiI) [![vCloudInfo Blog Post](https://img.shields.io/static/v1?label=vCloudInfo&message=Blog%20Post&color=21759B&logo=wordpress&logoColor=white)](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` | | [![YAML source: telegram_bot](https://img.shields.io/static/v1?label=YAML&message=telegram_bot&color=lightgrey&logo=github&logoColor=181717)](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` | diff --git a/config/packages/docker_infrastructure.yaml b/config/packages/docker_infrastructure.yaml index ef9f8a2b..05973686 100644 --- a/config/packages/docker_infrastructure.yaml +++ b/config/packages/docker_infrastructure.yaml @@ -10,8 +10,10 @@ # Blog: https://www.vcloudinfo.com/2026/07/using-codex-clean-up-home-assistant-entities.html # ------------------------------------------------------------------- # Notes: Hosts run daily read-only APT pending checks plus Mon/Thu 12:00 APT jobs. +# Notes: All Docker hosts use America/New_York so staggered maintenance shares one local window. # Notes: Reboots are handled directly on each host by apt_weekly.sh. # Notes: Reboot staggering: docker_14, docker_69, docker_17, docker_10. +# Notes: Per-host action-due helpers preserve overdue state across daily checks and HA restarts. # Notes: Container monitoring is dynamic with binary_sensor status preferred over switch state. # Notes: Weekly Joanna reconcile checks discovered container switches vs configured group members. # Notes: Includes Portainer stack status repairs, 20-minute Joanna dispatch for persistent container outages, and scheduled image prune. @@ -37,6 +39,10 @@ input_datetime: name: "docker_10 APT last update" has_date: true has_time: true + apt_docker_10_action_due: + name: "docker_10 APT action due" + has_date: true + has_time: true apt_docker_17_last_check: name: "docker_17 APT last check" has_date: true @@ -45,6 +51,10 @@ input_datetime: name: "docker_17 APT last update" has_date: true has_time: true + apt_docker_17_action_due: + name: "docker_17 APT action due" + has_date: true + has_time: true apt_docker_14_last_check: name: "docker_14 APT last check" has_date: true @@ -53,6 +63,10 @@ input_datetime: name: "docker_14 APT last update" has_date: true has_time: true + apt_docker_14_action_due: + name: "docker_14 APT action due" + has_date: true + has_time: true apt_docker_69_last_check: name: "docker_69 APT last check" has_date: true @@ -61,6 +75,10 @@ input_datetime: name: "docker_69 APT last update" has_date: true has_time: true + apt_docker_69_action_due: + name: "docker_69 APT action due" + has_date: true + has_time: true docker_container_alerts_snooze_until: name: "Docker container alerts snooze until" has_date: true @@ -929,24 +947,62 @@ automation: packages: "{{ payload.get('packages', 0) | int(0) }}" security_packages: "{{ payload.get('security_packages', 0) | int(0) }}" message: "{{ payload.get('message', '') | string }}" + event_kind: "{{ payload.get('event', 'maintenance') | string }}" helpers: docker_10: last_check: input_datetime.apt_docker_10_last_check last_update: input_datetime.apt_docker_10_last_update last_result: input_text.apt_docker_10_last_result + action_due: input_datetime.apt_docker_10_action_due + reboot_delay: 20 docker_14: last_check: input_datetime.apt_docker_14_last_check last_update: input_datetime.apt_docker_14_last_update last_result: input_text.apt_docker_14_last_result + action_due: input_datetime.apt_docker_14_action_due + reboot_delay: 5 docker_17: last_check: input_datetime.apt_docker_17_last_check last_update: input_datetime.apt_docker_17_last_update last_result: input_text.apt_docker_17_last_result + action_due: input_datetime.apt_docker_17_action_due + reboot_delay: 15 docker_69: last_check: input_datetime.apt_docker_69_last_check last_update: input_datetime.apt_docker_69_last_update last_result: input_text.apt_docker_69_last_result + action_due: input_datetime.apt_docker_69_action_due + reboot_delay: 10 host_helpers: "{{ helpers[host_id] if host_id in helpers else none }}" + previous_result: "{{ states(host_helpers.last_result) | upper }}" + previous_actionable: >- + {{ 'PENDING' in previous_result or 'REBOOT REQ' in previous_result }} + previous_reboot: "{{ 'REBOOT REQ' in previous_result }}" + actionable: "{{ success and (packages > 0 or reboot_required) }}" + due_state: "{{ states(host_helpers.action_due) }}" + due_missing: >- + {{ due_state in ['unknown', 'unavailable', 'none', ''] or + due_state.endswith('00:00:00') }} + set_action_due: >- + {{ actionable and + (not previous_actionable or due_missing or previous_reboot != reboot_required) }} + action_due: >- + {% set noon = today_at('12:00') %} + {% set weekday = now().weekday() %} + {% set maintenance_report = event_kind == 'maintenance' %} + {% set current_window = maintenance_report and weekday in [0, 3] + and now() >= noon and now() < noon + timedelta(hours=4) %} + {% if current_window %} + {% set offset = 0 %} + {% elif weekday in [0, 3] and now() < noon %} + {% set offset = 0 %} + {% elif weekday < 3 %} + {% set offset = 3 - weekday %} + {% else %} + {% set offset = 7 - weekday %} + {% endif %} + {% set delay = host_helpers.reboot_delay if reboot_required else 0 %} + {{ (noon + timedelta(days=offset, minutes=delay)).strftime('%Y-%m-%d %H:%M:%S') }} result: >- {% set security = ' (' ~ security_packages ~ ' SEC)' if security_packages > 0 else '' %} {% if not success %} @@ -976,6 +1032,14 @@ automation: entity_id: "{{ host_helpers.last_result }}" data: value: "{{ result }}" + - choose: + - conditions: "{{ set_action_due }}" + sequence: + - service: input_datetime.set_datetime + target: + entity_id: "{{ host_helpers.action_due }}" + data: + datetime: "{{ action_due }}" - choose: - conditions: "{{ success and updated }}" sequence: diff --git a/config/packages/infrastructure.yaml b/config/packages/infrastructure.yaml index 158c2b7c..0ce2f76b 100644 --- a/config/packages/infrastructure.yaml +++ b/config/packages/infrastructure.yaml @@ -4,13 +4,12 @@ # Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig # ------------------------------------------------------------------- # Infrastructure - Observability, disk pressure, and Joanna review workflows -# WAN/DNS/website/domain/cert/Docker host state normalized for dashboards, plus scheduled infrastructure reviews. +# WAN/DNS/website/Docker host state normalized for dashboards, plus scheduled infrastructure reviews. # Video: https://youtu.be/aceV7ObKJVA # Blog: https://www.vcloudinfo.com/2026/07/using-codex-clean-up-home-assistant-entities.html # ------------------------------------------------------------------- # Related Issue: 1584 # Notes: Home dashboard consumes `infra_*` entities for exceptions-only alerts. -# Notes: Domain warning threshold is <30 days; critical threshold is <14 days. # Notes: Nightly Duplicati verification runs at 08:00 after the 05:30 Duplicati job and docker_14 reboot window. # Notes: Duplicati transport/API errors are logged only; repairs are reserved for proven failed or stale backups. # Notes: Duplicati failure Repairs enable a recovery poll that clears the Repair after a later successful run. @@ -21,7 +20,8 @@ # Notes: Warning-level Docker host disk pressure is Joanna-only; Repairs are reserved for critical pressure. # Notes: Nebula Sync DNS consistency compares primary/backup Pi-hole answers and dispatches Joanna on sustained drift or container loss. # Notes: Promoted IoT DNS consistency compares primary/backup Pi-hole answers for reserved IoT host records. -# Notes: Immediate website-down states create Repairs and dispatch Joanna; SLO/latency automations cover longer-term UptimeRobot trends. +# Notes: Garage compute health uses the same 145 F threshold as the existing temperature notification. +# Notes: Immediate website-down states create Repairs; the installed UptimeRobot integration exposes current state, not trend rollups. ###################################################################### input_text: @@ -144,72 +144,6 @@ template: availability: "{{ states('sensor.docker69_disk_usage') not in ['unknown', 'unavailable', 'none', ''] }}" state: "{{ states('sensor.docker69_disk_usage') | float(0) | round(1) }}" - - name: "Infra Domain Expiry Min Days" - unique_id: infra_domain_expiry_min_days - unit_of_measurement: "d" - state: >- - {% set ids = [ - 'sensor.vcloudinfo_com_days_until_expiration', - 'sensor.ipmer_com_days_until_expiration', - 'sensor.fordst_com_days_until_expiration', - 'sensor.kingcrafthomes_com_days_until_expiration' - ] %} - {% set ns = namespace(min=9999, any=false) %} - {% for id in ids %} - {% if expand(id) | count > 0 %} - {% set raw = states(id) %} - {% if raw not in ['unknown', 'unavailable', 'none', ''] %} - {% set ns.any = true %} - {% set val = raw | float(9999) %} - {% if val < ns.min %} - {% set ns.min = val %} - {% endif %} - {% endif %} - {% endif %} - {% endfor %} - {% if ns.any %} - {{ ns.min | round(0) }} - {% else %} - {{ none }} - {% endif %} - - - name: "Infra Cert Expiry Min Days" - unique_id: infra_cert_expiry_min_days - unit_of_measurement: "d" - state: >- - {% set ns = namespace(min=9999, any=false) %} - {% for item in states.sensor %} - {% if item.entity_id is search('(vcloudinfo|ipmer|fordst|kingcrafthomes).*(cert|ssl|tls)') %} - {% set raw = item.state %} - {% if raw not in ['unknown', 'unavailable', 'none', ''] %} - {% set value = raw | float(9999) %} - {% if value != 9999 %} - {% set ns.any = true %} - {% if value < ns.min %} - {% set ns.min = value %} - {% endif %} - {% endif %} - {% endif %} - {% endif %} - {% endfor %} - {% if ns.any %} - {{ ns.min | round(0) }} - {% else %} - {{ none }} - {% endif %} - - - name: "Infra Cert Telemetry Count" - unique_id: infra_cert_telemetry_count - icon: mdi:counter - state: >- - {% set ns = namespace(count=0) %} - {% for item in states.sensor %} - {% if item.entity_id is search('(vcloudinfo|ipmer|fordst|kingcrafthomes).*(cert|ssl|tls)') %} - {% set ns.count = ns.count + 1 %} - {% endif %} - {% endfor %} - {{ ns.count }} - - name: "Infra Website Down Count" unique_id: infra_website_down_count icon: mdi:counter @@ -256,6 +190,30 @@ template: {% endfor %} {{ ns.items }} + - name: "Infra Dashboard Active Issue Count" + unique_id: infra_dashboard_active_issue_count + icon: mdi:alert-circle-check-outline + state_class: measurement + state: >- + {% set categories = [ + 'binary_sensor.infra_wan_quality_degraded', + 'binary_sensor.infra_dns_pihole_degraded', + 'binary_sensor.infra_compute_degraded', + 'binary_sensor.infra_storage_degraded', + 'binary_sensor.infra_external_monitoring_degraded' + ] %} + {{ expand(categories) | selectattr('state', 'eq', 'on') | list | count }} + attributes: + active_entities: >- + {% set categories = [ + 'binary_sensor.infra_wan_quality_degraded', + 'binary_sensor.infra_dns_pihole_degraded', + 'binary_sensor.infra_compute_degraded', + 'binary_sensor.infra_storage_degraded', + 'binary_sensor.infra_external_monitoring_degraded' + ] %} + {{ expand(categories) | selectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} + - binary_sensor: - name: "Infra WAN Quality Degraded" unique_id: infra_wan_quality_degraded @@ -273,9 +231,22 @@ template: unique_id: infra_dns_pihole_degraded device_class: problem state: >- - {% set switch_state = states('switch.pi_hole') %} - {% set service_state = states('binary_sensor.pihole_status') %} - {{ switch_state != 'on' or service_state in ['off', 'unavailable', 'unknown'] }} + {% set members = [ + 'switch.pi_hole', + 'binary_sensor.pi_hole_status', + 'switch.pi_hole_2', + 'binary_sensor.pi_hole_status_2' + ] %} + {{ expand(members) | rejectattr('state', 'eq', 'on') | list | count > 0 }} + attributes: + problem_entities: >- + {% set members = [ + 'switch.pi_hole', + 'binary_sensor.pi_hole_status', + 'switch.pi_hole_2', + 'binary_sensor.pi_hole_status_2' + ] %} + {{ expand(members) | rejectattr('state', 'eq', 'on') | map(attribute='entity_id') | list }} - name: "Infra Nebula Sync Degraded" unique_id: infra_nebula_sync_degraded @@ -376,51 +347,41 @@ template: {% endfor %} {{ ns.seen and ns.breach }} - - name: "Infra Domain Expiry Critical" - unique_id: infra_domain_expiry_critical + - name: "Infra Compute Degraded" + unique_id: infra_compute_degraded device_class: problem state: >- - {% set d = states('sensor.infra_domain_expiry_min_days') %} - {% if d in ['unknown', 'unavailable', 'none', ''] %} - false - {% else %} - {{ d | float(9999) < 14 }} - {% endif %} - - - name: "Infra Domain Expiry Warning" - unique_id: infra_domain_expiry_warning - device_class: problem - state: >- - {% set d = states('sensor.infra_domain_expiry_min_days') %} - {% if d in ['unknown', 'unavailable', 'none', ''] %} - false - {% else %} - {% set days = d | float(9999) %} - {{ days < 30 and days >= 14 }} - {% endif %} + {{ is_state('binary_sensor.docker_container_telemetry_degraded', 'on') or + states('binary_sensor.proxmox1_runtime_healthy') != 'on' or + states('binary_sensor.proxmox02_runtime_healthy') != 'on' or + is_state('binary_sensor.node_proxmox1_updates_packages', 'on') or + is_state('binary_sensor.node_proxmox02_updates_packages', 'on') or + states('sensor.proxmox_garage_average_temperature') in ['unknown', 'unavailable', 'none', ''] or + states('sensor.proxmox_garage_average_temperature') | float(0) > 145 }} - - name: "Infra Cert Expiry Critical" - unique_id: infra_cert_expiry_critical + - name: "Infra Storage Degraded" + unique_id: infra_storage_degraded device_class: problem state: >- - {% set d = states('sensor.infra_cert_expiry_min_days') %} - {% if d in ['unknown', 'unavailable', 'none', ''] %} - false - {% else %} - {{ d | float(9999) < 14 }} - {% endif %} + {% set limits = { + 'sensor.disk_use_percent': 80, + 'sensor.carlo_nvr_volume_1_volume_used': 85, + 'sensor.carlo_nas01_volume_1_volume_used': 85 + } %} + {% set ns = namespace(degraded=false) %} + {% for entity_id, limit in limits.items() %} + {% set raw = states(entity_id) %} + {% if raw in ['unknown', 'unavailable', 'none', ''] or raw | float(0) > limit %} + {% set ns.degraded = true %} + {% endif %} + {% endfor %} + {{ ns.degraded }} - - name: "Infra Cert Expiry Warning" - unique_id: infra_cert_expiry_warning + - name: "Infra External Monitoring Degraded" + unique_id: infra_external_monitoring_degraded device_class: problem state: >- - {% set d = states('sensor.infra_cert_expiry_min_days') %} - {% if d in ['unknown', 'unavailable', 'none', ''] %} - false - {% else %} - {% set days = d | float(9999) %} - {{ days < 30 and days >= 14 }} - {% endif %} + {{ is_state('binary_sensor.infra_website_degraded', 'on') }} automation: - alias: "Infrastructure - External IP Change Logbook" diff --git a/config/packages/tugtainer_updates.yaml b/config/packages/tugtainer_updates.yaml index 85bfd11c..67b98a4c 100644 --- a/config/packages/tugtainer_updates.yaml +++ b/config/packages/tugtainer_updates.yaml @@ -11,6 +11,7 @@ # Notes: Creates persistent notifications and stamps last-update time. # Notes: Fires update events independently when a report has both Available and Updated sections. # Notes: Fires `tugtainer_home_assistant_core_updated` when `### Updated:` includes Home Assistant. +# Notes: Failed or rolled-back reports dispatch Joanna immediately, outside the Available-report cooldown. # Notes: Home Assistant changelog dispatch uses core-YYYY.M URL format from parsed/fallback version. # Notes: Joanna dispatch cooldown uses mode=single with a 24-hour delay lockout. # Notes: Available reports must not auto-update Home Assistant; HA core updates require explicit approval, config check, and a maintenance window. @@ -29,7 +30,7 @@ input_datetime: automation: - alias: "Tugtainer Update Report" id: tugtainer_update_report - description: "Receive Tugtainer update notifications and post persistent alerts." + description: "Receive Tugtainer reports, post persistent alerts, and dispatch failed updates." mode: queued trigger: - platform: webhook @@ -43,6 +44,9 @@ automation: message: "{{ payload.message | default('Update event received') }}" event_type: "{{ payload.type | default('info') }}" has_available_section: "{{ '### available:' in (message | lower) }}" + has_failed_section: "{{ '### failed:' in (message | lower) }}" + has_rolled_back_section: "{{ '### rolled-back:' in (message | lower) }}" + has_failure_section: "{{ has_failed_section or has_rolled_back_section }}" updated_section: >- {% set sections = message | regex_findall('(?is)###\\s*updated:\\s*(.*?)(?:\\n###\\s|$)') %} {{ sections[0] if sections | count > 0 else '' }} @@ -101,6 +105,38 @@ automation: title: "{{ title }}" event_type: "{{ event_type }}" message: "{{ message }}" + - if: + - condition: template + value_template: "{{ has_failure_section }}" + then: + - service: script.send_to_logbook + data: + topic: "DOCKER" + message: >- + Tugtainer reported failed or rolled-back container updates. + Joanna dispatch requested. + - service: script.joanna_dispatch + data: + trigger_context: "HA automation tugtainer_update_report (Tugtainer Update Report)" + source: "home_assistant_automation.tugtainer_update_report" + summary: "Tugtainer reported failed or rolled-back container updates" + entity_ids: + - "input_datetime.tugtainer_last_update" + diagnostics: >- + title={{ title }}, + event_type={{ event_type }}, + failed_section={{ has_failed_section }}, + rolled_back_section={{ has_rolled_back_section }}, + message={{ message }} + request: >- + Investigate this Tugtainer failure report. Inspect the owning Docker + host, Tugtainer logs, and live container state before changing + anything. Recover failed or rolled-back services through their + Compose definitions when safe, verify application health, and + reconcile Tugtainer state. Do not update, recreate, or restart Home + Assistant (`home-assistant` or + `ghcr.io/home-assistant/home-assistant`) from this dispatch. Report + what was fixed and any remaining blockers. - if: - condition: template value_template: "{{ ha_core_update_detected and (ha_core_version_minor | trim != '') }}" diff --git a/config/recorder.yaml b/config/recorder.yaml index 4bc27a58..e778934e 100755 --- a/config/recorder.yaml +++ b/config/recorder.yaml @@ -13,9 +13,10 @@ # Notes: Tesla Fleet Spaceship telemetry is live-only in HA; TeslaMate is the historical car database. # Notes: Life360 trackers are explicitly included for map/history queries despite the broad device_tracker exclusion. # Notes: Raw Portainer container/stack status telemetry is live-only; keep Docker aggregate outage sensors, Repairs, and curated logbook events instead. -# Notes: Mobile app phone telemetry is live-only; Life360 keeps location history and notify services remain available. +# Notes: Mobile app phone telemetry is live-only except daily pedometer metrics for Carlo and Stacey, retained for fitness history; Life360 keeps location history and notify services remain available. # Notes: Rolling maintenance days-since sensors are live-only; durable interval/count/total sensors carry the history. # Notes: TP-Link lamp voltage diagnostics are live-only; useful energy/power sensors stay recorded. +# Notes: WHOIS days-until-expiration countdowns are live-only; actual expiry timestamps and alert-state changes remain durable. ###################################################################### db_url: !secret recorder_db_url purge_keep_days: 180 @@ -34,6 +35,16 @@ include: - device_tracker.life360_paige_costanzo - device_tracker.life360_stacey_costanzo - device_tracker.life360_yolanda_costanzo + - sensor.carlo_maxpro_average_active_pace + - sensor.carlo_maxpro_distance + - sensor.carlo_maxpro_floors_ascended + - sensor.carlo_maxpro_floors_descended + - sensor.carlo_maxpro_steps + - sensor.stacey_iphone11_average_active_pace + - sensor.stacey_iphone11_distance + - sensor.stacey_iphone11_floors_ascended + - sensor.stacey_iphone11_floors_descended + - sensor.stacey_iphone11_steps exclude: domains: - button @@ -175,6 +186,10 @@ exclude: - sensor.hvac_condenser_lines_days_since_cleaned - sensor.front_office_lamp_voltage - sensor.water_softener_salt_days_since_last_add + - sensor.fordst_com_days_until_expiration + - sensor.ipmer_com_days_until_expiration + - sensor.kingcrafthomes_com_days_until_expiration + - sensor.vcloudinfo_com_days_until_expiration # BEGIN generated Portainer recorder/logbook noise exclusions # Portainer per-container/status plumbing is live-only; keep aggregate Docker outage sensors historically. - binary_sensor.docker_container_alerts_snoozed