Compare commits

...

161 Commits

Author SHA1 Message Date
0129a56866 Comment out total rain sensors template 2025-05-23 04:35:35 -04:00
b305f7c880 Rewrite rain detection sensor 2025-05-23 04:34:26 -04:00
6ee4bacf55 Notifications for school status changes (delay/cancel)
#245
2025-05-23 03:57:44 -04:00
4710700f7e Fix adaptive lighting reset in basement studio goodnight script 2025-05-22 19:06:41 -04:00
895e99657b The new way of doing weather forecasts in Home Assistant is fucking trash 2025-05-21 22:15:52 -04:00
0dc7d0f8e4 Fix Weather.com attributes in template weather stations 2025-05-21 20:45:59 -04:00
d38cf59812 Make sure the correct teams are inhibited for MLB if playing each other 2025-05-21 20:41:35 -04:00
a489ecdf14 Update .HA_VERSION 2025-05-20 18:35:56 -04:00
8698a46d4f Exclude Tempest data from long-term stats, found another solution 2025-05-16 19:59:57 -04:00
7d5aa32834 Use Tempest rainfall sensor to trigger window warning 2025-05-15 18:19:03 -04:00
37458be1b8 Unfuck my recorder config... 2025-05-15 17:48:09 -04:00
72421b8716 Switch from Weather.com to Weatherflow for weather sensors 2025-05-15 06:26:41 -04:00
8be8f4bb58 Narrow down to just using the Tempest lighting strikes over past hour 2025-05-15 05:38:24 -04:00
6e619fa647 Input number for front porch lux threshold 2025-05-15 04:08:04 -04:00
9dca18048c Incorporate Weatherflow forecasts into main weather templates 2025-05-15 02:30:03 -04:00
52bfb8bd49 Handle lightning monitoring as more of a group effort 2025-05-15 01:14:19 -04:00
43feaa9b06 Lightning warning now uses local Tempest sensor by default 2025-05-15 00:05:10 -04:00
0847e7fd10 Add dewpoint and apparent temperature templates to INWS weather template 2025-05-15 00:04:49 -04:00
425b1fb0cf Add local Tempest Weather data to INWS weather template 2025-05-15 00:04:23 -04:00
f589cc0e6c Remove automations and blueprint for Chromecasting to TVs 2025-05-15 00:03:16 -04:00
49a4f4650b Update sensor light blueprint 2025-05-15 00:02:51 -04:00
3a2fc504f3 Update Twanne's lighting blueprints 2025-05-15 00:02:28 -04:00
f1180cc34b Track Weatherflow Tempest data in databases 2025-05-14 20:08:52 -04:00
b936838376 Updated readme 2025-05-14 01:28:00 -04:00
2d755be935 Shower Mode Auto Off automation 2025-05-13 23:57:42 -04:00
ed0431ae56 Update .HA_VERSION 2025-05-13 23:57:17 -04:00
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
b5dd9621d1 Don't turn basement heat on if it was off 2025-03-11 02:07:15 -04:00
587ac4d203 Update .HA_VERSION 2025-03-08 15:24:32 -05:00
b459d78446 Add new dashboard format to weather report macro 2025-03-05 17:26:55 -05:00
352e4f1ada Update weather report jinja template 2025-03-05 17:08:30 -05:00
09d82abdb1 Monthly update 2025-03-05 16:25:21 -05:00
8b120ae347 Tweak temperature scales for bubble cards slightly 2025-03-04 02:17:56 -05:00
da03ea826b Add temperature coloring module for bubble cards 2025-03-04 02:09:27 -05:00
66fc0fb906 Default bubble modules file 2025-03-04 01:38:14 -05:00
4c81a8a6a5 Updated gitignore 2025-03-04 01:32:15 -05:00
35a511710e Add "do not enter" input boolean tm24fan8/Home-Assistant-Configs#218 2025-03-01 20:49:06 -05:00
4c7bf9a85c Include .HA_VERSION file 2025-02-28 00:46:44 -05:00
754e3d6095 Don't consider K's computer as occupying the basement if I am upstairs 2025-02-28 00:30:26 -05:00
8f707c71bb Make it easier to activate nightlight in master bedroom 2025-02-27 00:50:53 -05:00
08b5c7b764 Remove old scrape-based gas sensors 2025-02-26 03:37:22 -05:00
fd37fe589c Push security disarm 5 minutes earlier for K's school mornings
Close #215
2025-02-26 02:27:18 -05:00
36906d6207 Updated readme 2025-02-26 01:17:33 -05:00
29dcb654b4 Copy ibuprofen and tylenol trackers for Tina 2025-02-21 22:19:37 -05:00
ec0aed386a Begin simplification of wife's desk lighting 2025-02-18 15:40:35 -05:00
a96bc99271 Basement presence now checks if I'm using wife's PC upstairs
#188
2025-02-15 16:03:59 -05:00
a085e71c86 Remove wife's desk strip as it broke 2025-02-11 02:41:43 -05:00
4a61f5a45c Fix sections showing up in sports dashboard when they shouldn't 2025-01-30 17:19:24 -05:00
47f23a4e02 Change some entity names 2025-01-28 16:36:39 -05:00
fbec1ae6e2 Tweak vtherm tolerance and cycle times 2025-01-28 16:36:27 -05:00
d5ddf65270 Adaptive second floor scene sets upstairs bathroom to single nightlight 2025-01-28 16:35:54 -05:00
53b67bfc87 Add VTherm for E's bedroom 2025-01-25 20:21:37 -05:00
725250acd7 Add K and guest mode to "people present" sensor 2025-01-25 20:20:53 -05:00
f988f1cccc Improve basement climate control 2025-01-25 20:20:08 -05:00
515731fc68 Attempting to automate a space heater in the basement 2025-01-14 05:45:19 -05:00
e1bd79e176 Fix notification reset on Tony's Med Tracker 2025-01-12 17:15:37 -05:00
a57cb4ecb7 Update gitignore 2025-01-12 17:14:58 -05:00
89ef394817 Fix bottom button in master bedroom switching both fan and closet light 2024-12-29 15:10:36 -05:00
6b9380f015 Move "services down" to a macro for possible re-use elsewhere
Also improved the wording
2024-12-10 16:03:31 -05:00
6c145f0ca9 Attempt to fix fade duration on recliner mode shutoff 2024-11-30 20:51:58 -05:00
ff98142b9e Increased darkness upstairs when people are sleeping 2024-11-29 14:54:11 -05:00
2ceba7cb57 Small tweak to scheduling for morning briefing
To make sure K hasn't already walked out the door for the bus before it plays
2024-11-14 16:46:36 -05:00
1b2ce1e097 Add individual allow switches for housewide briefings 2024-11-14 16:40:46 -05:00
7459005500 Add morning announcements for K 2024-11-14 16:25:39 -05:00
9ed2f658a4 Add new blueprint for inverted binary sensor, apparently 2024-11-11 20:14:17 -05:00
91d6a32274 Remove Emma naptime entities and related code 2024-11-11 20:13:33 -05:00
f2e9f6049c Adjust scheduling for K riding the bus 2024-10-22 13:15:20 -04:00
6f9c9fc8a9 Add adjustment issue template 2024-10-22 13:11:02 -04:00
b819156cfa Push back K's bedtime schedules by an hour across the board 2024-10-14 18:19:29 -04:00
df583c23ff Remove html5 notify config as it is now in UI 2024-10-12 15:46:27 -04:00
84f0e54ddb Remove unnecessary state attribute from computer idle sensors
The information is available in its own sensor, and is thus unnecessary to have as an attribute. It was causing unnecessary database bloat.
2024-10-01 16:19:24 -04:00
3803e9f9c2 Fix grammar around NCAAF team names
The changed response from ESPN resulted in teams being called "the Michigan" etc instead of "the Wolverines". So I removed the "the" for NCAAF games.
2024-09-22 13:41:29 -04:00
66d27a09d3 Add new weather entities for comparison project 2024-09-20 20:11:58 -04:00
ed71c557df Only send TTS notifications for my meds if I'm actually home 2024-09-20 20:11:25 -04:00
35e5891f5e Add start of school year automation 2024-09-04 15:01:59 -04:00
3d4dc4c1d9 Fix wife and K's med notification scheduling
#205
2024-08-09 16:57:13 -04:00
8c029143f2 Add scheduling automations for sports notifications
Signed-off-by: Tony Stork <tm24fan8@gmail.com>
2024-08-09 16:57:12 -04:00
c773b29573 Fix typo for wife's name 2024-08-09 16:57:11 -04:00
76841ecb19 Use time_from_calendar macro for K scheduling for two hour delays 2024-08-09 16:57:10 -04:00
f3d5d90593 Fix scheduling for wife's morning meds reminder
#205
2024-08-09 16:57:09 -04:00
c7d1696cca Add new macro for setting time AND date from calendars 2024-08-09 16:57:08 -04:00
db9b221fd9 Change template condition to "or" condition for my meds cleanup
#205
2024-08-09 16:57:07 -04:00
955bf32e81 Change template condition to "or" condition for wife meds cleanup
#205
2024-08-09 16:57:06 -04:00
fc498ca23b Implement new trackers for K
#205
2024-08-09 16:57:05 -04:00
f61d79dee7 Implement new trackers for wife
#205
2024-08-09 16:57:04 -04:00
cc5a94e683 We need to START the med scripts by incrementing the counter
Doing it at the end means things that should happen on the third reminder will not actually happen until the fourth.

#205
2024-08-09 16:57:03 -04:00
c8678d831a Rewrite Tony meds scripts to simply handle sending the reminders
#205
2024-08-09 16:57:02 -04:00
e566d94d90 Add Tony Meds Cleanup automation
#205
2024-08-09 16:57:01 -04:00
54de982d95 Rewrite Tony Meds Handler automation
#205
2024-08-09 16:57:00 -04:00
8a4545abed Switch from template sensors to input booleans for reminders
#205
2024-08-09 16:56:59 -04:00
bb9e604d33 Change logic for setting and resetting notification times
#205
2024-08-09 16:56:58 -04:00
e912733bbc Add triggers to help with reboot survival
#205
2024-08-09 16:56:57 -04:00
53b230e0ad Fix UUIDs
#205
2024-08-09 16:56:56 -04:00
4761855858 Initial notification framework for meds rework 2024-08-09 16:56:55 -04:00
b83c3e2ecd Disallow default issue template 2024-08-09 16:56:35 -04:00
22ba35d631 Add feature request template 2024-08-09 16:47:39 -04:00
b6539ea85c Add bug label to bug report template 2024-08-09 16:47:25 -04:00
37f5314e88 See if labels can be assigned by yaml issue templates 2024-08-09 16:31:49 -04:00
faef1d02b2 Add bug report issue template
(cherry picked from commit 94cbb81be1)
2024-08-08 22:29:56 -04:00
46df823c24 Add min/max/average temp and lux sensors to database 2024-07-30 18:00:25 -04:00
707c03804d Update to latest relative_time_plus.jinja 2024-07-24 15:58:55 -04:00
9fea293c23 Add med reminder counts for K 2024-07-24 15:55:35 -04:00
703fed14c3 Move wife's med tracker to UI, add reminder counts 2024-07-23 21:54:39 -04:00
37a6f31a1e Add night meds reminder count, reset reminder counts when meds are taken 2024-07-23 21:54:15 -04:00
8411488ab3 Make E's actual wakeup time actually update properly 2024-07-23 21:52:49 -04:00
bda6fc97ba Move Minnesota Twins to first spot for baseball teams 2024-07-23 15:25:07 -04:00
261913371f Updated readme 2024-07-22 22:54:28 -04:00
b718ad2de2 Add text notifications for shower mode window alert #204 2024-07-22 22:29:39 -04:00
2c559ec2c4 Shower mode window alert, close #204 2024-07-22 21:56:53 -04:00
53 changed files with 12003 additions and 5726 deletions

1
.HA_VERSION Normal file
View File

@@ -0,0 +1 @@
2025.5.2

20
.gitignore vendored
View File

