|
145 | 145 | (c.condition or null) == "state" && (c.entity_id or null) == entityId && (c.state or null) == state |
146 | 146 | ) conditions; |
147 | 147 |
|
| 148 | + hasStateConditionDeep = |
| 149 | + conditions: entityId: state: |
| 150 | + any ( |
| 151 | + c: |
| 152 | + ( |
| 153 | + (c.condition or null) == "state" && (c.entity_id or null) == entityId && (c.state or null) == state |
| 154 | + ) |
| 155 | + || (if c ? conditions then hasStateConditionDeep (toList c.conditions) entityId state else false) |
| 156 | + ) conditions; |
| 157 | + |
148 | 158 | toList = |
149 | 159 | v: |
150 | 160 | if builtins.isList v then |
|
175 | 185 | voiceWebhookSleep = findAutomation "voice_webhook_sleep"; |
176 | 186 | voiceWebhookInBed = findAutomation "voice_webhook_in_bed"; |
177 | 187 | bedtimeNudgeWebhook = findAutomation "bedtime_nudge_webhook"; |
178 | | - whiteNoiseAfterBothInBed = findAutomation "white_noise_after_both_in_bed"; |
| 188 | + whiteNoiseWithBedtimeAudiobook = findAutomation "white_noise_with_bedtime_audiobook"; |
179 | 189 | syncIphoneAlarm8sleep = findAutomation "sync_iphone_alarm_8sleep"; |
180 | 190 | sleepFocusOffEdmund = findAutomation "sleep_focus_off_stop_edmund"; |
181 | 191 | sleepFocusOffMonica = findAutomation "sleep_focus_off_stop_monica"; |
@@ -262,44 +272,48 @@ let |
262 | 272 | msg = "automation 'bedtime_nudge_webhook' missing"; |
263 | 273 | } |
264 | 274 | { |
265 | | - test = whiteNoiseAfterBothInBed != null; |
266 | | - msg = "automation 'white_noise_after_both_in_bed' missing"; |
| 275 | + test = whiteNoiseWithBedtimeAudiobook != null; |
| 276 | + msg = "automation 'white_noise_with_bedtime_audiobook' missing"; |
267 | 277 | } |
268 | 278 | { |
269 | | - test = hasStateTrigger whiteNoiseAfterBothInBed "input_boolean.sleep_done" "on"; |
270 | | - msg = "white_noise_after_both_in_bed must trigger when sleep_done turns on"; |
| 279 | + test = hasStateTrigger whiteNoiseWithBedtimeAudiobook "input_boolean.sleep_done" "on"; |
| 280 | + msg = "white_noise_with_bedtime_audiobook must trigger when sleep_done turns on"; |
271 | 281 | } |
272 | 282 | { |
273 | | - test = hasStateTriggerAny whiteNoiseAfterBothInBed "sensor.edmund_s_eight_sleep_side_heart_rate"; |
274 | | - msg = "white_noise_after_both_in_bed must trigger when Edmund heart rate updates"; |
| 283 | + test = hasStateTrigger whiteNoiseWithBedtimeAudiobook "media_player.bathroom_nightstand" "playing"; |
| 284 | + msg = "white_noise_with_bedtime_audiobook must trigger when bathroom nightstand starts playing"; |
275 | 285 | } |
276 | 286 | { |
277 | | - test = hasStateTriggerAny whiteNoiseAfterBothInBed "sensor.monica_s_eight_sleep_side_heart_rate"; |
278 | | - msg = "white_noise_after_both_in_bed must trigger when Monica heart rate updates"; |
| 287 | + test = hasStateTrigger whiteNoiseWithBedtimeAudiobook "media_player.window_nightstand" "playing"; |
| 288 | + msg = "white_noise_with_bedtime_audiobook must trigger when window nightstand starts playing"; |
279 | 289 | } |
280 | 290 | { |
281 | 291 | test = |
282 | 292 | let |
283 | | - conditions = toList (whiteNoiseAfterBothInBed.condition or [ ]); |
284 | | - templates = map (c: c.value_template or "") conditions; |
285 | | - hasTemplate = needle: any (t: hasInfix needle t) templates; |
| 293 | + conditions = toList (whiteNoiseWithBedtimeAudiobook.condition or [ ]); |
| 294 | + hasBedroomSpeakerOr = any ( |
| 295 | + c: |
| 296 | + (c.condition or null) == "or" |
| 297 | + && hasStateCondition (toList (c.conditions or [ ])) "media_player.bathroom_nightstand" "playing" |
| 298 | + && hasStateCondition (toList (c.conditions or [ ])) "media_player.window_nightstand" "playing" |
| 299 | + ) conditions; |
286 | 300 | in |
287 | 301 | hasStateCondition conditions "input_boolean.goodnight" "on" |
288 | 302 | && hasStateCondition conditions "input_boolean.sleep_done" "on" |
289 | | - && hasTemplate "sensor.edmund_s_eight_sleep_side_heart_rate" |
290 | | - && hasTemplate "sensor.monica_s_eight_sleep_side_heart_rate" |
291 | | - && hasTemplate "last_updated" |
292 | | - && hasTemplate "hr >= 35" |
293 | | - && hasTemplate "hr <= 130" |
294 | | - && !(hasStateCondition conditions "binary_sensor.edmund_bed_presence_reliable" "on") |
295 | | - && !(hasStateCondition conditions "binary_sensor.monica_bed_presence_reliable" "on"); |
296 | | - msg = "white_noise_after_both_in_bed must require goodnight, sleep_done, and fresh human heart-rate signals instead of bed presence"; |
| 303 | + && hasBedroomSpeakerOr |
| 304 | + && !(hasStateConditionDeep conditions "binary_sensor.edmund_bed_presence_reliable" "on") |
| 305 | + && !(hasStateConditionDeep conditions "binary_sensor.monica_bed_presence_reliable" "on") |
| 306 | + && !(hasStateTriggerAny whiteNoiseWithBedtimeAudiobook "sensor.edmund_s_eight_sleep_side_heart_rate") |
| 307 | + && !(hasStateTriggerAny whiteNoiseWithBedtimeAudiobook "sensor.monica_s_eight_sleep_side_heart_rate"); |
| 308 | + msg = "white_noise_with_bedtime_audiobook must require goodnight, sleep_done, and either bedroom speaker playing without bed-presence or HR gates"; |
297 | 309 | } |
298 | 310 | { |
299 | 311 | test = |
300 | | - hasActionCall (toList (whiteNoiseAfterBothInBed.action or [ ])) "switch.turn_on" |
301 | | - && hasTargetEntity (toList (whiteNoiseAfterBothInBed.action or [ ])) "switch.eve_energy_20ebu4101"; |
302 | | - msg = "white_noise_after_both_in_bed must turn on the whitenoise machine"; |
| 312 | + hasActionCall (toList (whiteNoiseWithBedtimeAudiobook.action or [ ])) "switch.turn_on" |
| 313 | + && hasTargetEntity (toList ( |
| 314 | + whiteNoiseWithBedtimeAudiobook.action or [ ] |
| 315 | + )) "switch.eve_energy_20ebu4101"; |
| 316 | + msg = "white_noise_with_bedtime_audiobook must turn on the whitenoise machine"; |
303 | 317 | } |
304 | 318 | { |
305 | 319 | test = syncIphoneAlarm8sleep != null && (syncIphoneAlarm8sleep.initial_state or null) == false; |
@@ -494,11 +508,11 @@ let |
494 | 508 | } |
495 | 509 | { |
496 | 510 | test = (goodNightScene.entities."switch.eve_energy_20ebu4101" or null) == "off"; |
497 | | - msg = "Good Night scene must leave whitenoise off until bed-presence gate"; |
| 511 | + msg = "Good Night scene must leave whitenoise off until audiobook speaker gate"; |
498 | 512 | } |
499 | 513 | { |
500 | 514 | test = (sleepScene.entities."switch.eve_energy_20ebu4101" or null) == "off"; |
501 | | - msg = "Sleep scene must leave whitenoise off until bed-presence gate"; |
| 515 | + msg = "Sleep scene must leave whitenoise off until audiobook speaker gate"; |
502 | 516 | } |
503 | 517 | { |
504 | 518 | test = (sleepScene.entities."switch.desk_monitor" or null) == "off"; |
|
0 commit comments