Compare commits

...

53 Commits

Author SHA1 Message Date
a1b68f80b6 Changes for new version of Bubble Cards 2025-05-08 21:35:45 -04:00
adc4bc9b42 Update .HA_VERSION 2025-05-08 21:35:08 -04:00
1500151c12 Handle Tina's meds resetting when she wakes up #243 2025-05-07 11:48:56 -04:00
67d1d3d43e Fix #241 2025-04-29 18:11:36 -04:00
1c5ccbb926 Update time macros 2025-04-29 18:06:31 -04:00
5d4457c198 Adjust MBR climate scheduling 2025-04-29 01:54:06 -04:00
d16a0f8353 Update scheduled reset for wife's night meds 2025-04-29 01:53:40 -04:00
c8242c2fea Update .HA_VERSION 2025-04-29 01:52:52 -04:00
713ddb9f75 Fix Emma's climate scheduling using old logic 2025-04-28 21:33:49 -04:00
10d7ec5e03 Account for overtime in sports reports 2025-04-28 21:33:33 -04:00
95ffb38b7e Exclude RSSI sensors from recorder 2025-04-28 21:32:50 -04:00
b5c295a19d Add config stuff for new default theme 2025-04-24 01:51:11 -04:00
bd9dde2455 Remove eco mode sensors for aircons as they are no longer needed 2025-04-24 01:32:52 -04:00
857870e0b1 Add a few more lights to monitor for unintended switching 2025-04-19 22:50:35 -04:00
003fe6614d Update .HA_VERSION 2025-04-19 22:19:38 -04:00
364c81e8b1 Use night volumes if people are sleeping
#238
2025-04-19 14:37:47 -04:00
0d42142a07 Simplify default speaker volume settings
#238
2025-04-19 14:30:41 -04:00
7d6d72c6ef Update eco mode sensors to reflect new Midea integration in use 2025-04-19 13:58:08 -04:00
41228c1304 Gotta actually CALL an entity to run a service on it...fix #216 2025-04-18 17:49:48 -04:00
b4f4d06d6c Fix scenes using deprecated Hue effect "None" 2025-04-18 17:32:20 -04:00
002919483f Lower-case format period_str 2025-04-16 14:35:14 -04:00
ef548c2df1 Use period_str instead of "inning" 2025-04-16 14:32:28 -04:00
1d60a4df32 Update .HA_VERSION 2025-04-16 14:31:19 -04:00
57c27d4e48 Sports updates are now clock/inning aware
We know at LEAST baseball works. Will have to test hockey at the start of the playoffs in a few days, and football later this year.
2025-04-16 14:23:53 -04:00
c06bd894ae Working on adding clock updates to sports update macros 2025-04-16 13:52:12 -04:00
1b3cf79f25 Reading mode for waifu
#236
2025-04-13 01:50:06 -04:00
7cf9c13e38 Sensor for unavailable lights due to potential light switch usage
home_automation/Home-Assistant-Configs#235
2025-04-13 01:29:20 -04:00
e8c6cd8deb Remove cache parameter from AWS Polly config 2025-04-05 17:14:54 -04:00
df92fc4df6 Remove amazon auto breaths from speech engine 2025-04-05 17:05:19 -04:00
a936b22bb9 Switch AWS Polly from neural voice engine to generative 2025-04-05 16:55:41 -04:00
9aa918d335 Rearrange reboot handling automation, add reset of night modes 2025-04-05 16:55:25 -04:00
c7d6297934 Update .HA_VERSION 2025-04-05 16:54:55 -04:00
ce29e80330 Try to fix Tina Desk Switch weirdness 2025-04-02 15:53:12 -04:00
10deee4f04 Always play Emma wakeup announcement, and play it in common areas 2025-03-29 01:15:20 -04:00
6fa762a113 Adjust scheduling for ridiculously OP air conditioner 2025-03-29 01:10:58 -04:00
7b529895e5 Whole fuckload of changes for Emma's new air conditioner 2025-03-28 21:56:58 -04:00
bdb278dd28 Adjust TTS briefings for K riding the bus
#219
2025-03-24 18:38:55 -04:00
000efa7562 Adjust status macros for K riding the bus
#219
2025-03-24 18:38:54 -04:00
b6911a0f59 Rework scheduling for K riding the bus
#219
2025-03-24 18:38:53 -04:00
d49563435d Raise threshold to show computers on, ignore idle power spikes
This caused my computer to briefly register as on, and thus my Awake switch was turned on and prevented Emma's door alert from playing in the bedroom
2025-03-24 18:38:38 -04:00
1a89d088f6 Automations to deal with Emma Awake toggle 2025-03-24 03:00:13 -04:00
ee6499bec8 Add option for Adjustment request in reporting system 2025-03-22 20:50:01 -04:00
148f78aecd Update .HA_VERSION 2025-03-22 07:20:42 -04:00
49f9e99439 Add warnings for considerable destructive t-storm, confirmed tornado 2025-03-19 17:11:34 -04:00
6254fb5953 Track new weather alert sensors for long-term stats 2025-03-18 01:38:17 -04:00
334b7963e8 Add ability to show when tornado production is possible 2025-03-18 01:37:52 -04:00
4466b17df1 Update .HA_VERSION 2025-03-17 16:12:03 -04:00
f96056edda Use correct sensor for master bedroom temperature in welcome home brief 2025-03-16 04:16:44 -04:00
652b4e7dff Additional editing added for weather briefing 2025-03-16 04:16:16 -04:00
26bcf136e6 Update med scripts to use AI-generated snark 2025-03-14 02:14:46 -04:00
9e90998a21 Update Kallen morning meds script, he can now mark morning meds himself 2025-03-14 00:59:22 -04:00
30c8307272 Improve aircon fan/compressor template sensors 2025-03-14 00:19:26 -04:00
e6b0db142e Update .HA_VERSION 2025-03-14 00:18:59 -04:00
26 changed files with 2018 additions and 936 deletions

View File

@ -1 +1 @@
2025.3.1
2025.5.0

View File

@ -311,38 +311,54 @@
- id: '1651787468337'
alias: Reboot handling
description: ''
trigger:
- platform: homeassistant
event: start
triggers:
- event: start
id: hass_start
- platform: homeassistant
event: shutdown
trigger: homeassistant
- event: shutdown
id: hass_stop
condition: []
action:
- if:
trigger: homeassistant
conditions: []
actions:
- alias: Routing
choose:
- conditions:
- condition: trigger
id: hass_start
alias: Startup
then:
sequence:
- delay:
hours: 0
minutes: 1
seconds: 0
milliseconds: 0
- service: automation.turn_on
data: {}
- data: {}
target:
entity_id:
- automation.family_has_arrived
- automation.family_has_left
- automation.scheduled_alarm_rearm
- automation.scheduled_alarm_disarm
- service: switch.turn_off
action: automation.turn_on
- if:
- condition: state
entity_id: binary_sensor.early_night_mode
state: 'off'
then:
- action: input_boolean.turn_off
metadata: {}
data: {}
target:
entity_id:
- input_boolean.give_me_darkness
- input_boolean.night_mode
- input_boolean.goodnight
alias: If early night mode is off, turn off other night-related modes
- target:
entity_id:
- switch.presence_simulation
data: {}
action: switch.turn_off
- if:
- condition: and
conditions:
@ -356,57 +372,57 @@
alias: Is early night mode on?
alias: Test conditions
then:
- service: switch.turn_on
data: {}
- data: {}
target:
entity_id: switch.animated_scene_{{ states('input_select.holiday_animation')
| lower }}
alias: Turn on the appropriate animated holiday scene
action: switch.turn_on
alias: Turn on animated holiday scene if night time and holiday mode is on
- service: script.tony_desktop_refresh
data: {}
- service: script.tina_desktop_refresh
data: {}
- service: script.asus_laptop_refresh
data: {}
- service: script.kallen_desktop_refresh
data: {}
- service: script.win10vm_refresh
data: {}
- service: mqtt.publish
data:
- data: {}
action: script.tony_desktop_refresh
- data: {}
action: script.tina_desktop_refresh
- data: {}
action: script.asus_laptop_refresh
- data: {}
action: script.kallen_desktop_refresh
- data: {}
action: script.win10vm_refresh
- data:
topic: house/basement/server/glances
payload: restart
qos: 0
retain: false
alias: Restart Glances via MQTT
- service: script.volume_reset
data: {}
action: mqtt.publish
- data: {}
alias: Reset all speaker volumes
action: script.volume_reset
- if:
- condition: state
entity_id: input_boolean.studio_quiet
state: 'off'
then:
- service: script.status_annc
data:
- data:
who: basement
call_ha_started: 1
action: script.status_annc
else:
- stop: Studio has requested quiet, and Jarvis respects this
alias: Announce back online, unless studio has requested quiet
- if:
- conditions:
- condition: trigger
id: hass_stop
alias: Shutdown
then:
- service: automation.turn_off
data:
sequence:
- data:
stop_actions: true
target:
entity_id:
- automation.family_has_arrived
- automation.family_has_left
action: automation.turn_off
mode: queued
- id: '1654547257475'
alias: Battery Monitoring
@ -514,127 +530,126 @@
- id: '1667341156218'
alias: White Noise
description: ''
trigger:
- platform: state
entity_id:
triggers:
- entity_id:
- input_boolean.white_noise_emma_bedroom
to: 'on'
from: 'off'
id: emma-on
alias: Emma On
- platform: state
entity_id:
trigger: state
- entity_id:
- input_boolean.white_noise_basement
to: 'on'
from: 'off'
id: basement-on
alias: Basement On
- platform: state
entity_id:
trigger: state
- entity_id:
- input_boolean.white_noise_kallen_bedroom
to: 'on'
from: 'off'
id: kallen-on
alias: Kallen On
- platform: state
entity_id:
trigger: state
- entity_id:
- input_boolean.white_noise_emma_bedroom
from: 'on'
to: 'off'
id: emma-off
alias: Emma Off
- platform: state
entity_id:
trigger: state
- entity_id:
- input_boolean.white_noise_basement
from: 'on'
to: 'off'
id: basement-off
alias: Basement Off
- platform: state
entity_id:
trigger: state
- entity_id:
- input_boolean.white_noise_kallen_bedroom
from: 'on'
to: 'off'
id: kallen-off
alias: Kallen Off
trigger: state
- alias: Emma Timeout
platform: state
id: emma-timeout
entity_id:
- media_player.emma_bedroom_google_speaker
to: 'off'
trigger: state
- alias: Basement Timeout
platform: state
id: basement-timeout
entity_id:
- media_player.basement_google_speaker
to: 'off'
trigger: state
- alias: Kallen Timeout
platform: state
id: kallen-timeout
entity_id:
- media_player.kallen_bedroom_google_speaker
to: 'off'
condition: []
action:
trigger: state
conditions: []
actions:
- choose:
- conditions:
- condition: trigger
id: emma-on
sequence:
- alias: Start river sounds
service: google_assistant_sdk.send_text_command
data:
command: give me river noise on emma bedroom speaker
- service: media_player.volume_set
data:
volume_level: '{{ states(''input_number.emma_bedroom_google_speaker_night_volume'')
action: google_assistant_sdk.send_text_command
- data:
volume_level: '{{ states(''sensor.emma_bedroom_google_speaker_volume'')
}}'
target:
entity_id: media_player.emma_bedroom_google_speaker
alias: Set volume
action: media_player.volume_set
alias: Emma On
- conditions:
- condition: trigger
id: basement-on
sequence:
- service: google_assistant_sdk.send_text_command
data:
- data:
command: give me thunderstorm sounds on basement studio speaker
alias: Start thunderstorm sounds
- service: media_player.volume_set
data:
volume_level: '{{ states(''input_number.basement_google_speaker_night_volume'')
}}'
action: google_assistant_sdk.send_text_command
- data:
volume_level: '{{ states(''sensor.basement_google_speaker_volume'') }}'
target:
entity_id: media_player.basement_google_speaker
alias: Set volume
action: media_player.volume_set
alias: Basement On
- conditions:
- condition: trigger
id: kallen-on
sequence:
- alias: Start river sounds
service: google_assistant_sdk.send_text_command
data:
command: give me river noise on kallen bedroom speaker
- service: media_player.volume_set
data:
volume_level: '{{ states(''input_number.kallen_bedroom_google_speaker_night_volume'')
action: google_assistant_sdk.send_text_command
- data:
volume_level: '{{ states(''sensor.kallen_bedroom_google_speaker_volume'')
}}'
target:
entity_id: media_player.kallen_bedroom_google_speaker
alias: Set volume
action: media_player.volume_set
alias: Kallen On
- conditions:
- condition: trigger
id: emma-off
sequence:
- service: media_player.turn_off
data: {}
- data: {}
target:
entity_id: media_player.emma_bedroom_google_speaker
alias: Turn off speaker
action: media_player.turn_off
- alias: If Emma is awake, reset volume
if:
- condition: state
@ -646,49 +661,44 @@
minutes: 0
seconds: 5
milliseconds: 0
- service: media_player.volume_set
data:
volume_level: "{% if is_state('input_boolean.give_me_darkness','on') %}\n
\ {{ states('input_number.emma_bedroom_google_speaker_night_volume')
}}\n{% else %}\n {{ states('input_number.emma_bedroom_google_speaker_day_volume')
}}\n{% endif %}\n"
- data:
volume_level: '{{ states(''sensor.emma_bedroom_google_speaker_volume'')
}}'
target:
entity_id: media_player.emma_bedroom_google_speaker
alias: Reset volume
action: media_player.volume_set
alias: Emma Off
- conditions:
- condition: trigger
id: basement-off
sequence:
- service: media_player.turn_off
data: {}
- data: {}
target:
entity_id: media_player.basement_google_speaker
alias: Turn off speaker
action: media_player.turn_off
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- service: media_player.volume_set
data:
volume_level: "{% if is_state('input_boolean.give_me_darkness','on') %}\n
{{ states('input_number.basement_google_speaker_night_volume') }}\n{%
else %}\n {{ states('input_number.basement_google_speaker_day_volume')
}}\n{% endif %}\n"
- data:
volume_level: '{{ states(''sensor.basement_google_speaker_volume'') }}'
target:
entity_id: media_player.basement_google_speaker
alias: Reset volume
action: media_player.volume_set
alias: Basement Off
- conditions:
- condition: trigger
id: kallen-off
sequence:
- service: media_player.turn_off
data: {}
- data: {}
target:
entity_id: media_player.kallen_bedroom_google_speaker
alias: Turn off speaker
action: media_player.turn_off
- alias: If Kallen is awake, reset volume
if:
- condition: and
@ -705,15 +715,13 @@
minutes: 0
seconds: 5
milliseconds: 0
- service: media_player.volume_set
data:
volume_level: "{% if is_state('input_boolean.give_me_darkness','on') %}\n
\ {{ states('input_number.kallen_bedroom_google_speaker_night_volume')
}}\n{% else %}\n {{ states('input_number.kallen_bedroom_google_speaker_day_volume')
}}\n{% endif %}\n"
- data:
volume_level: '{{ states(''sensor.kallen_bedroom_google_speaker_volume'')
}}'
target:
entity_id: media_player.kallen_bedroom_google_speaker
alias: Reset volume
action: media_player.volume_set
alias: Kallen Off
- conditions:
- condition: trigger
@ -733,16 +741,16 @@
seconds: 5
milliseconds: 0
- alias: Start river sounds
service: google_assistant_sdk.send_text_command
data:
command: give me river noise on emma bedroom speaker
- service: media_player.volume_set
data:
volume_level: '{{ states(''input_number.emma_bedroom_google_speaker_night_volume'')
action: google_assistant_sdk.send_text_command
- data:
volume_level: '{{ states(''sensor.emma_bedroom_google_speaker_volume'')
}}'
target:
entity_id: media_player.emma_bedroom_google_speaker
alias: Set volume
action: media_player.volume_set
alias: Emma Timeout
- conditions:
- condition: trigger
@ -762,16 +770,15 @@
seconds: 5
milliseconds: 0
- alias: Start thunderstorm sounds
service: google_assistant_sdk.send_text_command
data:
command: give me thunderstorm sounds on basement studio speaker
- service: media_player.volume_set
data:
volume_level: '{{ states(''input_number.basement_google_speaker_night_volume'')
}}'
action: google_assistant_sdk.send_text_command
- data:
volume_level: '{{ states(''sensor.basement_google_speaker_volume'') }}'
target:
entity_id: media_player.basement_google_speaker
alias: Set volume
action: media_player.volume_set
alias: Basement Timeout
- conditions:
- condition: trigger
@ -791,16 +798,16 @@
seconds: 5
milliseconds: 0
- alias: Start river sounds
service: google_assistant_sdk.send_text_command
data:
command: give me river noise on kallen bedroom speaker
- service: media_player.volume_set
data:
volume_level: '{{ states(''input_number.kallen_bedroom_google_speaker_night_volume'')
action: google_assistant_sdk.send_text_command
- data:
volume_level: '{{ states(''sensor.kallen_bedroom_google_speaker_volume'')
}}'
target:
entity_id: media_player.kallen_bedroom_google_speaker
alias: Set volume
action: media_player.volume_set
alias: Kallen Timeout
mode: parallel
max: 20
@ -1310,10 +1317,23 @@
input:
dimmer_device: 40c14ccfe958d21d75888a968bbbf908
on_short_action:
- data: {}
- if:
- condition: state
entity_id: light.tina_desk_lights
state: 'off'
then:
- action: input_select.select_option
metadata: {}
data:
option: Reset
target:
entity_id: input_select.tina_desk_scenes
else:
- action: light.turn_off
metadata: {}
data: {}
target:
entity_id: light.tina_desk_lights
action: light.turn_on
on_long_action:
- data:
option: Reset
@ -2612,100 +2632,100 @@
- id: '1696356974829'
alias: Scheduled Reset
description: Reset all context entities for the next day at the appropriate times
trigger:
- platform: time
at: 00:00:00
triggers:
- at: 00:00:00
id: midnight
- platform: time
at: input_datetime.audible_notification_on
trigger: time
- at: input_datetime.audible_notification_on
id: audible-on
- platform: time
at: input_datetime.kallen_school_day_end
trigger: time
- at: input_datetime.kallen_school_day_end
id: school-end
- platform: state
entity_id: sensor.twitch_ironnerd24
trigger: time
- entity_id: sensor.twitch_ironnerd24
from: streaming
to: offline
id: stream-offline
- platform: time
at: 04:00:00
trigger: state
- at: 04:00:00
id: 4am
- platform: time
at: '16:00:00'
id: 4pm
- platform: time
at: 06:00:00
trigger: time
- at: '12:00:00'
id: noon
trigger: time
- at: 06:00:00
id: 6am
condition: []
action:
trigger: time
conditions: []
actions:
- choose:
- conditions:
- condition: trigger
id: midnight
sequence:
- service: script.scheduling_reset
data: {}
- service: script.kallen_school_reset_late
data: {}
- service: automation.turn_on
target:
- data: {}
action: script.scheduling_reset
- data: {}
action: script.kallen_school_reset_late
- target:
entity_id:
- automation.scheduled_alarm_rearm
- automation.scheduled_alarm_disarm
data: {}
- service: input_boolean.turn_off
target:
action: automation.turn_on
- target:
entity_id:
- input_boolean.skip_disarm
- input_boolean.skip_rearm
data: {}
- service: counter.reset
target:
action: input_boolean.turn_off
- target:
entity_id:
- counter.back_door_opened_today
- counter.front_door_opened_today
- counter.basement_studio_door_opened_today
- counter.basement_led_strip_resets
data: {}
action: counter.reset
- conditions:
- condition: trigger
id:
- audible-on
sequence:
- service: script.reset_annc_switches
data: {}
- data: {}
action: script.reset_annc_switches
- conditions:
- condition: trigger
id: school-end
sequence:
- service: script.kallen_school_reset
data: {}
- data: {}
action: script.kallen_school_reset
- conditions:
- condition: trigger
id: stream-offline
sequence:
- service: input_boolean.turn_off
target:
- target:
entity_id: input_boolean.tony_streaming_today
data: {}
action: input_boolean.turn_off
- conditions:
- condition: trigger
id: 4am
sequence:
- service: input_boolean.turn_off
target:
- target:
entity_id:
- input_boolean.kallen_morning_meds_taken
- input_boolean.kallen_night_meds_taken
- input_boolean.tina_morning_meds_taken
- input_boolean.emma_scheduling_evening_ran
data: {}
- service: counter.reset
target:
action: input_boolean.turn_off
- target:
entity_id:
- counter.tony_morning_meds_reminder_count
- counter.tony_afternoon_meds_reminder_count
data: {}
action: counter.reset
- conditions:
- condition: trigger
id: 6am
@ -2715,19 +2735,16 @@
entity_id: sensor.twitch_ironnerd24
state: offline
then:
- service: input_boolean.turn_off
target:
- target:
entity_id: input_boolean.tony_streaming_today
data: {}
action: input_boolean.turn_off
- conditions:
- condition: trigger
id: 4pm
id:
- noon
sequence:
- service: input_boolean.turn_off
target:
entity_id:
- input_boolean.tina_night_meds_taken
data: {}
- stop: No current actions scheduled at noon, remove this action if this changes
mode: restart
- id: '1696361494561'
alias: Turn On Audible Notifications
@ -5030,38 +5047,6 @@
alias: Update Notification
mode: parallel
max: 10
- id: '1714595577405'
alias: Emma Bedroom Cooling
description: ''
trigger:
- platform: time
at: input_datetime.emma_bedroom_cooling
alias: At the scheduled cooling time
condition:
- condition: state
entity_id: input_boolean.emma_sleeping
state: 'off'
alias: If Emma is not already asleep
- condition: state
entity_id: input_select.scheduled_climate_mode_emma_bedroom
state: AC
alias: If the AC is scheduled to run
action:
- service: fan.turn_on
metadata: {}
data: {}
target:
entity_id: fan.emma_air_conditioner
alias: Turn on Emma's air conditioner
- service: script.text_notify
data:
who: parents
title: Emma Climate Schedule
message: The air conditioner in Emma's Bedroom has been activated.
type: normal
tag: emma-climate
alias: Send AC notification
mode: restart
- id: '1716497196985'
alias: Emma Bedtime Rescheduler
description: Keeps Emma's bedtime up-to-date with reality
@ -6097,3 +6082,94 @@
action: script.tina_tylenol
mode: parallel
max: 10
- id: '1742799079017'
alias: Emma Sleep Handling
description: Awareness of when Emma is asleep or wakes up
triggers:
- trigger: state
entity_id:
- input_boolean.emma_sleeping
from: 'on'
to: 'off'
id: sleep-off
alias: Sleep Off
- trigger: state
entity_id:
- binary_sensor.family_home
from: 'on'
to: 'off'
id: family-left
alias: Family Left
conditions: []
actions:
- action: input_boolean.turn_on
metadata: {}
data: {}
target:
entity_id: input_boolean.emma_awake
alias: Turn on Emma Awake
mode: restart
- id: '1746632520108'
alias: Tina Sleep Handling
description: Awareness of when Tina is asleep or wakes up
triggers:
- alias: Leave Home
entity_id: person.christina_stork
zone: zone.home
event: leave
id: wake-leave
trigger: zone
- alias: Sentence
command:
- Tina is awake
- Christina is awake
id: wake-sentence
trigger: conversation
- alias: Focus off
entity_id:
- binary_sensor.tinas_iphone_focus
from: 'on'
to: 'off'
for:
hours: 0
minutes: 0
seconds: 30
id: wake-focus
trigger: state
conditions: []
actions:
- alias: Routing
choose:
- conditions:
- condition: and
conditions:
- alias: Wakeup
condition: trigger
id:
- wake-sentence
- wake-focus
- wake-leave
- condition: state
entity_id: input_boolean.tina_awake
state: 'off'
alias: Wakeup Trigger
sequence:
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Set context that Tina is awake
data: {}
action: input_boolean.turn_on
target:
entity_id: input_boolean.tina_awake
- action: input_boolean.turn_off
metadata: {}
data: {}
target:
entity_id:
- input_boolean.tina_morning_meds_taken
- input_boolean.tina_night_meds_taken
alias: Reset Tina meds taken switches
mode: restart