@@ -3,30 +3,27 @@
/.cloud
/.google.token
/.ssh
/.codegpt
# ignore some directories.
/icloud/
/www/
/www/*
/tts/
/deps/
/hadashboards/
/intents/
/themes/
/custom_components
/deps
/hacs
/image
/node-red/
/files
/appdaemon/*
/appdaemon/apps/*
/appdaemon/
/glances/
/downloads/
/lightwand/
# ignore any of these files no matter where they are using double *
**.DS_Store
**._*
**.HA_VERSION
**.pyc
**.conf
**.uuid
@@ -71,11 +68,4 @@
**test.jinja
# exceptions
!/appdaemon/apps/
!/appdaemon/apps/apps.yaml
!/node-red/projects/
!/node-red/projects/NerdFlows/
!/node-red/projects/NerdFlows/flows.json
!/node-red/projects/NerdFlows/flows_cred.json
!/node-red/projects/NerdFlows/package.json
!/node-red/projects/NerdFlows/README.md
!/www/bubble/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
blueprint:
name: Smart Lux Dimmer
author: AntonH
description: 'Version 4.1
description: 'Version 4.3
Switch or dim lights based on the value of a light sensor.
@@ -24,10 +24,11 @@ blueprint:
value?
selector:
entity:
domain:
- sensor
device_class:
- illuminance
filter:
- domain:
- sensor
device_class:
- illuminance
multiple: false
target_light:
name: Target lights
@@ -81,8 +82,8 @@ blueprint:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
mode: slider
light_value_2:
name: Brightness at minimum light level
description: Brightness of the light at minimum ambient light.
@@ -92,8 +93,8 @@ blueprint:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
mode: slider
transition_time:
name: Transition time
description: 'The time it takes for the light to transition from the set value
@@ -124,9 +125,9 @@ blueprint:
value: include_color
- label: Set temperature
value: include_temp
multiple: false
sort: false
custom_value: false
sort: false
multiple: false
light_color:
name: Light color
description: Color of the light when between minimum and maximum ambient light
@@ -161,8 +162,8 @@ blueprint:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
mode: slider
light_brightness_under_min:
name: Brightness when ambient light value under min.
description: Brightness of the light when the ambient light is lower than the
@@ -173,8 +174,8 @@ blueprint:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
mode: slider
include_color_or_temp_over_under:
name: Include color or temperature values when outside range
description: 'Set a color or temperature value for the light when over maximum
@@ -193,9 +194,9 @@ blueprint:
value: include_color_outside_range
- label: Set temperature when outside range
value: include_temp_outside_range
multiple: false
sort: false
custom_value: false
sort: false
multiple: false
light_color_over_max:
name: Color when ambient light value over max.
description: Color of the light when the ambient light is higher than the set
@@ -236,18 +237,25 @@ variables:
include_brightness_over_under: !input include_brightness_over_under
include_color_or_temp_over_under: !input include_color_or_temp_over_under
light_sensor: !input light_sensor_entity
maxB: !input max_brightness_value
minB: !input min_brightness_value
light1: !input light_value_1
light2: !input light_value_2
max_brightness_value: !input max_brightness_value
min_brightness_value: !input min_brightness_value
maxB: '{{ max_brightness_value * 2.55 }}'
minB: '{{ min_brightness_value * 2.55 }}'
light_value_1: !input light_value_1
light_value_2: !input light_value_2
light1: '{{ light_value_1 * 2.55 }}'
light2: '{{ light_value_2 * 2.55 }}'
slope: '{{ ( light1 - light2 ) / ( maxB - minB ) }}'
constant: '{{ light1 - ( slope * maxB ) }}'
trigger:
platform: state
light_brightness_over_max: !input light_brightness_over_max
light_brightness_under_min: !input light_brightness_under_min
brightness_over_max_pct: '{{ light_brightness_over_max * 2.55 }}'
brightness_under_min_pct: '{{ light_brightness_under_min * 2.55 }}'
triggers:
trigger: state
entity_id: !input light_sensor_entity
condition:
- condition: !input run_conditions
action:
conditions: !input run_conditions
actions:
- choose:
- conditions:
- condition: template
@@ -258,20 +266,20 @@ action:
- condition: template
value_template: '{{ include_color_or_temp == "include_no_color_temp" }}'
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: '{{ (( slope * states(light_sensor)|int ) + constant)|round
brightness: '{{ (( slope * states(light_sensor)|int ) + constant)|round
}}'
target: !input target_light
- conditions:
- condition: template
value_template: '{{ include_color_or_temp == "include_color" }}'
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: '{{ (( slope * states(light_sensor)|int ) + constant)|round
brightness: '{{ (( slope * states(light_sensor)|int ) + constant)|round
}}'
rgb_color: !input light_color
target: !input target_light
@@ -279,10 +287,10 @@ action:
- condition: template
value_template: '{{ include_color_or_temp == "include_temp" }}'
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: '{{ (( slope * states(light_sensor)|int ) + constant)|round
brightness: '{{ (( slope * states(light_sensor)|int ) + constant)|round
}}'
color_temp: !input light_temp
target: !input target_light
@@ -302,20 +310,20 @@ action:
entity_id: !input light_sensor_entity
above: !input max_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: !input light_brightness_over_max
brightness: '{{ brightness_over_max_pct }}'
target: !input target_light
- conditions:
- condition: numeric_state
entity_id: !input light_sensor_entity
below: !input min_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: !input light_brightness_under_min
brightness: '{{ brightness_under_min_pct }}'
target: !input target_light
- conditions:
- condition: numeric_state
@@ -323,10 +331,10 @@ action:
below: !input max_brightness_value
above: !input min_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: '{{ (( slope * states(light_sensor)|int ) + constant)|round
brightness: '{{ (( slope * states(light_sensor)|int ) + constant)|round
}}'
target: !input target_light
- conditions:
@@ -340,10 +348,10 @@ action:
entity_id: !input light_sensor_entity
above: !input max_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: !input light_brightness_over_max
brightness: '{{ brightness_over_max_pct }}'
rgb_color: !input light_color_over_max
target: !input target_light
- conditions:
@@ -351,10 +359,10 @@ action:
entity_id: !input light_sensor_entity
below: !input min_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: !input light_brightness_under_min
brightness: '{{ brightness_under_min_pct }}'
rgb_color: !input light_color_under_min
target: !input target_light
- conditions:
@@ -363,10 +371,10 @@ action:
below: !input max_brightness_value
above: !input min_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: '{{ (( slope * states(light_sensor)|int ) + constant)|round
brightness: '{{ (( slope * states(light_sensor)|int ) + constant)|round
}}'
rgb_color: !input light_color
target: !input target_light
@@ -381,10 +389,10 @@ action:
entity_id: !input light_sensor_entity
above: !input max_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: !input light_brightness_over_max
brightness: '{{ brightness_over_max_pct }}'
color_temp: !input light_temp_over_max
target: !input target_light
- conditions:
@@ -392,10 +400,10 @@ action:
entity_id: !input light_sensor_entity
below: !input min_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: !input light_brightness_under_min
brightness: '{{ brightness_under_min_pct }}'
color_temp: !input light_temp_under_min
target: !input target_light
- conditions:
@@ -404,10 +412,10 @@ action:
below: !input max_brightness_value
above: !input min_brightness_value
sequence:
- service: light.turn_on
- action: light.turn_on
data:
transition: !input transition_time
brightness_pct: '{{ (( slope * states(light_sensor)|int ) + constant)|round
brightness: '{{ (( slope * states(light_sensor)|int ) + constant)|round
}}'
color_temp: !input light_temp
target: !input target_light

View File

@@ -31,12 +31,15 @@ blueprint:
text: {}
light_sensor_entity:
name: Light Sensor
description: Which light sensor do you want to use to measure the ambient light
value?
selector:
entity:
domain:
- sensor
device_class:
- illuminance
filter:
- domain:
- sensor
device_class:
- illuminance
multiple: false
max_brightness_value:
name: Maximum ambient light value
@@ -94,15 +97,17 @@ variables:
light_sensor: !input light_sensor_entity
maxB: !input max_brightness_value
minB: !input min_brightness_value
light1: !input light_value_1
light2: !input light_value_2
light_value_1: !input light_value_1
light_value_2: !input light_value_2
light1: '{{ light_value_1 * 2.55 }}'
light2: '{{ light_value_2 * 2.55 }}'
slope: '{{ ( light1 - light2 ) / ( maxB - minB ) }}'
constant: '{{ light1 - ( slope * maxB ) }}'
days: !input schedule_days
trigger:
platform: state
triggers:
trigger: state
entity_id: !input light_sensor_entity
condition:
conditions:
- condition: numeric_state
entity_id: !input light_sensor_entity
above: !input min_brightness_value
@@ -111,9 +116,9 @@ condition:
before: !input schedule_stop
- condition: template
value_template: '{{ now().strftime(''%a'') | lower in days }}'
action:
- service: light.turn_on
actions:
- action: light.turn_on
data:
brightness_pct: "{% if states(light_sensor)|int > maxB %}\n 0\n{% else %}\n {{
(( slope * states(light_sensor)|int ) + constant)|round }}\n{% endif %}\n"
brightness: "{% if states(light_sensor)|int > maxB %}\n 0\n{% else %}\n {{ ((
slope * states(light_sensor)|int ) + constant)|round }}\n{% endif %}\n"
target: !input target_light

View File

@@ -1,7 +1,7 @@
blueprint:
name: The Everything Light
author: AntonH
description: "**Version 2.5**\nThe Everything Light: select any trigger and turn
description: "**Version 2.10**\nThe Everything Light: select any trigger and turn
on your light in multiple ways:\n - just turn the light on in it's default state\n
\ - turn it on with a set brightness, color and/or temperature value\n - turn
it on dynamically with a brightness value that changes according to an ambient
@@ -55,13 +55,13 @@ blueprint:
Toggle the light.
- **FIXED MODE: **
- **FIXED MODE:**
The light will turn on at a set brightness percentage, optionally color or
temperature can be set.
- **DYNAMIC MODE**
- **DYNAMIC MODE:**
The light will be assigned a brightness value based on the value of a ambient
light sensor, optionally color or temperature can be set.
@@ -74,15 +74,15 @@ blueprint:
options:
- label: DEFAULT MODE
value: default
- label: TOGGLE
- label: TOGGLE MODE
value: toggle
- label: FIXED MODE
value: fixed
- label: DYNAMIC MODE
value: dynamic
multiple: false
sort: false
custom_value: false
sort: false
multiple: false
transition_time:
name: Transition time (FIXED & DYNAMIC MODE)
description: "The time it takes for the light to transition to the assigned
@@ -110,9 +110,9 @@ blueprint:
value: include_color
- label: Set temperature
value: include_temperature
multiple: false
sort: false
custom_value: false
sort: false
multiple: false
light_color:
name: Light color (FIXED & DYNAMIC MODE)
description: Color of the light when between minimum and maximum ambient light
@@ -125,22 +125,28 @@ blueprint:
color_rgb: {}
light_temperature:
name: Light temperature (FIXED & DYNAMIC MODE)
description: Temperature of the light when between minimum and maximum ambient
description: 'Temperature of the light when between minimum and maximum ambient
light values.
(not all lights will support all values, please consult your lights spec sheet.)
'
default: 2000
selector:
color_temp: {}
color_temp:
unit: kelvin
min: 1500
max: 6500
brightness:
name: Brightness (FIXED BRIGHTNESS MODE)
description: Set the brightness value the light needs to turn on at
default: 0
default: 100
selector:
number:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
light_sensor_entity:
name: Light Sensor (DYNAMIC MODE)
description: Which light sensor do you want to use to measure the ambient light
@@ -188,7 +194,6 @@ blueprint:
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
light_value_2:
name: Brightness at minimum light level (DYNAMIC MODE)
description: Brightness of the light at minimum ambient light.
@@ -199,7 +204,6 @@ blueprint:
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
light_brightness_over_max:
name: Brightness when ambient light value over max (DYNAMIC MODE)
description: Brightness of the light when the ambient light is higher than the
@@ -211,19 +215,17 @@ blueprint:
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
light_brightness_under_min:
name: Brightness when ambient light value under min (DYNAMIC MODE)
description: Brightness of the light when the ambient light is lower than the
set minimum value.
default: 100
default: 255
selector:
number:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
include_color_or_temp_over_under:
name: Include color or temperature values when outside range (DYNAMIC MODE)
description: 'Set a color or temperature value for the light when over maximum
@@ -242,9 +244,9 @@ blueprint:
value: include_color_outside_range
- label: Set temperature when outside range
value: include_temp_outside_range
multiple: false
sort: false
custom_value: false
sort: false
multiple: false
light_color_over_max:
name: Color when ambient light value over max (DYNAMIC MODE)
description: Color of the light when the ambient light is higher than the set
@@ -267,18 +269,32 @@ blueprint:
color_rgb: {}
light_temp_over_max:
name: Temperature when ambient light value over max (DYNAMIC MODE)
description: Temperature of the light when the ambient light is higher than
description: 'Temperature of the light when the ambient light is higher than
the set maximum value.
(not all lights will support all values, please consult your lights spec sheet.)
'
default: 2000
selector:
color_temp: {}
color_temp:
unit: kelvin
min: 1500
max: 6500
light_temp_under_min:
name: Temperature when ambient light value under min (DYNAMIC MODE)
description: Temperature of the light when the ambient light is lower than the
set minimum value.
description: 'Temperature of the light when the ambient light is lower than
the set minimum value.
(not all lights will support all values, please consult your lights spec sheet.)
'
default: 2000
selector:
color_temp: {}
color_temp:
unit: kelvin
min: 1500
max: 6500
include_turn_off:
name: Include light turn off function
description: 'Select if the light needs to turn back off again and how you want
@@ -307,8 +323,8 @@ blueprint:
value: trigger
- label: Staircase function
value: staircase
sort: false
custom_value: false
sort: false
turn_off_triggers:
name: Turn off triggers
description: Triggers that turn the light off
@@ -343,71 +359,75 @@ variables:
include_color_or_temp: !input include_color_or_temp
light_color: !input light_color
light_temperature: !input light_temperature
light_brightness: !input brightness
brightness: !input brightness
light_brightness: '{{ brightness * 2.55 }}'
light_sensor: !input light_sensor_entity
maxB: !input max_brightness_value
minB: !input min_brightness_value
light1: !input light_value_1
light2: !input light_value_2
light_value_1: !input light_value_1
light_value_2: !input light_value_2
light1: '{{ light_value_1 * 2.55 }}'
light2: '{{ light_value_2 * 2.55 }}'
slope: '{{ ( light1 - light2 ) / ( maxB - minB ) }}'
constant: '{{ light1 - ( slope * maxB ) }}'
dynamic_brightness_pct: "{% if mode == \"dynamic\" %}\n {{ (( slope * states(light_sensor)|int
dynamic_brightness: "{% if mode == \"dynamic\" %}\n {{ (( slope * states(light_sensor)|int
) + constant)|round }}\n{% else %}\n 0\n{% endif %}\n"
include_color_or_temp_over_under: !input include_color_or_temp_over_under
light_brightness_over_max: !input light_brightness_over_max
brightness_over_max_pct: '{{ light_brightness_over_max * 2.55 }}'
light_color_over_max: !input light_color_over_max
light_temp_over_max: !input light_temp_over_max
light_brightness_under_min: !input light_brightness_under_min
brightness_under_min_pct: '{{ light_brightness_under_min * 2.55 }}'
light_color_under_min: !input light_color_under_min
light_temp_under_min: !input light_temp_under_min
include_turn_off: !input include_turn_off
trigger: !input triggers
condition:
- condition: !input run_conditions
action:
conditions: !input run_conditions
actions:
- choose:
- conditions: '{{ mode == "toggle" }}'
sequence:
- service: homeassistant.toggle
- action: homeassistant.toggle
target: !input target_light
- conditions: '{{ mode == "default" }}'
sequence:
- service: homeassistant.turn_on
- action: homeassistant.turn_on
target: !input target_light
- conditions: '{{ mode == "fixed" }}'
sequence:
- service: light.turn_on
- action: light.turn_on
data: "{% if include_color_or_temp == \"include_color\" %}\n {{ { \"transition\":
transition_time, \"brightness_pct\": light_brightness, \"rgb_color\": light_color
transition_time, \"brightness\": light_brightness, \"rgb_color\": light_color
} }}\n{% elif include_color_or_temp == \"include_temperature\" %}\n {{ {
\"transition\": transition_time, \"brightness_pct\": light_brightness, \"color_temp\":
\"transition\": transition_time, \"brightness\": light_brightness, \"color_temp\":
light_temperature } }}\n{% else %}\n {{ { \"transition\": transition_time,
\"brightness_pct\": light_brightness } }}\n{% endif %}\n"
\"brightness\": light_brightness } }}\n{% endif %}\n"
target: !input target_light
- conditions: '{{ mode == "dynamic" }}'
sequence:
- service: light.turn_on
- action: light.turn_on
data: "{% if states(light_sensor)|int > maxB %}\n {% if include_color_or_temp_over_under
== \"include_color_outside_range\" %}\n {{ { \"transition\": transition_time,
\"brightness_pct\": light_brightness_over_max, \"rgb_color\": light_color_over_max
\"brightness\": brightness_over_max_pct, \"rgb_color\": light_color_over_max
} }}\n {% elif include_color_or_temp_over_under == \"include_temp_outside_range\"
%}\n {{ { \"transition\": transition_time, \"brightness_pct\": light_brightness_over_max,
%}\n {{ { \"transition\": transition_time, \"brightness\": brightness_over_max_pct,
\"color_temp\": light_temp_over_max } }}\n {% else %}\n {{ { \"transition\":
transition_time, \"brightness_pct\": light_brightness_over_max } }}\n {%
endif %}\n{% elif states(light_sensor)|int < minB %}\n {% if include_color_or_temp_over_under
transition_time, \"brightness\": brightness_over_max_pct } }}\n {% endif
%}\n{% elif states(light_sensor)|int < minB %}\n {% if include_color_or_temp_over_under
== \"include_color_outside_range\" %}\n {{ { \"transition\": transition_time,
\"brightness_pct\": light_brightness_under_min, \"rgb_color\": light_color_under_min
\"brightness\": brightness_under_min_pct, \"rgb_color\": light_color_under_min
} }}\n {% elif include_color_or_temp_over_under == \"include_temp_outside_range\"
%}\n {{ { \"transition\": transition_time, \"brightness_pct\": light_brightness_under_min,
%}\n {{ { \"transition\": transition_time, \"brightness\": brightness_under_min_pct,
\"color_temp\": light_temp_under_min } }}\n {% else %}\n {{ { \"transition\":
transition_time, \"brightness_pct\": light_brightness_under_min } }}\n {%
endif %}\n{% else %}\n {% if include_color_or_temp == \"include_color\" %}\n
\ {{ { \"transition\": transition_time, \"brightness_pct\": light_brightness,
\"rgb_color\": light_color } }}\n {% elif include_color_or_temp == \"include_temperature\"
%}\n {{ { \"transition\": transition_time, \"brightness_pct\": dynamic_brightness_pct,
transition_time, \"brightness\": brightness_under_min_pct } }}\n {% endif
%}\n{% else %}\n {% if include_color_or_temp == \"include_color\" %}\n {{
{ \"transition\": transition_time, \"brightness\": light_brightness, \"rgb_color\":
light_color } }}\n {% elif include_color_or_temp == \"include_temperature\"
%}\n {{ { \"transition\": transition_time, \"brightness\": dynamic_brightness,
\"color_temp\": light_temperature } }}\n {% else %}\n {{ { \"transition\":
transition_time, \"brightness_pct\": dynamic_brightness_pct } }}\n {% endif
%}\n{% endif %}\n"
transition_time, \"brightness\": dynamic_brightness } }}\n {% endif %}\n{%
endif %}\n"
target: !input target_light
- if: !input turn_off_conditions
then:
@@ -420,11 +440,11 @@ action:
timeout: !input staircase_duration
else:
- delay: !input staircase_duration
- service: homeassistant.turn_off
- action: homeassistant.turn_off
target: !input target_light
- conditions: '{{ "trigger" in include_turn_off and not "staircase" in include_turn_off
}}'
sequence:
- wait_for_trigger: !input turn_off_triggers
- service: homeassistant.turn_off
- action: homeassistant.turn_off
target: !input target_light

View File

@@ -10,6 +10,7 @@ blueprint:
selector:
entity:
integration: cast
multiple: false
view:
name: Lovelace view path
description: Path of the view to cast. A path has to be defined in your Lovelace
@@ -21,11 +22,11 @@ blueprint:
source_url: https://community.home-assistant.io/t/cast-and-re-cast-a-lovelace-view-to-a-google-hub/259631
trigger:
- platform: state
entity_id: !input 'player'
entity_id: !input player
to: 'off'
for: 00:00:20
- platform: state
entity_id: !input 'player'
entity_id: !input player
to: paused
for: 00:00:20
- platform: time_pattern
@@ -38,38 +39,38 @@ action:
- condition: or
conditions:
- condition: state
entity_id: !input 'player'
entity_id: !input player
state: 'off'
- condition: state
entity_id: !input 'player'
entity_id: !input player
state: paused
for: 00:00:20
sequence:
- service: media_player.volume_mute
data:
is_volume_muted: true
entity_id: !input 'player'
entity_id: !input player
- service: media_player.turn_off
data:
entity_id: !input 'player'
entity_id: !input player
- delay:
seconds: 2
- service: media_player.turn_on
data:
entity_id: !input 'player'
entity_id: !input player
- service: cast.show_lovelace_view
data:
view_path: !input 'view'
dashboard_path: !input 'dashboard'
entity_id: !input 'player'
view_path: !input view
dashboard_path: !input dashboard
entity_id: !input player
- service: cast.show_lovelace_view
data:
view_path: !input 'view'
dashboard_path: !input 'dashboard'
entity_id: !input 'player'
view_path: !input view
dashboard_path: !input dashboard
entity_id: !input player
- delay:
seconds: 10
- service: media_player.volume_mute
data:
is_volume_muted: false
entity_id: !input 'player'
entity_id: !input player

View File

@@ -0,0 +1,27 @@
blueprint:
name: Invert a binary sensor
description: Creates a binary_sensor which holds the inverted value of a reference binary_sensor
domain: template
source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/template/blueprints/inverted_binary_sensor.yaml
input:
reference_entity:
name: Binary sensor to be inverted
description: The binary_sensor which needs to have its value inverted
selector:
entity:
domain: binary_sensor
variables:
reference_entity: !input reference_entity
binary_sensor:
state: >
{% if states(reference_entity) == 'on' %}
off
{% elif states(reference_entity) == 'off' %}
on
{% else %}
{{ states(reference_entity) }}
{% endif %}
# delay_on: not_used in this example
# delay_off: not_used in this example
# auto_off: not_used in this example
availability: "{{ states(reference_entity) not in ('unknown', 'unavailable') }}"

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,8 @@ recorder:
- sensor.*gpu_core_load
- sensor.portainer*
- sensor.mosquitto*
- sensor.*_rssi
- sensor.weatherflow_hub*
entities:
- sensor.avg_ping
- sensor.max_ping
@@ -121,6 +131,8 @@ recorder:
- sensor.mariadb_database_size
- sensor.random_joke
- sensor.bypassed_sensors
- sensor.home_tempest_signal_strength
- sensor.home_tempest_uptime
include:
entities:
- media_player.living_room_tv
@@ -166,6 +178,8 @@ influxdb:
entity_globs:
- binary_sensor.*tamper*
- light.*screen*
- sensor.weatherflow_hub*
- sensor.home_tempest*
entities:
- sensor.last_boot
- sensor.date
@@ -178,6 +192,8 @@ influxdb:
- light.all_lights
- fan.all_fans
- sensor.random_joke
- sensor.home_tempest_signal_strength
- sensor.home_tempest_uptime
include:
domains:
- sun
@@ -260,6 +276,8 @@ influxdb:
- binary_sensor.kallen_desktop*
- sensor.asus_laptop*
- binary_sensor.asus_laptop*
- sensor.*ashland*
- sensor.*kasx*
entities:
- media_player.living_room_tv
- media_player.basement_tv
@@ -280,6 +298,7 @@ influxdb:
- binary_sensor.internet
- binary_sensor.people_present
- weather.iron_nerd_weather_station
- weather.ashland_weather_station
- sensor.circle_k
- sensor.kroger
- sensor.kecks
@@ -312,6 +331,15 @@ influxdb:
- sensor.bypassed_sensors
- input_boolean.shower_mode
- sensor.services_down
- sensor.average_room_temperature
- sensor.average_room_illuminance
- sensor.brightest_room
- 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:
@@ -335,6 +363,8 @@ prometheus:
exclude_entity_globs:
- binary_sensor.*tamper*
- light.*screen*
- sensor.weatherflow_hub*
- sensor.home_tempest*
exclude_entities:
- sensor.last_boot
- sensor.date
@@ -347,6 +377,8 @@ prometheus:
- light.all_lights
- fan.all_fans
- sensor.random_joke
- sensor.home_tempest_signal_strength
- sensor.home_tempest_uptime
include_domains:
- sun
- light
@@ -428,6 +460,8 @@ prometheus:
- binary_sensor.kallen_desktop*
- sensor.asus_laptop*
- binary_sensor.asus_laptop*
- sensor.*ashland*
- sensor.*kasx*
include_entities:
- media_player.living_room_tv
- media_player.basement_tv
@@ -448,6 +482,7 @@ prometheus:
- binary_sensor.internet
- binary_sensor.people_present
- weather.iron_nerd_weather_station
- weather.ashland_weather_station
- sensor.circle_k
- sensor.kroger
- sensor.kecks
@@ -480,3 +515,12 @@ prometheus:
- sensor.bypassed_sensors
- input_boolean.shower_mode
- sensor.services_down
- sensor.average_room_temperature
- sensor.average_room_illuminance
- sensor.brightest_room
- 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

@@ -79,7 +79,7 @@
45: 'quarter to {hour}',
59: 'a minute to {hour}',
'past_hour': '{minute} past {hour}',
'to_hour': '{minute} to {hour}',
'to_hour': '{minute} to {hour}',
},
'time_of_day':{
'midnight': 'midnight',
@@ -157,7 +157,7 @@
'November',
'December',
]
},
},
'nl':{
'_language': 'Nederlands',
'and': 'en',
@@ -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,246 +1,569 @@
{#
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
set phrases to be used in the relative_time_period macro
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',
'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'],
'combine': 'and',
'error': 'Invalid date'
}
},
{
'language': 'pl',
'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'],
'combine': 'i',
'error': 'Niepoprawna data'
}
},
{
'language': 'fr',
'phrases':
{
'year': ['année', 'années', 'an'],
'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'],
'combine': 'et',
'error': 'Date non valide'
}
},
{
'language': 'it',
'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'],
'combine': 'e',
'error': 'Data non valida'
}
},
{
'language': 'nl',
'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'],
'combine': 'en',
'error': 'Ongeldige datum'
}
},
{
'language': 'de',
'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': ['Milliseconde', 'Milliseconden', 'ms'],
'combine': 'und',
'error': 'Falsches Datum'
}
},
{
'language': 'pt',
'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'],
'combine': 'e',
'error': 'Data Inválida'
}
},
{
'language': 'dk',
'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.'],
'combine': 'og',
'error': 'Ugyldig dato'
}
}
]
%}
{
'language': 'en',
'plural_form': 'english',
'phrases': {
'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': ['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': ['an', 'année', 'années'],
'month': ['mois', 'mois', 'mois'],
'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': ['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': ['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': ['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': ['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': ['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': ['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': ['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å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', 'rok', 'roky', 'let'],
'month': ['měs', 'měsíc', 'měsíce', 'měsíců'],
'week': ['týd', 'týden', 'týdny', 'týdnů'],
'day': ['d', 'den', 'dny', 'dní'],
'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'
}
},
{
'language': 'fi',
'plural_form': 'english',
'phrases': {
'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': ['мс', 'милисекунда', 'милисекунды', 'милисекунд'],
'combine': 'и',
'error': 'Неверная дата',
}
},
{
'language': 'uk',
'plural_form': 'russian',
'phrases': {
'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 #}
{%- macro _abbr_to_full(input) -%}
{# determine not_use list #}
{%- set abbr_to_full = dict(yr='year', mth='month', wk='week', day='day', hr='hour', min='minute', sec='second', ms='millisecond') -%}
{%- set list = input if input is list else (input | replace(' ', '')).split(',') -%}
{%- if list | select('in', abbr_to_full) | list | count > 0 -%}
{%- set ns = namespace(output=[]) -%}
{%- for i in list -%}
{%- set ns.output = ns.output + [abbr_to_full[i] | default(i)] -%}
{%- endfor -%}
{%- set list = ns.output -%}
{%- endif -%}
{{- list | select('in', abbr_to_full.values()) | list | to_json -}}
{%- endmacro -%}
{#
macro to split a timedelta in years, months, weeks, days, hours, minutes, seconds
macro to split a timedelta in years, months, weeks, days, hours, minutes, seconds and milliseconds
used by the relative time plus macro, set up as a seperate macro so it can be reused
#}
{%- macro time_split(date, compare_date=now(), time=true, not_use=[]) -%}
{# set defaults for variables #}
{%- set date = date | as_local if time else date.date()-%}
{%- macro time_split(date, parts=8, compare_date=now(), not_use=[], always_show=['all'], time=true, round_mode='floor') -%}
{#- set defaults for input if not entered #}
{%- set date = date if date is datetime else date | as_datetime('invalid') -%}
{%- set compare_date = compare_date if compare_date is datetime else compare_date | as_datetime('invalid') -%}
{%- set time = time | bool(true) -%}
{%- set comp_date = compare_date if time else compare_date.date() -%}
{%- set date_max = [comp_date, date] | max -%}
{%- set date_min = [comp_date, date] | min -%}
{#- set time periods in seconds #}
{%- set m, h, d, w = 60, 3600, 86400, 604800 -%}
{#- set numer of years, and set lowest date using this number of years #}
{%- set yrs = date_max.year - date_min.year - (1 if date_max.replace(year=date_min.year) < date_min else 0) -%}
{%- set date_max = date_max.replace(year=date_max.year - yrs) -%}
{#- set numer of months, and set lowest date using this number of months #}
{%- if 'month' not in not_use -%}
{%- set mth = (date_max.month - date_min.month - (1 if date_max.day < date_min.day else 0) + 12) % 12 -%}
{%- set month_new = (((date_max.month - mth) + 12) % 12) | default(12, true) -%}
{%- set day_max = ((date_max.replace(day=1, month=month_new) + timedelta(days=31)).replace(day=1) - timedelta(days=1)).day -%}
{%- set extra_days = [0, date_max.day - day_max] | max -%}
{%- set date_temp = date_max.replace(month=month_new, day=[date_max.day, day_max]|min) -%}
{%- set date_max = date_temp if date_temp <= date_max else date_temp.replace(year=date_max.year-1) -%}
{%- set mth = mth + yrs * 12 if 'year' in not_use else mth -%}
{%- endif -%}
{%- set date_max = date_max.replace(year=date_max.year + yrs) if 'year' in not_use and 'month' in not_use else date_max -%}
{%- set yrs = 0 if 'year' in not_use else yrs -%}
{#- set other time period variables #}
{%- set s = (date_max - date_min).total_seconds() + extra_days | default(0) * 86400 -%}
{%- set wks = 0 if 'week' in not_use else (s // w) | int -%}
{%- set day = 0 if 'day' in not_use else ((s - wks * w) // d) | int -%}
{%- set hrs = 0 if 'hour' in not_use else ((s - wks * w - day * d) // h) | int -%}
{%- set min = 0 if 'minute' in not_use else ((s - wks * w - day * d - hrs * h) // m) | int -%}
{%- set sec = 0 if 'second' in not_use else (s - wks * w - day * d - hrs * h - min * m) | int -%}
{%- set ms = (s % 1 * 1000) | round | int -%}
{# output result #}
{%- set output = dict(year=yrs, month=mth | default(0), week=wks, day=day, hour=hrs, minute=min, second=sec, millisecond=ms) %}
{{- dict(output.items() | rejectattr('0', 'in', not_use)) | to_json -}}
{%- 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 #}
{%- set date = date | as_local if time else (date | as_local).date() -%}
{%- set compare_date = compare_date | as_local if time else (compare_date | as_local).date() -%}
{# determine highest and lowest date #}
{%- set date_max = [compare_date, date] | max -%}
{%- set date_min = [compare_date, date] | min -%}
{#- set time periods in seconds #}
{%- set days_year = 365 + (1 if (compare_date.replace(month=3, day=1) - timedelta(days=1)).day == 29 else 0) -%}
{%- set days_month = ((compare_date.replace(day=20) + timedelta(days=20)).replace(day=1) - timedelta(days=1)).day -%}
{%- set dur = dict(
year=days_year * 86400000,
month=days_month * 86400000,
week=604800000,
day=86400000,
hour=3600000,
minute=60000,
second=1000,
millisecond=1,
)
-%}
{# make sure input for not_use and always_show is correct #}
{%- if not not_use in [['millisecond'], []] -%}
{%- set not_use = _abbr_to_full(not_use) | from_json -%}
{%- endif -%}
{%- set not_use = not_use + ['hour', 'minute', 'second', 'millisecond' ] if not time else not_use -%}
{%- if always_show in [['all'], 'all'] -%}
{%- set always_show = dur.keys() | list -%}
{%- elif always_show != [] -%}
{%- set always_show = _abbr_to_full(always_show) | from_json | reject('in' , not_use) | list -%}
{%- endif -%}
{%- set always_show = always_show | reject('in', not_use) | list -%}
{%- set do_use = dur.keys() | reject('in', not_use) | list -%}
{# determine number of milliseconds #}
{%- set ms = ((date_max - date_min).total_seconds() * 1000) | round(0, 'ceil')-%}
{# 2: Check if the number of milliseconds is more then the duration of the last time part to output #}
{%- if do_use and ms < dur[do_use|last] -%}
{{- {do_use | last: (ms / dur[do_use|last]) | round(0, round_mode)} | to_json -}}
{%- else -%}
{# check if it is needed to determine years #}
{%- if ms >= dur.day * 365 -%}
{#- set numer of years, and set highest date using this number of years #}
{%- set yrs = date_max.year - date_min.year - (1 if date_max.replace(year=date_min.year) < date_min else 0) -%}
{%- set date_max = date_max.replace(year=date_max.year - yrs) -%}
{%- set ms = (date_max - date_min).total_seconds() * 1000 -%}
{%- set ms_yrs = ms -%}
{%- endif -%}
{%- set yrs = yrs | default(0) -%}
{# check if it is needed to determine months #}
{%- set check_mth =
ms >= dur.day * 28
and 'month' in do_use
-%}
{%- if check_mth -%}
{#- set numer of months, and set highest date using this number of months #}
{%- set ns = namespace(dm=date_max, mth=0) -%}
{%- set dmd = ns.dm.day -%}
{%- for m in range(1, 12) -%}
{%- set dmm, dmy = ns.dm.month, ns.dm.year -%}
{%- set day_max = (ns.dm.replace(day=1) - timedelta(days=1)).day -%}
{%- set dm = ns.dm.replace(
month=12 if dmm == 1 else dmm - 1,
year=dmy - 1 if dmm == 1 else dmy,
day= [dmd, day_max] | min
)
-%}
{%- if dm < date_min -%}
{%- break -%}
{%- else -%}
{%- set ns.mth = ns.mth + 1 -%}
{%- set ns.dm = dm -%}
{%- endif -%}
{%- endfor -%}
{%- set date_max, mth = ns.dm, ns.mth -%}
{%- set mth = mth + yrs * 12 if 'year' in not_use else mth -%}
{%- set ms = (date_max - date_min).total_seconds() * 1000 -%}
{%- endif -%}
{%- set mth = mth | default(0) -%}
{# prepare for other time parts #}
{%- set date_max = date_max.replace(year=date_max.year + yrs) if 'year' in not_use and 'month' in not_use else date_max -%}
{#- set other time period variables #}
{%- set ms = ((date_max - date_min).total_seconds() * 1000 + extra_days | default(0) * dur.day) | round(0) -%}
{%- set wks = (ms // dur.week) | int -%}
{%- set days = ((ms % dur.week // dur.day) + (wks * dur.week / dur.day if 'week' in not_use else 0)) | int -%}
{%- set hrs = ((ms % dur.day // dur.hour) + (days * dur.day / dur.hour if 'day' in not_use else 0)) | int -%}
{%- set min = ((ms % dur.hour // dur.minute) + (hrs * dur.hour / dur.minute if 'hour' in not_use else 0)) | int -%}
{%- set sec = ((ms % dur.minute // dur.second) + (min * dur.minute / dur.second if 'minute' in not_use else 0)) | int -%}
{%- set mis = ((ms % dur.second) | round + (sec * dur.second if 'second' in not_use else 0)) | int -%}
{# prepare dict with ouput #}
{%- set output = dict(year=yrs, month=mth | default(0), week=wks, day=days, hour=hrs, minute=min, second=sec, millisecond=mis) -%}
{%- 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] -%}
{%- 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] -%}
{%- set always_return = to_output | last -%}
{# check if all values for always_show are included #}
{%- set as_check = always_show | reject('in', to_output) | list | count -%}
{%- if always_show and as_check > 0 -%}
{%- 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 + ['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 #}
{%- set ms = ms_yrs if last == 'year' else ms -%}
{%- set remain = ms % dur[last] -%}
{%- 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 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, '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), **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')-}}
{%- 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, verbose=false, language='en', compare_date=now(), month=none, week=none, millisecond=none, not_use=['millisecond'], always_show=[], time=true) -%}
{#- set defaults for input if not entered #}
{%- set date = date if date is datetime else date | as_datetime -%}
{%- set compare_date = compare_date if compare_date is datetime else compare_date | as_datetime -%}
{%- 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 #}
{%- set phrases = _time_period_phrases -%}
{%- 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 -%}
{#- perform smart stuff #}
{%- if date is datetime and compare_date is datetime -%}
{# determine not_use list #}
{%- set abbr_to_full = dict(yr='year', mth='month', wk='week', hr='hour', min='minute', sec='second', ms='millisecond') -%}
{%- set add = [('month', month),('week',week),('millisecond',millisecond)] | selectattr('1', 'eq', false) | map(attribute='0') | list -%}
{%- set not_use = not_use if not_use is list else (not_use | replace(' ', '')).split(',') -%}
{%- set not_use = (not_use + add) | unique | list -%}
{%- if not_use | select('in', abbr_to_full) | list | count > 0 -%}
{%- set ns = namespace(not_use=[]) -%}
{%- for i in not_use -%}
{%- set ns.not_use = ns.not_use + [abbr_to_full[i] | default(i)] -%}
{%- endfor -%}
{%- set not_use = ns.not_use | unique | list -%}
{%- endif -%}
{# set variables #}
{%- set date, compare_date = date | as_local, compare_date | as_local -%}
{%- set parts = parts | int(1) -%}
{%- set time = time | bool(true) -%}
{%- set abbr = abbr | bool(false) or verbose | bool(false) -%}
{# split timedelta #}
{%- set time_parts = time_split(date, compare_date, time, not_use) | from_json -%}
{#- find first non zero time period #}
{%- set time_periods = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'] -%}
{%- set do_use = time_periods | reject('in', not_use) | list -%}
{# continue if there are still time periods to use #}
{%- if do_use | count > 0 -%}
{%- set always_return = do_use | last -%}
{%- set always_show = always_show if always_show is list else (always_show | replace(' ', '')).split(',') -%}
{%- if always_show | select('in', abbr_to_full) | list | count > 0 -%}
{%- set ns = namespace(always_show=[]) -%}
{%- for i in always_show -%}
{%- set ns.always_show = ns.always_show + [abbr_to_full[i] | default(i)] -%}
{%- endfor -%}
{%- set always_show = ns.always_show | unique | list -%}
{%- endif -%}
{%- set parts = [parts, always_show | count] | max -%}
{%- set to_show = (time_parts.items() | selectattr('1') | map(attribute='0') | list + always_show) | unique | list | default([always_return], true) -%}
{%- set first = do_use | select('in', to_show) | first -%}
{#-select itemw to show based on input #}
{%- set index_first = (time_parts.keys() | list).index(first) -%}
{%- set items = (time_parts.keys() | list)[index_first:index_first + parts] -%}
{# convert to phrases #}
{%- set ns = namespace(phrases=[]) -%}
{%- for i in items if i in to_show or i == first -%}
{%- 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 ns.phrases = ns.phrases + [phrase] -%}
{%- endfor -%}
{#- join phrases in a string, using phr.combine for the last item #}
{{- '{} {} {}'.format(ns.phrases[:-1] | join(', '), phr.combine, ns.phrases[-1]) if ns.phrases | count > 1 else ns.phrases | first -}}
{%- else -%}
All time periods are excluded
{%- endif -%}
{%- 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 -%}
{# check for error #}
{%- if 'error' in time_parts -%}
{{- time_parts['error'] -}}
{%- else -%}
{{- phr.error -}}
{# convert to phrases #}
{%- set ns = namespace(phrases=[]) -%}
{%- for i in time_parts.keys() -%}
{%- 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 #}
{{- '{} {} {}'.format(ns.phrases[:-1] | join(', '), phr.combine, ns.phrases[-1]) if ns.phrases | count > 1 else ns.phrases | first -}}
{%- endif -%}
{%- endmacro -%}
{%- endmacro -%}

View File

@@ -0,0 +1,11 @@
{% from 'formatting.jinja' import cleanup %}
{% macro services_down() %}
{% if states('sensor.services_down') | int == 1 %}
There is one service offline. It is {{ state_attr('sensor.services_down','services') }}.
{% elif states('sensor.services_down') | int > 1 %}
There are {{ states('sensor.services_down') }} services currently offline. They are {{ state_attr('sensor.services_down','services') }}.
{% else %}
There are no services currently offline.
{% endif %}
{% endmacro %}

View File

@@ -146,7 +146,7 @@ It is {{ now().strftime("%I:%M %p") }}.
{% endmacro %}
{% macro kallenSleepMsg() %}
{% set schedMode = states('input_select.scheduled_climate_mode_kallen_fan') %}
{% set schedMode = states('input_select.scheduled_climate_mode_kallen_bedroom') %}
{% if schedMode == 'White Noise' %}
{{ [
"No fan in Collin's room tonight. Too cold outside. Brr. Enjoy your white noise.",

View File

@@ -12,21 +12,64 @@
{% 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 the {{ 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 %}
{% endmacro%}
{% endmacro %}
{{ cleanup(data()) }}
{% endmacro %}
{% 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 the {{ 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 the {{ 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 the {{ 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 the {{ 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 the {{ 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 the {{ 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 the {{ 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 the {{ 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 the {{ 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 %}
@@ -71,7 +114,9 @@
{% endmacro %}
{% macro sports_inhibit(team) %}
{% if state_attr(team,'kickoff_in') %}
{% if is_state(team,'NOT_FOUND') %}
true
{% elif state_attr(team,'kickoff_in') %}
{{ 'months' in state_attr(team,'kickoff_in') or
'month' in state_attr(team,'kickoff_in') or
'weeks' in state_attr(team,'kickoff_in') }}
@@ -107,12 +152,12 @@
{% if is_state('binary_sensor.san_francisco_49ers_inhibit','off') %}
{{ sports_pregame('sensor.san_francisco_49ers') }}
{% endif %}
{% if is_state('binary_sensor.cleveland_guardians_inhibit','off') %}
{{ sports_pregame('sensor.cleveland_guardians') }}
{% endif %}
{% if is_state('binary_sensor.minnesota_twins_inhibit','off') %}
{{ sports_pregame('sensor.minnesota_twins') }}
{% endif %}
{% if is_state('binary_sensor.cleveland_guardians_inhibit','off') %}
{{ sports_pregame('sensor.cleveland_guardians') }}
{% endif %}
{% if is_state('binary_sensor.los_angeles_dodgers_inhibit','off') %}
{{ sports_pregame('sensor.los_angeles_dodgers') }}
{% endif %}
@@ -135,12 +180,12 @@
{% if is_state('binary_sensor.san_francisco_49ers_inhibit','off') %}
{{ sports_main('sensor.san_francisco_49ers') }}
{% endif %}
{% if is_state('binary_sensor.cleveland_guardians_inhibit','off') %}
{{ sports_main('sensor.cleveland_guardians') }}
{% endif %}
{% if is_state('binary_sensor.minnesota_twins_inhibit','off') %}
{{ sports_main('sensor.minnesota_twins') }}
{% endif %}
{% if is_state('binary_sensor.cleveland_guardians_inhibit','off') %}
{{ sports_main('sensor.cleveland_guardians') }}
{% endif %}
{% if is_state('binary_sensor.los_angeles_dodgers_inhibit','off') %}
{{ sports_main('sensor.los_angeles_dodgers') }}
{% endif %}
@@ -152,4 +197,6 @@
{{ cleanup(data()) }}
{% endmacro %}
{{ sports_updates('pregame') }}
{% macro sports_datetime(team) %}
{{ as_timestamp(state_attr(team,'date')) | timestamp_custom('%Y-%m-%d %H:%M:%S') }}
{% endmacro%}

View File

@@ -13,9 +13,21 @@
{% set houseEveningRan = is_state('input_boolean.house_scheduling_evening_ran','on') %}
{% set masterBedroomEveningRan = is_state('input_boolean.master_bedroom_scheduling_evening_ran','on') %}
{% set emmaEveningRan = is_state('input_boolean.emma_scheduling_evening_ran','on') %}
{% set kallenMorningAnnc = is_state('input_boolean.kallen_morning_announcements','on') %}
{% set kallenText = 'Kallen' %}
{% set kallenTTS = 'Collin' %}
{% macro morning_annc(type,method) %}
{% if method == 'text' %}
{% set identKallen = kallenText %}
{% elif method == 'tts' %}
{% set identKallen = kallenTTS %}
{% endif %}
{% if kallenMorningAnnc %}
First things first, we have some announcements for {{ identKallen }}. {{ states('input_text.kallen_morning_announcements') }}
{% endif %}
{% endmacro %}
{% macro laundry_report(type,method) %}
{% macro data() %}
{% set washerTimer = states('timer.washer_timer') %}
@@ -461,12 +473,11 @@
Collin has Beyond The Bells today after school.
{% 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 }}.
{{ states('input_text.kallen_pickup') }} will be picking Collin up from school today.
{% 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. '
@@ -532,10 +543,11 @@
{% 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') %}
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 }}.
{% 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.
@@ -591,38 +603,20 @@
{% endmacro %}
{% macro emma_sleep(type,method) %}
{% set asleep = state_attr('input_datetime.emma_down_for_nap','timestamp') | int %}
{% set wakeup = state_attr('input_datetime.emma_up_from_nap','timestamp') | int %}
{% set day = now().strftime("%-d") %}
{% set asleep_day = asleep | timestamp_custom("%-d") %}
{% set wakeup_day = wakeup | timestamp_custom("%-d") %}
{% if is_state('input_boolean.emma_sleeping','off') and (is_state('input_boolean.emma_has_napped','on') or ((asleep_day == day) and (wakeup > asleep))) %}
Emma napped today for {{ custom_time_between('input_datetime.emma_down_for_nap','input_datetime.emma_up_from_nap','hour,minute') }}. She was retrieved from her room at around {{ input_datetime_read('input_datetime.emma_up_from_nap') | trim }}.
{% elif (is_state('input_boolean.emma_has_napped','off') and (((asleep_day == day) and (wakeup_day != day)) or wakeup < asleep)) and is_state('input_boolean.emma_sleeping','on') %}
Emma is down for nap. She was put down at around {{ input_datetime_read('input_datetime.emma_down_for_nap') | trim }}. She has been asleep for {{ custom_time('input_datetime.emma_down_for_nap','hour,minute') }}.
{% elif is_state('input_boolean.emma_sleeping','on') %}
{% if is_state('input_boolean.emma_sleeping','on') %}
{% if is_state('binary_sensor.early_night_mode','on') %}
Emma is asleep for the night. She went to bed at {{ input_datetime_read('input_datetime.emma_asleep_at') | trim }}.
{% else %}
Emma has not yet awoken for the day. She went to bed at {{ input_datetime_read('input_datetime.emma_asleep_at') | trim }}. Her wakeup time is scheduled for {{ input_datetime_read('input_datetime.emma_wakeup') | trim }}.
{% endif %}
{% else %}
Emma is awake, and does not appear to have napped yet. She woke up at {{ input_datetime_read('input_datetime.emma_awake_at') | trim }}.
Emma is awake. She woke up at {{ input_datetime_read('input_datetime.emma_awake_at') | trim }}.
{% endif %}
{% endmacro %}
{% macro emma_sleep_notification(type,method) %}
{% set asleep = state_attr('input_datetime.emma_down_for_nap','timestamp') | int %}
{% set wakeup = state_attr('input_datetime.emma_up_from_nap','timestamp') | int %}
{% set day = now().strftime("%-d") %}
{% set asleep_day = asleep | timestamp_custom("%-d") %}
{% set wakeup_day = wakeup | timestamp_custom("%-d") %}
{% if is_state('input_boolean.emma_sleeping','off') and (is_state('input_boolean.emma_has_napped','on') or ((asleep_day == day) and (wakeup > asleep))) %}
Emma has awoken. She napped today for {{ custom_time_between('input_datetime.emma_down_for_nap','input_datetime.emma_up_from_nap','hour,minute') }}. She was retrieved from her room at {{ clock('12-hr') }}
{% elif is_state('input_boolean.emma_has_napped','off') and is_state('input_boolean.emma_sleeping','off') and ((asleep_day != day) or (wakeup_day != day)) %}
{% if is_state('input_boolean.emma_sleeping','off') %}
Emma has awoken for the day at {{ clock('12-hr') }}
{% elif is_state('input_boolean.emma_has_napped','off') and ((asleep_day == day) and (wakeup_day != day)) and is_state('input_boolean.emma_sleeping','on') %}
Emma is being put down for nap. She was put down at {{ clock('12-hr') }}
{% elif is_state('input_boolean.emma_sleeping','on') %}
Emma is asleep for the night (or at least, her sleep switch is active) at {{ clock('12-hr') }}
{% else %}

View File

@@ -68,6 +68,31 @@
{% endif %}
{% endmacro %}
{% macro datetime_from_calendar(calendar,start_or_end,action,operator,days,hours,minutes) %}
{% set base = as_timestamp(strptime(state_attr(calendar,start_or_end), '%Y-%m-%d %H:%M:%S')) | int %}
{% if minutes is defined %}
{% set mod = ((((days * 24) * 60) * 60) + (hours* 60) * 60) + (minutes * 60) | int %}
{% elif hours is defined %}
{% set mod = (((days * 24) * 60) * 60) + (hours* 60) * 60 | int %}
{% elif days is defined %}
{% set mod = ((days * 24) * 60) * 60 | int %}
{% endif %}
{% if action == 'set' %}
{% set ts = "%Y-%m-%d %H:%M:%S" %}
{% elif action == 'read' %}
{% set ts = "%Y-%m-%d %-I:%M %p" %}
{% endif %}
{% if operator is defined %}
{% if operator == 'add' %}
{{ (base + mod) | timestamp_custom(ts) }}
{% elif operator == 'subtract' %}
{{ (base - mod) | timestamp_custom(ts) }}
{% endif %}
{% else %}
{{ base | timestamp_custom(ts) }}
{% endif %}
{% endmacro %}
{% macro set_datetime(hours,minutes,seconds) %}
{% if seconds is defined %}
{{ (as_timestamp(now()) + (((hours * 60) * 60) + (minutes * 60)) + seconds) | int | timestamp_custom('%Y-%m-%d %H:%M:%S') }}

View File

@@ -4,9 +4,9 @@
{% macro weatherInfo(type,method,time) %}
{% set time = time|default('day') %}
{% if method == 'text' %}
{% if method in ['text','dashboard'] %}
{% if type in ['current','full'] %}
The current weather is {{ states('weather.iron_nerd_weather_station') | lower }}. It is {{ state_attr('weather.iron_nerd_weather_station','temperature') | round }} degrees outside and feels like {{ states('sensor.stratton_ave_apparent_temperature') | round }} degrees.
The current weather is {{ states('weather.iron_nerd_weather_station') | lower }}. It is {{ state_attr('weather.iron_nerd_weather_station','temperature') | round }} degrees outside and feels like {{ states('sensor.home_temperature_feels_like') | round }} degrees.
{% endif %}
{% if type in ['forecast','full'] %}
{% if 14400 <= ct <= 61200 %}
@@ -19,15 +19,28 @@
{% 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!
{% elif states('sensor.weatheralerts_active_alerts') > '0' %}
{% 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 %}
{% if is_state('binary_sensor.lightning_warning','on') %}
{% set ltgdist = (states('sensor.blitzortung_lightning_distance') | int) / 1.609 | round %}
There is lightning in the area. Nearest strike is {{ ltgdist }} miles away.
{% endif %}
{% if is_state('binary_sensor.raining','on') %}
It is currently raining. Make sure all doors and windows are closed!
{% if method != 'dashboard' %}
{% if is_state('binary_sensor.lightning_warning','on') %}
{% set ltgdist = (states('sensor.blitzortung_lightning_distance') | int) / 1.609 | round %}
There is lightning in the area. Nearest strike is {{ ltgdist }} miles away.
{% endif %}
{% if is_state('binary_sensor.raining','on') %}
It is currently raining. Make sure all doors and windows are closed!
{% endif %}
{% endif %}
{% if state_attr('weather.iron_nerd_weather_station','visibility') | int < 3 %}
Caution: Current outdoor visibility is {{ state_attr('weather.iron_nerd_weather_station','visibility') }} miles.
@@ -47,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. ",
@@ -101,7 +125,11 @@
{% macro weatherReport(type,method,time) %}
{% macro data() %}
{{ weatherInfo(type,method,time) | replace('clear-night','clear') | replace('partlycloudy','partly cloudy') }}
{{ weatherInfo(type,method,time) |
replace('clear-night','clear') |
replace('partlycloudy','partly cloudy') |
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

@@ -0,0 +1,25 @@
name: Adjustment
about: Request a change/adjustment to an existing feature
title: "[Adjustment]: "
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this adjustment request!
- type: markdown
attributes:
value: |
This issue was created by an issue **template**
visible: [content]
- type: textarea
id: adjustment-request
attributes:
label: Describe your request
description: Which existing feature would you like changed/adjusted?
placeholder: Tell me what you want, what you really really want!
value: "Request here!"
validations:
required: true
labels:
- type/adjustment
- needs-response

View File

@@ -0,0 +1,25 @@
name: Bug Report
about: Report a bug that you have found
title: "[Bug]: "
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: markdown
attributes:
value: |
This issue was created by an issue **template**
visible: [content]
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also, what were you expecting to happen?
placeholder: Tell me what you saw!
value: "A bug happened!"
validations:
required: true
labels:
- type/bug
- needs-response

View File

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -0,0 +1,25 @@
name: Feature Request
about: Request a new feature to be added
title: "[Feature Request]: "
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this feature request form!
- type: markdown
attributes:
value: |
This issue was created by an issue **template**
visible: [content]
- type: textarea
id: feature-request
attributes:
label: Feature Request
description: What new feature would you like to see?
placeholder: What is your feature request!
value: "I would like this feature"
validations:
required: true
labels:
- type/enhancement
- needs-response

View File

@@ -61,6 +61,10 @@ input_text:
name: Kallen Briefing Extras
icon: mdi:plus
max: 255
kallen_morning_announcements:
name: Kallen Morning Announcements
icon: mdi:bullhorn
max: 255
input_boolean:
briefing_extras:
@@ -69,6 +73,9 @@ input_boolean:
kallen_briefing_extras:
name: Kallen Briefing Extras
icon: mdi:plus
kallen_morning_announcements:
name: Kallen Morning Announcements
icon: mdi:bullhorn
good_morning:
name: Good Morning Ran
icon: mdi:home-analytics
@@ -96,6 +103,15 @@ input_boolean:
sun_reports:
name: Sun Reports
icon: mdi:weather-sunny-alert
morning_briefing_allowed:
name: Morning Briefing Allowed
icon: mdi:bullhorn
daily_briefing_allowed:
name: Daily Briefing Allowed
icon: mdi:bullhorn
nightly_briefing_allowed:
name: Nightly Briefing Allowed
icon: mdi:bullhorn
intent_script:
PlayAnnouncement:
@@ -267,7 +283,6 @@ script:
- light.living_room_color_1
- light.living_room_color_2
- light.living_room_color_3
- light.tina_desk_strip
- light.tina_lamp_side
- light.tina_lamp_top
- light.mud_room_overhead
@@ -304,7 +319,6 @@ script:
entity_id:
- light.living_room_lights
- light.tina_lamp
- light.tina_desk_strip
- light.basement_studio_lights
data:
color_name: >

View File

@@ -0,0 +1,4 @@
input_boolean:
do_not_enter_basement_studio:
name: Do Not Enter - Basement Studio
icon: mdi:minus-circle

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:
@@ -217,6 +235,14 @@ input_boolean:
name: Cold Day
icon: mdi:snowflake
basement_studio_heat_allowed:
name: Basement Studio Heat Allowed
icon: mdi:heating-coil
emma_bedroom_heater_installed:
name: Emma Bedroom Heater Installed
icon: mdi:heating-coil
input_select:
scheduled_climate_mode_master_bedroom_aircon:
name: Scheduled Climate Mode - Master Bedroom Aircon
@@ -231,22 +257,17 @@ input_select:
- Fan
- N/A
icon: mdi:home-thermometer
scheduled_climate_mode_emma_aircon:
name: Scheduled Climate Mode - Emma Aircon
scheduled_climate_mode_emma_bedroom:
name: Scheduled Climate Mode - Emma Bedroom
options:
- AC
- Fan
- Heat
- White Noise
- N/A
icon: mdi:home-thermometer
naptime_climate_mode_emma_aircon:
name: Naptime Climate Mode - Emma Aircon
options:
- AC
- White Noise
- N/A
icon: mdi:home-thermometer
scheduled_climate_mode_kallen_fan:
name: Scheduled Climate Mode - Kallen Fan
scheduled_climate_mode_kallen_bedroom:
name: Scheduled Climate Mode - Kallen Bedroom
options:
- Fan
- White Noise
@@ -303,20 +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_naptime_aircon_threshold:
name: Emma Naptime Aircon Threshold
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
@@ -374,6 +430,38 @@ input_number:
unit_of_measurement: °F
icon: mdi:thermometer
climate:
- platform: generic_thermostat
unique_id: c2979677-045e-4393-a1cb-e6618978394f
name: Basement Studio Thermostat
heater: switch.basement_studio_heater
target_sensor: sensor.basement_studio_temperature
min_temp: 50
max_temp: 80
target_temp: 62
ac_mode: false
min_cycle_duration:
minutes: 2
cold_tolerance: 1
hot_tolerance: 0
initial_hvac_mode: "off"
precision: 1.0
- platform: generic_thermostat
unique_id: 52cb7523-155a-4b26-808a-d6037b3ef7e4
name: Emma Bedroom Thermostat
heater: switch.emma_bedroom_heater
target_sensor: sensor.emma_bedroom_temperature
min_temp: 50
max_temp: 80
target_temp: 62
ac_mode: false
min_cycle_duration:
minutes: 2
cold_tolerance: 1
hot_tolerance: 0
initial_hvac_mode: "off"
precision: 1.0
intent_script:
MasterBedroomModes:
action:

View File

@@ -3,6 +3,7 @@ weather:
name: "Iron Nerd Weather Station"
condition_template: >
{% set stations = [
states.weather.home_tempest_forecast_home,
states.weather.home,
states.weather.kdfi_daynight,
states.weather.iron_nerd_studios,
@@ -12,6 +13,7 @@ weather:
{{ states(result) }}
temperature_template: >
{% set temps = [
states.sensor.home_tempest_temperature,
states.sensor.home_temperature,
states.sensor.kdfi_temperature,
states.sensor.pirateweather_temperature,
@@ -20,8 +22,28 @@ weather:
{% set sensor = temps | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(sensor) | float }}
temperature_unit: °F
dew_point_template: >
{% set dewpoints = [
states.sensor.home_tempest_dew_point,
states.sensor.home_dew_point,
states.sensor.kdfi_dew_point,
states.sensor.pirateweather_dew_point,
states.sensor.openweathermap_dew_point
] %}
{% set sensor = dewpoints | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(sensor) | float }}
apparent_temperature_template: >
{% set apparent_temps = [
states.sensor.home_tempest_feels_like,
states.sensor.home_temperature_feels_like,
states.sensor.pirateweather_apparent_temperature,
states.sensor.stratton_ave_apparent_temperature
] %}
{% set sensor = apparent_temps | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(sensor) | float }}
humidity_template: >
{% set humidity = [
states.sensor.home_tempest_humidity,
states.sensor.home_relative_humidity,
states.sensor.kdfi_relative_humidity,
states.sensor.pirateweather_humidity,
@@ -40,12 +62,13 @@ weather:
{{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }}
forecast_hourly_template: >
{% set forecasts = [
states.sensor.weather_com_hourly_weather_forecast,
states.sensor.weather_com_hourly_weather_forecast.attributes,
states.sensor.pirateweather_hourly_weather_forecast.attributes
] %}
{{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }}
pressure_template: >
{% set pressures = [
states.sensor.home_tempest_cloud_sensors_sea_level_pressure,
states.sensor.home_pressure,
states.sensor.kdfi_barometric_pressure
] %}
@@ -92,6 +115,7 @@ weather:
name: "Iron Nerd Weather Station - Hourly"
condition_template: >
{% set stations = [
states.weather.home_tempest_forecast_home,
states.weather.home,
states.weather.tomorrow_io_stratton_ave_hourly,
states.weather.iron_nerd_studios,
@@ -102,6 +126,7 @@ weather:
{{ states(result) }}
temperature_template: >
{% set temps = [
states.sensor.home_tempest_temperature,
states.sensor.home_temperature,
states.sensor.kdfi_temperature,
states.sensor.pirateweather_temperature,
@@ -110,8 +135,28 @@ weather:
{% set sensor = temps | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(sensor) | float }}
temperature_unit: °F
dew_point_template: >
{% set dewpoints = [
states.sensor.home_tempest_dew_point,
states.sensor.home_dew_point,
states.sensor.kdfi_dew_point,
states.sensor.pirateweather_dew_point,
states.sensor.openweathermap_dew_point
] %}
{% set sensor = dewpoints | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(sensor) | float }}
apparent_temperature_template: >
{% set apparent_temps = [
states.sensor.home_tempest_feels_like,
states.sensor.home_temperature_feels_like,
states.sensor.pirateweather_apparent_temperature,
states.sensor.stratton_ave_apparent_temperature
] %}
{% set sensor = apparent_temps | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(sensor) | float }}
humidity_template: >
{% set humidity = [
states.sensor.home_tempest_humidity,
states.sensor.home_relative_humidity,
states.sensor.kdfi_relative_humidity,
states.sensor.pirateweather_humidity,
@@ -121,13 +166,14 @@ weather:
{{ states(result) | float }}
forecast_hourly_template: >
{% set forecasts = [
states.sensor.weather_com_hourly_weather_forecast,
states.sensor.weather_com_hourly_weather_forecast.attributes,
states.weather.tomorrow_io_stratton_ave_hourly.attributes,
states.sensor.pirateweather_hourly_weather_forecast.attributes
] %}
{{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }}
pressure_template: >
{% set pressures = [
states.sensor.home_tempest_cloud_sensors_sea_level_pressure,
states.sensor.home_pressure,
states.sensor.kdfi_barometric_pressure
] %}
@@ -170,6 +216,87 @@ weather:
{{ states(result) | float }}
precipitation_unit: in
- platform: template
name: "Ashland Weather Station"
condition_template: >
{% set stations = [
states.weather.ashland,
states.weather.kasx,
states.weather.pirateweather_ashland
] %}
{% set result = stations | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(result) }}
temperature_template: >
{% set temps = [
states.sensor.ashland_temperature,
states.sensor.kasx_temperature,
states.sensor.pirateweather_ashland_temperature
] %}
{% set sensor = temps | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(sensor) | float }}
temperature_unit: °F
humidity_template: >
{% set humidity = [
states.sensor.ashland_relative_humidity,
states.sensor.kasx_relative_humidity,
states.sensor.pirateweather_ashland_humidity
] %}
{% set result = humidity | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(result) | float }}
forecast_daily_template: >
{% set forecasts = [
states.sensor.weather_com_ashland_daily_weather_forecast.attributes,
states.weather.kasx.attributes,
states.sensor.pirateweather_ashland_daily_weather_forecast.attributes
] %}
{{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }}
forecast_hourly_template: >
{% set forecasts = [
states.sensor.weather_com_ashland_hourly_weather_forecast,
states.sensor.pirateweather_ashland_hourly_weather_forecast.attributes
] %}
{{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }}
pressure_template: >
{% set pressures = [
states.sensor.ashland_pressure,
states.sensor.kasx_barometric_pressure
] %}
{% set result = pressures | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(result) | float }}
pressure_unit: inHg
wind_speed_template: >
{% set windspeeds = [
states.sensor.ashland_wind_speed,
states.sensor.pirateweather_ashland_wind_speed,
states.sensor.kasx_wind_speed
] %}
{% set result = windspeeds | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(result) | float }}
wind_speed_unit: mph
wind_bearing_template: >
{% set windbearings = [
states.sensor.ashland_wind_direction_degrees,
states.sensor.pirateweather_ashland_wind_bearing
] %}
{% set result = windbearings | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(result) | float }}
visibility_template: >
{% set vis = [
states.sensor.kasx_visibility,
states.sensor.pirateweather_ashland_visibility
] %}
{% set result = vis | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(result) | float }}
visibility_unit: mi
attribution_template: "Daily weather data from Iron Nerd's custom weather station template"
ozone_template: >
{% set ozones = [
states.sensor.pirateweather_ashland_ozone
] %}
{% set result = ozones | selectattr('state','ne','unavailable') | selectattr('state','ne','unknown') | map(attribute='entity_id') | list | first %}
{{ states(result) | float }}
precipitation_unit: in
# binary_sensor:
# - platform: bayesian
# unique_id: 3e9640d9-57a0-4495-8731-e64b34774065
@@ -241,6 +368,60 @@ sensor:
# days: 7
template:
- trigger:
- platform: time_pattern
minutes: /15
- platform: state
entity_id: weather.home_tempest_forecast_home
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.home_tempest_forecast_home
response_variable: daily
- variables:
today: "{{ daily['weather.home_tempest_forecast_home'].forecast[0] }}"
sensor:
- name: Weatherflow Daily Weather Forecast
unique_id: 2c70c4ee-7f7f-42b4-ad40-90ce2b6c6d77
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ daily['weather.home_tempest_forecast_home'].forecast }}"
- name: Weatherflow High
unique_id: 296b4361-459a-48e7-9793-c003b88fcdef
state: "{{ today.temperature }}"
unit_of_measurement: °F
- name: Weatherflow Low
unique_id: 61c344be-33d3-4e1d-8d0d-277c2b850c0d
state: "{{ today.templow }}"
unit_of_measurement: °F
- name: Weatherflow Rain Chance Today
unique_id: ab0327ff-f20f-4d16-aeb5-78682b3e2397
state: "{{ today.precipitation_probability }}"
unit_of_measurement: "%"
- trigger:
- platform: time_pattern
minutes: /15
- platform: state
entity_id: weather.home_tempest_forecast_home
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.home_tempest_forecast_home
response_variable: hourly
sensor:
- name: Weatherflow Hourly Weather Forecast
unique_id: aa0b368c-ea23-4514-a697-e122353eb76d
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ hourly['weather.home_tempest_forecast_home'].forecast }}"
- trigger:
- platform: time_pattern
minutes: /15
@@ -386,6 +567,119 @@ template:
unique_id: 5bece9ad-2e1e-45a9-a690-93f8ff1d8780
state: "{{ today.precipitation_probability }}"
unit_of_measurement: "%"
- trigger:
- platform: time_pattern
minutes: /15
- platform: state
entity_id: weather.pirateweather_ashland
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.pirateweather_ashland
response_variable: daily
- variables:
today: "{{ daily['weather.pirateweather_ashland'].forecast[0] }}"
sensor:
- name: Pirateweather Ashland Daily Weather Forecast
unique_id: 9b103d9e-0fa3-4b47-b95d-c0caa4621895
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ daily['weather.pirateweather_ashland'].forecast }}"
- name: Pirateweather Ashland High
unique_id: 21bf1e49-c3e3-4cec-8c89-add9e9efe9f3
state: "{{ today.temperature }}"
unit_of_measurement: °F
- name: Pirateweather Ashland Low
unique_id: fe06c076-807e-43a1-8413-c31ec389ec08
state: "{{ today.templow }}"
unit_of_measurement: °F
- name: Pirateweather Ashland Rain Chance Today
unique_id: 687b2246-ae49-47e0-95f3-f93dd159a43c
state: "{{ today.precipitation_probability }}"
unit_of_measurement: "%"
- trigger:
- platform: time_pattern
minutes: /15
- platform: state
entity_id: weather.pirateweather_ashland
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.pirateweather_ashland
response_variable: hourly
sensor:
- name: Pirateweather Ashland Hourly Weather Forecast
unique_id: bcc4ca8c-aee7-4238-a78d-c35dae8c2c2b
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ hourly['weather.pirateweather_ashland'].forecast }}"
- trigger:
- platform: time_pattern
minutes: /15
- platform: state
entity_id: weather.ashland
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.ashland
response_variable: daily
- variables:
today: "{{ daily['weather.ashland'].forecast[0] }}"
sensor:
- name: Weather.com Ashland Daily Weather Forecast
unique_id: f658e6ce-26a2-4c0d-9dc1-0bf26e95caf3
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ daily['weather.ashland'].forecast }}"
- name: Weather.com Ashland High
unique_id: b5cf81b7-9a24-47c5-a5ee-9f3367251c83
state: >
{% if is_number(today.temperature) %}
{{ today.temperature }}
{% else %}
{{ state_attr('weather.ashland','temperature') }}
{% endif %}
unit_of_measurement: °F
- name: Weather.com Ashland Low
unique_id: 196fb8a5-8ff5-47f1-ada5-dd1d3a69d596
state: "{{ today.templow }}"
unit_of_measurement: °F
- name: Weather.com Ashland Rain Chance Today
unique_id: 2e84209b-8d0a-425a-8c24-10ad8cf0c029
state: "{{ today.precipitation_probability }}"
unit_of_measurement: "%"
- trigger:
- platform: time_pattern
minutes: /15
- platform: state
entity_id: weather.ashland
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.ashland
response_variable: hourly
sensor:
- name: Weather.com Ashland Hourly Weather Forecast
unique_id: 463cbe89-997c-49cc-a644-9e05ffd804ff
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ hourly['weather.ashland'].forecast }}"
- binary_sensor:
- name: Heat Threshold
unique_id: 849a08bb-d4e6-40e9-ae42-50f7fb71b727
@@ -474,10 +768,10 @@ template:
{% endif %}
- name: "Lightning Warning"
unique_id: edaddfc4-f7f0-4d75-aada-a2c588afe029
state: "{{ states('sensor.blitzortung_lightning_counter') | int > 0 }}"
state: "{{ states('sensor.home_tempest_cloud_sensors_lightning_strikes_last_hour') | int > 0 }}"
device_class: safety
attributes:
current_strikes: "{{ states('sensor.blitzortung_lightning_counter') | int }}"
current_strikes: "{{ states('sensor.home_tempest_cloud_sensors_lightning_strikes_last_hour') | int }}"
icon: "{{ 'mdi:flash-alert' if states('sensor.blitzortung_lightning_counter') | int > 0 else 'mdi:flash-outline'}}"
- name: "Audible Weather Alerts Allowed"
unique_id: 03851823-32d5-44c1-af42-256fcd922069
@@ -507,52 +801,57 @@ template:
- name: Raining
unique_id: 232b43a4-4598-4315-ab76-42348c11e6ff
state: >
{{ states('sensor.total_rain_sensors') | int > 1 }}
icon: "{{ 'mdi:weather-rainy' if states('sensor.total_rain_sensors') | int > 1 else 'mdi:weather-cloudy' }}"
{{ states('sensor.home_tempest_precipitation_intensity') | float > 0 or
states('sensor.home_tempest_precipitation_type') in ['rain','hail','rain_hail'] or
states('sensor.home_tempest_cloud_sensors_precipitation_description') in ['rain','heavy_rain'] or
is_state('binary_sensor.home_tempest_cloud_binary_sensors_is_raining','on') }}
icon: "{{ 'mdi:weather-rainy' if this.state == 'on' else 'mdi:weather-cloudy' }}"
- sensor:
- name: Total Rain Sensors
unique_id: b7c2e709-8f5c-4263-aa1d-fa8280afcddb
unit_of_measurement: 'sensors'
state: >
{% set sensors = [
states.sensor.pirateweather_precip,
states.sensor.openweathermap_precipitation_kind,
states.sensor.tomorrow_io_stratton_ave_precipitation_type
] %}
{% set numeric_sensors = [
states.sensor.stratton_ave_precipitation
] %}
{% set c1 = sensors | selectattr('state','eq','rain') | list | count %}
{% set c2 = numeric_sensors | map(attribute='state') | map('float') | select('gt',0) | list | count %}
{{ (c1 + c2) | int }}
# - name: Total Rain Sensors
# unique_id: b7c2e709-8f5c-4263-aa1d-fa8280afcddb
# unit_of_measurement: 'sensors'
# state: >
# {% set sensors = [
# states.sensor.home_tempest_precipitation_type,
# states.sensor.pirateweather_precip,
# states.sensor.openweathermap_precipitation_kind,
# states.sensor.tomorrow_io_stratton_ave_precipitation_type
# ] %}
# {% set numeric_sensors = [
# states.sensor.home_tempest_precipitation_intensity,
# states.sensor.stratton_ave_precipitation
# ] %}
# {% set c1 = sensors | selectattr('state','eq','rain') | list | count %}
# {% set c2 = numeric_sensors | map(attribute='state') | map('float') | select('gt',0) | list | count %}
# {{ (c1 + c2) | int }}
- name: Current Forecast
unique_id: c0faea33-2ac3-40f1-8558-584c3f5d6b16
icon: mdi:weather-sunny
state: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{{ forecast.condition }}
attributes:
high_temp: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{{ forecast.temperature }}
overnight_low: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{{ forecast.templow }}
wind_bearing: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{{ forecast.wind_bearing }}
wind_speed: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{{ forecast.wind_speed }}
precipitation: >-
{% if state_attr('weather.iron_nerd_weather_station','precipitation') %}
{% set forecast = state_attr('weather.iron_nerd_weather_station','forecast')[0] %}
{% else %}
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{% endif %}
{{ forecast.precipitation }}
friendly: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{{ forecast.condition | replace("partlycloudy","partly cloudy") }}
- name: Current Forecast Detail
unique_id: e5ae9864-70b5-402c-9d2f-c4d6a10085df
@@ -667,23 +966,23 @@ template:
unique_id: a8ae26b0-ed26-4568-bb2b-f7c72707b009
icon: mdi:weather-sunny
state: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[1] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[1] %}
{{ forecast.condition }}
attributes:
high_temp: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[1] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[1] %}
{{ forecast.temperature }}
overnight_low: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[1] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[1] %}
{{ forecast.templow }}
wind_bearing: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[1] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[1] %}
{{ forecast.wind_bearing }}
wind_speed: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[1] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[1] %}
{{ forecast.wind_speed }}
precipitation: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[1] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[1] %}
{{ forecast.precipitation }}
- name: Tomorrow Forecast Detail
unique_id: 21374ed0-80d1-49ba-817d-3e93eb3865e4
@@ -988,7 +1287,7 @@ template:
unit_of_measurement: '°F'
device_class: temperature
state: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{% if is_number(forecast.temperature) %}
{{ forecast.temperature }}
{% else %}
@@ -999,14 +1298,14 @@ template:
unit_of_measurement: '°F'
device_class: temperature
state: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[2] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[2] %}
{{ forecast.temperature }}
- name: "Tonight's Low Temp"
unique_id: 8ddc55b6-4728-4897-a32f-90be970f744b
unit_of_measurement: '°F'
device_class: temperature
state: >-
{% set forecast = state_attr('sensor.weather_com_daily_weather_forecast','forecast')[0] %}
{% set forecast = state_attr('sensor.weatherflow_daily_weather_forecast','forecast')[0] %}
{{ forecast.templow }}
- name: "Clothing Forecast"
unique_id: 8ed2684b-d0ad-402c-bc3c-340cb9b2437a
@@ -1267,8 +1566,8 @@ template:
unit_of_measurement: '°F'
state: >
{% set ns = namespace(temps=[]) %}
{% set x = state_attr('sensor.weather_com_hourly_weather_forecast','forecast') | count %}
{% set pd = state_attr('sensor.weather_com_hourly_weather_forecast','forecast') %}
{% set x = state_attr('sensor.weatherflow_hourly_weather_forecast','forecast') | count %}
{% set pd = state_attr('sensor.weatherflow_hourly_weather_forecast','forecast') %}
{% for i in range(0,x) %}
{% set hr = as_timestamp(as_local(as_datetime(pd[i].datetime))) | timestamp_custom('%H') | int %}
{% if hr in range(21,24) or hr in range(0,8) %}

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

@@ -4,9 +4,6 @@ input_boolean:
emma_sleeping:
name: Emma Sleeping
icon: mdi:sleep
emma_has_napped:
name: Emma Has Napped
icon: mdi:check
emma_alternating_meds_active:
name: Emma Alternating Meds Active
icon: mdi:medication
@@ -71,16 +68,6 @@ input_datetime:
has_date: false
has_time: true
icon: mdi:weather-sunset-up
emma_down_for_nap:
name: Emma Down For Nap
has_date: true
has_time: true
icon: mdi:sleep
emma_up_from_nap:
name: Emma Up From Nap
has_date: true
has_time: true
icon: mdi:eye
# These are for use in remembering which medications she has had when she is sick, and when to safely give them again
emma_ibuprofen:
name: Emma Ibuprofen
@@ -145,31 +132,13 @@ automation:
id: sleep-on
sequence:
- service: script.emma_sleep
- if:
- condition: and
conditions:
- condition: state
entity_id: input_boolean.emma_has_napped
state: 'off'
- condition: time
before: "23:00:00"
after: "07:00:00"
then:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_down_for_nap
data:
datetime: >
{% from 'time.jinja' import current_time %}
{{ current_time('datetime',24) }}
else:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_asleep_at
data:
time: >
{% from 'time.jinja' import current_time %}
{{ current_time('time',24) }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_asleep_at
data:
time: >
{% from 'time.jinja' import current_time %}
{{ current_time('time',24) }}
- delay:
seconds: 1
- service: script.text_notify
@@ -186,28 +155,6 @@ automation:
- condition: trigger
id: sleep-off
sequence:
- if:
- condition: and
conditions:
- condition: state
entity_id: input_boolean.emma_has_napped
state: 'off'
- condition: time
after: "18:00:00"
before: "01:00:00"
then:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.emma_has_napped
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_up_from_nap
data:
datetime: >
{% from 'time.jinja' import current_time %}
{{ current_time('datetime',24) }}
- delay:
seconds: 1
- if:
- condition: state
entity_id: input_boolean.emma_scheduling_evening_ran
@@ -260,41 +207,6 @@ automation:
target:
entity_id: input_boolean.emma_sleeping
- id: e44c2ab8-00cd-40ab-9b42-824511ac20aa
alias: Emma Naptime Climate
description: Sets the climate mode for when Emma goes down for nap
mode: restart
trigger:
- platform: time_pattern
minutes: "/5"
- platform: state
entity_id: input_number.emma_naptime_aircon_threshold
- platform: state
entity_id: input_boolean.hot_day
condition:
- condition: state
entity_id: input_boolean.emma_sleeping
state: 'off'
- condition: state
entity_id: input_boolean.emma_bedroom_climate_override
state: 'off'
- condition: state
entity_id: input_boolean.emma_bedroom_aircon_installed
state: 'on'
action:
- service: input_select.select_option
target:
entity_id: input_select.naptime_climate_mode_emma_aircon
data:
option: >
{% set temp = state_attr('weather.iron_nerd_weather_station','temperature') | int %}
{% set threshold = states('input_number.emma_naptime_aircon_threshold') | int %}
{% if (temp >= threshold) or is_state('input_boolean.hot_day','on') %}
AC
{% else %}
White Noise
{% endif %}
- id: 5b45eeb2-171e-4bac-825b-8ac7aa672dab
alias: Emma Asleep Update
description: Attempt to make readouts of when Emma went to bed more accurate
@@ -310,11 +222,6 @@ automation:
event_data:
entity_id: timer.emma_bedtime_update
id: bedtime-timer-finished
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.emma_naptime_update
id: naptime-timer-finished
- platform: state
entity_id: light.emma_bedroom_light
to: 'off'
@@ -325,37 +232,11 @@ automation:
- condition: trigger
id: initial
sequence:
- choose:
- conditions:
- condition: and
conditions:
- condition: state
entity_id: input_boolean.emma_has_napped
state: 'off'
- condition: time
before: "23:00:00"
after: "07:00:00"
sequence:
- service: timer.start
target:
entity_id: timer.emma_naptime_update
data:
duration: "01:00:00"
- conditions:
- condition: or
conditions:
- condition: state
entity_id: input_boolean.emma_has_napped
state: 'on'
- condition: time
after: "23:00:00"
before: "07:00:00"
sequence:
- service: timer.start
target:
entity_id: timer.emma_bedtime_update
data:
duration: "01:00:00"
- service: timer.start
target:
entity_id: timer.emma_bedtime_update
data:
duration: "01:00:00"
- conditions:
- condition: trigger
id: lights-off
@@ -364,71 +245,21 @@ automation:
target:
entity_id:
- timer.emma_bedtime_update
- timer.emma_naptime_update
- if:
- condition: state
entity_id: input_boolean.emma_sleeping
state: 'on'
then:
- choose:
- conditions:
- condition: and
conditions:
- condition: state
entity_id: input_boolean.emma_has_napped
state: 'off'
- condition: time
before: "23:00:00"
after: "07:00:00"
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_down_for_nap
data:
datetime: >
{% from 'time.jinja' import current_time %}
{{ current_time('datetime',24) }}
- conditions:
- condition: or
conditions:
- condition: state
entity_id: input_boolean.emma_has_napped
state: 'on'
- condition: time
after: "23:00:00"
before: "07:00:00"
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_asleep_at
data:
time: >
{% from 'time.jinja' import current_time %}
{{ current_time('time',24) }}
- conditions:
- condition: trigger
id: naptime-timer-finished
sequence:
- if:
- condition: state
entity_id: light.emma_bedroom_light
state: 'on'
then:
- delay:
seconds: 1
- service: timer.start
target:
entity_id: timer.emma_naptime_update
data:
duration: "01:00:00"
else:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_down_for_nap
entity_id: input_datetime.emma_asleep_at
data:
datetime: >
time: >
{% from 'time.jinja' import current_time %}
{{ current_time('datetime',24) }}
{{ current_time('time',24) }}
- service: input_boolean.turn_off
target:
entity_id: input_boolean.emma_awake
- conditions:
- condition: trigger
id: bedtime-timer-finished
@@ -453,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
@@ -976,27 +810,18 @@ 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
type: normal
message: Emma has awoken, so it is time to make your way upstairs now
- if:
- condition: template
value_template: "{{ is_state('binary_sensor.morning','on') or is_state('binary_sensor.midday','on') }}"
then:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_awake_at
data:
time: >
{% from 'time.jinja' import current_time %}
{{ current_time('time',24) }}
- service: script.speech_engine
data:
who: common
type: normal
message: Emma has awoken, so it is time to make your way upstairs now
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.emma_awake_at
data:
time: >
{% from 'time.jinja' import current_time %}
{{ current_time('time',24) }}
- service: switch.turn_off
target:
entity_id:
@@ -1074,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

@@ -1,101 +1,3 @@
scrape:
- resource: https://www.gasbuddy.com/station/59010
sensor:
- name: South Side Shell
unique_id: b3385058-173c-4446-9f0f-3a45f21715d8
select: &selector "#root > div > div.Page-module__content___196kn.Page-module__padded___3hQ0U > div > div > div:nth-child(2) > div.grid__column___nhz7X.grid__desktop10___2T18R > div:nth-child(1) > div.grid__column___nhz7X.grid__desktop8___38Y4U > div:nth-child(3) > div > div.GasPriceCollection-module__collectionContainer___29Ngz > div:nth-child(2) > div:nth-child(1) > span"
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59007
sensor:
- name: Circle K
unique_id: 63d947bc-486a-478e-9fbe-7fb2f38a1e1e
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/123478
sensor:
- name: Kroger
unique_id: b705d912-8ef4-4e55-9168-d7e152773ba0
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59014
sensor:
- name: Kecks
unique_id: 4fa4a7bb-45b1-4d17-ab92-06ebd6a39ebb
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59006
sensor:
- name: The Barn
unique_id: 51137245-9c4a-4992-aa7c-19cd38bd614d
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59016
sensor:
- name: The Big Fish
unique_id: d5e057d5-3f7b-4c6b-ad0c-5e6ffa10b861
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/107803
sensor:
- name: Marathon Cleveland Avenue
unique_id: 3ef9c1d0-46b0-4850-8df2-d478c833aa4d
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59013
sensor:
- name: Speedway
unique_id: 44484541-1a71-4e36-9e81-486eea3882cc
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59009
sensor:
- name: Meijer
unique_id: dc687fd2-ed4d-4fae-a2b8-38ae7a944a68
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59012
sensor:
- name: East Side Shell
unique_id: db36f6b4-6f87-48af-a339-1f8e8bbc95e3
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/59011
sensor:
- name: Shell Ottawa Avenue
unique_id: d9508ad6-4298-4262-bac9-931a3bc510df
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
- resource: https://www.gasbuddy.com/station/71535
sensor:
- name: Ridis
unique_id: 9db2cbc3-39ea-4471-9541-64aa7aa8de71
select: *selector
device_class: monetary
value_template: '{{ value | replace("$", "") | float }}'
icon: mdi:gas-station
sensor:
- platform: statistics
unique_id: fcf4e80e-8459-4e23-a94f-5f127b628c20

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

@@ -16,9 +16,15 @@ input_boolean:
kallen_late_bedtime:
name: Kallen Late Bedtime
icon: mdi:weather-night
kallen_morning_meds_reminder:
name: Kallen Morning Meds Reminder
icon: mdi:medication
kallen_morning_meds_taken:
name: Kallen Morning Meds Taken
icon: mdi:medication
kallen_night_meds_reminder:
name: Kallen Night Meds Reminder
icon: mdi:medication
kallen_night_meds_taken:
name: Kallen Night Meds Taken
icon: mdi:medication
@@ -67,12 +73,12 @@ input_datetime:
icon: mdi:medication
kallen_morning_meds_notify:
name: Kallen Morning Meds Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
kallen_night_meds_notify:
name: Kallen Night Meds Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
kallen_alarm_clock:

View File

@@ -32,9 +32,6 @@ input_boolean:
give_me_darkness:
name: Give Me Darkness
icon: mdi:weather-night
tina_desk_lights:
name: Tina Desk Lights
icon: mdi:desk
holiday_mode_hold:
name: Holiday Mode Hold
icon: mdi:party-popper
@@ -210,6 +207,14 @@ input_number:
step: 5
unit_of_measurement: lx
icon: mdi:sun-wireless
front_porch_lux_threshold:
name: Front Porch Lux Threshold
min: 0
max: 2000
step: 5
mode: box
unit_of_measurement: lx
icon: mdi:sun-wireless
# Settings for adaptive adjustments
daytime_colortemp_front_porch:
@@ -492,6 +497,7 @@ input_select:
- Evening Mode
- Night Mode
- Bright Mode
- Reading Mode
- Reset
initial: Select
icon: mdi:desk
@@ -656,6 +662,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
@@ -819,7 +844,6 @@ switch:
- light.living_room_color_3
- light.tina_lamp_top
- light.tina_lamp_side
- light.tina_desk_strip
colors:
- color_type: rgb_color
color: [255,0,0]

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:
@@ -301,10 +352,6 @@ notify:
services:
- service: alexa_media_living_room_echo_dot
- service: alexa_media_basement_echo_dot
- platform: html5
vapid_pub_key: !secret vapid_pub_key
vapid_prv_key: !secret vapid_prv_key
vapid_email: tm24fan8@gmail.com
script:
volume_reset:
@@ -329,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
@@ -377,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
@@ -409,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
@@ -439,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
@@ -487,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
@@ -540,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
@@ -1241,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'] %}
@@ -1332,53 +1317,34 @@ 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') %}
{% 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') }}
{% 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') }}
{% else %}
{{ kidsgroup_night }}
{% endif %}
{% elif who in ['kallen_bedroom','media_player.kallen_bedroom_google_speaker'] %}
{{ states('input_number.kallen_bedroom_google_speaker_night_volume') }}
{% elif who in ['emma_bedroom','media_player.emma_bedroom_google_speaker'] %}
{{ states('input_number.emma_bedroom_google_speaker_night_volume') }}
{% elif who in ['Basement Google','basement_google'] %}
{{ states('input_number.basement_google_speaker_night_volume') }}
{% else %}
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') }}
{{ 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_day_volume') }}
{{ states('sensor.emma_bedroom_google_speaker_volume') }}
{% else %}
{{ kidsgroup_day }}
{{ kidsgroup }}
{% endif %}
{% elif who in ['kallen_bedroom','media_player.kallen_bedroom_google_speaker'] %}
{{ states('input_number.kallen_bedroom_google_speaker_day_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_day_volume') }}
{{ states('sensor.emma_bedroom_google_speaker_volume') }}
{% elif who in ['Basement Google','basement_google'] %}
{{ states('input_number.basement_google_speaker_day_volume') }}
{{ states('sensor.basement_google_speaker_volume') }}
{% else %}
0.6
{% if is_state('input_boolean.give_me_darkness','on') %}
0.3
{% else %}
0.6
{% endif %}
{% endif %}
{% endif %}
- service: tts.amazon_polly_say
@@ -1786,6 +1752,15 @@ script:
] | random }}
{%- endmacro -%}
{%- macro snark_shower_mode_window() -%}
{{ [
'Now that you have finished showering, you may want to consider shutting the upstairs bathroom window.',
'As there is no screen in the upstairs bathroom window, you should shut it to prevent bugs and other unwanted creatures from getting into the house.',
'Hey, you left the upstairs bathroom window open after your shower. Do something about that ASAP.',
'The second floor already has enough trouble maintaining temperature, please close the upstairs bathroom window after your shower.'
] | random }}
{%- endmacro -%}
{%- macro school_pickup_reminder() -%}
{{ [
'It is almost time to head to school ',
@@ -1943,7 +1918,11 @@ script:
{% endif %}
{% if call_snark_door_closed == 1 %}
{{ snark_door_closed () }}
{{ snark_door_closed() }}
{% endif %}
{% if call_snark_shower_mode_window == 1 %}
{{ snark_shower_mode_window() }}
{% endif %}
{% if call_school_pickup_reminder == 1 %}

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

@@ -89,7 +89,7 @@ template:
- binary_sensor:
- name: People Present
state: >
{{ is_state('person.tony_stork', 'home') or is_state('person.christina_stork', 'home') }}
{{ is_state('person.tony_stork', 'home') or is_state('person.christina_stork', 'home') or is_state('person.kallen_stork', 'home') or is_state('input_boolean.guest_mode', 'on') }}
- name: "Tony Home"
unique_id: 4f0d8c3d-dc49-4b7a-a1fc-5d286b4a954d
state: "{{ is_state('device_tracker.tony_s_iphone', 'home') }}" # Add new tracker when we have one
@@ -124,6 +124,8 @@ template:
state: >
{% if is_state('binary_sensor.basement_studio_motion','on') %}
true
{% elif is_state('sensor.xia_desktop_current_username','tm24f') %}
false
{% elif is_state('binary_sensor.tony_desktop_on','off') and
is_state('binary_sensor.kallen_desktop_on','off') %}
false
@@ -405,7 +407,6 @@ automation:
# - light.living_room_led_strip
# - light.tina_lamp_top
# - light.tina_lamp_side
# - light.tina_desk_strip
# - alias: "Save Current Adaptive State"
# service: scene.create
# data:
@@ -425,7 +426,6 @@ automation:
# entity_id:
# - light.living_room_lights
# - light.tina_lamp
# - light.tina_desk_strip
# - light.living_room_led_strip
# data:
# color_name: green
@@ -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
@@ -865,9 +864,7 @@ script:
- front_porch
- living_room
- mud_room
- service: input_boolean.turn_on
target:
entity_id: input_boolean.tina_desk_lights
- tina_desk
- delay:
hours: 0
minutes: 0
@@ -925,9 +922,7 @@ script:
area_id:
- living_room
- mud_room
- service: input_boolean.turn_on
target:
entity_id: input_boolean.tina_desk_lights
- tina_desk
- delay:
hours: 0
minutes: 0

View File

@@ -164,7 +164,7 @@ script:
time: >
{% from 'time.jinja' import time_from_calendar %}
{% if is_state('input_boolean.two_hour_delay','on') %}
10:00
{{ time_from_calendar('calendar.kallen_school_days','start_time','set','add',2)}}
{% else %}
{{ time_from_calendar('calendar.kallen_school_days','start_time','set') }}
{% endif %}
@@ -247,11 +247,14 @@ script:
target:
entity_id: input_datetime.kallen_morning_meds_notify
data:
time: >
datetime: >
{% set date = now().strftime('%Y-%m-%d') %}
{% set wakeup = state_attr('input_datetime.kallen_wakeup_time','timestamp') | int %}
{% set wakeup_mod = (wakeup + 600) | timestamp_custom('%T',false) %}
{% if is_state('input_boolean.kallen_school_today','on') %}
{{ (state_attr('input_datetime.kallen_wakeup_time','timestamp') + 600) | timestamp_custom('%H:%M', false) }}
{{ date + ' ' + wakeup_mod }}
{% else %}
{{ states('input_datetime.kallen_wakeup_time') }}
{{ date + ' ' + states('input_datetime.kallen_wakeup_time') }}
{% endif %}
- service: input_boolean.turn_on
target:
@@ -271,16 +274,16 @@ script:
time: >
{% if is_state('input_boolean.school_in_session','on') %}
{% if is_state('binary_sensor.kallen_school_tomorrow', 'on') %}
21:00
{% else %}
22:00
{% endif %}
{% else %}
{% if is_state('binary_sensor.kallen_btb_tomorrow','on') %}
22:00
{% else %}
23:00
{% endif %}
{% else %}
{% if is_state('binary_sensor.kallen_btb_tomorrow','on') %}
23:00
{% else %}
00:00
{% endif %}
{% endif %}
- delay:
seconds: 1
@@ -300,7 +303,7 @@ script:
then:
- service: input_select.select_option
target:
entity_id: input_select.scheduled_climate_mode_kallen_fan
entity_id: input_select.scheduled_climate_mode_kallen_bedroom
data:
option: >
{% if is_state('input_boolean.kallen_overnight','on') %}
@@ -324,7 +327,15 @@ script:
target:
entity_id: input_datetime.kallen_night_meds_notify
data:
time: "{{ (state_attr('input_datetime.kallen_bedtime','timestamp') - 600) | timestamp_custom('%H:%M', false) }}"
datetime: >
{% set bedtime = state_attr('input_datetime.kallen_bedtime','timestamp') | int %}
{% set bedtime_mod = (bedtime - 600) | timestamp_custom('%T',false) %}
{% if bedtime < 13800 %}
{% set date = (as_timestamp(now()) + 86400) | timestamp_custom("%Y-%m-%d", True) %}
{% else %}
{% set date = now().strftime('%Y-%m-%d') %}
{% endif %}
{{ date + ' ' + bedtime_mod }}
- if:
- condition: state
entity_id: input_boolean.kallen_late_bedtime
@@ -354,7 +365,7 @@ script:
target:
entity_id: input_datetime.kallen_night_meds_notify
data:
time: "{{ (state_attr('input_datetime.kallen_night_meds_notify','timestamp') + 3600) | timestamp_custom('%H:%M', false) }}"
datetime: "{{ (state_attr('input_datetime.kallen_night_meds_notify','timestamp') + 3600) | timestamp_custom('%Y-%m-%d %H:%M:%S') }}"
- service: input_boolean.turn_on
target:
entity_id: input_boolean.kallen_scheduling_evening_ran
@@ -383,11 +394,7 @@ script:
{% set kallenbriefing = state_attr('input_datetime.kallen_morning_briefing','timestamp') %}
{% set kallenloc = states('input_select.kallen_morning_briefing_location') %}
{% if is_state('input_boolean.kallen_school_today','on') %}
{% if is_state('input_boolean.two_hour_delay','on') %}
9:20
{% else %}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 2400) | timestamp_custom('%H:%M', false) }}
{% endif %}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 3600) | timestamp_custom('%H:%M', false) }}
{% elif is_state('input_boolean.work_today','on') and is_state('input_boolean.kallen_school_today','off') %}
{% if (state_attr('input_datetime.tina_workday_start','timestamp')) > 43200 %}
{% if kallenloc == 'Common Areas' and kallenbriefing == 43200 %}
@@ -411,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
@@ -554,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
@@ -586,11 +575,13 @@ script:
target:
entity_id: input_datetime.tina_morning_meds_notify
data:
time: >
datetime: >
{% from 'time.jinja' import datetime_from_calendar %}
{% set date = now().strftime('%Y-%m-%d') %}
{% if is_state('input_boolean.work_today','on') %}
{{ (state_attr('input_datetime.tina_workday_start','timestamp') | int - 1800) | timestamp_custom('%H:%M', false) }}
{{ datetime_from_calendar('calendar.family_tinawork','start_time','set','subtract',0,0,30) }}
{% else %}
{{ states('input_datetime.master_bedroom_wakeup') }}
{{ date + ' ' + states('input_datetime.master_bedroom_wakeup') }}
{% endif %}
- service: input_boolean.turn_on
target:
@@ -609,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') %}
{{ (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') %}
{{ kallen_bedtime | timestamp_custom('%H:%M',false) }}
{% elif 56 <= low <= 60 %}
22:30
{% elif low > 60 %}
{% 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 low >= 56 or high >= 75 %}
{{ (kallen_bedtime - 1800) | timestamp_custom('%H:%M',false) }}
{% else %}
{{ kallen_bedtime | timestamp_custom('%H:%M',false) }}
{% 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 %}
@@ -633,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 %}
@@ -676,7 +672,7 @@ script:
target:
entity_id: input_datetime.tina_night_meds_notify
data:
time: '03:00'
datetime: "{{ (as_timestamp(now()) + 86400) | timestamp_custom('%Y-%m-%d', True) + ' 03:00:00' }}"
- service: input_boolean.turn_on
target:
entity_id: input_boolean.master_bedroom_scheduling_evening_ran
@@ -684,9 +680,6 @@ script:
emma_bedroom_scheduling_morning:
alias: 'Emma Bedroom Scheduling Morning'
sequence:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.emma_has_napped
- if:
- condition: state
entity_id: input_boolean.emma_wakeup_override
@@ -696,11 +689,6 @@ script:
entity_id: input_datetime.emma_wakeup
data:
time: "{{ states('input_datetime.master_bedroom_wakeup') }}"
- service: input_select.select_option
target:
entity_id: input_select.naptime_climate_mode_emma_aircon
data:
option: "{{ states('input_select.scheduled_climate_mode_emma_aircon') }}"
- service: input_boolean.turn_on
target:
entity_id: input_boolean.emma_scheduling_morning_ran
@@ -718,15 +706,9 @@ script:
data:
time: >
{% set awake = state_attr('input_datetime.emma_awake_at','timestamp') | int %}
{% set up_from_nap = state_attr('input_datetime.emma_up_from_nap','timestamp') | int %}
{% set hours = states('input_number.emma_bedtime_hours') | int %}
{% set math = (hours * 60) * 60 %}
{% set math_nap = 14400 %}
{% if is_state('input_boolean.emma_has_napped','on') %}
{{ (up_from_nap + math_nap) | timestamp_custom('%H:%M') }}
{% else %}
{{ (awake + math) | timestamp_custom('%H:%M',false) }}
{% endif %}
{{ (awake + math) | timestamp_custom('%H:%M',false) }}
- if:
- condition: state
entity_id: input_boolean.emma_bedroom_climate_override
@@ -734,14 +716,19 @@ script:
then:
- service: input_select.select_option
target:
entity_id: input_select.scheduled_climate_mode_emma_aircon
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
@@ -755,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:
@@ -778,16 +765,16 @@ script:
{% if ct > state_attr('input_datetime.kallen_school_day_start','timestamp') %}
{{ (state_attr('input_datetime.tina_workday_start','timestamp') - 1800) | timestamp_custom('%H:%M', false) }}
{% elif ct > state_attr('input_datetime.tina_workday_start','timestamp') and ct < state_attr('input_datetime.kallen_school_day_start','timestamp') %}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 2700) | timestamp_custom('%H:%M', false) }}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 3900) | timestamp_custom('%H:%M', false) }}
{% elif state_attr('input_datetime.tina_workday_start','timestamp') < (state_attr('input_datetime.kallen_school_day_start','timestamp')) %}
{{ (state_attr('input_datetime.tina_workday_start','timestamp') - 1800) | timestamp_custom('%H:%M', false) }}
{% else %}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 2700) | timestamp_custom('%H:%M', false) }}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 3900) | timestamp_custom('%H:%M', false) }}
{% endif %}
{% elif is_state('input_boolean.work_today','on') and is_state('input_boolean.kallen_school_today','off') %}
{{ (state_attr('input_datetime.tina_workday_start', 'timestamp') - 1800) | timestamp_custom('%H:%M', false) }}
{% elif is_state('input_boolean.kallen_school_today','on') %}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 2700) | timestamp_custom('%H:%M', false) }}
{{ (state_attr('input_datetime.kallen_school_day_start','timestamp') - 3900) | timestamp_custom('%H:%M', false) }}
{% else %}
11:00
{% endif %}

View File

@@ -288,6 +288,17 @@ automation:
target:
entity_id: input_boolean.school_today_ran
- id: 59ae3bfe-5c58-4ff4-aaf5-7b76fd0ac442
alias: Start of School Year
initial_state: true
trigger:
- platform: template
value_template: "{{ states('sensor.school_start_days2go') | int == 1 }}"
action:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.school_in_session
- id: 05ee0f8d-5411-4486-8acf-9bfadad2b23a
alias: End of School Year
initial_state: true

View File

@@ -3,6 +3,53 @@ input_boolean:
name: Sports Updates
icon: mdi:strategy
input_datetime:
michigan_wolverines_start:
name: Michigan Wolverines Start
has_date: true
has_time: true
icon: mdi:football
ohio_state_buckeyes_start:
name: Ohio State Buckeyes Start
has_date: true
has_time: true
icon: mdi:football
toledo_rockets_start:
name: Toledo Rockets Start
has_date: true
has_time: true
icon: mdi:football
minnesota_vikings_start:
name: Minnesota Vikings Start
has_date: true
has_time: true
icon: mdi:football
san_francisco_49ers_start:
name: San Francisco 49ers Start
has_date: true
has_time: true
icon: mdi:football
minnesota_twins_start:
name: Minnesota Twins Start
has_date: true
has_time: true
icon: mdi:baseball
cleveland_guardians_start:
name: Cleveland Guardians Start
has_date: true
has_time: true
icon: mdi:baseball
los_angeles_dodgers_start:
name: Los Angeles Dodgers Start
has_date: true
has_time: true
icon: mdi:baseball
minnesota_wild_start:
name: Minnesota Wild Start
has_date: true
has_time: true
icon: mdi:hockey-puck
template:
- binary_sensor:
- name: Michigan Wolverines Inhibit
@@ -55,31 +102,31 @@ template:
state: >
{% from 'sports.jinja' import sports_today %}
{{ sports_today('sensor.san_francisco_49ers') }}
- name: Cleveland Guardians Inhibit
unique_id: b0980d47-d762-4f23-97b1-9e88da729d8f
state: >
{% from 'sports.jinja' import sports_inhibit %}
{{ sports_inhibit('sensor.cleveland_guardians') }}
- name: Cleveland Guardians Event Today
unique_id: 985a7b2c-9ebd-4a2e-8ee2-2ab5359310e0
state: >
{% from 'sports.jinja' import sports_today %}
{{ sports_today('sensor.cleveland_guardians') }}
- name: Minnesota Twins Inhibit
unique_id: 2987ae95-f55d-4994-b9dd-018278d2f5ad
state: >
{% from 'sports.jinja' import sports_inhibit %}
{{ state_attr('sensor.minnesota_twins','opponent_abbr') in ['CLE','LAD'] or sports_inhibit('sensor.minnesota_twins') }}
{{ sports_inhibit('sensor.minnesota_twins') }}
- name: Minnesota Twins Event Today
unique_id: 30055cb3-d259-4cef-90e1-7dea0a5cb439
state: >
{% from 'sports.jinja' import sports_today %}
{{ sports_today('sensor.minnesota_twins') }}
- name: Cleveland Guardians Inhibit
unique_id: b0980d47-d762-4f23-97b1-9e88da729d8f
state: >
{% from 'sports.jinja' import sports_inhibit %}
{{ state_attr('sensor.cleveland_guardians','opponent_abbr') in ['MIN','LAD'] or sports_inhibit('sensor.cleveland_guardians') }}
- name: Cleveland Guardians Event Today
unique_id: 985a7b2c-9ebd-4a2e-8ee2-2ab5359310e0
state: >
{% from 'sports.jinja' import sports_today %}
{{ sports_today('sensor.cleveland_guardians') }}
- name: Los Angeles Dodgers Inhibit
unique_id: 2c6aae6e-eff6-46e5-bee9-311f9bbc0c0e
state: >
{% from 'sports.jinja' import sports_inhibit %}
{{ state_attr('sensor.los_angeles_dodgers','opponent_abbr') in ['CLE'] or sports_inhibit('sensor.los_angeles_dodgers') }}
{{ state_attr('sensor.los_angeles_dodgers','opponent_abbr') in ['MIN'] or sports_inhibit('sensor.los_angeles_dodgers') }}
- name: Los Angeles Dodgers Event Today
unique_id: 7c2bd060-ea2c-4b81-8af7-3e6b9b3c639d
state: >

View File

@@ -63,48 +63,40 @@ 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"
- name: Tony Desktop Idle
unique_id: f0ace986-a874-4fb0-ad29-8f3ebf95d8cc
state: "{{ (states('sensor.tony_asus_system_idle_time') | int) > (states('input_number.basement_computers_idle_time') | int * 60) }}"
attributes:
idle_time: "{{ states('sensor.tony_asus_system_idle_time') | int }}s"
- name: Tina Desktop Idle
unique_id: 1933c638-c94b-468e-bb7a-c1c5b36c3651
state: "{{ (states('sensor.xia_desktop_system_idle_time') | int) > (states('input_number.first_floor_computers_idle_time') | int * 60) }}"
attributes:
idle_time: "{{ states('sensor.xia_desktop_system_idle_time') | int }}s"
- name: Kallen Desktop Idle
unique_id: 680c6ae3-2ed2-451e-858b-2aee688af461
state: "{{ (states('sensor.kallen_desktop_system_idle_time') | int) > (states('input_number.basement_computers_idle_time') | int * 60) }}"
attributes:
idle_time: "{{ states('sensor.kallen_desktop_system_idle_time') | int }}s"
- name: Asus Laptop Idle
unique_id: 7d8eb80a-0a2e-48a9-84b3-33175304dd95
state: "{{ states('sensor.asus_laptop_system_idle_time') | int > 1800 }}"
attributes:
idle_time: "{{ states('sensor.asus_laptop_system_idle_time') }}s"
- sensor:
- name: "Min Ping"
unique_id: ddcb9f6f-7c94-41fe-9453-2a2205b078e0

View File

@@ -7,12 +7,30 @@ input_boolean:
work_today_extended:
name: Work Today Extended
icon: mdi:briefcase-plus
tina_morning_meds_reminder:
name: Tina Morning Meds Reminder
icon: mdi:medication
tina_morning_meds_taken:
name: Tina Morning Meds Taken
icon: mdi:medication
tina_night_meds_reminder:
name: Tina Night Meds Reminder
icon: mdi:medication
tina_night_meds_taken:
name: Tina Night Meds Taken
icon: mdi:medication
tina_ibuprofen_active:
name: Tina Ibuprofen Active
icon: mdi:medication
tina_ibuprofen_taken:
name: Tina Ibuprofen Taken
icon: mdi:medication
tina_tylenol_active:
name: Tina Tylenol Active
icon: mdi:medication
tina_tylenol_taken:
name: Tina Tylenol Taken
icon: mdi:medication
tina_awake:
name: Tina Awake
icon: mdi:eye-check
@@ -35,7 +53,7 @@ input_datetime:
icon: mdi:medication
tina_morning_meds_notify:
name: Tina Morning Meds Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tina_night_meds_taken:
@@ -45,7 +63,27 @@ input_datetime:
icon: mdi:medication
tina_night_meds_notify:
name: Tina Night Meds Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tina_ibuprofen_taken:
name: Tina Ibuprofen Taken
has_date: true
has_time: true
icon: mdi:medication
tina_ibuprofen_notify:
name: Tina Ibuprofen Notify
has_date: true
has_time: true
icon: mdi:medication
tina_tylenol_taken:
name: Tina Tylenol Taken
has_date: true
has_time: true
icon: mdi:medication
tina_tylenol_notify:
name: Tina Tylenol Notify
has_date: true
has_time: true
icon: mdi:medication
@@ -103,78 +141,6 @@ automation:
data:
reason: "{{ reason }}"
- id: 513e33b8-a236-474b-a9cc-e40af36a052d
alias: Tina Meds Handler
description: Make sure Tina has taken her meds in the morning and at night
mode: parallel
max: 4
trigger:
- platform: time
at: input_datetime.tina_morning_meds_notify
id: wakeup
- platform: state
entity_id: input_boolean.tina_morning_meds_taken
to: 'on'
id: boolean-morning
- platform: time
at: input_datetime.tina_night_meds_notify
id: sleep
- platform: state
entity_id: input_boolean.tina_night_meds_taken
to: 'on'
id: boolean-night
action:
- choose:
- conditions:
- condition: and
conditions:
- condition: trigger
id: wakeup
- condition: state
entity_id: input_boolean.tina_morning_meds_taken
state: 'off'
sequence:
- service: script.turn_on
target:
entity_id: script.tina_morning_meds
- conditions:
- condition: trigger
id: boolean-morning
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.tina_morning_meds_taken
data:
datetime: >
{% from 'time.jinja' import current_time %}
{{ current_time('datetime',24) }}
- conditions:
- condition: and
conditions:
- condition: trigger
id: sleep
- condition: state
entity_id: input_boolean.tina_night_meds_taken
state: 'off'
- condition: state
entity_id: input_boolean.master_bedroom_sleeping
state: 'off'
sequence:
- service: script.turn_on
target:
entity_id: script.tina_night_meds
- conditions:
- condition: trigger
id: boolean-night
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.tina_night_meds_taken
data:
datetime: >
{% from 'time.jinja' import current_time %}
{{ current_time('datetime',24) }}
script:
tina_work_today:
alias: 'Tina Work Today'
@@ -263,165 +229,3 @@ script:
- service: script.master_bedroom_scheduling_evening
- service: script.emma_bedroom_scheduling_evening
- service: script.security_scheduling
tina_morning_meds:
alias: 'Tina Morning Meds'
icon: mdi:medication
mode: restart
sequence:
- service: script.text_notify
data:
who: tina
type: alert
title: Morning Meds
message: You need to take your morning meds
tag: tina-morning-meds
actions:
- action: "TINA_MORNING_MEDS_TAKEN"
title: Taken
- action: "TINA_MORNING_MEDS_SKIPPED"
title: Skip
- action: "TINA_MORNING_MEDS_ASK_LATER"
title: Ask Later
- wait_for_trigger:
- platform: event
event_type: ios.notification_action_fired
event_data:
actionName: "TINA_MORNING_MEDS_TAKEN"
id: taken
- platform: event
event_type: ios.notification_action_fired
event_data:
actionName: "TINA_MORNING_MEDS_SKIPPED"
id: skipped
- platform: event
event_type: ios.notification_action_fired
event_data:
actionName: "TINA_MORNING_MEDS_ASK_LATER"
id: ask-later
- platform: state
entity_id: person.christina_stork
from: 'home'
id: left
- platform: state
entity_id: input_boolean.tina_morning_meds_taken
to: 'on'
id: manual
timeout: "00:30:00"
continue_on_timeout: true
- choose:
- conditions: "{{ wait.trigger.id in ['taken','manual'] }}"
sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.tina_morning_meds_taken
- conditions: "{{ wait.trigger.id == 'ask-later' }}"
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.tina_morning_meds_notify
data:
datetime: >
{% from 'time.jinja' import set_datetime %}
{{ set_datetime(0,30) }}
- conditions: "{{ wait.trigger.id == 'left' }}"
sequence:
- service: script.text_notify
data:
who: tina
type: alert
title: HEY DUMBASS
message: YOU FORGOT TO TAKE YOUR MORNING MEDS!!!!!
- conditions: "{{ wait.trigger == 'none' or wait.trigger.idx is undefined }}"
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.tina_morning_meds_notify
data:
datetime: >
{% from 'time.jinja' import set_datetime %}
{{ set_datetime(0,1) }}
- service: script.text_notify
data:
type: alert
who: tina
message: clear_notification
tag: tina-morning-meds
tina_night_meds:
alias: 'Tina Night Meds'
icon: mdi:medication
mode: restart
sequence:
- service: script.text_notify
data:
who: tina
type: alert
title: Night Meds
message: You need to take your night meds
tag: tina-night-meds
actions:
- action: "TINA_NIGHT_MEDS_TAKEN"
title: Taken
- action: "TINA_NIGHT_MEDS_SKIPPED"
title: Skip
- action: "TINA_NIGHT_MEDS_ASK_LATER"
title: Ask Later
- wait_for_trigger:
- platform: event
event_type: ios.notification_action_fired
event_data:
actionName: "TINA_NIGHT_MEDS_TAKEN"
id: taken
- platform: event
event_type: ios.notification_action_fired
event_data:
actionName: "TINA_NIGHT_MEDS_SKIPPED"
id: skipped
- platform: event
event_type: ios.notification_action_fired
event_data:
actionName: "TINA_NIGHT_MEDS_ASK_LATER"
id: ask-later
- platform: state
entity_id: input_boolean.tina_night_meds_taken
to: 'on'
id: manual
- platform: state
entity_id:
- input_boolean.master_bedroom_sleeping
- input_boolean.goodnight
to: 'on'
id: sleeping
timeout: "00:30:00"
continue_on_timeout: true
- choose:
- conditions: "{{ wait.trigger.id in ['taken','manual'] }}"
sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.tina_night_meds_taken
- conditions: "{{ wait.trigger.id == 'ask-later' }}"
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.tina_night_meds_notify
data:
datetime: >
{% from 'time.jinja' import set_datetime %}
{{ set_datetime(0,30) }}
- conditions: "{{ wait.trigger == 'none' or wait.trigger.idx is undefined }}"
sequence:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.tina_night_meds_notify
data:
datetime: >
{% from 'time.jinja' import set_datetime %}
{{ set_datetime(0,1) }}
- service: script.text_notify
data:
type: alert
who: tina
message: clear_notification
tag: tina-night-meds

View File

@@ -4,12 +4,21 @@ input_boolean:
tony_streaming_today:
name: Tony Streaming Today
icon: mdi:twitch
tony_morning_meds_reminder:
name: Tony Morning Meds Reminder
icon: mdi:medication
tony_morning_meds_taken:
name: Tony Morning Meds Taken
icon: mdi:medication
tony_afternoon_meds_reminder:
name: Tony Afternoon Meds Reminder
icon: mdi:medication
tony_afternoon_meds_taken:
name: Tony Afternoon Meds Taken
icon: mdi:medication
tony_night_meds_reminder:
name: Tony Night Meds Reminder
icon: mdi:medication
tony_night_meds_taken:
name: Tony Night Meds Taken
icon: mdi:medication
@@ -64,17 +73,17 @@ input_datetime:
icon: mdi:medication
tony_morning_meds_notify:
name: Tony Morning Meds Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tony_afternoon_meds_notify:
name: Tony Afternoon Meds Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tony_night_meds_notify:
name: Tony Night Meds Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tony_custom_meds_taken_p1:
@@ -84,7 +93,7 @@ input_datetime:
icon: mdi:medication
tony_custom_meds_notify_p1:
name: Tony Custom Meds Notify P1
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tony_custom_meds_taken_p2:
@@ -94,7 +103,7 @@ input_datetime:
icon: mdi:medication
tony_custom_meds_notify_p2:
name: Tony Custom Meds Notify P2
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tony_ibuprofen_taken:
@@ -104,7 +113,7 @@ input_datetime:
icon: mdi:medication
tony_ibuprofen_notify:
name: Tony Ibuprofen Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
tony_tylenol_taken:
@@ -114,7 +123,7 @@ input_datetime:
icon: mdi:medication
tony_tylenol_notify:
name: Tony Tylenol Notify
has_date: false
has_date: true
has_time: true
icon: mdi:medication
@@ -178,4 +187,34 @@ sensor:
json_attributes:
- project
- items
scan_interval: 30
scan_interval: 30
# template:
# - binary_sensor:
# - name: Tony Morning Meds Needed
# unique_id: 32f2f158-8c59-486e-bf85-f14909375ff7
# state: >
# {% set ct = as_timestamp(now()) %}
# {% set notify = state_attr('input_datetime.tony_morning_meds_notify','timestamp') %}
# {{ (ct >= notify) and is_state('input_boolean.tony_morning_meds_taken','off') }}
# attributes:
# reminder_time: "{{ states('input_datetime.tony_morning_meds_notify') }}"
# icon: mdi:medication
# - name: Tony Afternoon Meds Needed
# unique_id: 363b5ea0-3ad7-4e98-b0b0-5ff67bbef2f4
# state: >
# {% set ct = as_timestamp(now()) %}
# {% set notify = state_attr('input_datetime.tony_afternoon_meds_notify','timestamp') %}
# {{ (ct >= notify) and is_state('input_boolean.tony_afternoon_meds_taken','off') }}
# attributes:
# reminder_time: "{{ states('input_datetime.tony_afternoon_meds_notify') }}"
# icon: mdi:medication
# - name: Tony Night Meds Needed
# unique_id: b927b5a4-27a7-42aa-af4e-fa37a7036d25
# state: >
# {% set ct = as_timestamp(now()) %}
# {% set notify = state_attr('input_datetime.tony_night_meds_notify','timestamp') %}
# {{ (ct >= notify) and is_state('input_boolean.tony_night_meds_taken','off') }}
# attributes:
# reminder_time: "{{ states('input_datetime.tony_night_meds_notify') }}"
# icon: mdi:medication

View File

@@ -1617,7 +1617,6 @@ script:
# snapshot_entities:
# - light.tina_lamp_side
# - light.tina_lamp_top
# - light.tina_desk_strip
# - switch.adaptive_lighting_living_room
# - switch.adaptive_lighting_tina_lamp
# - service: switch.turn_off
@@ -1631,7 +1630,6 @@ script:
# entity_id:
# - light.tina_lamp_side
# - light.tina_lamp_top
# - light.tina_desk_strip
# data:
# color_name: red
# - service: script.living_room_lights_alert

View File

@@ -2,11 +2,9 @@ # Tony's Home Assistant Configs
Just a place to track my work on my personal Home Assistant configuration, and learn as I go. Maybe also TRY to keep myself a little bit more organized ;)
## New location for Node-RED flows
## Node-RED flows
I have recently started using the Node-RED Projects feature, which makes version control for my flows a LOT easier than it was before.
With this change, the Node-RED flows are now in their own repo. They can be found at [HA-NerdFlows](https://github.com/tm24fan8/HA-NerdFlows).
My Node-RED flows can be found at [HA-NerdFlows](https://gitea.nerdhomeinc.com/home_automation/HA-NerdFlows). Additionally, code used in function nodes in my Node-RED flows can be found at [HA-NerdFlows-Functions](https://gitea.nerdhomeinc.com/home_automation/HA-NerdFlows-Functions).
## Attributions
@@ -34,7 +32,6 @@ ## HACS Components
- [Node-RED Companion](https://github.com/zachowj/hass-node-red)
- [Holidays](https://github.com/bruxy70/Holidays)
- [Twitch Helix](https://github.com/Radioh/ha_twitch_helix)
- [Local Tuya](https://github.com/rospogrigio/localtuya)
- [Pirate Weather](https://github.com/alexander0042/pirate-weather-ha)
- [Holidays](https://github.com/bruxy70/Holidays)
- [Thermal Comfort](https://github.com/dolezsa/thermal_comfort)
@@ -42,7 +39,7 @@ ## HACS Components
- [HASS.Agent Media Player](https://github.com/LAB02-Research/HASS.Agent-MediaPlayer)
- [Music Assistant](https://github.com/music-assistant/hass-music-assistant)
- [Blitzortung Lightning Detector](https://github.com/mrk-its/homeassistant-blitzortung)
- [Midea Air Conditioning](https://github.com/mill1000/midea-ac-py)
- [Midea Air Conditioning](https://github.com/wuwentao/midea_ac_lan)
- [WeatherAPI](https://github.com/iprak/weatherapi)
- [Browser Mod](https://github.com/thomasloven/hass-browser_mod)
- [Watchman](https://github.com/dummylabs/thewatchman)
@@ -50,13 +47,16 @@ ## HACS Components
- [PyScript](https://github.com/custom-components/pyscript)
- [Hass Animated Scenes](https://github.com/chazzu/hass-animated-scenes)
- [Jokes](https://github.com/LaggAt/ha-jokes)
- [Google Photos](https://github.com/Daanoz/ha-google-photos)
- [Uptime Kuma](https://github.com/meichthys/uptime_kuma)
- [Jellyfin](https://github.com/koying/jellyfin_ha)
- [Sonoff LAN](https://github.com/AlexxIT/SonoffLAN)
- [Powercalc](https://github.com/bramstroker/homeassistant-powercalc)
- [Govee LAN Control](https://github.com/wez/govee-lan-hass)
- [Discord Game](https://github.com/LordBoos/discord_game)
- [Versatile Thermostat](https://github.com/jmcollin78/versatile_thermostat)
- [GasBuddy](https://github.com/firstof9/ha-gasbuddy)
- [Union Pacific Big Boy Tracker](https://github.com/jheizer/up_4014_tracker)
- [WeatherFlow Forecast](https://github.com/briis/weatherflow_forecast)
</details>
@@ -67,65 +67,50 @@ ## HACS Lovelace Cards
<details>
<summary>Click here</summary>
- [Card Tools](https://github.com/thomasloven/lovelace-card-tools) (required for various other cards)
- [Bubble Card](https://github.com/Clooos/Bubble-Card) Backbone of the new mobile dashboard
- [Config Template Card](https://github.com/iantrich/config-template-card)
- [Streamline Card](https://github.com/brunosabot/streamline-card)
- [Layout Card](https://github.com/thomasloven/lovelace-layout-card)
- [Scheduler Card](https://github.com/nielsfaber/scheduler-card) (required for Scheduler component)
- [Horizon Card](https://github.com/rejuvenate/lovelace-horizon-card)
- [Lovelace Home Feed Card](https://github.com/gadgetchnnel/lovelace-home-feed-card)
- [Mini Graph Card](https://github.com/kalkih/mini-graph-card)
- [Battery State Card](https://github.com/maxwroc/battery-state-card)
- [Compass Card](https://github.com/tomvanswam/compass-card)
- [Flipdown Timer Card](https://github.com/pmongloid/flipdown-timer-card)
- [Atomic Calendar Revive](https://github.com/totaldebug/atomic-calendar-revive)
- [Plotly Graph Card](https://github.com/dbuezas/lovelace-plotly-graph-card)
- [Mushroom](https://github.com/piitaya/lovelace-mushroom)
- [Todoist Card](https://github.com/tm24fan8/todoist-card)
- [Apexcharts Card](https://github.com/RomRider/apexcharts-card)
- [Auto Entities Card](https://github.com/thomasloven/lovelace-auto-entities)
- [Header Cards](https://github.com/gadgetchnnel/lovelace-header-cards)
- [Plex Meets Home Assistant](https://github.com/JurajNyiri/PlexMeetsHomeAssistant)
- [Slider Button Card](https://github.com/custom-cards/slider-button-card)
- [Weather Radar Card](https://github.com/Makin-Things/weather-radar-card)
- [Platinum Weather Card](https://github.com/Makin-Things/platinum-weather-card) (Not currently in use, but VERY nicely done)
- [Stack In Card](https://github.com/custom-cards/stack-in-card)
- [Canary](https://github.com/jcwillox/lovelace-canary)
- [Paper Buttons Row](https://github.com/jcwillox/lovelace-paper-buttons-row)
- [State Switch](https://github.com/thomasloven/lovelace-state-switch)
- [Multiple Entity Row](https://github.com/benct/lovelace-multiple-entity-row)
- [Weather Card](https://github.com/bramkragten/weather-card)
- [Template Entity Row](https://github.com/thomasloven/lovelace-template-entity-row)
- [Config Template Card](https://github.com/iantrich/config-template-card)
- [Canvas Gauge Card](https://github.com/custom-cards/canvas-gauge-card)
- [Datetime Card](https://github.com/a-p-z/datetime-card)
- [Waze Travel Time](https://github.com/r-renato/ha-card-waze-travel-time)
- [Fold Entity Row](https://github.com/thomasloven/lovelace-fold-entity-row)
- [Slider Entity Row](https://github.com/thomasloven/lovelace-slider-entity-row)
- [Room Card](https://github.com/marcokreeft87/room-card)
- [Simple Thermostat Card](https://github.com/nervetattoo/simple-thermostat)
- [Clock Weather Card](https://github.com/pkissling/clock-weather-card)
- [Tabbed Card](https://github.com/kinghat/tabbed-card)
- [HA Team Tracker Card](https://github.com/vasqued2/ha-teamtracker-card)
- [Banner Card](https://github.com/nervetattoo/banner-card)
- [Lovelace Lock Card](https://github.com/CyrisXD/love-lock-card)
- [Card Templater](https://github.com/gadgetchnnel/lovelace-card-templater)
- [Energy Overview Card](https://github.com/Sese-Schneider/ha-energy-overview-card)
- [Button Card](https://github.com/custom-cards/button-card)
- [Number Box Card](https://github.com/htmltiger/numberbox-card)
- [Restriction Card](https://github.com/iantrich/restriction-card)
- [Timer Bar Card](https://github.com/rianadon/timer-bar-card)
- [Minimalistic Area Card](https://github.com/junalmeida/homeassistant-minimalistic-area-card)
- [Sankey Chart Card](https://github.com/MindFreeze/ha-sankey-chart)
- [Hourly Weather Card](https://github.com/decompil3d/lovelace-hourly-weather)
- [Formula One Card](https://github.com/marcokreeft87/formulaone-card)
- [UV Index Card](https://github.com/t1gr0u/uv-index-card)
- [Github Flexi Card](https://github.com/maxwroc/github-flexi-card)
- [Windrose Card](https://github.com/aukedejong/lovelace-windrose-card)
- [Swipe Card](https://github.com/bramkragten/swipe-card)
- [Meteoalarm Card](https://github.com/MrBartusek/MeteoalarmCard)
- [Bubble Card](https://github.com/Clooos/Bubble-Card)
- [Weather Chart Card](https://github.com/mlamberts78/weather-chart-card)
- [Twitch Followed Live Streams Card](https://github.com/stefmde/HomeAssistant-TwitchFollowedLiveStreamsCard)
- [Comfortable Environment Card](https://github.com/argaar/comfortable-environment-card)
- [Versatile Thermostat UI Card](https://github.com/jmcollin78/versatile-thermostat-ui-card)
</details>
@@ -138,6 +123,16 @@ ## AppDaemon Apps
</details>
## Custom Jinja2 Templates/Macros
<details>
<summary>Click here</summary>
- [Easy Time](https://github.com/Petro31/easy-time-jinja)
- [Relative Time](https://github.com/TheFes/relative-time-plus)
</details>
## Themes/Icons
<details>
@@ -149,5 +144,6 @@ ## Themes/Icons
- [BHA Icon Pack](https://github.com/hulkhaugen/hass-bha-icons)
- [Custom Icons Library](https://github.com/Mariusthvdb/custom-icons)
- [FontAwesome](https://github.com/thomasloven/hass-fontawesome)
- [Material Symbols](https://github.com/beecho01/material-symbols)
</details>

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:

File diff suppressed because it is too large Load Diff

View File

@@ -68,7 +68,6 @@
states.light.downstairs_bathroom_right,
states.light.tina_lamp_top,
states.light.tina_lamp_side,
states.light.tina_desk_strip,
states.light.basement_tall_lamp,
states.light.basement_short_lamp,
states.light.basement_stairwell,
@@ -103,7 +102,6 @@
states.light.downstairs_bathroom_right,
states.light.tina_lamp_top,
states.light.tina_lamp_side,
states.light.tina_desk_strip
] %}
{{ lights | selectattr('state','eq','on') | list | count | int }}
- name: Second Floor Lights On
@@ -170,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 }}
@@ -179,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 }}
@@ -198,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

@@ -6,6 +6,7 @@
{% from 'speech.jinja' import greeting, today_is, sun_status %}
{% from 'weather.jinja' import weatherReport %}
{% from 'sports.jinja' import sports_updates %}
{% from 'server.jinja' import services_down %}
<p>
{{ greeting('date') }}
</p>
@@ -22,10 +23,7 @@
</p>
<p>
There are {{ states('sensor.services_down') }} services currently offline.
{% if states('sensor.services_down') | int > 0 %}
They are {{ state_attr('sensor.services_down','services') }}.
{% endif %}
{{ services_down() }}
</p>
<p>

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

@@ -3,7 +3,7 @@
{% from 'formatting.jinja' import cleanup %}
{%- macro getReport() -%}
{% from 'speech.jinja' import greeting, dadjoke, inspirational_quote, today_is %}
{% from 'status.jinja' import tony_status_report, tina_status_report, kallen_status_report, emma_status_report %}
{% from 'status.jinja' import tony_status_report, tina_status_report, kallen_status_report, emma_status_report, morning_annc %}
{% from 'easy_time.jinja' import count_the_days %}
{% from 'weather.jinja' import weatherReport %}
{% from 'sports.jinja' import sports_updates %}
@@ -14,6 +14,10 @@
{{ today_is() }}
</p>
<p>
{{ morning_annc('full','tts') }}
</p>
<p>
{{ weatherReport('full','tts','morning') }}
</p>

View File

@@ -61,20 +61,24 @@
{% endif %}
{% endif %}
{% if is_state('input_boolean.kallen_overnight','off') %}
{% if not is_state('input_select.scheduled_climate_mode_kallen_fan','N/A') %}
{% if is_state('input_select.scheduled_climate_mode_kallen_fan','Fan') and is_state('fan.kallen_bedroom_fan','off') %}
{% if not is_state('input_select.scheduled_climate_mode_kallen_bedroom','N/A') %}
{% if is_state('input_select.scheduled_climate_mode_kallen_bedroom','Fan') and is_state('fan.kallen_bedroom_fan','off') %}
"Collin's fan will activate at {{ input_datetime_read('input_datetime.kallen_fan') }}. "
{% elif is_state('input_select.scheduled_climate_mode_kallen_fan','White Noise') and is_state('input_boolean.white_noise_kallen_bedroom','off') %}
{% elif is_state('input_select.scheduled_climate_mode_kallen_bedroom','White Noise') and is_state('input_boolean.white_noise_kallen_bedroom','off') %}
"Collin's white noise generator will activate at {{ input_datetime_read('input_datetime.kallen_bedtime') }}. "
{% endif %}
{% endif %}
{% 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_aircon') != 'N/A' %}
{% if is_state('input_select.scheduled_climate_mode_emma_aircon','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') }}. "
{% elif is_state('input_select.scheduled_climate_mode_emma_aircon','White Noise') and is_state('input_boolean.white_noise_emma_bedroom','off') %}
{% 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 %}
{% endif %}

View File

@@ -75,28 +75,39 @@
<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. "
{% 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. "
{% elif is_state('climate.master_bedroom_aircon','fan_only') %}
"and the master bedroom air conditioner is in fan only mode. "
{% elif is_state('climate.master_bedroom_aircon','dry') %}
"and the master bedroom air conditioner is moonlighting as a dehumidifier. "
{% elif is_state('climate.master_bedroom_aircon','auto') %}
"and the master bedroom air conditioner is making its own decisions. Be afraid, be very afraid. "
{% else %}
"and the master bedroom air conditioner is currently not speaking to me. Was it something I said? "
{% endif %}
{% if is_state('input_boolean.master_bedroom_aircon_installed','on') %}
"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. "
{% elif is_state('climate.master_bedroom_aircon','fan_only') %}
"and the master bedroom air conditioner is in fan only mode. "
{% elif is_state('climate.master_bedroom_aircon','dry') %}
"and the master bedroom air conditioner is moonlighting as a dehumidifier. "
{% elif is_state('climate.master_bedroom_aircon','auto') %}
"and the master bedroom air conditioner is making its own decisions. Be afraid, be very afraid. "
{% else %}
"and the master bedroom air conditioner is currently not speaking to me. Was it something I said? "
{% 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') }}. "
{% endif %}
{% endif %}
{% endif %}
{% 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>
<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 %}

View File

@@ -0,0 +1,429 @@
# Bubble Modules
#
# How to use:
#
# - To edit or add modules (global styles and templates), first copy the
# "bubble-modules.yaml" file from "/www/community/Bubble-Card/" (if installed via HACS)
# to "/www/bubble/" (you'll need to create this folder).
#
# Then add these lines in your "configuration.yaml" under "homeassistant:":
#
# homeassistant:
# allowlist_external_dirs:
# - /config/www/bubble
# # This step is not needed if you already have this line:
# - /config/www
#
# Then save and restart Home Assistant.
#
# - After making changes, you need to refresh your page to apply the modifications.
#
# - Styles and templates defined under "default:" are applied globally to all cards by default.
#
# - See the final example in this file for further details on how to create a module.
#
# - You can share/find modules here:
# github.com/Clooos/Bubble-Card/discussions/categories/share-your-modules
default:
name: Default
description: Empty and enabled by default. Move your styles/templates here in the <code>bubble-modules.yaml</code> file to apply them to all cards.
code: |
/* CSS or JS templates (see examples below) */
home-assistant-default:
name: Home Assistant default styling
version: "v1.1"
creator: "Clooos"
link: "https://github.com/Clooos/Bubble-Card/discussions/1230"
description: This module applies Home Assistants default styling to Bubble Card. To set it as the default, move it under <code>default:</code> in the <code>bubble-modules.yaml</code> file.
code: |
:host {
--bubble-button-accent-color: rgba(0,140,255,0.3); /* Edit this color if needed */
--bubble-main-background-color: var(--ha-card-background, var(--card-background-color, #fff));
--bubble-border-radius: var(--ha-card-border-radius, 12px);
--bubble-icon-border-radius: 32px;
--bubble-button-border-radius: var(--bubble-border-radius);
--bubble-climate-button-background-color: var(--bubble-icon-background-color);
--bubble-border: var(--ha-card-border-width, 1px) solid var(--ha-card-border-color, var(--divider-color, #e0e0e0));
--bubble-secondary-background-color: transparent;
}
.bubble-container {
-webkit-backdrop-filter: var(--ha-card-backdrop-filter, none);
backdrop-filter: var(--ha-card-backdrop-filter, none);
box-shadow: var(--ha-card-box-shadow, none);
box-sizing: border-box;
}
.bubble-icon-container,
.large .bubble-icon-container {
--mdc-icon-size: 22px;
min-width: 36px !important;
min-height: 36px !important;
}
.large .bubble-cover-card-container > .bubble-buttons {
--bubble-cover-main-background-color: none;
}
.bubble-range-fill {
--bubble-accent-color: var(--bubble-button-accent-color);
}
.bubble-sub-button.background-on::before,
.bubble-sub-button.background-off::before,
.bubble-temperature-container::before,
.bubble-icon-container::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: var(--control-number-buttons-background-opacity, .2);
border-radius: var(--bubble-border-radius);
background: var(--control-number-buttons-background-color, var(--disabled-color));
}
.is-on {
--bubble-icon-background-color: var(--view-background,var(--lovelace-background,var(--primary-background-color)));
transition: all ease-in 0.3s !important;
}
.bubble-icon-container::before {
background: var(--state-inactive-color);
border-radius: var(--bubble-icon-border-radius);
}
.bubble-sub-button {
border: 0px solid transparent !important;
}
.no-icon-select-arrow {
right: 4px !important;
}
.large .bubble-icon-container {
margin-left: 9px;
}
.bubble-state {
opacity: 1;
font-weight: 400;
font-size: 12px;
letter-spacing: .4px;
}
:not(.bubble-separator) > .bubble-name {
font-weight: 500;
font-size: 14px;
letter-spacing: 0.1px;
}
.bubble-pop-up-background {
filter: brightness(0.96); /* Improve pop-up background contrast */
--bubble-pop-up-border-radius: calc(var(--ha-card-border-radius, 12px) * 1.4);
}
.bubble-header-container {
--bubble-secondary-background-color: var(--background-color-2);
}
ha-select {
--bubble-list-item-accent-color: none !important;
--mdc-theme-surface: var(--card-background-color);
}
mwc-list-item[selected] {
color: inherit !important;
--mdc-ripple-press-opacity: 0 !important;
}
mwc-list-item[selected]::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--primary-color);
opacity: 0.24;
}
icon_container_color:
name: "Example: Customize the icon container color"
version: "v1.1"
creator: "Clooos"
link: "https://github.com/Clooos/Bubble-Card/discussions/1231"
unsupported:
- horizontal-buttons-stack
- separator
description: |
A list of predefined colors to customize the icon container color.
Configure this module via the editor or in YAML, for example:
<br><br>
<code-block><pre>
icon_container_color:
color: light-blue
</pre></code-block>
code: |
.bubble-icon-container {
opacity: 1 !important;
background: var(--${this.config.icon_container_color?.color}-color) !important;
}
editor:
- name: color
label: "Color"
selector:
ui_color:
include_none: true
get_state_attribute:
# Some informations about your module (this is shown in the editor)
name: "Advanced example: Get state/attribute from other entities"
version: "v1.1"
creator: "Clooos"
link: "https://github.com/Clooos/Bubble-Card"
# Disable this module for unsupported "card_type"
unsupported:
- horizontal-buttons-stack
- separator
# The description have HTML support like in this example. This model is my favorite.
description: |
Get state/attribute from other entities and replace the default state/attribute field.
<img class="example" src="https://github.com/Clooos/Bubble-Card/blob/main/img/get_state_template_example.png?raw=true" />
Configure this module via the editor or in YAML, for example:
<br><br>
<code-block><pre>
get_state_attribute:
- entity: weather.home
- entity: sensor.weather_station
attribute: humidity
- entity: sensor.weather_station
attribute: temperature
</pre></code-block>
<br>
<b>If it doesn't work, make sure at least one of "Show state" or "Show attribute" is turned on in your card configuration.</b>
# Code blocks must always start with ${(() => { and end with })()}
# Inline codes must always start with ${ and end with }
#
# This section only supports JavaScript and/or CSS
code: |
${(() => {
// Retrieve the configuration or use an empty array by default
const config = this.config.get_state_attribute || [];
// Format the retrieved value from the entity for each entry
const values = config
.map(cfg => {
const entity = hass.states[cfg.entity];
if (entity) {
return cfg.attribute
? hass.formatEntityAttributeValue(entity, cfg.attribute)
: hass.formatEntityState(entity);
}
return null;
})
.filter(value => value !== null); // Remove null values
// Update the DOM element with the class 'bubble-state'
// displaying values separated by ' • '
card.querySelector('.bubble-state').innerText = values.join(' • ');
})()}
# The editor part can be tricky, but improves modules a lot!
#
# In this example, it will create your configuration to this variable:
# this.config.get_state_attribute
#
# To understand what you can do here, take a look at the "ha-form" sources here:
# https://github.com/home-assistant/frontend/tree/03a415beff6e6f9c87a95287804f6c03c8fef3d5/src/components/ha-form
#
# And here for the selectors:
# https://github.com/home-assistant/frontend/blob/03a415beff6e6f9c87a95287804f6c03c8fef3d5/src/data/selector.ts
#
# I will try to document that for clarity!
editor:
- type: expandable
title: "Select entities and attributes"
icon: "mdi:list-box-outline"
schema:
- name: '0'
type: expandable
title: "Entity 1"
schema:
- name: entity
label: "Entity"
selector:
entity: {}
- name: attribute
label: "Attribute"
selector:
attribute: {}
- name: '1'
type: expandable
title: "Entity 2"
schema:
- name: entity
label: "Entity"
selector:
entity: {}
- name: attribute
label: "Attribute"
selector:
attribute: {}
- name: '2'
type: expandable
title: "Entity 3"
schema:
- name: entity
label: "Entity"
selector:
entity: {}
- name: attribute
label: "Attribute"
selector:
attribute: {}
- name: '3'
type: expandable
title: "Entity 4"
schema:
- name: entity
label: "Entity"
selector:
entity: {}
- name: attribute
label: "Attribute"
selector:
attribute: {}
# Temperature
temperature_colouring:
name: "Temperature colouring"
version: "v1.0"
creator: "Timmy"
unsupported:
- horizontal-buttons-stack
- media-player
description: |
This module provides dynamic colouring based on temperature sensor values.
Colour adjustments are applied to selected sub-buttons and/or state display elements.
Required entities:
- A temperature sensor
You can configure which elements should receive dynamic colouring:
- Sub-buttons (1-6)
- State display
Example YAML configuration:
temperature_colouring:
temperature_sensor: sensor.kitchen_temperature
elements:
sub_buttons: [1, 3, 5] # Apply to sub-buttons 1, 3, and 5
state_display: true # Apply to state display element
code: |
${(() => {
const temperature = parseFloat(hass?.states[this.config?.temperature_colouring?.temperature_sensor]?.state || 0);
const elements = this.config?.temperature_colouring?.elements || {};
let color;
if (temperature <= 32) {
color = 'rgba(0,0,139,0.8)';
} else if (temperature <= 41) {
color = 'rgba(0,71,171,0.8)';
} else if (temperature <= 50) {
color = 'rgba(30,144,255,0.8)';
} else if (temperature <= 61) {
color = 'rgba(100,149,237,0.8)';
} else if (temperature <= 68) {
color = 'rgba(60,179,113,0.8)';
} else if (temperature <= 73) {
color = 'rgba(152,251,152,0.8)';
} else if (temperature <= 78) {
color = 'rgba(255,223,186,0.8)';
} else if (temperature <= 80) {
color = 'rgba(255,215,0,0.8)';
} else if (temperature <= 95) {
color = 'rgba(178,34,34,0.8)';
} else {
color = 'rgba(139,0,0,0.8)';
}
// Apply colour to selected sub-buttons
if (elements.sub_buttons) {
const subButtons = Array.isArray(elements.sub_buttons) ? elements.sub_buttons : [];
subButtons.forEach(num => {
if (num >= 1 && num <= 6) {
const subButton = card?.querySelector(`.bubble-sub-button-${num} ha-icon`);
if (subButton) {
subButton.style.color = color;
}
}
});
}
// Apply colour to state display if enabled
if (elements.state_display) {
const stateElement = card?.querySelector('.bubble-state.state.display-state');
if (stateElement) {
stateElement.style.color = color;
}
}
return ''; // No CSS needed as we're applying styles directly to elements
})()}
editor:
- type: expandable
title: "Entity Configuration"
icon: "mdi:thermometer"
schema:
- name: temperature_sensor
label: "Temperature Sensor (Required)"
selector:
entity:
device_class: temperature
required: true
- name: elements
type: grid
schema:
- name: sub_buttons
label: "Sub-buttons to Style"
selector:
select:
multiple: true
options:
- label: "Sub-button 1"
value: 1
- label: "Sub-button 2"
value: 2
- label: "Sub-button 3"
value: 3
- label: "Sub-button 4"
value: 4
- label: "Sub-button 5"
value: 5
- label: "Sub-button 6"
value: 6
- name: state_display
label: "State Display"
selector:
boolean: {}