Skip to content

Commit 4c99abe

Browse files
authored
Add bedroom wake alarm helpers
Normalize Alexa bedroom wake alarm helpers and recorder exclusions.
1 parent 240fd6f commit 4c99abe

3 files changed

Lines changed: 136 additions & 2 deletions

File tree

config/packages/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this
3939
| Package | What it unlocks | Notable entities / services |
4040
| --- | --- | --- |
4141
| [alarm.yaml](alarm.yaml) | NodeMCU-powered perimeter monitoring with arm/disarm helpers and rich notifications. | `binary_sensor.mcu*_gpio*`, `group.family`, notify + siren scripts |
42+
| [alexa_media_player.yaml](alexa_media_player.yaml) | Alexa Media helper sensors including stable bedroom wake-alarm wrappers for Carlo and Stacey plus a combined next-wake view. | `sensor.last_alexa`, `sensor.bedroom_next_wake_alarm`, `sensor.bedroom_next_wake_alarm_source`, `binary_sensor.bedroom_next_wake_alarm_active` |
4243
| [garadget.yaml](garadget.yaml) | MQTT-based control + status for both garage doors, feeding entry/exit lighting routines. | `cover.large_garage_door`, `cover.small_garage_door`, `sensor.garadget_reflection` |
4344
| [august.yaml](august.yaml) | Front-door August smart lock with Alexa Show camera pop-up when unlocked. | `lock.front_door`, media_player actions for front doorbell camera |
4445
| [holiday.yaml](holiday.yaml) | REST-driven US holiday + flag sensors that color scenes and exterior lighting. | `sensor.holiday`, `sensor.flag`, JSON feed at `config/json_data/holidays.json` |
@@ -54,7 +55,7 @@ Live collection of plug-and-play Home Assistant packages. Each YAML file in this
5455
| [mariadb.yaml](mariadb.yaml) | MariaDB recorder health and capacity SQL sensors. | `sensor.mariadb_status`, `sensor.database_size` |
5556
| [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` |
5657
| [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 plus QMD/memory-index sensors for Infrastructure dashboards. | `rest_command.bearclaw_*`, `sensor.bearclaw_status_telemetry`, `sensor.joanna_*`, `binary_sensor.joanna_*`, `automation.bearclaw_*`, `script.send_to_logbook` |
57-
| [telegram_bot.yaml](telegram_bot.yaml) | Telegram transport package for BearClaw and other ops flows; the shared `joanna_send_telegram` helper now lives under `config/script/`. | `telegram_bot.send_message`, `script.joanna_send_telegram` |
58+
| [telegram_bot.yaml](telegram_bot.yaml) | Telegram transport package for BearClaw and other ops flows; the shared `joanna_send_telegram` helper now lives under `config/script/`. | `telegram_bot.send_message`, `script.joanna_send_telegram` |
5859
| [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` |
5960
| [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` |
6061
| [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` |

config/packages/alexa_media_player.yaml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
# Alexa Media Player - Sensors and notifications via Alexa Media integration.
77
# Track Alexa media state and expose routine/command triggers.
88
# -------------------------------------------------------------------
9+
# Related Issue: 858
10+
# Notes: Wrapper wake-alarm sensors normalize Alexa Media `next_alarm` IDs.
11+
# Notes: Current wake-alarm scope is limited to Carlo Bedroom + Stacey Bedroom.
912
######################################################################
1013

1114
template:
@@ -14,3 +17,132 @@ template:
1417
unique_id: last_alexa
1518
state: >
1619
{{ states.media_player | selectattr('attributes.last_called','eq',True) | map(attribute='entity_id') | first | default('none') }}
20+
- name: "Carlo Bedroom Wake Alarm"
21+
unique_id: carlo_bedroom_wake_alarm
22+
device_class: timestamp
23+
icon: mdi:alarm
24+
state: >
25+
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
26+
{% set primary = states('sensor.carlo_bedroom_next_alarm') %}
27+
{% set secondary = states('sensor.carlo_bedroom_next_alarm_2') %}
28+
{% set value = primary if primary not in invalid else secondary %}
29+
{% set ts = as_timestamp(value, none) %}
30+
{{ ts | timestamp_local if ts is not none else none }}
31+
- name: "Stacey Bedroom Wake Alarm"
32+
unique_id: stacey_bedroom_wake_alarm
33+
device_class: timestamp
34+
icon: mdi:alarm
35+
state: >
36+
{% set invalid = ['unknown', 'unavailable', 'none', ''] %}
37+
{% set primary = states('sensor.stacey_bedroom_next_alarm') %}
38+
{% set secondary = states('sensor.stacey_bedroom_next_alarm_2') %}
39+
{% set value = primary if primary not in invalid else secondary %}
40+
{% set ts = as_timestamp(value, none) %}
41+
{{ ts | timestamp_local if ts is not none else none }}
42+
- name: "Bedroom Next Wake Alarm"
43+
unique_id: bedroom_next_wake_alarm
44+
device_class: timestamp
45+
icon: mdi:alarm
46+
state: >
47+
{% set now_ts = as_timestamp(now()) %}
48+
{% set max_ts = now_ts + 172800 %}
49+
{% set carlo_raw = states('sensor.carlo_bedroom_next_alarm') %}
50+
{% set carlo_fallback = states('sensor.carlo_bedroom_next_alarm_2') %}
51+
{% set stacey_raw = states('sensor.stacey_bedroom_next_alarm') %}
52+
{% set stacey_fallback = states('sensor.stacey_bedroom_next_alarm_2') %}
53+
{% set carlo_ts = as_timestamp(carlo_raw, none) if carlo_raw not in ['unknown', 'unavailable', 'none', ''] else as_timestamp(carlo_fallback, none) %}
54+
{% set stacey_ts = as_timestamp(stacey_raw, none) if stacey_raw not in ['unknown', 'unavailable', 'none', ''] else as_timestamp(stacey_fallback, none) %}
55+
{% set carlo_ok = carlo_ts is not none and carlo_ts >= (now_ts - 900) and carlo_ts <= max_ts %}
56+
{% set stacey_ok = stacey_ts is not none and stacey_ts >= (now_ts - 900) and stacey_ts <= max_ts %}
57+
{% if carlo_ok and stacey_ok %}
58+
{{ [carlo_ts, stacey_ts] | min | timestamp_local }}
59+
{% elif carlo_ok %}
60+
{{ carlo_ts | timestamp_local }}
61+
{% elif stacey_ok %}
62+
{{ stacey_ts | timestamp_local }}
63+
{% else %}
64+
{{ none }}
65+
{% endif %}
66+
- name: "Bedroom Next Wake Alarm Source"
67+
unique_id: bedroom_next_wake_alarm_source
68+
icon: mdi:account-voice
69+
state: >
70+
{% set now_ts = as_timestamp(now()) %}
71+
{% set max_ts = now_ts + 172800 %}
72+
{% set carlo_raw = states('sensor.carlo_bedroom_next_alarm') %}
73+
{% set carlo_fallback = states('sensor.carlo_bedroom_next_alarm_2') %}
74+
{% set stacey_raw = states('sensor.stacey_bedroom_next_alarm') %}
75+
{% set stacey_fallback = states('sensor.stacey_bedroom_next_alarm_2') %}
76+
{% set carlo_ts = as_timestamp(carlo_raw, none) if carlo_raw not in ['unknown', 'unavailable', 'none', ''] else as_timestamp(carlo_fallback, none) %}
77+
{% set stacey_ts = as_timestamp(stacey_raw, none) if stacey_raw not in ['unknown', 'unavailable', 'none', ''] else as_timestamp(stacey_fallback, none) %}
78+
{% set carlo_ok = carlo_ts is not none and carlo_ts >= (now_ts - 900) and carlo_ts <= max_ts %}
79+
{% set stacey_ok = stacey_ts is not none and stacey_ts >= (now_ts - 900) and stacey_ts <= max_ts %}
80+
{% if carlo_ok and stacey_ok %}
81+
{{ 'Carlo Bedroom' if carlo_ts <= stacey_ts else 'Stacey Bedroom' }}
82+
{% elif carlo_ok %}
83+
Carlo Bedroom
84+
{% elif stacey_ok %}
85+
Stacey Bedroom
86+
{% else %}
87+
none
88+
{% endif %}
89+
- name: "Bedroom Next Wake Alarm Minutes"
90+
unique_id: bedroom_next_wake_alarm_minutes
91+
unit_of_measurement: min
92+
state_class: measurement
93+
icon: mdi:timer-outline
94+
state: >
95+
{% set now_ts = as_timestamp(now()) %}
96+
{% set max_ts = now_ts + 172800 %}
97+
{% set carlo_raw = states('sensor.carlo_bedroom_next_alarm') %}
98+
{% set carlo_fallback = states('sensor.carlo_bedroom_next_alarm_2') %}
99+
{% set stacey_raw = states('sensor.stacey_bedroom_next_alarm') %}
100+
{% set stacey_fallback = states('sensor.stacey_bedroom_next_alarm_2') %}
101+
{% set carlo_ts = as_timestamp(carlo_raw, none) if carlo_raw not in ['unknown', 'unavailable', 'none', ''] else as_timestamp(carlo_fallback, none) %}
102+
{% set stacey_ts = as_timestamp(stacey_raw, none) if stacey_raw not in ['unknown', 'unavailable', 'none', ''] else as_timestamp(stacey_fallback, none) %}
103+
{% set carlo_ok = carlo_ts is not none and carlo_ts >= (now_ts - 900) and carlo_ts <= max_ts %}
104+
{% set stacey_ok = stacey_ts is not none and stacey_ts >= (now_ts - 900) and stacey_ts <= max_ts %}
105+
{% if carlo_ok and stacey_ok %}
106+
{{ ((([carlo_ts, stacey_ts] | min) - now_ts) / 60) | round(0) }}
107+
{% elif carlo_ok %}
108+
{{ ((carlo_ts - now_ts) / 60) | round(0) }}
109+
{% elif stacey_ok %}
110+
{{ ((stacey_ts - now_ts) / 60) | round(0) }}
111+
{% else %}
112+
{{ none }}
113+
{% endif %}
114+
- binary_sensor:
115+
- name: "Carlo Bedroom Wake Alarm Armed"
116+
unique_id: carlo_bedroom_wake_alarm_armed
117+
icon: mdi:alarm-check
118+
state: >
119+
{% set now_ts = as_timestamp(now()) %}
120+
{% set max_ts = now_ts + 172800 %}
121+
{% set primary = states('sensor.carlo_bedroom_next_alarm') %}
122+
{% set secondary = states('sensor.carlo_bedroom_next_alarm_2') %}
123+
{% set value = primary if primary not in ['unknown', 'unavailable', 'none', ''] else secondary %}
124+
{% set ts = as_timestamp(value, none) %}
125+
{{ ts is not none and ts >= now_ts and ts <= max_ts }}
126+
- name: "Stacey Bedroom Wake Alarm Armed"
127+
unique_id: stacey_bedroom_wake_alarm_armed
128+
icon: mdi:alarm-check
129+
state: >
130+
{% set now_ts = as_timestamp(now()) %}
131+
{% set max_ts = now_ts + 172800 %}
132+
{% set primary = states('sensor.stacey_bedroom_next_alarm') %}
133+
{% set secondary = states('sensor.stacey_bedroom_next_alarm_2') %}
134+
{% set value = primary if primary not in ['unknown', 'unavailable', 'none', ''] else secondary %}
135+
{% set ts = as_timestamp(value, none) %}
136+
{{ ts is not none and ts >= now_ts and ts <= max_ts }}
137+
- name: "Bedroom Next Wake Alarm Armed"
138+
unique_id: bedroom_next_wake_alarm_armed
139+
icon: mdi:alarm-check
140+
state: >
141+
{{ states('sensor.bedroom_next_wake_alarm') not in ['unknown', 'unavailable', 'none', ''] }}
142+
- name: "Bedroom Next Wake Alarm Active"
143+
unique_id: bedroom_next_wake_alarm_active
144+
icon: mdi:alarm-light
145+
state: >
146+
{% set next_alarm = as_timestamp(states('sensor.bedroom_next_wake_alarm'), none) %}
147+
{% set now_ts = as_timestamp(now()) %}
148+
{{ next_alarm is not none and now_ts >= next_alarm and now_ts <= (next_alarm + 900) }}

config/recorder.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# Recorder Configuration - database retention and exclusions
77
# Stores HA history while purging noise and controlling DB size.
88
# -------------------------------------------------------------------
9-
# Notes: Keeps 180 days (1/2 year); excludes vcloudinfo pings, noisy connectivity telemetry, and other high-churn entities; MariaDB via recorder_db_url.
9+
# Notes: Keeps 180 days (1/2 year); excludes vcloudinfo pings, noisy connectivity telemetry, countdown-style alarm helpers, and other high-churn entities; MariaDB via recorder_db_url.
1010
######################################################################
1111
db_url: !secret recorder_db_url
1212
purge_keep_days: 180
@@ -56,6 +56,7 @@ exclude:
5656
- sensor.*_wi_fi_signal
5757
- sensor.*_wifi_signal
5858
- sensor.*_wifi_signal_strength
59+
- sensor.*_wake_alarm_minutes
5960
- sensor.*_temperature_state
6061
- sensor.*_humidity_state
6162
- sensor.*_last_seen*

0 commit comments

Comments
 (0)