View File

@ -32,8 +32,16 @@ frontend:
extra_module_url:
- /hacsfiles/hass-hue-icons/hass-hue-icons.js
- /hacsfiles/hass-bha-icons/hass-bha-icons.js
- /hacsfiles/material-you-utilities/material-you-utilities.min.js
javascript_version: latest
panel_custom:
- name: material-you-panel
url_path: material-you-configuration
sidebar_title: Material You Utilities
sidebar_icon: mdi:material-design
module_url: /hacsfiles/material-you-utilities/material-you-utilities.min.js
http:
use_x_forwarded_for: true
trusted_proxies:
@ -107,6 +115,7 @@ recorder:
- sensor.*gpu_core_load
- sensor.portainer*
- sensor.mosquitto*
- sensor.*_rssi
entities:
- sensor.avg_ping
- sensor.max_ping
@ -321,6 +330,9 @@ influxdb:
- sensor.dimmest_room
- sensor.warmest_room_temperature
- sensor.coldest_room_temperature
- sensor.national_tornado_warnings
- sensor.national_severe_thunderstorm_warnings
- binary_sensor.severe_thunderstorm_warning
logbook:
include:
@ -498,3 +510,6 @@ prometheus:
- sensor.dimmest_room
- sensor.warmest_room_temperature
- sensor.coldest_room_temperature
- sensor.national_tornado_warnings
- sensor.national_severe_thunderstorm_warnings
- binary_sensor.severe_thunderstorm_warning

View File

