Home Assistant

Quiet-hours notification hub

One script every automation calls with a priority; it checks who is home and whether quiet hours are on, holds low-priority alerts until morning, always passes critical, and writes each send to helpers a history card can show.

Difficulty · IntermediateSetup · 45–90 minutesHA · current stable (blueprint)
Get the pack · from $29Have us set it up

Ten automations each inventing their own quiet-hours if is how a laundry nudge pages the bedroom at 01:00 and a leak does not. This workflow is one script. Every other automation calls it with a title, a message, and a priority. The script decides: is anyone in zone.home (or a person list you pass)? Are we inside quiet hours? Low waits until the window ends, then sends. Critical always goes out — Companion critical / alarm stream, and optional TTS on a speaker. Each send is copied into text helpers so a dashboard history card can show the latest alerts without opening the Logbook.

Entity ids and notify services are script inputs. Do not publish who lives in the house; use person entities and generic notify groups.

What problem it solves

You want every “tell a phone or a speaker” path to share one policy — who is home, what is allowed at night, what is always allowed — and a glanceable history of what was actually sent.

How it works

  1. Single entry — automations call script.notify_hub (name yours) with title, message, priority (low / normal / critical), and optional flags for Companion vs TTS. They do not call notify.mobile_app_* themselves.
  2. Who is home — if you enabled the home filter, the script builds the notify target list from people (or device trackers) currently home. Nobody home + non-critical → skip or fall back to an “away” notify input (pack default: still push a designated phone so a leak is not silent). Critical ignores an empty house and uses the full critical list.
  3. Quiet hours — a wrapping time window (handles midnight). low: do not send now; start a wait_for_trigger on the window end (or drop onto a queue helper the morning automation flushes). normal: Companion is allowed, TTS is not (bedroom speaker stays dark). critical: both allowed; iOS interruption-level: critical, Android alarm_stream.
  4. Route — Companion group and/or tts.speak / media_player.play_media on the speaker you picked. Critical can raise TTS volume via a number helper and restore it after. Missing speaker → push only.
  5. History — shift input_text.alert_previous ← current latest, then write now + title + message into input_text.alert_latest (255-char cap; the pack truncates). A third optional input_text.alert_third gives a three-line card. Logbook still has the script run; the helpers are what a dashboard can show without a custom integration.

Callers such as laundry handoff reminders should pass low at night and let this script hold the nudge. A leak or smoke path passes critical and does not wait.

Hardware notes

  • No extra sensors. This is a script, helpers, and notify services on phones and speakers you already have.
  • Companion. Same critical-alert / alarm_stream setup as any other high-priority pack. Enable Critical Alerts on iOS; raise the Android channel.
  • TTS speaker. Any media_player that can speak (a satellite speaker, a smart speaker, a local TTS pipeline). Keep it out of the bedroom if normal still talks; that is what the quiet-hours TTS gate is for.
  • People. person entities or a group. Do not put given names in a published script.

Snippet

The pack ships a script blueprint. Automations call it; they do not duplicate notify YAML:

sequence:
  - variables:
      priority: "{{ priority | default('normal') }}"
      in_quiet: >
        {{ now().strftime('%H:%M') >= quiet_start
           or now().strftime('%H:%M') < quiet_end }}
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ priority == 'low' and in_quiet }}"
        sequence:
          - wait_for_trigger:
              - platform: time
                at: !input quiet_end
          - service: !input default_notify
            data:
              title: "{{ title }}"
              message: "{{ message }}"
      - conditions:
          - condition: template
            value_template: "{{ priority == 'critical' }}"
        sequence:
          - service: !input critical_notify
            data:
              title: "{{ title }}"
              message: "{{ message }}"
              data:
                push:
                  interruption-level: critical
                channel: alarm_stream
          - service: tts.speak
            target:
              entity_id: !input tts_engine
            data:
              media_player_entity_id: !input tts_player
              message: "{{ message }}"
    default:
      - service: !input default_notify
        data:
          title: "{{ title }}"
          message: "{{ message }}"
  - service: input_text.set_value
    target:
      entity_id: !input history_previous
    data:
      value: "{{ states(history_latest) }}"
  - service: input_text.set_value
    target:
      entity_id: !input history_latest
    data:
      value: "{{ now().strftime('%H:%M') }} · {{ title }} — {{ message }}"

Example caller (another automation):

action:
  - service: script.notify_hub
    data:
      title: "Washer"
      message: "Cycle finished."
      priority: low

Dashboard card (helpers only — no live household names):

type: entities
title: Alert history
entities:
  - entity: input_text.alert_latest
    name: Latest
  - entity: input_text.alert_previous
    name: Previous

Setup outline

  1. Create two (or three) input_text helpers at 255 characters, plus optional queue/boolean helpers the pack lists.
  2. Import the script blueprint. Fill default notify, critical notify, quiet start/end, person list or home zone, optional TTS player.
  3. Point one existing automation at the script with priority: low and one test call with priority: critical.
  4. Test: low inside quiet hours → no phone until the window ends, then one push and a history line; critical inside quiet hours → immediate push (+ TTS if configured); history card shows latest then previous on the next send.

Troubleshooting

  • Low alerts vanish. You used stop instead of waiting for quiet end, or the morning flush automation is disabled. The pack’s wait / queue must stay enabled overnight.
  • TTS talks at 2 a.m. on a laundry nudge. The caller passed normal or critical, or quiet hours do not wrap midnight (after only). Use low for nags; keep the pack’s wrapping window.
  • Nobody got the leak. Home filter dropped an empty house and you left the away fallback blank. Set an away notify, or disable the home filter for critical.
  • History card is empty. Helpers were never written (script failed before the last two steps) or the card points at different entity ids. The script must write helpers even when TTS is skipped.
  • Critical still silent. Same OS permission issue as other critical packs: iOS Critical Alerts off, Android channel not alarm_stream. Fix the channel before debugging the script.

Credits

Based on the community blueprint Master Notify — Dashboard Edition (notifications, TTS, history). This write-up is an original overview of a priority-aware hub with quiet hours, presence routing, and helper-backed history.

Changelog

v1.0 · Oct 17, 2026: First publish.