@ -203,6 +203,8 @@
'today': 'vandaag',
'tomorrow': 'morgen',
'yesterday': 'gisteren',
'next': 'volgende',
'last': 'afgelopen',
},
'days':[
"maandag",
@ -226,12 +228,30 @@
'oktober',
'november',
'december',
]
],
'time_of_hour':{
0: '{hour} uur',
1: '1 over {hour}',
15: 'kwart over {hour}',
30: 'half {hour}',
45: 'kwart voor {hour}',
59: '1 voor {hour}',
'past_hour': '{minute} over {hour}',
'to_hour': '{minute} voor {hour}',
'to_half_hour': '{minute} voor half {hour}',
'past_half_hour': '{minute} over half {hour}',
'half_hour': 'half {hour}',
'use_twelve': true,
},
'time_of_day':{
'midnight': 'middernacht',
'noon': 'middag',
},
},
'sv':{
'_language': 'Svenska',
'and': 'och',
'in': 'i',
'in': 'om',
'ago': 'sedan',
'now': 'nu',
'lose': 'förlora',
@ -273,6 +293,7 @@
'today': 'idag',
'tomorrow': 'imorgon',
'yesterday': 'igår',
'next': 'nästa',
},
'days':[
"måndag",
@ -302,7 +323,7 @@
'_language': 'Deutsch',
'and': 'und',
'in': 'in',
'ago': 'vor',
'ago': 'vor %s',
'now': 'jetzt',
'lose': 'Du verlierst',
'gain': 'Du gewinnst',
@ -363,7 +384,7 @@
'Juli',
'August',
'September',
'October',
'Oktober',
'November',
'Dezember',
]
@ -623,6 +644,8 @@
'today': "aujourd'hui",
'tomorrow': 'demain',
'yesterday': 'hier',
'next': 'prochain',
'last': 'dernier',
},
'days':[
"lundi",
@ -693,6 +716,8 @@
'today': 'hoy',
'tomorrow': 'mañana',
'yesterday': 'ayer',
'next': 'el próximo',
'last': 'el pasado',
},
'days':[
'lunes',
@ -711,12 +736,26 @@
'mayo',
'junio',
'julio',
'agosto'
'agosto',
'septiembre',
'octubre',
'noviembre',
'diciembre'
]
],
'time_of_hour':{
0: '{hour} en punto',
1: '{hour} y un minuto',
15: '{hour} y quarto',
30: '{hour} y media',
45: '{hour} menos quarto',
59: '{hour} menos uno',
'past_hour': '{hour} y {minute}',
'to_hour': '{hour} menos {minute}',
},
'time_of_day':{
'midnight': 'medianoche',
'noon': 'mediodía',
},
},
'it':{
'_language': 'Italiano',
@ -865,9 +904,9 @@
'and': 'i',
'in': 'u',
'ago': 'prije',
'now': 'sad',
'now': 'sada',
'lose': 'gubiš',
'gain': 'dobijaš',
'gain': 'dobivaš',
'time':{
'format': '24-hr',
'year': [
@ -905,8 +944,8 @@
'today': 'danas',
'tomorrow': 'sutra',
'yesterday': 'jučer',
'next': 'slijedeći',
'last': 'prošli',
'next': 'sljedeći',
'last': 'protekli',
},
'days':[
"Ponedjeljak",
@ -1003,11 +1042,421 @@
'Listopad',
'Grudzień',
]
},
'ru':{
'_language': 'Русский',
'and': 'и',
'in': 'в',
'ago': 'назад',
'now': 'сейчас',
'lose': 'уменьшение',
'gain': 'увеличение',
'time':{
'format': '24-hr',
'year': [
'г',
'год',
'лет',
],
'week': [
'нед',
'неделя',
'недель',
],
'day': [
'д',
'день',
'дней',
],
'hour': [
'ч',
'час',
'часов',
],
'minute': [
'мин',
'минута',
'минут',
],
'second': [
'сек',
'секунда',
'секунд',
],
},
'delta':{
'today': 'сегодня',
'tomorrow': 'завтра',
'yesterday': 'вчера',
'next': 'следующий',
'last': 'последний',
},
'days':[
"Понедельник",
"Вторник",
"Среда",
"Четверг",
"Пятница",
"Суббота",
"Воскресенье",
],
'months':[
'Январь',
'Февраль',
'Март',
'Апрель',
'Май',
'Июнь',
'Июль',
'Август',
'Сентябрь',
'Октябрь',
'Ноябрь',
'Декабрь',
],
'time_of_hour':{
0: '{hour} часов ровно',
1: '{hour} и 1 минута',
15: '{hour} с четвертью',
30: '{hour} с половиной',
45: 'без четверти {hour}',
59: 'без минуты {hour}',
'past_hour': '{hour} и {minute} минут',
'to_hour': 'без {minute} минут {hour}',
},
'time_of_day':{
'midnight': 'полночь',
'noon': 'полдень',
},
},
'uk':{
'_language': 'Українська',
'and': 'і',
'in': 'в',
'ago': 'тому',
'now': 'зараз',
'lose': 'зменшення',
'gain': 'збільшення',
'time':{
'format': '24-hr',
'year': [
'р',
'рік',
'роки',
],
'week': [
'тиж',
'тиждень',
'тижні',
],
'day': [
'д',
'день',
'дні',
],
'hour': [
'год',
'година',
'години',
],
'minute': [
'хв',
'хвилина',
'хвилини',
],
'second': [
'сек',
'секунда',
'секунди',
],
},
'delta':{
'today': 'сьогодні',
'tomorrow': 'завтра',
'yesterday': 'вчора',
'next': 'наступний',
'last': 'останній',
},
'days':[
"Понеділок",
"Вівторок",
"Середа",
"Четвер",
"П'ятниця",
"Субота",
"Неділя",
],
'months':[
'Січень',
'Лютий',
'Березень',
'Квітень',
'Травень',
'Червень',
'Липень',
'Серпень',
'Вересень',
'Жовтень',
'Листопад',
'Грудень',
],
'time_of_hour':{
0: '{hour} годин',
1: '{hour} годин(а) одна хвилина',
15: 'чверть на {hour}',
30: 'пів на {hour}',
45: 'за чверть {hour}',
59: 'за хвилину {hour}',
'past_hour': '{hour} та {minute} хвилин',
'to_hour': 'за {minute} хвилин {hour}',
},
'time_of_day':{
'midnight': 'опівночі',
'noon': 'опівдні',
},
},
'zh-Hans':{
'_language': '简体中文',
'and': '',
'in': '',
'ago': '之前',
'now': '现在',
'lose': '失去',
'gain': '获得',
'time':{
'format': '24-hr',
'year': [
'年',
'年',
'年',
],
'week': [
'周',
'星期',
'星期',
],
'day': [
'天',
'天',
'天',
],
'hour': [
'时',
'小时',
'小时',
],
'minute': [
'分',
'分钟',
'分钟',
],
'second': [
'秒',
'秒',
'秒',
],
},
'delta':{
'today': '今天',
'tomorrow': '明天',
'yesterday': '昨天',
'next': '下一个',
'last': '上一个',
},
'days':[
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
"星期日",
],
'months':[
'一月',
'二月',
'三月',
'四月',
'五月',
'六月',
'七月',
'八月',
'九月',
'十月',
'十一月',
'十二月',
],
'time_of_day':{
'midnight': '午夜',
'noon': '正午',
},
},
'ko':{
'_language':'Korean',
'and':'',
'in':'후',
'ago':'전',
'now':'지금',
'lose':'감소',
'gain':'증가',
'time':{
'format':'24-hr',
'year':[
'년',
'년',
'년',
],
'week':[
'주',
'주',
'주',
],
'day':[
'일',
'일',
'일',
],
'hour':[
'시',
'시간',
'시간',
],
'minute':[
'분',
'분',
'분',
],
'second':[
'초',
'초',
'초',
],
},
'delta':{
'today':'오늘',
'tomorrow':'내일',
'yesterday':'어제',
'next':'다음',
'last':'지난',
},
'days':[
'월요일',
'화요일',
'수요일',
'목요일',
'금요일',
'토요일',
'일요일',
],
'months':[
'1월',
'2월',
'3월',
'4월',
'5월',
'6월',
'7월',
'8월',
'9월',
'10월',
'11월',
'12월',
],
'time_of_day':{
'midnight':'자정',
'noon':'정오',
},
},
'cs': {
'_language': 'Čeština',
'and': 'a',
'in': 'za',
'ago': 'před %s',
'now': 'nyní',
'lose': 'ztratit',
'gain': 'získat',
'time': {
'format': '12-hodin',
'year': [
'rok',
'rok',
'roky'
],
'week': [
'týd',
'týden',
'týdny'
],
'day': [
'd',
'den',
'dny'
],
'hour': [
'hod',
'hodina',
'hodiny'
],
'minute': [
'min',
'minuta',
'minuty'
],
'second': [
'sek',
'sekunda',
'sekundy'
]
},
'delta': {
'today': 'dnes',
'tomorrow': 'zítra',
'yesterday': 'včera',
'next': 'příští',
'last': 'poslední'
},
'days': [
'Pondělí',
'Úterý',
'Středa',
'Čtvrtek',
'Pátek',
'Sobota',
'Neděle'
],
'months': [
'Leden',
'Únor',
'Březen',
'Duben',
'Květen',
'Červen',
'Červenec',
'Srpen',
'Září',
'Říjen',
'Listopad',
'Prosinec'
],
'time_of_hour': {
0: '{hour} hodin',
1: 'minuta po {hour}',
15: 'čtvrt na {hour}',
30: 'půl {hour}',
45: 'tři čtvrtě na {hour}',
59: 'minuta do {hour}',
'past_hour': '{minute} po {hour}',
'to_hour': '{minute} do {hour}'
},
'time_of_day': {
'midnight': 'půlnoc',
'noon': 'poledne'
}
}
} %}
{# DO NOT MODIFY BELOW THIS LINE #}
{% set valid_entity_id_pattern = '^(?!.+__)(?!_)[\\da-z_]+(?<!_)\\.(?!_)[\\da-z_]+(?<!_)$' %}
{% set _bad_value = '?' %}
{% set _durations = {
'year': 31536000,
@ -1091,10 +1540,10 @@
{%- endmacro -%}
{%- macro _check_for_duration_sensor(input) %}
{%- if input is string and input | regex_search('^(?!.+__)(?!_)[\da-z_]+(?<!_)\.(?!_)[\da-z_]+(?<!_)$') and input.startswith('sensor') and states[input] is not none and states[input].attributes.device_class is defined and states[input].attributes.unit_of_measurement is defined -%}
{%- if input is string and input | regex_search(valid_entity_id_pattern) and input.startswith('sensor') and states[input] is not none and states[input].attributes.device_class is defined and states[input].attributes.unit_of_measurement is defined -%}
{%- set obj = states[input] -%}
{%- set divisor = _duration_sensor.get(obj.attributes.unit_of_measurement) -%}
{{- (obj.state | float / divisor) | string | as_timedelta -}}
{%- set multiplier = _duration_sensor.get(obj.attributes.unit_of_measurement) -%}
{{- (obj.state | float * multiplier) | string | as_timedelta -}}
{%- else %}
{{- '' -}}
{%- endif -%}
@ -1116,7 +1565,7 @@
{#- assume time as string or entity_id -#}
{%- elif input is string and input not in ['', 'None'] -%}
{#- if entity_id -#}
{%- if input | regex_search('^(?!.+__)(?!_)[\da-z_]+(?<!_)\.(?!_)[\da-z_]+(?<!_)$') -%}
{%- if input | regex_search(valid_entity_id_pattern) -%}
{%- if attribute is not none and attribute is string -%}
{{- _to_datetime(state_attr(input, attribute), None) -}}
{%- elif input.startswith('input_datetime') and is_state_attr(input, 'has_date', False) -%}
@ -1201,7 +1650,7 @@
{%- set index = values.index(values | first | default) %}
{%- for item in values[index:] %}
{%- set duration = _durations.get(item, 1) %}
{%- set period = _periods.get(item, 1) %}
{%- set period = _periods.get(item, 0) %}
{%- set value = ((seconds // duration) % (period if period else duration)) | int %}
{%- if value > 0 or raw %}
{%- if ns.ret | length == 0 %}
@ -1252,8 +1701,8 @@
{%- endmacro %}
{%- macro _time_between(func, input1, attr1, utc1, input2, attr2, utc2) -%}
{%- set t1 = _to_datetime(input1, attr1, utc1) | as_datetime -%}
{%- set t2 = _to_datetime(input2, attr2, utc2) | as_datetime -%}
{%- set t1 = _to_datetime(input1, attr1, utc1) | as_datetime | as_local -%}
{%- set t2 = _to_datetime(input2, attr2, utc2) | as_datetime | as_local -%}
{%- if t1 is not none and t2 is not none -%}
{{- func(t1, t2) -}}
{%- else -%}
@ -1320,9 +1769,12 @@
{%- if uptime %}
{%- set value = _delta_seconds(now(), uptime) | int %}
{%- set seconds = value | abs %}
{%- set future = value / seconds > 0 %}
{%- set current = value == 0 %}
{%- set future = not current and value / seconds > 0 %}
{%- set items = _just_time(seconds, language, values, biggest, short=short, floor=floor) %}
{%- if future %}
{%- if current %}
{{- items }}
{%- elif future %}
{{- translate('in', language=language) }} {{ items }}
{%- else %}
{%- set t = translate('ago', language=language) %}
@ -1411,6 +1863,16 @@
{{- _next_weekday(weekday, -7) }}
{%- endmacro %}
{%- macro nearest_day(weekday) %}
{%- set today_timestamp = as_timestamp(today_at())|int %}
{%- set this_weekday_timestamp = as_timestamp(this_weekday(weekday))|int %}
{%- if today_timestamp < this_weekday_timestamp %}
{{- _next_weekday(weekday, 0) }}
{%- else %}
{{- _next_weekday(weekday, 7) }}
{%- endif %}
{%- endmacro %}
{%- macro days_in_month(month=None) %}
{%- set today = today_at() %}
{%- set input = month if month is not none else today.month %}
@ -1527,30 +1989,36 @@
{%- endif -%}
{%- endmacro -%}
{%- macro month(month=None, language=None) %}
{%- macro month(month=None, language=None, short=False) %}
{%- if month is datetime %}
{%- set idx = month.month - 1 %}
{%- elif month is integer and month > 0 %}
{%- set idx = (month - 1) % 12 %}
{%- elif month | regex_match(valid_entity_id_pattern) %}
{%- set idx = (states(month) | as_datetime | as_local).month - 1 %}
{%- else %}
{%- set idx = now().month - 1 %}
{%- endif %}
{{- translate('months', index=idx, language=language) }}
{%- set ret = translate('months', index=idx, language=language) %}
{{- ret[:3] if short else ret }}
{%- endmacro %}
{%- macro weekday(weekday=None, language=None) %}
{%- macro weekday(weekday=None, language=None, short=False) %}
{%- if weekday is datetime %}
{%- set idx = weekday.weekday() %}
{%- elif weekday is integer and weekday > 0 %}
{%- set idx = (weekday - 1) % 7 %}
{%- elif weekday | regex_match(valid_entity_id_pattern) %}
{%- set idx = (states(weekday) | as_datetime | as_local).weekday() %}
{%- else %}
{%- set idx = now().weekday() %}
{%- endif %}
{{- translate('days', index=idx, language=language) }}
{%- set ret = translate('days', index=idx, language=language) %}
{{- ret[:3] if short else ret }}
{%- endmacro %}
{%- macro count_the_days(input, attr, utc=False) %}
{%- set input = _to_datetime(input, attr, utc) | as_datetime %}
{%- set input = _to_datetime(input, attr, utc) | as_datetime | as_local %}
{%- set midnight = today_at() %}
{{- (input - midnight).days }}
{%- endmacro %}
@ -1561,7 +2029,7 @@
{%- set ns = namespace(days=[]) %}
{%- for i in range(-7, 14) %}
{%- set prefix = translate('delta', 'last', language=language) ~ ' ' if i < -1 else translate('delta', 'next', language=language) ~ ' ' if i > 6 else '' %}
{%- set ns.days = ns.days + [ (i | string, prefix ~ _days.get(i, weekday(midnight.weekday() + i + 1, language))) ] %}
{%- set ns.days = ns.days + [ (i | string, prefix ~ _days.get(i, weekday(midnight.weekday() + (i % 7) + 1, language))) ] %}
{%- endfor %}
{%- set collection = dict.from_keys(ns.days) %}
{%- set days = count_the_days(input, attr, utc) %}
@ -1586,16 +2054,20 @@
{%- macro hour(hour, language=None) %}
{%- if hour is datetime %}
{%- set hour = hour.hour %}
{%- elif hour | regex_match(valid_entity_id_pattern) %}
{%- set hour = (states(hour) | as_datetime | as_local).hour %}
{%- endif %}
{%- set _12 = not (hour % 12) %}
{%- set _24 = not (hour % 24) %}
{%- set _12hr = translate('time','format') == '12-hr' %}
{%- if _12 and _24 and _12hr %}
{%- set use_twelve = translate('time_of_day', 'use_twelve', language=language, fallback=false) %}
{%- set _12hr = translate('time','format', language=language) == '12-hr' %}
{%- if _12 and _24 and _12hr and not use_twelve %}
{{- translate('time_of_day', 'midnight', language=language) }}
{%- elif _12 and _12hr %}
{%- elif _12 and _12hr and not use_twelve %}
{{- translate('time_of_day', 'noon', language=language) }}
{%- else %}
{{- hour % 12 if _12hr else hour }}
{%- set ret = hour % 12 if _12hr else hour %}
{{- 12 if ret == 0 and use_twelve else ret }}
{%- endif %}
{%- endmacro %}
@ -1617,7 +2089,22 @@
{%- set hour_phrase = hour(this_hour, language=language) %}
{%- set minute_phrase = _phrase('minute', 60 * this_minute, language, True, True) if this_minute % 5 else this_minute | string %}
{%- endif %}
{%- if this_minute in [0, 1, 15, 30, 45, 59] %}
{%- set this_config = translate('time_of_hour', language=language) %}
{%- if (16 <= this_minute <= 29 and 'to_half_hour' in this_config) or (31 <= this_minute <= 44 and 'past_half_hour' in this_config) or (this_minute == 30 and 'half_hour' in this_config) %}
{%- set hour_phrase = hour(this_hour + 1, language=language) %}
{%- if 16 <= this_minute <= 29 %}
{%- set minute_calc = 30 - this_minute %}
{%- set fmat = translate('time_of_hour', 'to_half_hour', language=language) %}
{%- set minute_phrase = _phrase('minute', 60 * minute_calc, language, True, True) if this_minute % 5 else minute_calc | string %}
{%- elif 31 <= this_minute <= 44 %}
{%- set minute_calc = this_minute - 30 %}
{%- set fmat = translate('time_of_hour', 'past_half_hour', language=language) %}
{%- set minute_phrase = _phrase('minute', 60 * minute_calc, language, True, True) if this_minute % 5 else minute_calc | string %}
{%- else %}
{%- set minute_calc = None %}
{%- set fmat = translate('time_of_hour', 'half_hour', language=language) %}
{%- endif %}
{%- elif this_minute in [0, 1, 15, 30, 45, 59] %}
{%- if hour_phrase in ['noon', 'midnight'] and this_minute == 0 %}
{%- set fmat = '{hour}' %}
{%- else %}

View File

@ -1,234 +1,342 @@
{#
set phrases to be used in the relative_time_period macro
one list item per language, each time fraction contains a list with the singular, plural and abbriviated phrase
one list item per language, each time fraction contains a list with the short and several long forms of time units
combine contains the text to combine the last time fraction, and error the text to display on wrong date input
Plural forms for languages: https://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms
asian: ja, vi, ko
english: en, de, nl, sv, da, no, nb, nn, fo, es, pt, it, bg, el, fi, et, he, eo, hu, tr, ca
french: pt_BR, fr
latvian: lv
irish: ga
romanian: ro
lithuanian: lv
russian: ru, uk, be, sr, hr
slovak: cs, sk
polish: pl
slovenian: sl
arabic: ar
#}
{%- set _time_period_phrases = [
{
'language': 'en',
'plural_form': 'english',
'phrases': {
'year': ['year', 'years', 'yr'],
'month': ['month', 'months', 'mth'],
'week': ['week', 'weeks', 'wk'],
'day': ['day', 'days', 'day'],
'hour': ['hour', 'hours', 'hr'],
'minute': ['minute', 'minutes', 'min'],
'second': ['second', 'seconds', 'sec'],
'millisecond': ['millisecond', 'milliseconds', 'ms'],
'year': ['yr', 'year', 'years'],
'month': ['mth', 'month', 'months'],
'week': ['wk', 'week', 'weeks'],
'day': ['day', 'day', 'days'],
'hour': ['hr', 'hour', 'hours'],
'minute': ['min', 'minute', 'minutes'],
'second': ['sec', 'second', 'seconds'],
'millisecond': ['ms', 'millisecond', 'milliseconds'],
'combine': 'and',
'error': 'Invalid date',
}
},
{
'language': 'pl',
'plural_form': 'polish',
'phrases': {
'year': ['rok', 'lat', 'r'],
'month': ['miesiąc', 'miesięcy', 'msc'],
'week': ['tydzień', 'tygodni', 'tyg'],
'day': ['dzień', 'dni', 'dzień'],
'hour': ['godzina', 'godzin', 'godz'],
'minute': ['minuta', 'minut', 'min'],
'second': ['sekunda', 'sekund', 'sek'],
'millisecond': ['milisekunda', 'milisekund', 'ms'],
'year': ['r', 'rok', 'lata', 'lat'],
'month': ['msc', 'miesiąc', 'miesiące', 'miesięcy'],
'week': ['tyg', 'tydzień', 'tygodnie', 'tygodni'],
'day': ['dzień', 'dzień', 'dni', 'dni'],
'hour': ['godz', 'godzina', 'godziny', 'godzin'],
'minute': ['min', 'minuta', 'minuty', 'minut'],
'second': ['sek', 'sekunda', 'sekundy', 'sekund'],
'millisecond': ['ms', 'milisekunda', 'milisekundy', 'milisekund'],
'combine': 'i',
'error': 'Niepoprawna data',
}
},
{
'language': 'fr',
'plural_form': 'french',
'phrases': {
'year': ['année', 'années', 'an'],
'year': ['an', 'année', 'années'],
'month': ['mois', 'mois', 'mois'],
'week': ['semaine', 'semaines', 'sem'],
'day': ['jour', 'jours', 'j'],
'hour': ['heure', 'heures', 'h'],
'minute': ['minute', 'minutes', 'min'],
'second': ['seconde', 'secondes', 'sec'],
'millisecond': ['milliseconde', 'millisecondes', 'ms'],
'week': ['sem', 'semaine', 'semaines'],
'day': ['j', 'jour', 'jours'],
'hour': ['h', 'heure', 'heures'],
'minute': ['min', 'minute', 'minutes'],
'second': ['sec', 'seconde', 'secondes'],
'millisecond': ['ms', 'milliseconde', 'millisecondes'],
'combine': 'et',
'error': 'Date non valide',
}
},
{
'language': 'it',
'plural_form': 'english',
'phrases': {
'year': ['anno', 'anni', 'aa'],
'month': ['mese', 'mesi', 'mm'],
'week': ['settimana', 'settimane', 'set'],
'day': ['giorno', 'giorni', 'gg'],
'hour': ['ora', 'ore', 'h'],
'minute': ['minuto', 'minuti', 'min'],
'second': ['secondo', 'secondi', 'sec'],
'millisecond': ['millisecondo', 'millisecondi', 'ms'],
'year': ['aa', 'anno', 'anni'],
'month': ['mm', 'mese', 'mesi'],
'week': ['set', 'settimana', 'settimane'],
'day': ['gg', 'giorno', 'giorni'],
'hour': ['h', 'ora', 'ore'],
'minute': ['min', 'minuto', 'minuti'],
'second': ['sec', 'secondo', 'secondi'],
'millisecond': ['ms', 'millisecondo', 'millisecondi'],
'combine': 'e',
'error': 'Data non valida',
}
},
{
'language': 'nb',
'plural_form': 'english',
'phrases': {
'year': ['år', 'år', 'år'],
'month': ['måned', 'måneder', 'mnd'],
'week': ['uke', 'uker', 'u'],
'day': ['dag', 'dager', 'd'],
'hour': ['time', 'timer', 't'],
'minute': ['minutt', 'minutter', 'min'],
'second': ['sekund', 'sekunder', 'sek'],
'millisecond': ['millisekund', 'millisekunder', 'ms'],
'month': ['mnd', 'måned', 'måneder'],
'week': ['u', 'uke', 'uker'],
'day': ['d', 'dag', 'dager'],
'hour': ['t', 'time', 'timer'],
'minute': ['min', 'minutt', 'minutter'],
'second': ['sek', 'sekund', 'sekunder'],
'millisecond': ['ms', 'millisekund', 'millisekunder'],
'combine': 'og',
'error': 'Ugyldig dato',
}
},
{
'language': 'nl',
'plural_form': 'english',
'phrases': {
'year': ['jaar', 'jaar', 'jr'],
'month': ['maand', 'maanden', 'mnd'],
'week': ['week', 'weken', 'wk'],
'day': ['dag', 'dagen', 'dg'],
'hour': ['uur', 'uur', 'u'],
'minute': ['minuut', 'minuten', 'min'],
'second': ['seconde', 'seconden', 'sec'],
'millisecond': ['milliseconde', 'milliseconden', 'ms'],
'year': ['jr', 'jaar', 'jaar'],
'month': ['mnd', 'maand', 'maanden'],
'week': ['wk', 'week', 'weken'],
'day': ['dg', 'dag', 'dagen'],
'hour': ['u', 'uur', 'uur'],
'minute': ['min', 'minuut', 'minuten'],
'second': ['sec', 'seconde', 'seconden'],
'millisecond': ['ms', 'milliseconde', 'milliseconden'],
'combine': 'en',
'error': 'Ongeldige datum',
}
},
{
'language': 'nn',
'plural_form': 'english',
'phrases': {
'year': ['år', 'år', 'år'],
'month': ['månad', 'månader', 'mnd'],
'week': ['veke', 'veker', 'v'],
'day': ['dag', 'dagar', 'd'],
'hour': ['time', 'timar', 't'],
'minute': ['minutt', 'minutt', 'min'],
'second': ['sekund', 'sekund', 'sek'],
'millisecond': ['millisekund', 'millisekund', 'ms'],
'month': ['mnd', 'månad', 'månader'],
'week': ['v', 'veke', 'veker'],
'day': ['d', 'dag', 'dagar'],
'hour': ['t', 'time', 'timar'],
'minute': ['min', 'minutt', 'minutt'],
'second': ['sek', 'sekund', 'sekund'],
'millisecond': ['ms', 'millisekund', 'millisekund'],
'combine': 'og',
'error': 'Ugyldig dato',
}
},
{
'language': 'de',
'plural_form': 'english',
'phrases': {
'year': ['Jahr', 'Jahre', 'J.'],
'month': ['Monat', 'Monate', 'M.'],
'week': ['Woche', 'Wochen', 'Wo.'],
'day': ['Tag', 'Tage', 'Tg.'],
'hour': ['Stunde', 'Stunden', 'Std.'],
'minute': ['Minute', 'Minuten', 'Min.'],
'second': ['Sekunde', 'Sekunden', 'Sek.'],
'millisecond': ['Millisekunde', 'Millisekunden', 'ms'],
'year': ['J.', 'Jahr', 'Jahre'],
'month': ['M.', 'Monat', 'Monate'],
'week': ['Wo.', 'Woche', 'Wochen'],
'day': ['Tg.', 'Tag', 'Tage'],
'hour': ['Std.', 'Stunde', 'Stunden'],
'minute': ['Min.', 'Minute', 'Minuten'],
'second': ['Sek.', 'Sekunde', 'Sekunden'],
'millisecond': ['ms', 'Millisekunde', 'Millisekunden'],
'combine': 'und',
'error': 'Falsches Datum',
}
},
{
'language': 'pt',
'plural_form': 'english',
'phrases': {
'year': ['ano', 'anos', 'aa'],
'month': ['mês', 'meses', 'mm'],
'week': ['semana', 'semanas', 'sem'],
'day': ['dia', 'dias', 'd'],
'hour': ['hora', 'horas', 'h'],
'minute': ['minuto', 'minutos', 'min'],
'second': ['segundo', 'segundos', 'seg'],
'millisecond': ['millissegundo', 'millissegundos', 'ms'],
'year': ['aa', 'ano', 'anos'],
'month': ['mm', 'mês', 'meses'],
'week': ['sem', 'semana', 'semanas'],
'day': ['d', 'dia', 'dias'],
'hour': ['h', 'hora', 'horas'],
'minute': ['min', 'minuto', 'minutos'],
'second': ['seg', 'segundo', 'segundos'],
'millisecond': ['ms', 'millissegundo', 'millissegundos'],
'combine': 'e',
'error': 'Data Inválida',
}
},
{
'language': 'dk',
'plural_form': 'english',
'phrases': {
'year': ['år', 'år', 'år'],
'month': ['måned', 'måneder', 'mnd'],
'week': ['uge', 'uger', 'uge'],
'day': ['dag', 'dage', 'dag'],
'hour': ['time', 'timer', 't.'],
'minute': ['minut', 'minuter', 'min.'],
'second': ['sekund', 'sekunder', 'sek.'],
'millisecond': ['millisekund', 'millisekunder', 'ms.'],
'month': ['mnd', 'måned', 'måneder'],
'week': ['uge', 'uge', 'uger'],
'day': ['dag', 'dag', 'dage'],
'hour': ['t.', 'time', 'timer'],
'minute': ['min.', 'minut', 'minuter'],
'second': ['sek.', 'sekund', 'sekunder'],
'millisecond': ['ms.', 'millisekund', 'millisekunder'],
'combine': 'og',
'error': 'Ugyldig dato',
}
},
{
'language': 'sv',
'plural_form': 'english',
'phrases': {
'year': ['år', 'år', 'år'],
'month': ['månad', 'månader', 'mån'],
'week': ['vecka', 'veckor', 'v'],
'day': ['dag', 'dagar', 'dag'],
'hour': ['timme', 'timmar', 'tim'],
'minute': ['minut', 'minuter', 'min'],
'second': ['sekund', 'sekunder', 'sek'],
'millisecond': ['millisekund', 'millisekunder', 'ms'],
'month': ['mån', 'månad', 'månader'],
'week': ['v', 'vecka', 'veckor'],
'day': ['dag', 'dag', 'dagar'],
'hour': ['tim', 'timme', 'timmar'],
'minute': ['min', 'minut', 'minuter'],
'second': ['sek', 'sekund', 'sekunder'],
'millisecond': ['ms', 'millisekund', 'millisekunder'],
'combine': 'och',
'error': 'Ogiltigt datum',
}
},
{
'language': 'cs',
'plural_form': 'slovak',
'phrases': {
'year': ['rok', 'roky', 'rok'],
'month': ['měsíc', 'měsíce', 'měs'],
'week': ['týden', 'týdny', 'týd'],
'day': ['den', 'dny', 'd'],
'hour': ['hodina', 'hodiny', 'hod'],
'minute': ['minuta', 'minuty', 'min'],
'second': ['sekunda', 'sekundy', 'sek'],
'millisecond': ['millisekunda', 'millisekundy', 'ms'],
'year': ['rok', 'rok', 'roky', 'let'],
'month': ['měs', 'měsíc', 'měsíce', 'měsíců'],
'week': ['týd', 'týden', 'týdny', 'týd'],
'day': ['d', 'den', 'dny', 'd'],
'hour': ['hod', 'hodina', 'hodiny', 'hodin'],
'minute': ['min', 'minuta', 'minuty', 'minut'],
'second': ['sek', 'sekunda', 'sekundy', 'sekund'],
'millisecond': ['ms', 'millisekunda', 'millisekundy', 'millisekund'],
'combine': 'a',
'error': 'špatný datum'
'error': 'špatné datum'
}
},
{
'language': 'fi',
'plural_form': 'english',
'phrases': {
'year': ['vuosi', 'vuotta', 'v'],
'month': ['kuukausi', 'kuukautta', 'kk'],
'week': ['viikko', 'viikkoa', 'vk'],
'day': ['päivä', 'päivää', 'pv'],
'hour': ['tunti', 'tuntia', 't'],
'minute': ['minuutti', 'minuuttia', 'min'],
'second': ['sekunti', 'sekuntia', 's'],
'millisecond': ['millisekunti', 'millisekuntia', 'ms'],
'year': ['v', 'vuosi', 'vuotta'],
'month': ['kk', 'kuukausi', 'kuukautta'],
'week': ['vk', 'viikko', 'viikkoa'],
'day': ['pv', 'päivä', 'päivää'],
'hour': ['t', 'tunti', 'tuntia'],
'minute': ['min', 'minuutti', 'minuuttia'],
'second': ['s', 'sekunti', 'sekuntia'],
'millisecond': ['ms', 'millisekunti', 'millisekuntia'],
'combine': 'ja',
'error': 'Väärä päivämäärä',
}
},
{
'language': 'ru',
'plural_form': 'russian',
'phrases': {
'year': ['год', 'года', 'г'],
'month': ['месяц', 'месяцы', 'м'],
'week': ['неделя', 'недели', 'н'],
'day': ['день', 'дни', 'д'],
'hour': ['час', 'часы', 'ч'],
'minute': ['минута', 'минут', 'м'],
'second': ['секунд', 'секунды', 'с'],
'millisecond': ['милисекунд', 'милисекунды', 'мс'],
'year': ['г', 'год', 'года', 'лет'],
'month': ['м', 'месяц', 'месяца', 'месяцев'],
'week': ['н', 'неделя', 'недели', 'недель'],
'day': ['д', 'день', 'дня', 'дней'],
'hour': ['ч', 'час', 'часа', 'часов'],
'minute': ['м', 'минута', 'минуты', 'минут'],
'second': ['с', 'секунда', 'секунды', 'секунд'],
'millisecond': ['мс', 'милисекунда', 'милисекунды', 'милисекунд'],
'combine': 'и',
'error': 'Неверная дата',
}
},
{
'language': 'uk',
'plural_form': 'russian',
'phrases': {
'year': ['рік', 'років', 'р'],
'month': ['місяць', 'місяців', 'м'],
'week': ['тиждень', 'тижнів', 'тижд'],
'day': ['день', 'днів', 'дн'],
'hour': ['годину', 'годин', 'год'],
'minute': ['хвилину', 'хвилин', 'хв'],
'second': ['секунду', 'секунд', 'сек'],
'millisecond': ['мілісекунду', 'мілісекунд', 'мсек'],
'year': ['р', 'рік', 'роки', 'років'],
'month': ['м', 'місяць', 'місяці', 'місяців'],
'week': ['тижд', 'тиждень', 'тижні', 'тижнів'],
'day': ['дн', 'день', 'дні', 'днів'],
'hour': ['год', 'година', 'години', 'годин'],
'minute': ['хв', 'хвилина', 'хвилини', 'хвилин'],
'second': ['сек', 'секунда', 'секунди', 'секунд'],
'millisecond': ['мсек', 'мілісекунда', 'мілісекунди', 'мілісекунд'],
'combine': 'та',
'error': 'Недійсна дата',
}
},
{
'language': 'bg',
'plural_form': 'english',
'phrases': {
'year': ['г', 'година', 'години'],
'month': ['м', 'месец', 'месеца'],
'week': ['седм', 'седмица', 'седмици'],
'day': ['д', 'ден', 'дни'],
'hour': ['ч', 'час', 'часа'],
'minute': ['м', 'минута', 'минути'],
'second': ['с', 'секунда', 'секунди'],
'millisecond': ['мс', 'милисекунда', 'милисекунди'],
'combine': 'и',
'error': 'Невалидна дата',
}
},
{
'language': 'vi',
'plural_form': 'asian',
'phrases': {
'year': ['y', 'năm'],
'month': ['m', 'tháng'],
'week': ['w', 'tuần'],
'day': ['d', 'ngày'],
'hour': ['h', 'giờ'],
'minute': ['m', 'phút', 'phút'],
'second': ['s', 'giây'],
'millisecond': ['ms', 'mili giây'],
'combine': 'và',
'error': 'Ngày không hợp lệ',
}
},
{
'language': 'es',
'plural_form': 'english',
'phrases': {
'year': ['a', 'año', 'años'],
'month': ['m', 'mes', 'meses'],
'week': ['sem', 'semana', 'semanas'],
'day': ['d', 'día', 'días'],
'hour': ['h', 'hora', 'horas'],
'minute': ['min', 'minuto', 'minutos'],
'second': ['s', 'segundo', 'segundos'],
'millisecond': ['ms', 'milisegundo', 'milisegundos'],
'combine': 'y',
'error': 'Fecha inválida',
}
},
{
'language': 'he',
'plural_form': 'english',
'phrases': {
'year': ['שנה', 'שנה', 'שנים'],
'month': ['חודש', 'חודש', 'חודשים'],
'week': ['שבוע', 'שבוע', 'שבועות'],
'day': ['יום', 'יום', 'ימים'],
'hour': ['שעה', 'שעה', 'שעות'],
'minute': ['דקה', 'דקה', 'דקות'],
'second': ['שניה', 'שניה', 'שניות'],
'millisecond': ['מילי', 'מילישניה', 'מילישניות'],
'combine': 'ו',
'error': 'תאריך לא חוקי',
}
},
{
'language': 'hu',
'plural_form': 'english',
'phrases': {
'year': ['é', 'év', 'év'],
'month': ['hó', 'hónap', 'hónap'],
'week': ['hét', 'hét', 'hét'],
'day': ['n', 'nap', 'nap'],
'hour': ['ó', 'óra', 'óra'],
'minute': ['p', 'perc', 'perc'],
'second': ['mp', 'másodperc', 'másodperc'],
'millisecond': ['ms', 'ezredmásodperc', 'ezredmásodperc'],
'combine': 'és',
'error': 'Érvénytelen dátum',
}
},
] -%}
{# macro to convert the abbreviated input for the not_use and always_show lists to the full time part names #}
@ -256,6 +364,8 @@
{%- set compare_date = compare_date if compare_date is datetime else compare_date | as_datetime('invalid') -%}
{%- set time = time | bool(true) -%}
{%- set parts = [parts | int(1), always_show | count] | max -%}
{# create namespace to store debug data #}
{%- set debug = namespace(debug="") -%}
{# 1: check if date input is correct #}
{%- if date is datetime and compare_date is datetime -%}
{# convert date input to local or date only #}
@ -354,7 +464,7 @@
{%- set first = keys | select('in', always_show | default([], true) + [first]) | first -%}
{%- set to_use = keys[keys.index(first):] -%}
{%- set to_output = to_use[:parts] -%}
{%- set last = to_output | last |default('millisecond') -%}
{%- set last = dur.items() | selectattr('0', 'in', to_output) | map(attribute='0') | list | last | default('millisecond') -%}
{# 3: check if there is anything left to use #}
{%- if to_use -%}
{%- set to_output = to_use[:parts] -%}
@ -365,9 +475,10 @@
{%- set to_reject = to_use | reject('in', to_output) | reject('in', always_show) | list -%}
{%- set not_use = not_use + to_output[as_check*-1:] + to_reject -%}
{%- set to_output = to_output | reject('in', not_use) | list + always_show -%}
{%- set to_output = keys | select('in', to_output) | list -%}
{%- set to_output = keys | select('in', to_output) | list + ['extra']-%}
{%- set output = time_split(date, parts, compare_date, not_use, always_show, time, round_mode) | from_json -%}
{%- endif -%}
{# apply round if needed #}
{%- if round_mode in ['common', 'ceil'] and last != 'millisecond' -%}
{# determine first and last item with data #}
@ -376,22 +487,59 @@
{%- set remain_part = remain / dur[last] -%}
{%- set to_round = 1 if remain_part >= 0.5 and round_mode == 'common' else remain_part | round(0, round_mode) -%}
{%- set sec_to_add = ((dur[last] + (dur.day if last in ['year', 'month'] else 1) - remain) | round(0, 'ceil') * to_round) / 1000 -%}
{%- set round_mode = 'floor' -%}
{%- set date_max = [compare_date, date] | max + timedelta(seconds=sec_to_add) -%}
{%- set date_min = [compare_date, date] | min -%}
{%- set output = time_split(date_max, parts, date_min, not_use, always_show, time, round_mode) | from_json -%}
{%- set output = time_split(date_max, parts, date_min, not_use, always_show, time, 'floor') | from_json -%}
{%- set output = dict(output.items() | selectattr('0', 'in', do_use)) -%}
{%- set keys = output.keys() | list -%}
{%- set with_value = output.items() | rejectattr('1', 'eq', 0) | map(attribute='0') | list -%}
{%- set first = with_value | first | default('millisecond') -%}
{%- set first = keys | select('in', always_show | default([], true) + [first]) | first -%}
{%- set to_use = keys[keys.index(first):] -%}
{%- set to_output = to_use[:parts] -%}
{%- endif -%}
{# output result #}
{%- set zero_values = output.items() | selectattr('1', 'eq', 0) | map(attribute='0') | list -%}
{%- set reject_list = zero_values | reject('in', always_show) | list -%}
{{- dict(output.items() | selectattr('0', 'in', to_output) | rejectattr('0', 'in', reject_list)) | default({always_return: 0}, true) | to_json -}}
{%- else -%} {{- dict(error='No time parts left to output') | to_json -}}
{{- dict(output.items() | selectattr('0', 'in', to_output) | rejectattr('0', 'in', reject_list), **dict(debug=debug.debug) if debug.debug else dict()) | default({always_return: 0}, true) | to_json-}}
{%- else -%} {{- dict(error='No time parts left to output') -}}
{%- endif -%} {# 3 #}
{%- endif -%} {# 2 #}
{%- else -%} {{- dict(error='Invalid date input') | to_json -}}
{%- else -%} {{- dict(error='Invalid date input')-}}
{%- endif -%} {# 1 #}
{%- endmacro -%}
{# macro for determining the time unit variant depending on the language #}
{%- macro plural(number=0, rule='english') -%}
{%- set mod100 = number % 100 -%}
{%- set mod10 = number % 10 -%}
{%- set form = 1 -%}
{%- if rule == 'english' -%}
{%- set form = 1 if number == 1 else 2 -%}
{%- elif rule == 'french' -%}
{%- set form = 1 if number <= 1 else 2 -%}
{%- elif rule == 'latvian' -%}
{%- set form = 1 if (mod10 == 1 and mod100 != 11) else 2 if number != 0 else 3 -%}
{%- elif rule == 'irish' -%}
{%- set form = 1 if number == 1 else 2 if number == 2 else 3 -%}
{%- elif rule == 'romanian' -%}
{%- set form = 1 if number == 1 else 2 if (number == 0 or (mod100 > 0 and mod100 < 20 )) else 3 -%}
{%- elif rule == 'lithuanian' -%}
{%- set form = 1 if (mod10 == 1 and mod100 != 11) else 2 if (mod10 >= 2 and (mod100 < 10 or mod100 >= 20)) else 3 -%}
{%- elif rule == 'russian' -%}
{%- set form = 1 if (mod10 == 1 and mod100 != 11) else 2 if (mod10 >= 2 and mod10 <= 4 and (mod100 < 10 or mod100 >= 20)) else 3 -%}
{%- elif rule == 'slovak' -%}
{%- set form = 1 if number == 1 else 2 if (number >= 2 and number <= 4) else 3 -%}
{%- elif rule == 'polish' -%}
{%- set form = 1 if number == 1 else 2 if (mod10 >= 2 and mod10 <= 4 and (mod100 < 10 or mod100 >= 20)) else 3 -%}
{%- elif rule == 'slovenian' -%}
{%- set form = 1 if mod100 == 1 else 2 if mod100 == 2 else 3 if (mod100 == 3 or mod100 == 4) else 4 -%}
{%- elif rule == 'arabic' -%}
{%- set form = 1 if number == 0 else 2 if number == 1 else 3 if number == 2 else 4 if (mod100 >= 3 and mod100 <= 10) else 5 if mod100 >= 11 else 6 -%}
{%- endif -%}
{{- form -}}
{%- endmacro -%}
{# macro to output a timedelta in a readable format #}
{%- macro relative_time_plus(date, parts=1, abbr=false, language='en', compare_date=now(), not_use=['millisecond'], always_show=[], time=true, round_mode='floor') -%}
{#- select correct phrases bases on language input #}
@ -399,6 +547,7 @@
{%- set languages = phrases | map(attribute='language') | list -%}
{%- set language = iif(language in languages, language, 'en') -%}
{%- set phr = phrases | selectattr('language', 'eq', language) | map(attribute='phrases') | list | first -%}
{%- set plural_form = phrases | selectattr('language', 'eq', language) | map(attribute='plural_form') | list | first -%}
{%- set abbr = abbr | bool(false) -%}
{# split timedelta #}
{%- set time_parts = time_split(date, parts, compare_date, not_use, always_show, time, round_mode) | from_json -%}
@ -409,9 +558,9 @@
{# convert to phrases #}
{%- set ns = namespace(phrases=[]) -%}
{%- for i in time_parts.keys() -%}
{%- set phr_abbr = phr[i][2] -%}
{%- set phr_verb = phr[i][1] if time_parts[i] != 1 else phr[i][0] -%}
{%- set phrase = '{} {}'.format(time_parts[i], phr_abbr if abbr else phr_verb) -%}
{%- set plural_variant = plural(time_parts[i], plural_form) | int -%}
{%- set phr_form = phr[i][0] if abbr else phr[i][plural_variant] -%}
{%- set phrase = '{} {}'.format(time_parts[i], phr_form) -%}
{%- set ns.phrases = ns.phrases + [phrase] -%}
{%- endfor -%}
{#- join phrases in a string, using phr.combine for the last item #}

View File

@ -12,12 +12,49 @@
{% endif %}
{% endmacro %}
{% macro period_str(team) %}
{% if state_attr(team,'league') in ['NFL','NCAAF'] %}
quarter
{% elif state_attr(team,'league') == 'MLB' %}
inning
{% else %}
period
{% endif %}
{% endmacro %}
{% macro sports_clock(team) %}
{% macro data() %}
{% set period_str = period_str(team) %}
{% set game_clock = state_attr(team,'clock') | lower %}
{% if state_attr(team,'league') == 'MLB' %}
{% set inning_parts = game_clock.split(' ') %}
in the {{ inning_parts[0] ~ ' of the ' ~ inning_parts[1] ~ ' ' ~ period_str }}
{% else %}
{% if ' - ' in game_clock %}
{% set clock_time, quarter = game_clock.split(' - ') %}
{% if quarter == 'ot' %}
with {{ clock_time ~ ' remaining in overtime' }}
{% else %}
with {{ clock_time ~ ' remaining in the ' ~ quarter ~ ' ' ~ period_str }}
{% endif %}
{% endif %}
{% endif %}
{% endmacro %}
{{ cleanup(data()) }}
{% endmacro %}
{% macro sports_pregame(team) %}
{% macro data() %}
{% if state_attr(team,'opponent_name') %}
{% set opponent_name = state_attr(team, 'opponent_name') %}
{% if opponent_name.endswith(' St') %}
{% set opponent_name = opponent_name | replace(' St', ' State') %}
{% endif %}
{% endif %}
{% if is_state(team,'PRE') %}
{% set date = state_attr(team,'date') | as_timestamp | timestamp_custom('%m-%d') %}
{% if date == now().strftime('%m-%d') %}
The {{ state_attr(team,'friendly_name') }} will be playing today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} at {{ state_attr(team,'venue') }}.
The {{ state_attr(team,'friendly_name') }} will be playing today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} at {{ state_attr(team,'venue') }}.
{{ sports_str(team,'start') }} is at {{ state_attr(team,'date') | as_timestamp | timestamp_custom('%I:%M %p') }}.
{% endif %}
{% endif %}
@ -27,6 +64,12 @@
{% macro sports_main(team) %}
{% macro data() %}
{% if state_attr(team,'opponent_name') %}
{% set opponent_name = state_attr(team, 'opponent_name') %}
{% if opponent_name.endswith(' St') %}
{% set opponent_name = opponent_name | replace(' St', ' State') %}
{% endif %}
{% endif %}
{% if is_state(team,'POST') %}
{% set date = state_attr(team,'date') | as_timestamp | timestamp_custom('%m-%d') %}
{% set yday = (as_timestamp(now()) - (24*3600)) | timestamp_custom('%m-%d') %}
@ -34,11 +77,11 @@
{% if state_attr(team,'clock') in ['postponed','Postponed'] %}
The {{ state_attr(team,'friendly_name') }} had their game postponed today, and it will be played at a later date.
{% elif (state_attr(team,'team_score') | int) == state_attr(team,'opponent_score') | int %}
The {{ state_attr(team,'friendly_name') }} tied in their game today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
The {{ state_attr(team,'friendly_name') }} tied in their game today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
{% elif state_attr(team,'team_winner') == true %}
The {{ state_attr(team,'friendly_name') }} won their game today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
The {{ state_attr(team,'friendly_name') }} won their game today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
{% elif state_attr(team,'opponent_winner') == true %}
The {{ state_attr(team,'friendly_name') }} lost their game today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} by a score of {{ state_attr(team,'opponent_score') }} to {{ state_attr(team,'team_score') }}.
The {{ state_attr(team,'friendly_name') }} lost their game today against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} by a score of {{ state_attr(team,'opponent_score') }} to {{ state_attr(team,'team_score') }}.
{% endif %}
{% if state_attr(team,'clock') not in ['postponed','Postponed'] %}
This brings their record to {{ state_attr(team,'team_record') | replace("-"," and ") }} on the season.
@ -47,11 +90,11 @@
{% if state_attr(team,'clock') in ['postponed','Postponed'] %}
The {{ state_attr(team,'friendly_name') }} had their game postponed yesterday, and it will be played at a later date.
{% elif (state_attr(team,'team_score') | int) == state_attr(team,'opponent_score') | int %}
The {{ state_attr(team,'friendly_name') }} tied in their game yesterday against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
The {{ state_attr(team,'friendly_name') }} tied in their game yesterday against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
{% elif state_attr(team,'team_winner') == true %}
The {{ state_attr(team,'friendly_name') }} won their game yesterday against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
The {{ state_attr(team,'friendly_name') }} won their game yesterday against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} by a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
{% elif state_attr(team,'opponent_winner') == true %}
The {{ state_attr(team,'friendly_name') }} lost their game yesterday against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} by a score of {{ state_attr(team,'opponent_score') }} to {{ state_attr(team,'team_score') }}.
The {{ state_attr(team,'friendly_name') }} lost their game yesterday against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} by a score of {{ state_attr(team,'opponent_score') }} to {{ state_attr(team,'team_score') }}.
{% endif %}
{% if state_attr(team,'clock') not in ['postponed','Postponed'] %}
This brings their record to {{ state_attr(team,'team_record') | replace("-"," and ") }} on the season.
@ -59,11 +102,11 @@
{% endif %}
{% elif is_state(team,'IN') %}
{% if (state_attr(team,'team_score') | int) == (state_attr(team,'opponent_score') | int) %}
The {{ state_attr(team,'friendly_name') }} are currently tied in their game against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} with a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
The {{ state_attr(team,'friendly_name') }} are currently tied in their game against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} with a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }} {{ sports_clock(team) }}.
{% elif (state_attr(team,'team_score') | int) > (state_attr(team,'opponent_score') | int) %}
The {{ state_attr(team,'friendly_name') }} are currently winning their game against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} with a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }}.
The {{ state_attr(team,'friendly_name') }} are currently winning their game against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} with a score of {{ state_attr(team,'team_score') }} to {{ state_attr(team,'opponent_score') }} {{ sports_clock(team) }}.
{% else %}
The {{ state_attr(team,'friendly_name') }} are currently losing their game against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ state_attr(team,'opponent_name') }} with a score of {{ state_attr(team,'opponent_score') }} to {{ state_attr(team,'team_score') }}.
The {{ state_attr(team,'friendly_name') }} are currently losing their game against {% if state_attr(team,'league') != 'NCAAF'%}the{% endif %} {{ opponent_name }} with a score of {{ state_attr(team,'opponent_score') }} to {{ state_attr(team,'team_score') }} {{ sports_clock(team) }}.
{% endif %}
{% endif %}
{% endmacro %}

View File

@ -474,11 +474,10 @@
{% endif %}
{% if is_state('input_boolean.kallen_alternate_pickup','on') %}
{{ states('input_text.kallen_pickup') }} will be picking Collin up from school today.
{% else %}
Pickup today will be at {{ input_datetime_read('input_datetime.kallen_school_day_end') | trim }}.
{% if is_state('input_boolean.kallen_school_early_release','on') %}
And It is early release!
Today is an early release day!
{% endif %}
Pickup today will be at {{ input_datetime_read('input_datetime.kallen_school_day_end') | trim }}.
{% endif %}
{% if states('sensor.windows_open') | int > 0 %}
'I detect that there are windows open. Make sure you close them before you leave, or else the security system will not arm. '
@ -544,11 +543,12 @@
{% endif %}
{% if is_state('input_boolean.kallen_alternate_pickup','on') %}
{{ states('input_text.kallen_pickup') }} will be picking him up from school today.
{% elif is_state('input_boolean.kallen_school_early_release','on') %}
{% if is_state('input_boolean.kallen_school_early_release','on') %}
The school is on an early release schedule, pickup is at {{ input_datetime_read('input_datetime.kallen_school_day_end') | trim }}.
{% else %}
His pickup time is {{ input_datetime_read('input_datetime.kallen_school_day_end') | trim }}.
{% endif %}
{% endif %}
{% else %}
{{ identKallen }} has school at {{ input_datetime_read('input_datetime.kallen_school_day_start') | trim }} today.
{% endif %}

View File

@ -19,6 +19,17 @@
{% if type in ['alerts','full'] %}
{% if is_state('input_boolean.tornado_alarm','on') %}
We are under a tornado warning. If you are not already in shelter, you should be. Get on it!
{% if state_attr('binary_sensor.tornado_warning','confirmed' == true) %}
A tornado has been confirmed in the area. Please take shelter immediately!
{% endif %}
{% elif is_state('binary_sensor.severe_thunderstorm_warning','on') %}
We are under a severe thunderstorm warning.
{% if state_attr('binary_sensor.severe_thunderstorm_warning','tornado_possible' == true) %}
The incoming storm has the potential to produce a tornado, so please pay attention and prepare to take shelter!
{% endif %}
{% if state_attr('binary_sensor.severe_thunderstorm_warning','considerable_destructive' == true) %}
This storm has the potential to cause considerable damage. Please take shelter and stay safe!
{% endif %}
{% elif states('sensor.weatheralerts_active_alerts') > '0' and method != 'dashboard' %}
Current weather alerts: {{ states('sensor.weather_alert_string') }}.
{% endif %}
@ -49,6 +60,17 @@
{% endif %}
{% if is_state('input_boolean.tornado_alarm','on') %}
"We are under a tornado warning. If you are not already in shelter, you should be. Get on it! "
{% if state_attr('binary_sensor.tornado_warning','confirmed' == true) %}
"A tornado has been confirmed in the area. Please take shelter immediately! "
{% endif %}
{% elif is_state('binary_sensor.severe_thunderstorm_warning','on') %}
"We are under a severe thunderstorm warning. "
{% if state_attr('binary_sensor.severe_thunderstorm_warning','tornado_possible' == true) %}
"The incoming storm has the potential to produce a tornado, so please pay attention and prepare to take shelter! "
{% endif %}
{% if state_attr('binary_sensor.severe_thunderstorm_warning','considerable_destructive' == true) %}
"This storm has the potential to cause considerable damage. Please take shelter and stay safe! "
{% endif %}
{% elif is_state('input_boolean.tornado_watch','on') %}
{{ [
"There is currently a tornado watch active. Please keep an eye on the sky and your local weather reports. ",
@ -106,7 +128,8 @@
{{ weatherInfo(type,method,time) |
replace('clear-night','clear') |
replace('partlycloudy','partly cloudy') |
replace('snowy-rainy','a mix of rain and snow') }}
replace('snowy-rainy','a mix of rain and snow') |
replace('lightning-rainy','stormy') }}
{% endmacro %}
{{ cleanup(data()) }}
{% endmacro %}

View File

@ -11,6 +11,7 @@ report_type:
options:
- Bug Report
- New Idea
- Adjustment
initial: Bug Report
icon: mdi:bug
select_testing:

View File

@ -1,20 +1,24 @@
template:
- binary_sensor:
- name: Emma Aircon - Compressor
- name: Emma Bedroom Aircon - Compressor
unique_id: 21bcbb62-823c-43ff-8c2c-26e940324ee6
state: "{{ is_state('fan.emma_air_conditioner','on') and states('sensor.emma_air_conditioner_power') | int > 150 }}"
state: "{{ states('sensor.emma_bedroom_aircon_power') | int > 150 }}"
availability: "{{ states('climate.emma_bedroom_aircon') not in ['unknown','unavailable'] }}"
device_class: running
- name: Emma Aircon - Fan
- name: Emma Bedroom Aircon - Fan
unique_id: 9e3054cf-8f7e-4fef-9da4-5b2f2bc99c9d
state: "{{ is_state('fan.emma_air_conditioner','on') and states('sensor.emma_air_conditioner_power') | int > 20 }}"
state: "{{ states('sensor.emma_bedroom_aircon_power') | int > 20 }}"
availability: "{{ states('climate.emma_bedroom_aircon') not in ['unknown','unavailable'] }}"
device_class: running
- name: Master Bedroom Aircon - Compressor
unique_id: 87051957-1dbc-4d65-b138-e8469728f58f
state: "{{ states('climate.master_bedroom_aircon') not in ['off','unknown','unavailable'] and states('sensor.master_bedroom_aircon_power') | int > 150 }}"
state: "{{ states('sensor.master_bedroom_aircon_power') | int > 150 }}"
availability: "{{ states('climate.master_bedroom_aircon') not in ['unknown','unavailable'] }}"
device_class: running
- name: Master Bedroom Aircon - Fan
unique_id: ae893dd6-129c-4886-a966-a89b958d9f08
state: "{{ states('climate.master_bedroom_aircon') not in ['off','unknown','unavailable'] and states('sensor.master_bedroom_aircon_power') | int > 20 }}"
state: "{{ states('sensor.master_bedroom_aircon_power') | int > 20 }}"
availability: "{{ states('climate.master_bedroom_aircon') not in ['unknown','unavailable'] }}"
device_class: running
- name: Kallen Fan - Separate Schedule
unique_id: 3f243861-6a1f-412f-b9e3-933b54793b08
@ -112,16 +116,6 @@ template:
unique_id: 2ce31844-b115-42b8-8213-feccf24e236c
state: "{{ state_attr('climate.master_bedroom_aircon','temperature') | float }}"
availability: "{{ states('climate.master_bedroom_aircon') not in ['unavailable','unknown'] }}"
- name: "Master Bedroom Eco Mode"
unique_id: edf36e23-adcf-4506-80eb-a14f4ea2fce0
state: "{{ is_state_attr('climate.master_bedroom_aircon','preset_mode','eco') }}"
icon: >-
{% if is_state_attr('climate.master_bedroom_aircon','preset_mode','eco') %}
mdi:home-lightning-bolt
{% else %}
mdi:home-lightning-bolt-outline
{% endif %}
availability: "{{ states('climate.master_bedroom_aircon') not in ['unavailable','unknown'] }}"
- name: "Master Bedroom Aircon Fan Mode"
unique_id: c0e4f9ba-0c6c-4673-9a75-13f253f2f2e8
state: "{{ state_attr('climate.master_bedroom_aircon','fan_mode') }}"
@ -138,6 +132,26 @@ template:
mdi:fan-off
{% endif %}
availability: "{{ states('climate.master_bedroom_aircon') not in ['unavailable','unknown'] }}"
- name: "Emma Bedroom Target Temp"
unique_id: b81152a1-d4d9-4e3e-8a78-6039de2884ad
state: "{{ state_attr('climate.emma_bedroom_aircon','temperature') | float }}"
availability: "{{ states('climate.emma_bedroom_aircon') not in ['unavailable','unknown'] }}"
- name: "Emma Bedroom Aircon Fan Mode"
unique_id: d678eb2e-be5b-4626-913d-fc1e32941ead
state: "{{ state_attr('climate.emma_bedroom_aircon','fan_mode') }}"
icon: >
{% if is_state_attr('climate.emma_bedroom_aircon','fan_mode','Auto') %}
mdi:fan-auto
{% elif is_state_attr('climate.emma_bedroom_aircon','fan_mode','Low') %}
mdi:fan-speed-1
{% elif is_state_attr('climate.emma_bedroom_aircon','fan_mode','Medium') %}
mdi:fan-speed-2
{% elif is_state_attr('climate.emma_bedroom_aircon','fan_mode','High') %}
mdi:fan-speed-3
{% else %}
mdi:fan-off
{% endif %}
availability: "{{ states('climate.emma_bedroom_aircon') not in ['unavailable','unknown'] }}"
- name: Living Room Average Temperature
unique_id: c4a901a6-87e2-4257-b60b-2944be8fdf04
state: >
@ -183,16 +197,17 @@ input_boolean:
master_bedroom_climate_protocol:
name: Master Bedroom Climate Protocol
icon: mdi:lightbulb-night
emma_bedroom_climate_protocol:
name: Emma Bedroom Climate Protocol
icon: mdi:lightbulb-night
kallen_bedtime_protocol:
name: Kallen Bedtime Protocol
icon: mdi:lightbulb-night
# Turn on when master bedroom air conditioner is installed, turn off in winter when we take it out, for smarter automations
# Turn on when air conditioners are installed, turn off in winter when we take them out
master_bedroom_aircon_installed:
name: Master Bedroom Aircon Installed
icon: mdi:tools
# Same thing, but for Emma's bedroom air conditioner
emma_bedroom_aircon_installed:
name: Emma Bedroom Aircon Installed
icon: mdi:tools
@ -201,6 +216,9 @@ input_boolean:
master_bedroom_cooling_on:
name: Master Bedroom Cooling On
icon: mdi:snowflake
emma_bedroom_cooling_on:
name: Emma Bedroom Cooling On
icon: mdi:snowflake
# Activated if the day will be excessively hot. For use with automations for daytime climate control.
hot_day:
@ -243,6 +261,7 @@ input_select:
name: Scheduled Climate Mode - Emma Bedroom
options:
- AC
- Fan
- Heat
- White Noise
- N/A
@ -305,13 +324,55 @@ input_number:
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
emma_aircon_threshold:
name: Emma Aircon Threshold
emma_bedroom_daytime_temp:
name: Emma Bedroom Daytime Temp
min: 65
max: 80
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
emma_bedroom_night_temp:
name: Emma Bedroom Night Temp
min: 65
max: 80
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
emma_bedroom_bedtime_temp:
name: Emma Bedroom Bedtime Temp
min: 65
max: 80
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
emma_bedroom_aircon_run_threshold:
name: Emma Bedroom Aircon Run Threshold
min: 40
max: 80
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
emma_bedroom_aircon_mode_threshold:
name: Emma Bedroom Aircon Mode Threshold
min: 40
max: 80
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
emma_bedroom_fan_threshold:
name: Emma Bedroom Fan Threshold
min: 30
max: 70
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
emma_bedroom_auto_cooling_threshold:
name: Emma Bedroom Auto Cooling Threshold
min: 70
max: 90
step: 1
unit_of_measurement: °F
icon: mdi:thermometer
kallen_fan_threshold:
name: Kallen Fan Threshold
min: 40

11
packages/dashboards.yaml Normal file
View File

@ -0,0 +1,11 @@
template:
- trigger:
- trigger: event
event_type: bubble_card_update_modules
sensor:
- name: "Bubble Card Modules"
state: "saved"
icon: "mdi:puzzle"
attributes:
modules: "{{ trigger.event.data.modules }}"
last_updated: "{{ trigger.event.data.last_updated }}"

View File

@ -257,6 +257,9 @@ automation:
time: >
{% from 'time.jinja' import current_time %}
{{ current_time('time',24) }}
- service: input_boolean.turn_off
target:
entity_id: input_boolean.emma_awake
- conditions:
- condition: trigger
id: bedtime-timer-finished
@ -281,6 +284,9 @@ automation:
datetime: >
{% from 'time.jinja' import current_time %}
{{ current_time('time',24) }}
- service: input_boolean.turn_off
target:
entity_id: input_boolean.emma_awake
- id: e59f638a-519f-4619-bf7d-b13251b3a374
alias: Emma Meds Handler
@ -804,14 +810,9 @@ script:
datetime: >
{% from 'time.jinja' import set_datetime %}
{{ set_datetime(0,5) }}
- if:
- condition: state
entity_id: binary_sensor.basement_occupied
state: 'on'
then:
- service: script.speech_engine
data:
who: basement
who: common
type: normal
message: Emma has awoken, so it is time to make your way upstairs now
- service: input_datetime.set_datetime
@ -898,26 +899,3 @@ script:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.white_noise_emma_bedroom
- if:
- condition: state
entity_id: fan.emma_air_conditioner
state: 'on'
then:
- service: script.turn_on
target:
entity_id: script.emma_aircon_shutoff
emma_aircon_shutoff:
alias: 'Emma Air Conditioner Shutoff'
mode: restart
description: 'Attempt to shut off air conditioner after compressor stops running'
sequence:
- wait_template: "{{ is_state('binary_sensor.emma_aircon_compressor','off') }}"
timeout:
minutes: 15
continue_on_timeout: true
- delay:
seconds: 5
- service: fan.turn_off
target:
entity_id: fan.emma_air_conditioner

View File

@ -31,8 +31,7 @@ tts:
region_name: 'us-east-1'
text_type: ssml
voice: Joanna
cache: true
engine: neural
engine: generative
conversation:

View File

@ -489,6 +489,7 @@ input_select:
- Evening Mode
- Night Mode
- Bright Mode
- Reading Mode
- Reset
initial: Select
icon: mdi:desk
@ -653,6 +654,25 @@ template:
{% endif %}
device_class: problem
delay_on: "00:00:10"
- name: Light Switch Issue
unique_id: 381e8038-ea96-474c-92ec-d1296dc1369e
state: >
{% set lights = states.light.upstairs_bathroom_lights,
states.light.hallway_overhead,
states.light.downstairs_bathroom_lights,
states.light.living_room_lights,
states.light.front_porch_light %}
{% set issues = lights | selectattr('state','eq','unavailable') | list | count %}
{{ issues > 0 }}
attributes:
issues: >
{% set lights = states.light.upstairs_bathroom_lights,
states.light.hallway_overhead,
states.light.downstairs_bathroom_lights,
states.light.living_room_lights,
states.light.front_porch_light %}
{% set ids = lights | selectattr('state','eq','unavailable') | map(attribute='attributes.friendly_name') | list %}
{{ ids | join(', ') }}
- sensor:
- name: "Basement Studio Lights - Brightness Actual"
unique_id: dee4dc84-a6a0-4150-903e-5b8bd436d962

View File

@ -198,6 +198,57 @@ input_number:
step: 0.05
icon: mdi:knob
template:
- sensor:
- name: "Basement Echo Dot Volume"
state: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.basement_echo_dot_night_volume') }}
{% else %}
{{ states('input_number.basement_echo_dot_day_volume') }}
{% endif %}
icon: mdi:volume-high
- name: "Basement Google Speaker Volume"
state: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.basement_google_speaker_night_volume') }}
{% else %}
{{ states('input_number.basement_google_speaker_day_volume') }}
{% endif %}
icon: mdi:volume-high
- name: "Living Room Echo Dot Volume"
state: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.living_room_echo_dot_night_volume') }}
{% else %}
{{ states('input_number.living_room_echo_dot_day_volume') }}
{% endif %}
icon: mdi:volume-high
- name: "Master Bedroom Echo Dot Volume"
state: >
{% if is_state('input_boolean.give_me_darkness','on') or is_state('binary_sensor.people_sleeping','on') %}
{{ states('input_number.master_bedroom_echo_dot_night_volume') }}
{% else %}
{{ states('input_number.master_bedroom_echo_dot_day_volume') }}
{% endif %}
icon: mdi:volume-high
- name: "Kallen Bedroom Google Speaker Volume"
state: >
{% if is_state('input_boolean.give_me_darkness','on') or is_state('input_boolean.kallen_sleeping','on') %}
{{ states('input_number.kallen_bedroom_google_speaker_night_volume') }}
{% else %}
{{ states('input_number.kallen_bedroom_google_speaker_day_volume') }}
{% endif %}
icon: mdi:volume-high
- name: "Emma Bedroom Google Speaker Volume"
state: >
{% if is_state('input_boolean.give_me_darkness','on') or is_state('input_boolean.emma_sleeping','on') %}
{{ states('input_number.emma_bedroom_google_speaker_night_volume') }}
{% else %}
{{ states('input_number.emma_bedroom_google_speaker_day_volume') }}
{% endif %}
icon: mdi:volume-high
# Amazon Polly Sensors to see last message and location of audible notification
mqtt:
sensor:
@ -325,24 +376,14 @@ script:
- condition: template
value_template: >
{% set current = state_attr('media_player.basement_echo_dot','volume_level') | float %}
{% set night = states('input_number.basement_echo_dot_night_volume') | float %}
{% set day = states('input_number.basement_echo_dot_day_volume') | float %}
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ current != night }}
{% else %}
{{ current != day }}
{% endif %}
{% set expected = states('sensor.basement_echo_dot_volume') | float %}
{{ current != expected }}
then:
- service: media_player.volume_set
target:
entity_id: media_player.basement_echo_dot
data:
volume_level: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.basement_echo_dot_night_volume') }}
{% else %}
{{ states('input_number.basement_echo_dot_day_volume') }}
{% endif %}
volume_level: "{{ states('sensor.basement_echo_dot_volume') }}"
# Basement Google Speaker
- if:
- condition: and
@ -373,24 +414,14 @@ script:
- condition: template
value_template: >
{% set current = state_attr('media_player.basement_google_speaker','volume_level') | float %}
{% set night = states('input_number.basement_google_speaker_night_volume') | float %}
{% set day = states('input_number.basement_google_speaker_day_volume') | float %}
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ current != night }}
{% else %}
{{ current != day }}
{% endif %}
{% set expected = states('sensor.basement_google_speaker_volume') | float %}
{{ current != expected }}
then:
- service: media_player.volume_set
target:
entity_id: media_player.basement_google_speaker
data:
volume_level: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.basement_google_speaker_night_volume') }}
{% else %}
{{ states('input_number.basement_google_speaker_day_volume') }}
{% endif %}
volume_level: "{{ states('sensor.basement_google_speaker_volume') }}"
- service: media_player.volume_mute
target:
entity_id: media_player.basement_google_speaker
@ -405,24 +436,14 @@ script:
- condition: template
value_template: >
{% set current = state_attr('media_player.living_room_echo_dot','volume_level') | float %}
{% set night = states('input_number.living_room_echo_dot_night_volume') | float %}
{% set day = states('input_number.living_room_echo_dot_day_volume') | float %}
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ current != night }}
{% else %}
{{ current != day }}
{% endif %}
{% set expected = states('sensor.living_room_echo_dot_volume') | float %}
{{ current != expected }}
then:
- service: media_player.volume_set
target:
entity_id: media_player.living_room_echo_dot
data:
volume_level: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.living_room_echo_dot_night_volume') }}
{% else %}
{{ states('input_number.living_room_echo_dot_day_volume') }}
{% endif %}
volume_level: "{{ states('sensor.living_room_echo_dot_volume') }}"
# Master Bedroom Echo Dot
- if:
- condition: state
@ -435,24 +456,14 @@ script:
- condition: template
value_template: >
{% set current = state_attr('media_player.master_bedroom_echo_dot','volume_level') | float %}
{% set night = states('input_number.master_bedroom_echo_dot_night_volume') | float %}
{% set day = states('input_number.master_bedroom_echo_dot_day_volume') | float %}
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ current != night }}
{% else %}
{{ current != day }}
{% endif %}
{% set expected = states('sensor.master_bedroom_echo_dot_volume') | float %}
{{ current != expected }}
then:
- service: media_player.volume_set
target:
entity_id: media_player.master_bedroom_echo_dot
data:
volume_level: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.master_bedroom_echo_dot_night_volume') }}
{% else %}
{{ states('input_number.master_bedroom_echo_dot_day_volume') }}
{% endif %}
volume_level: "{{ states('sensor.master_bedroom_echo_dot_volume') }}"
# Kallen Bedroom Speaker
- if:
- condition: and
@ -483,24 +494,14 @@ script:
- condition: template
value_template: >
{% set current = state_attr('media_player.kallen_bedroom_google_speaker','volume_level') | float %}
{% set night = states('input_number.kallen_bedroom_google_speaker_night_volume') | float %}
{% set day = states('input_number.kallen_bedroom_google_speaker_day_volume') | float %}
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ current != night }}
{% else %}
{{ current != day }}
{% endif %}
{% set expected = states('sensor.kallen_bedroom_google_speaker_volume') | float %}
{{ current != expected }}
then:
- service: media_player.volume_set
target:
entity_id: media_player.kallen_bedroom_google_speaker
data:
volume_level: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.kallen_bedroom_google_speaker_night_volume') }}
{% else %}
{{ states('input_number.kallen_bedroom_google_speaker_day_volume') }}
{% endif %}
volume_level: "{{ states('sensor.kallen_bedroom_google_speaker_volume') }}"
- service: media_player.volume_mute
target:
entity_id: media_player.kallen_bedroom_google_speaker
@ -536,24 +537,14 @@ script:
- condition: template
value_template: >
{% set current = state_attr('media_player.emma_bedroom_google_speaker','volume_level') | float %}
{% set night = states('input_number.emma_bedroom_google_speaker_night_volume') | float %}
{% set day = states('input_number.emma_bedroom_google_speaker_day_volume') | float %}
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ current != night }}
{% else %}
{{ current != day }}
{% endif %}
{% set expected = states('sensor.emma_bedroom_google_speaker_volume') | float %}
{{ current != expected }}
then:
- service: media_player.volume_set
target:
entity_id: media_player.emma_bedroom_google_speaker
data:
volume_level: >
{% if is_state('input_boolean.give_me_darkness','on') %}
{{ states('input_number.emma_bedroom_google_speaker_night_volume') }}
{% else %}
{{ states('input_number.emma_bedroom_google_speaker_day_volume') }}
{% endif %}
volume_level: "{{ states('sensor.kallen_bedroom_google_speaker_volume') }}"
- service: media_player.volume_mute
target:
entity_id: media_player.emma_bedroom_google_speaker
@ -1237,11 +1228,9 @@ script:
data:
message: >
<voice name="{{ voice }}">
<amazon:auto-breaths>
<prosody rate="fast">
{{ message }}
</prosody>
</amazon:auto-breaths>
</voice>
target: >
{% if who in ['living_room_echo_dot', 'media_player.living_room_echo_dot','living_room'] %}
@ -1328,55 +1317,36 @@ script:
media_player.basement_google_speaker
{% endif %}
volume_level: >-
{% set numbers_night = [
states.input_number.emma_bedroom_google_speaker_night_volume.state,
states.input_number.kallen_bedroom_google_speaker_night_volume.state
{% set numbers = [
states.sensor.emma_bedroom_google_speaker_volume.state,
states.sensor.kallen_bedroom_google_speaker_volume.state
] %}
{% set numbers_day = [
states.input_number.emma_bedroom_google_speaker_day_volume.state,
states.input_number.kallen_bedroom_google_speaker_day_volume.state
] %}
{% set kidsgroup_night = numbers_night | list | min | float %}
{% set kidsgroup_day = numbers_day | list | max | float %}
{% set kidsgroup = numbers | list | min | float %}
{% if type in ['critical'] %}
1.0
{% elif is_state('input_boolean.give_me_darkness','on') %}
{% else %}
{% if who in ['Everywhere','everywhere','kids_bedrooms','all_bedrooms'] %}
{% if is_state('input_boolean.emma_sleeping','on') and is_state('input_boolean.kallen_sleeping','off') %}
{{ states('input_number.kallen_bedroom_google_speaker_night_volume') }}
{{ states('sensor.kallen_bedroom_google_speaker_volume') }}
{% elif is_state('input_boolean.kallen_sleeping','on') and is_state('input_boolean.emma_sleeping','off') %}
{{ states('input_number.emma_bedroom_google_speaker_night_volume') }}
{{ states('sensor.emma_bedroom_google_speaker_volume') }}
{% else %}
{{ kidsgroup_night }}
{{ kidsgroup }}
{% endif %}
{% elif who in ['kallen_bedroom','media_player.kallen_bedroom_google_speaker'] %}
{{ states('input_number.kallen_bedroom_google_speaker_night_volume') }}
{{ states('sensor.kallen_bedroom_google_speaker_volume') }}
{% elif who in ['emma_bedroom','media_player.emma_bedroom_google_speaker'] %}
{{ states('input_number.emma_bedroom_google_speaker_night_volume') }}
{{ states('sensor.emma_bedroom_google_speaker_volume') }}
{% elif who in ['Basement Google','basement_google'] %}
{{ states('input_number.basement_google_speaker_night_volume') }}
{{ states('sensor.basement_google_speaker_volume') }}
{% else %}
{% if is_state('input_boolean.give_me_darkness','on') %}
0.3
{% endif %}
{% else %}
{% if who in ['Everywhere','everywhere','kids_bedrooms','all_bedrooms'] %}
{% if is_state('input_boolean.emma_sleeping','on') and is_state('input_boolean.kallen_sleeping','off') %}
{{ states('input_number.kallen_bedroom_google_speaker_day_volume') }}
{% elif is_state('input_boolean.kallen_sleeping','on') and is_state('input_boolean.emma_sleeping','off') %}
{{ states('input_number.emma_bedroom_google_speaker_day_volume') }}
{% else %}
{{ kidsgroup_day }}
{% endif %}
{% elif who in ['kallen_bedroom','media_player.kallen_bedroom_google_speaker'] %}
{{ states('input_number.kallen_bedroom_google_speaker_day_volume') }}
{% elif who in ['emma_bedroom','media_player.emma_bedroom_google_speaker'] %}
{{ states('input_number.emma_bedroom_google_speaker_day_volume') }}
{% elif who in ['Basement Google','basement_google'] %}
{{ states('input_number.basement_google_speaker_day_volume') }}
{% else %}
0.6
{% endif %}
{% endif %}
{% endif %}
- service: tts.amazon_polly_say
data:
entity_id: >-

View File

@ -17,8 +17,8 @@ sensor:
entity_id: switch.tina_desktop
power_sensor_id: sensor.tina_desktop_power
- platform: powercalc
entity_id: fan.emma_air_conditioner
power_sensor_id: sensor.emma_air_conditioner_power
entity_id: switch.emma_bedroom_aircon
power_sensor_id: sensor.emma_bedroom_aircon_power
- platform: powercalc
entity_id: switch.master_bedroom_aircon
power_sensor_id: sensor.master_bedroom_aircon_power

View File

@ -613,7 +613,6 @@ automation:
target:
entity_id:
- fan.kallen_bedroom_fan
- fan.emma_air_conditioner
- service: button.press
target:
entity_id: button.master_bedroom_climate_reset

View File

@ -418,21 +418,14 @@ script:
entity_id: input_datetime.daily_briefing
data:
time: >
{% from 'time.jinja' import time_from_calendar %}
{% if is_state('input_boolean.kallen_school_today','on') %}
{% if is_state('input_boolean.kallen_alternate_pickup','on') or is_state('input_boolean.kallen_btb','on') %}
15:30
{% else %}
{{ time_from_calendar('calendar.kallen_school_days','end_time','set','subtract',1) }}
{% endif %}
{% elif is_state('input_boolean.kallen_school_today','off') and is_state('input_boolean.work_today','off') %}
15:30
{% else %}
{% if is_state('input_boolean.kallen_school_today','off') and is_state('input_boolean.work_today','on') %}
{% if (state_attr('input_datetime.tina_workday_end','timestamp')) > 61200 %}
16:00
{% else %}
{{ (state_attr('input_datetime.tina_workday_end', 'timestamp') + 3600) | timestamp_custom('%H:%M', false) }}
{% endif %}
{% else %}
15:30
{% endif %}
- if:
- condition: state
@ -561,18 +554,7 @@ script:
- service: input_datetime.set_datetime
entity_id: input_datetime.master_bedroom_wakeup
data:
time: >
{% if is_state('input_boolean.kallen_school_today','on') %}
{% if is_state('input_boolean.kallen_alternate_pickup','on') or is_state('input_boolean.kallen_btb','on') %}
16:30
{% elif is_state('input_boolean.kallen_school_early_release','on') %}
12:30
{% else %}
13:00
{% endif %}
{% else %}
16:30
{% endif %}
time: "16:30"
- delay:
milliseconds: 500
- service: input_datetime.set_datetime
@ -618,20 +600,25 @@ script:
data:
time: >
{% set low = states('sensor.overnight_lowest_temperature') | int %}
{% set high = states('sensor.todays_high_temp') | int %}
{% set kallen_bedtime = state_attr('input_datetime.kallen_bedtime','timestamp') | int %}
{% set cutoff = 81000 %}
{% if is_state('input_boolean.hot_day','on') and is_state('binary_sensor.kallen_school_tomorrow','on') %}
{% set cutoff = 81000 %} {# Cutoff time is 22:30 #}
{% if is_state('binary_sensor.kallen_school_tomorrow','on') %}
{% if is_state('input_boolean.hot_day','on') %}
{{ (kallen_bedtime - 3600) | timestamp_custom('%H:%M',false) }}
{% elif is_state('input_boolean.hot_day','on') and is_state('binary_sensor.kallen_school_tomorrow','off') %}
{% elif low >= 56 or high >= 75 %}
{{ (kallen_bedtime - 1800) | timestamp_custom('%H:%M',false) }}
{% else %}
{{ kallen_bedtime | timestamp_custom('%H:%M',false) }}
{% elif 56 <= low <= 60 %}
22:30
{% elif low > 60 %}
{% endif %}
{% elif low > 60 or high > 74 %}
{% if kallen_bedtime < cutoff %}
{{ kallen_bedtime | timestamp_custom('%H:%M',false) }}
{% else %}
21:30
22:00
{% endif %}
{% elif 56 <= low <= 60 %}
22:30
{% else %}
00:00
{% endif %}
@ -642,11 +629,11 @@ script:
{% set low = states('sensor.overnight_lowest_temperature') | int %}
{% set high = states('sensor.todays_high_temp') | int %}
{% if low > 60 or is_state('input_boolean.hot_day','on') %}
00:00
{% elif 50 <= low <= 60 %}
01:00
{% elif low >= states('input_number.master_bedroom_fan_threshold') | int and high > 60 %}
{% elif 50 <= low <= 60 %}
02:00
{% elif low >= states('input_number.master_bedroom_fan_threshold') | int and high > 60 %}
03:00
{% else %}
06:00
{% endif %}
@ -732,11 +719,16 @@ script:
entity_id: input_select.scheduled_climate_mode_emma_bedroom
data:
option: >
{% if is_state('input_boolean.emma_bedroom_aircon_installed','on') %}
{% if (states('sensor.overnight_lowest_temperature') | int) >= (states('input_number.emma_aircon_threshold') | int) %}
{% set low = states('sensor.overnight_lowest_temperature') | int %}
{% set run_threshold = states('input_number.emma_bedroom_aircon_run_threshold') | int %}
{% set mode_threshold = states('input_number.emma_bedroom_aircon_mode_threshold') | int %}
{% if is_state('input_boolean.emma_bedroom_aircon_installed','off') %}
White Noise
{% elif low >= run_threshold %}
{% if low >= mode_threshold %}
AC
{% else %}
White Noise
Fan
{% endif %}
{% else %}
White Noise
@ -750,11 +742,11 @@ script:
{% set low = states('sensor.overnight_lowest_temperature') | int %}
{% set bedtime = state_attr('input_datetime.emma_bedtime','timestamp') | int %}
{% if is_state('input_boolean.hot_day','on') %}
{{ (bedtime - 7200) | timestamp_custom('%H:%M',false) }}
{% elif high >= 80 or low >= 60 %}
{{ (bedtime - 5400) | timestamp_custom('%H:%M',false) }}
{% else %}
{% elif high >= 80 or low >= 60 %}
{{ (bedtime - 3600) | timestamp_custom('%H:%M',false) }}
{% else %}
{{ (bedtime - 1800) | timestamp_custom('%H:%M',false) }}
{% endif %}
- service: input_boolean.turn_on
target:

View File

@ -63,25 +63,25 @@ template:
- binary_sensor:
- name: Tony Desktop On
unique_id: 82ce673a-96ad-4af5-a8d1-be9ca9fa9c36
state: "{{ states('sensor.tony_desktop_power') | int > 10 }}"
state: "{{ states('sensor.tony_desktop_power') | int > 25 }}"
device_class: running
attributes:
power_usage: "{{ states('sensor.tony_desktop_power') | int }}W"
- name: Tina Desktop On
unique_id: 8484dbd4-2fae-4368-a4bc-d1bdc09e003f
state: "{{ states('sensor.tina_desktop_power') | int > 10 }}"
state: "{{ states('sensor.tina_desktop_power') | int > 25 }}"
device_class: running
attributes:
power_usage: "{{ states('sensor.tina_desktop_power') | int }}W"
- name: Kallen Desktop On
unique_id: ccc25d75-4915-449d-9b2e-09ad14ffac29
state: "{{ states('sensor.kallen_desktop_power') | int > 10 }}"
state: "{{ states('sensor.kallen_desktop_power') | int > 25 }}"
device_class: running
attributes:
power_usage: "{{ states('sensor.kallen_desktop_power') | int }}W"
- name: Basement Server On
unique_id: e6df7d98-d3ba-4e01-bae2-2ebafc8d78d6
state: "{{ states('sensor.basement_server_power') | int > 10 }}"
state: "{{ states('sensor.basement_server_power') | int > 25 }}"
device_class: running
attributes:
power_usage: "{{ states('sensor.basement_server_power') | int }}W"

View File

@ -1210,14 +1210,23 @@
min_mireds: 153
max_mireds: 500
effect_list:
- None
- 'off'
- candle
- fire
- prism
- sparkle
- opal
- glisten
- underwater
- cosmos
- sunbeam
- enchant
- sunrise
- sunset
supported_color_modes:
- color_temp
- xy
effect: None
effect: 'off'
color_mode: xy
brightness: 179
color_temp_kelvin:
@ -1244,14 +1253,23 @@
min_mireds: 153
max_mireds: 500
effect_list:
- None
- 'off'
- candle
- fire
- prism
- sparkle
- opal
- glisten
- underwater
- cosmos
- sunbeam
- enchant
- sunrise
- sunset
supported_color_modes:
- color_temp
- xy
effect: None
effect: 'off'
color_mode: xy
brightness: 255
color_temp_kelvin:
@ -1278,10 +1296,13 @@
min_mireds: 153
max_mireds: 500
effect_list:
- None
- 'off'
- candle
- fire
- prism
- sparkle
- opal
- glisten
supported_color_modes:
- color_temp
- xy
@ -1342,14 +1363,23 @@
min_mireds: 153
max_mireds: 500
effect_list:
- None
- 'off'
- candle
- fire
- prism
- sparkle
- opal
- glisten
- underwater
- cosmos
- sunbeam
- enchant
- sunrise
- sunset
supported_color_modes:
- color_temp
- xy
effect: None
effect: 'off'
color_mode: xy
brightness: 255
color_temp_kelvin:
@ -1376,14 +1406,23 @@
min_mireds: 153
max_mireds: 500
effect_list:
- None
- 'off'
- candle
- fire
- prism
- sparkle
- opal
- glisten
- underwater
- cosmos
- sunbeam
- enchant
- sunrise
- sunset
supported_color_modes:
- color_temp
- xy
effect: None
effect: 'off'
color_mode: xy
brightness: 255
color_temp_kelvin:
@ -1441,14 +1480,17 @@
min_mireds: 153
max_mireds: 500
effect_list:
- None
- 'off'
- candle
- fire
- prism
- sparkle
- opal
- glisten
supported_color_modes:
- color_temp
- xy
effect: None
effect: 'off'
color_mode: xy
brightness: 204
color_temp_kelvin:

View File

@ -1544,14 +1544,14 @@ day_mode_in_tina_desk:
alias: Day Mode in Tina Desk
sequence:
- parallel:
- service: light.turn_on
target:
- target:
entity_id: light.tina_lamp_top
data: {}
- service: light.turn_off
target:
action: light.turn_on
- target:
entity_id: light.tina_lamp_side
data: {}
action: light.turn_off
- wait_template: '{{ is_state(''light.tina_lamp_side'',''off'') }}'
timeout:
seconds: 15
@ -1561,52 +1561,57 @@ day_mode_in_tina_desk:
- condition: state
entity_id: switch.adaptive_lighting_tina_lamp
state: 'off'
alias: If switch is off
alias: If adaptive lighting is off
then:
- service: switch.turn_on
- alias: Turn on adaptive lighting
data: {}
target:
entity_id: switch.adaptive_lighting_tina_lamp
alias: Turn on the switch
entity_id:
- switch.adaptive_lighting_tina_lamp
- switch.adaptive_lighting_adapt_brightness_tina_lamp
- switch.adaptive_lighting_adapt_color_tina_lamp
action: switch.turn_on
else:
- alias: Apply adaptive lighting
service: adaptive_lighting.apply
data:
entity_id: switch.adaptive_lighting_tina_lamp
adapt_brightness: true
adapt_color: true
action: adaptive_lighting.apply
mode: restart
icon: mdi:palette
evening_mode_in_tina_desk:
alias: Evening Mode in Tina Desk
sequence:
- alias: Turn on lamp
service: light.turn_on
data: {}
target:
entity_id:
- light.tina_lamp_top
- light.tina_lamp_side
action: light.turn_on
- alias: Apply adaptive lighting to lamp
if:
- condition: state
entity_id: switch.adaptive_lighting_tina_lamp
state: 'off'
alias: If switch is off
alias: If adaptive lighting is off
then:
- service: switch.turn_on
- alias: Turn on adaptive lighting
data: {}
target:
entity_id: switch.adaptive_lighting_tina_lamp
alias: Turn on the switch
entity_id:
- switch.adaptive_lighting_tina_lamp
- switch.adaptive_lighting_adapt_brightness_tina_lamp
- switch.adaptive_lighting_adapt_color_tina_lamp
action: switch.turn_on
else:
- service: adaptive_lighting.apply
- alias: Apply adaptive lighting
data:
entity_id: switch.adaptive_lighting_tina_lamp
adapt_brightness: true
adapt_color: true
turn_on_lights: true
alias: Apply adaptive lighting
action: adaptive_lighting.apply
mode: restart
icon: mdi:palette
night_mode_in_tina_desk:
@ -1663,6 +1668,32 @@ tony_morning_meds:
tag: tony-morning-meds
alias: Clear previous morning notification
action: script.text_notify
- alias: Send notifications, using AI if internet is connected
if:
- condition: state
entity_id: binary_sensor.internet
state: 'on'
then:
- alias: Generate reminder, be snarky if it's been several times
if:
- condition: numeric_state
entity_id: counter.tony_morning_meds_reminder_count
above: 2
then:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tony to take his morning meds. Use a maximum of two lines.
Be snarky, because at this point he's been reminded multiple times.
response_variable: response
alias: Generate snarky reminder
else:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tony to take his morning meds. Use a maximum of two lines.
response_variable: response
alias: Generate reminder
- delay:
hours: 0
minutes: 0
@ -1675,7 +1706,7 @@ tony_morning_meds:
who: tony
type: alert
title: Morning Meds
message: You need to take your morning meds
message: '{{ response.text }}'
tag: tony-morning-meds
actions:
- action: TONY_MORNING_MEDS_TAKEN
@ -1685,7 +1716,7 @@ tony_morning_meds:
action: script.text_notify
- alias: Send TTS if reminders > 2 and Tony is home
if:
- alias: If reminders > 2 and Tony is home
- alias: When reminders > 2 and Tony is home
condition: and
conditions:
- condition: numeric_state
@ -1700,10 +1731,50 @@ tony_morning_meds:
- data:
who: common_areas
type: alert
message: Tony, you need to take your morning meds. This is reminder number
{{ states('counter.tony_morning_meds_reminder_count') }} for today.
message: '{{ response.text }}'
alias: Send TTS notification
action: script.speech_engine
else:
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Send morning notifications via text, and TTS if needed
parallel:
- alias: Send text notification
data:
who: tony
type: alert
title: Morning Meds
tag: tony-morning-meds
actions:
- action: TONY_MORNING_MEDS_TAKEN
title: Taken
- action: TONY_MORNING_MEDS_SKIPPED
title: Skip
message: You need to take your morning meds
action: script.text_notify
- alias: Send TTS if reminders > 2 and Tony is home
if:
- alias: When reminders > 2 and Tony is home
condition: and
conditions:
- condition: numeric_state
entity_id: counter.tony_morning_meds_reminder_count
above: 2
alias: When reminder count > 2
- condition: state
entity_id: person.tony_stork
state: home
alias: If Tony is home
then:
- alias: Send TTS notification
data:
who: common_areas
type: alert
message: Tony, you need to take your morning meds
action: script.speech_engine
tony_night_meds:
alias: Tony Night Meds
icon: mdi:medication
@ -1904,6 +1975,32 @@ tony_afternoon_meds:
tag: tony-afternoon-meds
alias: Clear previous afternoon notification
action: script.text_notify
- alias: Send notifications, using AI if internet is connected
if:
- condition: state
entity_id: binary_sensor.internet
state: 'on'
then:
- alias: Generate reminder, be snarky if it's been several times
if:
- condition: numeric_state
entity_id: counter.tony_afternoon_meds_reminder_count
above: 2
then:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tony to take his afternoon meds. Use a maximum of two lines.
Be snarky, because at this point he's been reminded multiple times.
response_variable: response
alias: Generate snarky reminder
else:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tony to take his afternoon meds. Use a maximum of two lines.
response_variable: response
alias: Generate reminder
- delay:
hours: 0
minutes: 0
@ -1916,7 +2013,7 @@ tony_afternoon_meds:
who: tony
type: alert
title: Afternoon Meds
message: You need to take your afternoon meds
message: '{{ response.text }}'
tag: tony-afternoon-meds
actions:
- action: TONY_AFTERNOON_MEDS_TAKEN
@ -1941,10 +2038,50 @@ tony_afternoon_meds:
- data:
who: common_areas
type: alert
message: Tony, you need to take your afternoon meds. This is reminder number
{{ states('counter.tony_afternoon_meds_reminder_count') }} for today.
message: '{{ response.text }}'
alias: Send TTS notification
action: script.speech_engine
else:
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Send afternoon notifications via text, and TTS if needed
parallel:
- alias: Send text notification
data:
who: tony
type: alert
title: Afternoon Meds
tag: tony-afternoon-meds
actions:
- action: TONY_AFTERNOON_MEDS_TAKEN
title: Taken
- action: TONY_AFTERNOON_MEDS_SKIPPED
title: Skip
message: You need to take your afternoon meds
action: script.text_notify
- alias: Send TTS if reminders > 2 and Tony is home
if:
- alias: When reminders > 2 and Tony is home
condition: and
conditions:
- condition: numeric_state
entity_id: counter.tony_afternoon_meds_reminder_count
above: 2
alias: When reminder count > 2
- condition: state
entity_id: person.tony_stork
state: home
alias: If Tony is home
then:
- alias: Send TTS notification
data:
who: common_areas
type: alert
message: Tony, you need to take your afternoon meds
action: script.speech_engine
tony_ibuprofen:
alias: Tony Ibuprofen
sequence:
@ -2308,80 +2445,62 @@ tony_tylenol:
kallen_morning_meds:
alias: Kallen Morning Meds
sequence:
- service: counter.increment
metadata: {}
- metadata: {}
data: {}
target:
entity_id: counter.kallen_morning_meds_reminder_count
alias: Increment morning reminder counter
- alias: Clear previous morning notifications
parallel:
- service: script.text_notify
action: counter.increment
- alias: Clear previous text notifications
data:
type: alert
who: parents
who: all
message: clear_notification
tag: kallen-morning-meds-parents
alias: Clear for parents
- service: script.text_notify
data:
type: alert
who: kallen
message: clear_notification
tag: kallen-morning-meds-self
alias: Clear for Kallen
tag: kallen-morning-meds
action: script.text_notify
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Send text notifications
parallel:
- alias: Send to parents
service: script.text_notify
- alias: Send text notification
data:
who: parents
who: all
type: alert
title: Morning Meds
message: Kallen needs to take his morning meds
tag: kallen-morning-meds-parents
tag: kallen-morning-meds
actions:
- action: KALLEN_MORNING_MEDS_TAKEN
title: Taken
- action: KALLEN_MORNING_MEDS_SKIPPED
title: Skip
- service: script.text_notify
data:
who: kallen
type: alert
title: Morning Meds
message: You need to take your morning meds. Go to mom or dad to confirm.
tag: kallen-morning-meds-self
alias: Send to Kallen
action: script.text_notify
icon: mdi:medication
mode: restart
kallen_night_meds:
alias: Kallen Night Meds
sequence:
- service: counter.increment
- alias: Increment night reminder counter
metadata: {}
data: {}
alias: Increment night reminder counter
- service: script.text_notify
data:
action: counter.increment
target:
entity_id: counter.kallen_night_meds_reminder_count
- data:
type: alert
who: all
message: clear_notification
tag: kallen-night-meds
alias: Clear previous night notification
action: script.text_notify
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- parallel:
- service: script.text_notify
data:
- data:
who: "{% if states('person.christina_stork') in ['Bob Evans','BobEvans'] %}\n
\ tony\n{% else %}\n parents\n{% endif %}\n"
type: alert
@ -2394,8 +2513,8 @@ kallen_night_meds:
- action: KALLEN_NIGHT_MEDS_SKIPPED
title: Skip
alias: Send to parents
action: script.text_notify
- alias: Send to Kallen
service: script.text_notify
data:
who: kallen
type: alert
@ -2407,6 +2526,7 @@ kallen_night_meds:
title: Taken
- action: KALLEN_NIGHT_MEDS_SKIPPED
title: Skip
action: script.text_notify
alias: Send text notifications
icon: mdi:medication
mode: restart
@ -2859,35 +2979,7 @@ emma_sleep:
option: Adaptive
alias: Set lights to adaptive
action: input_select.select_option
- alias: Select climate mode
choose:
- conditions:
- alias: AC
condition: and
conditions:
- condition: state
entity_id: input_select.scheduled_climate_mode_emma_bedroom
state: AC
alias: Scheduled mode is AC
- condition: state
entity_id: fan.emma_air_conditioner
state: 'off'
alias: Air conditioner is not already on
sequence:
- target:
entity_id: fan.emma_air_conditioner
data: {}
alias: Turn on air conditioner
action: fan.turn_on
- data:
who: parents
title: Emma Climate Schedule
message: The air conditioner in Emma's Bedroom has been activated.
type: normal
tag: emma-climate
alias: Send AC notification
action: script.text_notify
- conditions:
- if:
- alias: White Noise
condition: and
conditions:
@ -2899,7 +2991,7 @@ emma_sleep:
entity_id: input_boolean.white_noise_emma_bedroom
state: 'off'
alias: White Noise is not already on
sequence:
then:
- target:
entity_id: input_boolean.white_noise_emma_bedroom
data: {}
@ -2913,15 +3005,7 @@ emma_sleep:
tag: emma-climate
alias: Send white noise notification
action: script.text_notify
default:
- data:
who: parents
title: Emma Climate Schedule
message: No option selected for Emma's climate mode. No devices will be activated.
type: normal
tag: emma-climate
alias: Send notification that no climate mode is selected
action: script.text_notify
alias: Select climate mode
icon: mdi:lightbulb-night
mode: restart
tina_morning_meds:
@ -2929,75 +3013,163 @@ tina_morning_meds:
icon: mdi:medication
mode: restart
sequence:
- service: counter.increment
metadata: {}
- metadata: {}
data: {}
target:
entity_id: counter.tina_morning_meds_reminder_count
alias: Increment morning reminder counter
- service: script.text_notify
data:
action: counter.increment
- data:
type: alert
who: tina
message: clear_notification
tag: tina-morning-meds
alias: Clear previous morning notification
action: script.text_notify
- alias: Send notifications, using AI if internet is connected
if:
- condition: state
entity_id: binary_sensor.internet
state: 'on'
then:
- if:
- condition: numeric_state
entity_id: counter.tina_morning_meds_reminder_count
above: 2
then:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tina to take her morning meds. Use a maximum of two lines.
Be snarky, because at this point she's been reminded multiple times.
response_variable: response
alias: Generate snarky reminder
else:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tina to take her morning meds. Use a maximum of two lines.
response_variable: response
alias: Generate reminder
alias: Generate reminder, be snarky if it's been several times
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Send text notification
service: script.text_notify
data:
who: tina
type: alert
title: Morning Meds
message: You need to take your morning meds
message: '{{ response.text }}'
tag: tina-morning-meds
actions:
- action: TINA_MORNING_MEDS_TAKEN
title: Taken
- action: TINA_MORNING_MEDS_SKIPPED
title: Skip
description: ''
tina_night_meds:
alias: Tina Night Meds
icon: mdi:medication
mode: restart
sequence:
- service: counter.increment
metadata: {}
data: {}
target:
entity_id: counter.tina_night_meds_reminder_count
alias: Increment night reminder counter
- service: script.text_notify
data:
type: alert
who: tina
message: clear_notification
tag: tina-night-meds
alias: Clear previous night notification
action: script.text_notify
else:
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Send text notification
data:
who: tina
type: alert
title: Morning Meds
tag: tina-morning-meds
actions:
- action: TINA_MORNING_MEDS_TAKEN
title: Taken
- action: TINA_MORNING_MEDS_SKIPPED
title: Skip
message: You need to take your morning meds
action: script.text_notify
tina_night_meds:
alias: Tina Night Meds
icon: mdi:medication
mode: restart
sequence:
- metadata: {}
data: {}
target:
entity_id: counter.tina_night_meds_reminder_count
alias: Increment night reminder counter
action: counter.increment
- data:
type: alert
who: tina
message: clear_notification
tag: tina-night-meds
alias: Clear previous night notification
action: script.text_notify
- alias: Send notifications, using AI if internet is connected
if:
- condition: state
entity_id: binary_sensor.internet
state: 'on'
then:
- if:
- condition: numeric_state
entity_id: counter.tina_night_meds_reminder_count
above: 2
then:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tina to take her night meds. Use a maximum of two lines.
Be snarky, because at this point she's been reminded multiple times.
response_variable: response
alias: Generate snarky reminder
else:
- action: google_generative_ai_conversation.generate_content
metadata: {}
data:
prompt: Remind Tina to take her night meds. Use a maximum of two lines.
response_variable: response
alias: Generate reminder
alias: Generate reminder, be snarky if it's been several times
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Send text notification
service: script.text_notify
data:
who: tina
type: alert
title: Night Meds
message: You need to take your night meds
message: '{{ response.text }}'
tag: tina-night-meds
actions:
- action: TINA_NIGHT_MEDS_TAKEN
title: Taken
- action: TINA_NIGHT_MEDS_SKIPPED
title: Skip
description: ''
action: script.text_notify
else:
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- alias: Send text notification
data:
who: tina
type: alert
title: Night Meds
tag: tina-night-meds
actions:
- action: TINA_NIGHT_MEDS_TAKEN
title: Taken
- action: TINA_NIGHT_MEDS_SKIPPED
title: Skip
message: You need to take your night meds
action: script.text_notify
tina_ibuprofen:
sequence:
- alias: Turn off boolean if this is a notification
@ -3360,3 +3532,41 @@ tina_tylenol:
icon: mdi:medication
max: 10
description: ''
reading_mode_in_tina_desk:
sequence:
- action: switch.turn_off
metadata: {}
data: {}
target:
entity_id: switch.adaptive_lighting_adapt_brightness_tina_lamp
alias: Turn off adaptive brightness, leave adaptive color on
- alias: Turn on lamp
action: light.turn_on
metadata: {}
data:
brightness_pct: 100
target:
entity_id: light.tina_desk_lights
- alias: Apply adaptive lighting to lamp
if:
- condition: state
entity_id: switch.adaptive_lighting_tina_lamp
state: 'off'
alias: If switch is off
then:
- data: {}
target:
entity_id: switch.adaptive_lighting_tina_lamp
alias: Turn on the switch
action: switch.turn_on
else:
- alias: Apply adaptive lighting
data:
entity_id: switch.adaptive_lighting_tina_lamp
adapt_color: true
turn_on_lights: true
adapt_brightness: false
action: adaptive_lighting.apply
alias: Reading Mode in Tina Desk
description: ''
icon: mdi:palette

View File

@ -168,7 +168,7 @@
unit_of_measurement: ''
state: >-
{% set compressors = [
states.binary_sensor.emma_aircon_compressor,
states.binary_sensor.emma_bedroom_aircon_compressor,
states.binary_sensor.master_bedroom_aircon_compressor
] %}
{{ compressors | selectattr('state','eq','on') | list | count | int }}
@ -177,7 +177,7 @@
unit_of_measurement: ''
state: >-
{% set fans = [
states.binary_sensor.emma_aircon_fan,
states.binary_sensor.emma_bedroom_aircon_fan,
states.binary_sensor.master_bedroom_aircon_fan
] %}
{{ fans | selectattr('state','eq','on') | list | count | int }}
@ -196,11 +196,7 @@
unit_of_measurement: ''
state: >-
{% set climate = states.climate | selectattr('state','ne','off') | rejectattr('state','eq','unavailable') | rejectattr('state','eq','unknown') | list | count | int %}
{% set fans = [
states.fan.emma_air_conditioner
] %}
{% set fans_on = fans | selectattr('state','eq','on') | list | count | int %}
{{ climate + fans_on | int }}
{{ climate | int }}
- name: Climate Devices Running
unique_id: 3c61c756-2934-4294-8085-7d3855b692dd
unit_of_measurement: ''

View File

@ -98,12 +98,7 @@
{% endif %}
{% if is_state('input_boolean.kallen_alternate_pickup','on') %}
Today, you will be picked up from school by {{ states('input_text.kallen_pickup') }}.
{% elif is_state('input_boolean.work_today','off') %}
Today, you will be picked up from school by your parents.
{% else %}
Today, you will be picked up from school by your dad.
{% endif %}
<s>Pickup today will be at {{ input_datetime_read('input_datetime.kallen_school_day_end') }}</s>
{% if count_the_days('input_datetime.school_last_day') | int == 0 -%}
But today is the last day of School!
{%- endif %}

View File

@ -71,9 +71,13 @@
{% else %}
"Collin's room will be left alone, as he is spending the night elsewhere tonight. "
{% endif %}
{% if states('input_select.scheduled_climate_mode_emma_bedroom') != 'N/A' %}
{% if is_state('input_select.scheduled_climate_mode_emma_bedroom','AC') and is_state('fan.emma_air_conditioner','off') %}
"Emma's air conditioner will be activated at {{ input_datetime_read('input_datetime.emma_bedroom_cooling') }}. "
{% if states('input_select.scheduled_climate_mode_emma_bedroom_aircon') != 'N/A' %}
{% if is_state('input_select.scheduled_climate_mode_emma_bedroom_aircon','AC') and is_state('input_boolean.hot_day','on') %}
"Today was a hot day, so Emma's bedroom air conditioner will start cooling a bit earlier tonight at {{ input_datetime_read('input_datetime.emma_bedroom_cooling') }}. "
{% elif is_state('input_select.scheduled_climate_mode_emma_bedroom_aircon','AC') %}
"Emma's bedroom air conditioner will start cooling at {{ input_datetime_read('input_datetime.emma_bedroom_cooling') }}. "
{% elif is_state('input_select.scheduled_climate_mode_emma_bedroom_aircon','Fan') %}
"Emma's bedroom air conditioner will activate fan only mode at {{ input_datetime_read('input_datetime.emma_bedroom_cooling') }}. "
{% elif is_state('input_select.scheduled_climate_mode_emma_bedroom','White Noise') and is_state('input_boolean.white_noise_emma_bedroom','off') %}
"Emma's white noise generator will activate at {{ input_datetime_read('input_datetime.emma_bedtime') }}. "
{% endif %}

View File

@ -76,7 +76,7 @@
<p>
{% if (states('sensor.climate_devices_installed') | int) > 0 %}
{% if is_state('input_boolean.master_bedroom_aircon_installed','on') %}
"the master bedroom temperature is {{ states('sensor.master_bedroom_aircon_indoor_temperature') | int }} degrees. "
"the master bedroom temperature is {{ states('sensor.master_bedroom_temperature') | int }} degrees. "
{% if not is_state('climate.master_bedroom_aircon','off') %}
{% if is_state('climate.master_bedroom_aircon','cool') %}
"and the master bedroom air conditioner is set for cooling to {{ state_attr('climate.master_bedroom_aircon','temperature') }} degrees. "
@ -90,11 +90,22 @@
"and the master bedroom air conditioner is currently not speaking to me. Was it something I said? "
{% endif %}
{% endif %}
{% elif is_state('input_boolean.master_bedroom_aircon_installed','off') %}
"There is no air conditioner or temperature sensor installed in the master bedroom. "
{% endif %}
{% if is_state('input_boolean.emma_bedroom_aircon_installed','on') and is_state('fan.emma_air_conditioner','on') %}
"Emma's air conditioner is {{ states('fan.emma_air_conditioner') }}. "
{% if is_state('input_boolean.emma_bedroom_aircon_installed','on') %}
"the temperature in Emma's bedroom is {{ states('sensor.emma_bedroom_temperature') | int }} degrees. "
{% if not is_state('climate.emma_bedroom_aircon','off') %}
{% if is_state('climate.emma_bedroom_aircon','cool') %}
"and Emma's bedroom air conditioner is set for cooling to {{ state_attr('climate.emma_bedroom_aircon','temperature') }} degrees. "
{% elif is_state('climate.emma_bedroom_aircon','fan_only') %}
"and Emma's bedroom air conditioner is in fan only mode. "
{% elif is_state('climate.emma_bedroom_aircon','dry') %}
"and Emma's bedroom air conditioner is moonlighting as a dehumidifier. "
{% elif is_state('climate.emma_bedroom_aircon','auto') %}
"and Emma's bedroom air conditioner is making its own decisions. Be afraid, be very afraid. "
{% else %}
"and Emma's bedroom air conditioner is currently not speaking to me. Was it something I said? "
{% endif %}
{% endif %}
{% endif %}
{% endif %}
</p>
@ -117,7 +128,7 @@
"Tina has work today. "
{% endif %}
{% if is_state('input_boolean.kallen_at_school','on') %}
"Collin is at school right now. His pickup time will be at {{ input_datetime_read('input_datetime.kallen_school_day_end') }}. "
"Collin is at school right now. His school day ends at {{ input_datetime_read('input_datetime.kallen_school_day_end') }}. "
{% elif is_state('input_boolean.kallen_school_today','on') %}
"Collin has school today. "
{% endif %}