Compare commits

..

29 Commits

Author SHA1 Message Date
034419f954 Turn off wife's night meds when she gets to work #243 2025-07-13 21:43:36 -04:00
f5953d23e6 Remove Main Button State Red as no longer used 2025-07-13 21:42:01 -04:00
473526390e Updated readme 2025-07-09 17:01:02 -04:00
a5a9d081d2 Early stages of a rotating icon module 2025-07-08 06:52:34 -04:00
0f25ce6f6a State Color Button module 2025-07-08 03:56:47 -04:00
eced9a763e Update .gitignore 2025-07-07 22:25:16 -04:00
5331c0d08a Popup timer bubble card module 2025-07-07 21:57:54 -04:00
c9e4a11604 Fix VSCode throwing a fit about no backticks 2025-07-07 21:32:42 -04:00
d55ad66264 Restructure bubble card modules folder 2025-07-07 20:57:47 -04:00
d56d899588 More bubble card modules 2025-07-07 18:23:26 -04:00
6afb3b7cb7 Main button state red now applies styles directly to DOM elements 2025-07-07 17:31:56 -04:00
e2ea214832 New modules I wrote for bubble cards 2025-07-07 05:06:06 -04:00
b1543676d5 Experimenting with trend sensor for local average gas price trends 2025-07-07 05:05:49 -04:00
bc45d6b7fd Update .HA_VERSION 2025-07-07 05:05:11 -04:00
1a706153a8 Fix handling of MLB rain delays, close #252 2025-06-26 17:27:26 -04:00
95b2c8cfc5 Update .HA_VERSION 2025-06-26 17:27:02 -04:00
61b04c05c6 Update time macros 2025-06-15 18:13:55 -04:00
41141e94df Add entity to denote ongoing server maintenance 2025-06-15 17:44:07 -04:00
cc9ec0b211 Update .HA_VERSION 2025-06-15 17:43:46 -04:00
adf881a106 Adjust scheduling to help K's room when it's hot upstairs 2025-06-13 20:09:52 -04:00
6ee298a3d2 Update .HA_VERSION 2025-06-13 20:09:35 -04:00
aa6358ce19 Merge branch 'sunset-rework' into dev 2025-05-29 17:32:50 -04:00
abe62888b2 Add outdoor lux threshold and triggered boolean for sunset lights
home_automation/HA-NerdFlows#32
2025-05-27 21:26:24 -04:00
0cabab0462 Adjustments to Recliner Mode 2025-05-26 00:01:21 -04:00
034cf2f972 Adaptive lighting should reset after tornado warnings #229 2025-05-25 19:22:25 -04:00
1d246e8018 Use locally calculated SLP in template weather provider 2025-05-24 20:17:12 -04:00
5cffb7208f Add rain intensity awareness to weather briefings
#247
2025-05-23 20:57:04 -04:00
a7b1a53754 Fix storm warning code I apparently wrote in my sleep... 2025-05-23 20:56:40 -04:00
de5efd39b4 Update .HA_VERSION 2025-05-23 20:56:02 -04:00
34 changed files with 988 additions and 72 deletions

View File

@ -1 +1 @@
2025.5.2 2025.7.1

1
.gitignore vendored
View File

@ -20,6 +20,7 @@
/glances/ /glances/
/downloads/ /downloads/
/lightwand/ /lightwand/
/bubble/Scratchpad/
# ignore any of these files no matter where they are using double * # ignore any of these files no matter where they are using double *
**.DS_Store **.DS_Store

View File

@ -1869,54 +1869,70 @@
to: 'on' to: 'on'
id: recliner-on id: recliner-on
trigger: state trigger: state
alias: Recliner Mode On
- entity_id: input_boolean.recliner_mode - entity_id: input_boolean.recliner_mode
from: 'on' from: 'on'
to: 'off' to: 'off'
id: recliner-off id: recliner-off
trigger: state trigger: state
alias: Recliner Mode Off
conditions: [] conditions: []
actions: actions:
- choose: - alias: Routing
choose:
- conditions: - conditions:
- condition: trigger - condition: trigger
id: recliner-on id: recliner-on
alias: Recliner Mode On
sequence: sequence:
- target: - target:
entity_id: input_select.basement_studio_scenes entity_id: input_select.basement_studio_scenes
data: data:
option: Stairwell option: Stairwell
action: input_select.select_option action: input_select.select_option
alias: Set scene to Stairwell
- target: - target:
entity_id: entity_id:
- input_boolean.white_noise_basement - input_boolean.white_noise_basement
- input_boolean.studio_quiet - input_boolean.studio_quiet
data: {} data: {}
action: input_boolean.turn_on action: input_boolean.turn_on
- if: alias: Turn on white noise and Studio Quiet
- alias: Turn off TV
if:
- condition: template - condition: template
value_template: "{% if is_state('media_player.basement_tv','playing') %}\n value_template: "{% if is_state('media_player.basement_tv','playing') %}\n
\ false\n{% elif is_state('media_player.basement_tv','paused') or is_state('media_player.basement_tv','idle') \ false\n{% elif is_state('media_player.basement_tv','paused') or is_state('media_player.basement_tv','idle')
%}\n {{ state_attr('media_player.basement_tv','app_name') in ['TV','Android %}\n {{ state_attr('media_player.basement_tv','app_name') in ['TV','Android
TV Launcher'] }}\n{% else %}\n false\n{% endif %}\n" TV Launcher'] }}\n{% else %}\n false\n{% endif %}\n"
alias: If nothing is playing
then: then:
- target: - target:
entity_id: media_player.basement_tv entity_id: media_player.basement_tv
data: {} data: {}
action: media_player.turn_off action: media_player.turn_off
- if: alias: Turn off TV
- condition: not enabled: false
- alias: Turn off computer monitors
if:
- alias: If I'm not watching something
condition: not
conditions: conditions:
- condition: state - condition: state
entity_id: media_player.tony_asus entity_id: media_player.tony_asus
state: playing state: playing
alias: PC playing video or music
then: then:
- target: - target:
entity_id: script.tony_desktop_displays_off entity_id: script.tony_desktop_displays_off
data: {} data: {}
action: script.turn_on action: script.turn_on
alias: Turn off computer monitors
enabled: false
- conditions: - conditions:
- condition: trigger - condition: trigger
id: recliner-off id: recliner-off
alias: Recliner Mode Off
sequence: sequence:
- data: {} - data: {}
target: target:
@ -2046,10 +2062,12 @@
- script.tony_desktop_displays_on - script.tony_desktop_displays_on
data: {} data: {}
action: script.turn_on action: script.turn_on
enabled: false
- target: - target:
entity_id: media_player.basement_tv entity_id: media_player.basement_tv
data: {} data: {}
action: media_player.turn_on action: media_player.turn_on
enabled: false
mode: restart mode: restart
- id: '1696286540644' - id: '1696286540644'
alias: Basement Lights Adaptive Resync alias: Basement Lights Adaptive Resync
@ -5569,53 +5587,59 @@
- id: '1722386174249' - id: '1722386174249'
alias: Tina Meds Cleanup alias: Tina Meds Cleanup
description: Handles the setting/clearing of medication configs for Tina description: Handles the setting/clearing of medication configs for Tina
trigger: triggers:
- platform: state - entity_id:
entity_id:
- input_boolean.tina_morning_meds_reminder - input_boolean.tina_morning_meds_reminder
from: 'on' from: 'on'
to: 'off' to: 'off'
id: morning-reminders-off id: morning-reminders-off
alias: Morning reminders off alias: Morning reminders off
trigger: state
- alias: Night reminders off - alias: Night reminders off
platform: state
entity_id: entity_id:
- input_boolean.tina_night_meds_reminder - input_boolean.tina_night_meds_reminder
from: 'on' from: 'on'
to: 'off' to: 'off'
id: night-reminders-off id: night-reminders-off
- platform: event trigger: state
event_type: ios.notification_action_fired - event_type: ios.notification_action_fired
event_data: event_data:
actionName: TINA_MORNING_MEDS_TAKEN actionName: TINA_MORNING_MEDS_TAKEN
id: morning-taken id: morning-taken
alias: Morning taken alias: Morning taken
trigger: event
- alias: Night taken - alias: Night taken
platform: event
event_type: ios.notification_action_fired event_type: ios.notification_action_fired
event_data: event_data:
actionName: TINA_NIGHT_MEDS_TAKEN actionName: TINA_NIGHT_MEDS_TAKEN
id: night-taken id: night-taken
trigger: event
- alias: Morning skipped - alias: Morning skipped
platform: event
event_type: ios.notification_action_fired event_type: ios.notification_action_fired
event_data: event_data:
actionName: TINA_MORNING_MEDS_SKIPPED actionName: TINA_MORNING_MEDS_SKIPPED
id: morning-skipped id: morning-skipped
trigger: event
- alias: Night skipped - alias: Night skipped
platform: event
event_type: ios.notification_action_fired event_type: ios.notification_action_fired
event_data: event_data:
actionName: TINA_NIGHT_MEDS_SKIPPED actionName: TINA_NIGHT_MEDS_SKIPPED
id: night-skipped id: night-skipped
- platform: state trigger: event
entity_id: - entity_id:
- person.christina_stork - person.christina_stork
from: home from: home
id: left id: left
alias: Left alias: Left
condition: [] trigger: state
action: - trigger: state
entity_id:
- person.christina_stork
to: Bob Evans
id: at-work
alias: At Work
conditions: []
actions:
- alias: Routing - alias: Routing
choose: choose:
- conditions: - conditions:
@ -5624,19 +5648,19 @@
- morning-reminders-off - morning-reminders-off
alias: Morning Reminders Off alias: Morning Reminders Off
sequence: sequence:
- service: counter.reset - metadata: {}
metadata: {}
data: {} data: {}
target: target:
entity_id: counter.tina_morning_meds_reminder_count entity_id: counter.tina_morning_meds_reminder_count
alias: Reset morning reminder count alias: Reset morning reminder count
- service: script.text_notify action: counter.reset
data: - data:
type: alert type: alert
who: tina who: tina
message: clear_notification message: clear_notification
tag: tina-morning-meds tag: tina-morning-meds
alias: Clear morning notification alias: Clear morning notification
action: script.text_notify
- conditions: - conditions:
- condition: trigger - condition: trigger
id: id:
@ -5644,66 +5668,66 @@
alias: Night reminders off alias: Night reminders off
sequence: sequence:
- alias: Reset night reminder count - alias: Reset night reminder count
service: counter.reset
metadata: {} metadata: {}
data: {} data: {}
target: target:
entity_id: counter.tina_night_meds_reminder_count entity_id: counter.tina_night_meds_reminder_count
- service: script.text_notify action: counter.reset
data: - data:
type: alert type: alert
who: tina who: tina
message: clear_notification message: clear_notification
tag: tina-night-meds tag: tina-night-meds
alias: Clear night notification alias: Clear night notification
action: script.text_notify
- conditions: - conditions:
- condition: trigger - condition: trigger
id: id:
- morning-taken - morning-taken
alias: Morning taken alias: Morning taken
sequence: sequence:
- service: input_boolean.turn_on - metadata: {}
metadata: {}
data: {} data: {}
target: target:
entity_id: input_boolean.tina_morning_meds_taken entity_id: input_boolean.tina_morning_meds_taken
alias: Turn on morning meds taken alias: Turn on morning meds taken
action: input_boolean.turn_on
- conditions: - conditions:
- condition: trigger - condition: trigger
id: id:
- night-taken - night-taken
alias: Night taken alias: Night taken
sequence: sequence:
- service: input_boolean.turn_on - metadata: {}
metadata: {}
data: {} data: {}
target: target:
entity_id: input_boolean.tina_night_meds_taken entity_id: input_boolean.tina_night_meds_taken
alias: Turn on night meds taken alias: Turn on night meds taken
action: input_boolean.turn_on
- conditions: - conditions:
- condition: trigger - condition: trigger
id: id:
- morning-skipped - morning-skipped
alias: Morning skipped alias: Morning skipped
sequence: sequence:
- service: input_boolean.turn_off - metadata: {}
metadata: {}
data: {} data: {}
target: target:
entity_id: input_boolean.tina_morning_meds_reminder entity_id: input_boolean.tina_morning_meds_reminder
alias: Deactivate morning reminders alias: Deactivate morning reminders
action: input_boolean.turn_off
- conditions: - conditions:
- condition: trigger - condition: trigger
id: id:
- night-skipped - night-skipped
alias: Night skipped alias: Night skipped
sequence: sequence:
- service: input_boolean.turn_off - metadata: {}
metadata: {}
data: {} data: {}
target: target:
entity_id: input_boolean.tina_night_meds_reminder entity_id: input_boolean.tina_night_meds_reminder
alias: Deactivate night reminders alias: Deactivate night reminders
action: input_boolean.turn_off
- conditions: - conditions:
- condition: trigger - condition: trigger
id: id:
@ -5725,7 +5749,6 @@
alias: Night meds reminder active alias: Night meds reminder active
then: then:
- alias: Send critical TTS notification - alias: Send critical TTS notification
service: script.text_notify
metadata: {} metadata: {}
data: data:
type: critical type: critical
@ -5733,6 +5756,19 @@
title: HEY DUMBASS title: HEY DUMBASS
message: YOU FORGOT TO TAKE YOUR MEDS!!!!! message: YOU FORGOT TO TAKE YOUR MEDS!!!!!
tag: tina-left-meds tag: tina-left-meds
action: script.text_notify
- conditions:
- condition: trigger
id:
- at-work
alias: At Work
sequence:
- action: input_boolean.turn_off
metadata: {}
data: {}
target:
entity_id: input_boolean.tina_night_meds_taken
alias: Turn off Night Meds Taken
mode: queued mode: queued
max: 10 max: 10
- id: '1722387020007' - id: '1722387020007'

View File

@ -0,0 +1,42 @@
`${(() => {
const occupancy = hass?.states[this.config?.main_button_floors?.occupancy_entity]?.state || '';
const hot = hass?.states[this.config?.main_button_floors?.hot_entity]?.state || '';
const cold = hass?.states[this.config?.main_button_floors?.cold_entity]?.state || '';
let bg_color = 'var(--bubble-main-background-color)';
let occupied_color = 'var(--accent-color)';
let hot_color = 'var(--error-color)';
let cold_color = 'var(--purple-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = occupancy === 'on' ? occupied_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Sub button 1
const subButton1 = card?.querySelector('.bubble-sub-button-1');
if (subButton1) {
if (hot === 'on') {
subButton1.style.backgroundColor = hot_color;
} else if (cold === 'on') {
subButton1.style.backgroundColor = cold_color;
} else if (occupancy === 'on') {
subButton1.style.backgroundColor = occupied_color;
} else {
subButton1.style.backgroundColor = bg_color;
}
}
// Unavailable state
if (mainButton && occupancy === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}`

View File

@ -0,0 +1,22 @@
- type: expandable
title: Entity Configuration
icon: mdi:format-list-bulleted
schema:
- name: occupancy_entity
label: Occupancy Entity
selector:
entity:
device_class: occupancy
required: false
- name: hot_entity
label: Hot Entity
selector:
entity:
device_class: heat
required: false
- name: cold_entity
label: Cold Entity
selector:
entity:
device_class: cold
required: false

View File

@ -0,0 +1,73 @@
main_button_floors:
name: Main Button Floors
version: '1.1'
creator: Tony Stork
supported:
- button
description: Module to provide theming for the main indoor floor buttons
code: |
${(() => {
const occupancy = hass?.states[this.config?.main_button_floors?.occupancy_entity]?.state || '';
const hot = hass?.states[this.config?.main_button_floors?.hot_entity]?.state || '';
const cold = hass?.states[this.config?.main_button_floors?.cold_entity]?.state || '';
let bg_color = 'var(--bubble-main-background-color)';
let occupied_color = 'var(--accent-color)';
let hot_color = 'var(--error-color)';
let cold_color = 'var(--purple-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = occupancy === 'on' ? occupied_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Sub button 1
const subButton1 = card?.querySelector('.bubble-sub-button-1');
if (subButton1) {
if (hot === 'on') {
subButton1.style.backgroundColor = hot_color;
} else if (cold === 'on') {
subButton1.style.backgroundColor = cold_color;
} else if (occupancy === 'on') {
subButton1.style.backgroundColor = occupied_color;
} else {
subButton1.style.backgroundColor = bg_color;
}
}
// Unavailable state
if (mainButton && occupancy === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}
editor:
- type: expandable
title: Entity Configuration
icon: mdi:format-list-bulleted
schema:
- name: occupancy_entity
label: Occupancy Entity
selector:
entity:
device_class: occupancy
required: false
- name: hot_entity
label: Hot Entity
selector:
entity:
device_class: heat
required: false
- name: cold_entity
label: Cold Entity
selector:
entity:
device_class: cold
required: false

View File

@ -0,0 +1,24 @@
`${(() => {
const occupancy = hass?.states[this.config?.main_button_outdoors?.occupancy_entity]?.state || '';
let bg_color = 'var(--bubble-main-background-color)';
let occupied_color = 'var(--accent-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = occupancy === 'on' ? occupied_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && occupancy === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}`

View File

@ -0,0 +1,10 @@
- type: expandable
title: Entity Configuration
icon: mdi:format-list-bulleted
schema:
- name: occupancy_entity
label: Occupancy Entity
selector:
entity:
device_class: occupancy
required: false

View File

@ -0,0 +1,43 @@
main_button_outdoors:
name: Main Button Outdoors
version: '1.1'
creator: Tony Stork
supported:
- button
description: Module to provide theming for outdoor floor buttons
code: |
${(() => {
const occupancy = hass?.states[this.config?.main_button_outdoors?.occupancy_entity]?.state || '';
let bg_color = 'var(--bubble-main-background-color)';
let occupied_color = 'var(--accent-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = occupancy === 'on' ? occupied_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && occupancy === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}
editor:
- type: expandable
title: Entity Configuration
icon: mdi:format-list-bulleted
schema:
- name: occupancy_entity
label: Occupancy Entity
selector:
entity:
device_class: occupancy
required: false

View File

@ -0,0 +1,24 @@
`${(() => {
const state = hass?.states[this.config?.entity]?.state || '';
let bg_color = 'var(--background-color-2)';
let accent_color = 'var(--accent-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = state === 'on' ? accent_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}`

View File

@ -0,0 +1,33 @@
popup_accent_color_button:
name: Popup Accent Color Button
version: '1.0'
creator: Tony Stork
supported:
- button
description: Will turn the button to accent color variable if config entity is on, otherwise default style applies
code: |-
${(() => {
const state = hass?.states[this.config?.entity]?.state || '';
let bg_color = 'var(--background-color-2)';
let accent_color = 'var(--accent-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = state === 'on' ? accent_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}
editor: ''

View File

@ -0,0 +1,24 @@
`${(() => {
const state = hass?.states[this.config?.entity]?.state || '';
let bg_color = 'var(--background-color-2)';
let red_color = 'var(--error-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = state === 'on' ? red_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}`

View File

@ -0,0 +1,33 @@
popup_security_button:
name: Popup Security Button
version: '1.0'
creator: Tony Stork
supported:
- button
description: Will turn the button red if there is a security fault, otherwise default style applies
code: |-
${(() => {
const state = hass?.states[this.config?.entity]?.state || '';
let bg_color = 'var(--background-color-2)';
let red_color = 'var(--error-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = state === 'on' ? red_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}
editor: ''

View File

@ -0,0 +1,32 @@
`${(() => {
const hot = hass?.states[this.config?.popup_temperature_button?.hot_entity]?.state || '';
const cold = hass?.states[this.config?.popup_temperature_button?.cold_entity]?.state || '';
let bg_color = 'var(--background-color-2)';
let hot_color = 'var(--error-color)';
let cold_color = 'var(--cyan-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
if (hot === 'on') {
mainButton.style.backgroundColor = hot_color;
} else if (cold === 'on') {
mainButton.style.backgroundColor = cold_color;
} else {
mainButton.style.backgroundColor = bg_color;
}
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}`

View File

@ -0,0 +1,14 @@
- type: expandable
title: Entity Configuration
icon: mdi:format-list-bulleted
schema:
- name: hot_entity
label: Hot Entity
selector:
entity:
device_class: heat
- name: cold_entity
label: Cold Entity
selector:
entity:
device_class: cold

View File

@ -0,0 +1,55 @@
popup_temperature_button:
name: Popup Temperature Button
version: '1.0'
creator: Tony Stork
supported:
- button
description: Will turn the button red if the room is too hot, cyan if too cold, otherwise default style applies
code: |-
${(() => {
const hot = hass?.states[this.config?.popup_temperature_button?.hot_entity]?.state || '';
const cold = hass?.states[this.config?.popup_temperature_button?.cold_entity]?.state || '';
let bg_color = 'var(--background-color-2)';
let hot_color = 'var(--error-color)';
let cold_color = 'var(--cyan-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
if (hot === 'on') {
mainButton.style.backgroundColor = hot_color;
} else if (cold === 'on') {
mainButton.style.backgroundColor = cold_color;
} else {
mainButton.style.backgroundColor = bg_color;
}
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}
editor:
- type: expandable
title: Entity Configuration
icon: mdi:format-list-bulleted
schema:
- name: hot_entity
label: Hot Entity
selector:
entity:
device_class: heat
- name: cold_entity
label: Cold Entity
selector:
entity:
device_class: cold

View File

@ -0,0 +1,92 @@
:host{
--circle-color: var(--bubble-accent-color, var(--accent-color));
--percentage: ${(() => {
card.timerEntity = hass.states[entity];
const now = new Date();
const endTime = new Date(card.timerEntity.attributes.finishes_at);
const runningTime = Math.round((endTime - now) / 1000);
const maxtime = Math.round(new Date("1970-01-01 " + card.timerEntity.attributes.duration + " UTC") / 1000);
const remainingTime = Math.round(new Date("1970-01-01 " + card.timerEntity.attributes.remaining + " UTC") / 1000);
var percentage = 0;
if (isNaN(runningTime)) {
percentage = 100 - Math.round( 100.0 * remainingTime / maxtime);
} else {
percentage = 100 - Math.round( 100.0 * runningTime / maxtime);
}
if (isNaN(percentage)) {
return "0%";
} else {
return "" + percentage +"%";
}
})()};
}
.bubble-icon-container {
background: radial-gradient(
var(--card-background-color) 60%,
transparent 0%
), conic-gradient(
var(--circle-color) var(--percentage) 0%,
var(--card-background-color) 0% 100%
) !important;
}
.bubble-icon-container:after {
content: "" !important;
height: 100% !important;
width: 100% !important;
position: absolute !important;
border-radius: 50% !important;
background: (var(--bubble-button-icon-background-color), 0.1) !important;
}
${(() => {
function UpdateState(){
try {
let now = new Date();
let endTime = new Date(card.timerEntity.attributes.finishes_at);
let runningTime = Math.round((endTime - now)/1000);
let hours = Math.floor(runningTime / 3600);
let minutes = Math.floor((runningTime - (hours * 3600)) / 60);
let remainingSeconds = runningTime % 60;
card.querySelector('.bubble-state').innerText =
(hours > 0 ? (hours + ":") : "") +
("0" + minutes).slice(-2) + ":" +
("0" + remainingSeconds).slice(-2);
} catch (error) {
card.querySelector('.bubble-state').innerText = card.timerEntity.attributes.duration;
}
};
if (card.timer == null && card.timerEntity.state === 'active') {
card.timer = setInterval(()=>{UpdateState()}, 500);
}else if (card.timerEntity.state != 'active'){
clearInterval(card.timer);
card.timer = null;
if (card.timerEntity.state !='paused') {
card.querySelector('.bubble-state').innerText = card.timerEntity.attributes.duration;
} else if(card.timerEntity.state==='paused') {
card.querySelector('.bubble-state').innerText = card.timerEntity.attributes.remaining;
}
}
})()}
${(() => {
subButtonIcon[0].setAttribute("icon",card.timerEntity.state != 'active' ?'mdi:play' : 'mdi:replay');
})()}
${(() => {
if (card.timerEntity.state != 'active') {
card.querySelector('.bubble-sub-button-2').classList.add("hidden");
}
})()}
${(() => {
if (card.timerEntity.state === 'idle') {
card.querySelector('.bubble-sub-button-3').classList.add("hidden");
}
})()}
${(() => {
if (card.timerEntity.state === 'idle') {
card.querySelector('.bubble-sub-button-4').classList.add("hidden");
}
})()}

View File

@ -0,0 +1,101 @@
popup_timer_card:
name: Popup Timer Card
version: '1.0'
creator: Tony Stork
supported:
- button
description: Will turn the button red if the entity state is on, otherwise default style applies
code: |-
:host{
--circle-color: var(--bubble-accent-color, var(--accent-color));
--percentage: ${(() => {
card.timerEntity = hass.states[entity];
const now = new Date();
const endTime = new Date(card.timerEntity.attributes.finishes_at);
const runningTime = Math.round((endTime - now) / 1000);
const maxtime = Math.round(new Date("1970-01-01 " + card.timerEntity.attributes.duration + " UTC") / 1000);
const remainingTime = Math.round(new Date("1970-01-01 " + card.timerEntity.attributes.remaining + " UTC") / 1000);
var percentage = 0;
if (isNaN(runningTime)) {
percentage = 100 - Math.round( 100.0 * remainingTime / maxtime);
} else {
percentage = 100 - Math.round( 100.0 * runningTime / maxtime);
}
if (isNaN(percentage)) {
return "0%";
} else {
return "" + percentage +"%";
}
})()};
}
.bubble-icon-container {
background: radial-gradient(
var(--card-background-color) 60%,
transparent 0%
), conic-gradient(
var(--circle-color) var(--percentage) 0%,
var(--card-background-color) 0% 100%
) !important;
}
.bubble-icon-container:after {
content: "" !important;
height: 100% !important;
width: 100% !important;
position: absolute !important;
border-radius: 50% !important;
background: (var(--bubble-button-icon-background-color), 0.1) !important;
}
${(() => {
function UpdateState(){
try {
let now = new Date();
let endTime = new Date(card.timerEntity.attributes.finishes_at);
let runningTime = Math.round((endTime - now)/1000);
let hours = Math.floor(runningTime / 3600);
let minutes = Math.floor((runningTime - (hours * 3600)) / 60);
let remainingSeconds = runningTime % 60;
card.querySelector('.bubble-state').innerText =
(hours > 0 ? (hours + ":") : "") +
("0" + minutes).slice(-2) + ":" +
("0" + remainingSeconds).slice(-2);
} catch (error) {
card.querySelector('.bubble-state').innerText = card.timerEntity.attributes.duration;
}
};
if (card.timer == null && card.timerEntity.state === 'active') {
card.timer = setInterval(()=>{UpdateState()}, 500);
}else if (card.timerEntity.state != 'active'){
clearInterval(card.timer);
card.timer = null;
if (card.timerEntity.state !='paused') {
card.querySelector('.bubble-state').innerText = card.timerEntity.attributes.duration;
} else if(card.timerEntity.state==='paused') {
card.querySelector('.bubble-state').innerText = card.timerEntity.attributes.remaining;
}
}
})()}
${(() => {
subButtonIcon[0].setAttribute("icon",card.timerEntity.state != 'active' ?'mdi:play' : 'mdi:replay');
})()}
${(() => {
if (card.timerEntity.state != 'active') {
card.querySelector('.bubble-sub-button-2').classList.add("hidden");
}
})()}
${(() => {
if (card.timerEntity.state === 'idle') {
card.querySelector('.bubble-sub-button-3').classList.add("hidden");
}
})()}
${(() => {
if (card.timerEntity.state === 'idle') {
card.querySelector('.bubble-sub-button-4').classList.add("hidden");
}
})()}
editor: ''

View File

@ -0,0 +1,21 @@
rotating_icon:
name: Rotating Icon
version: '0.1'
creator: Tony Stork
supported:
- button
- climate
- media-player
- pop-up
- separator
- horizontal-buttons-stack
description: Simple, make the icon rotate when the config entity is on
code: |-
.bubble-icon {
animation: ${state === 'on' ? 'slow-rotate 2s linear infinite' : ''};
}
@keyframes slow-rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
editor: ''

View File

@ -0,0 +1,34 @@
`${(() => {
let state;
if (this.config?.state_color_button?.alt_entity) {
state = hass?.states[this.config?.state_color_button?.alt_entity]?.state || '';
} else {
state = hass?.states[this.config?.entity]?.state || '';
}
let bg_color = 'var(--bubble-main-background-color)';
// Use the configured color or default to accent color
let on_color = this.config?.state_color_button?.color
? `var(--${this.config.state_color_button.color})`
: 'var(--accent-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = state === 'on' ? on_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.style.opacity = '0.5';
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}`

View File

@ -0,0 +1,10 @@
- name: color
label: Color (CSS Variable)
selector:
text: {}
required: false
- name: alt_entity
label: Entity (Optional, overrides main config)
selector:
entity: {}
required: false

View File

@ -0,0 +1,61 @@
state_color_button:
name: State Color Button
version: 1.1.2
creator: Tony Stork
supported:
- button
description: |-
Module for status buttons that turn a color based on the state of the config entity. Will default to the accent color in your theme. Use the name of a CSS variable. You can also specify an alternate entity to get state from, this will override the main card config.
<br><br>
Example:
<br><br>
<code-block><pre>
color: error-color
alt_entity: sensor.your_face
</pre></code-block>
code: |-
${(() => {
let state;
if (this.config?.state_color_button?.alt_entity) {
state = hass?.states[this.config?.state_color_button?.alt_entity]?.state || '';
} else {
state = hass?.states[this.config?.entity]?.state || '';
}
let bg_color = 'var(--bubble-main-background-color)';
// Use the configured color or default to accent color
let on_color = this.config?.state_color_button?.color
? `var(--${this.config.state_color_button.color})`
: 'var(--accent-color)';
// Main button background
const mainButton = card?.querySelector('.bubble-button-background');
if (mainButton) {
mainButton.style.opacity = '1';
mainButton.style.backgroundColor = state === 'on' ? on_color : bg_color;
mainButton.style.transition = 'background-color 1s';
}
// Unavailable state
if (mainButton && state === 'unavailable') {
mainButton.style.opacity = '0.5';
mainButton.classList.add('is-unavailable');
} else if (mainButton) {
mainButton.classList.remove('is-unavailable');
}
// No CSS string needed
return '';
})()}
editor:
- name: color
label: Color (CSS Variable)
selector:
text: {}
required: false
- name: alt_entity
label: Entity (Optional, overrides main config)
selector:
entity: {}
required: false

View File

@ -825,7 +825,21 @@
'ottobre', 'ottobre',
'novembre', 'novembre',
'dicembre', 'dicembre',
] ],
'time_of_hour':{
0: '{hour}',
1: '{hour} e un minuto',
15: '{hour} ed un quarto',
30: '{hour} e mezzo',
45: '15 minuti alle {hour}',
59: 'un minuto alle {hour}',
'past_hour': '{hour} e {minute}',
'to_hour': '{hour} meno {minute}',
},
'time_of_day':{
'midnight': 'mezzanotte',
'noon': 'mezzogiorno',
}
}, },
'pt':{ 'pt':{
'_language': 'Português', '_language': 'Português',
@ -1041,7 +1055,21 @@
'Październik', 'Październik',
'Listopad', 'Listopad',
'Grudzień', 'Grudzień',
] ],
'time_of_hour': {
0: '{hour}',
1: 'minuta po {hour}',
15: 'kwadrans po {hour}',
30: 'pół godziny po {hour}',
45: 'za kwadrans {hour}',
59: 'za minutę {hour}',
'past_hour': '{minute} po {hour}',
'to_hour': '{minute} do {hour}'
},
'time_of_day': {
'midnight': 'północ',
'noon': 'południe'
}
}, },
'ru':{ 'ru':{
'_language': 'Русский', '_language': 'Русский',
@ -1779,9 +1807,9 @@
{%- else %} {%- else %}
{%- set t = translate('ago', language=language) %} {%- set t = translate('ago', language=language) %}
{%- if '%s' in t %} {%- if '%s' in t %}
{{ t % items }} {{- t % items }}
{%- else %} {%- else %}
{{- items }} {{ translate('ago', language=language) }} {{- items }} {{ t }}
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
{%- else %} {%- else %}
@ -2045,7 +2073,7 @@
{%- if '%s' in t %} {%- if '%s' in t %}
{{- t % ret }} {{- t % ret }}
{%- else %} {%- else %}
{{- ret }} {{ translate('ago', language=language) }} {{- ret }} {{ t }}
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}

View File

@ -236,7 +236,7 @@
'hour': ['ч', 'час', 'часа', 'часов'], 'hour': ['ч', 'час', 'часа', 'часов'],
'minute': ['м', 'минута', 'минуты', 'минут'], 'minute': ['м', 'минута', 'минуты', 'минут'],
'second': ['с', 'секунда', 'секунды', 'секунд'], 'second': ['с', 'секунда', 'секунды', 'секунд'],
'millisecond': ['мс', 'милисекунда', 'милисекунды', 'милисекунд'], 'millisecond': ['мс', 'миллисекунда', 'миллисекунды', 'миллисекунд'],
'combine': 'и', 'combine': 'и',
'error': 'Неверная дата', 'error': 'Неверная дата',
} }
@ -337,6 +337,22 @@
'error': 'Érvénytelen dátum', 'error': 'Érvénytelen dátum',
} }
}, },
{
'language': 'tr',
'plural_form': 'english',
'phrases': {
'year': ['yıl', 'yıl', 'yıl'],
'month': ['ay', 'ay', 'ay'],
'week': ['hf', 'hafta', 'hafta'],
'day': ['gün', 'gün', 'gün'],
'hour': ['sa', 'saat', 'saat'],
'minute': ['dk', 'dakika', 'dakika'],
'second': ['sn', 'saniye', 'saniye'],
'millisecond': ['ms', 'milisaniye', 'milisaniye'],
'combine': 've',
'error': 'Geçersiz tarih',
}
},
] -%} ] -%}
{# macro to convert the abbreviated input for the not_use and always_show lists to the full time part names #} {# macro to convert the abbreviated input for the not_use and always_show lists to the full time part names #}

View File

@ -27,8 +27,15 @@
{% set period_str = period_str(team) %} {% set period_str = period_str(team) %}
{% set game_clock = state_attr(team,'clock') | lower %} {% set game_clock = state_attr(team,'clock') | lower %}
{% if state_attr(team,'league') == 'MLB' %} {% if state_attr(team,'league') == 'MLB' %}
{% if 'rain delay' in game_clock %}
{# Handle cases like "Rain Delay, Top 1st" #}
{% set status, inning = game_clock.split(',', 1) %}
{% set inning_parts = inning.split(' ') %}
in a {{ status | trim }} in the {{ inning_parts[1] ~ ' of the ' ~ inning_parts[2] }} {{ period_str }}
{% else %}
{% set inning_parts = game_clock.split(' ') %} {% set inning_parts = game_clock.split(' ') %}
in the {{ inning_parts[0] ~ ' of the ' ~ inning_parts[1] ~ ' ' ~ period_str }} in the {{ inning_parts[0] ~ ' of the ' ~ inning_parts[1] ~ ' ' ~ period_str }}
{% endif %}
{% else %} {% else %}
{% if ' - ' in game_clock %} {% if ' - ' in game_clock %}
{% set clock_time, quarter = game_clock.split(' - ') %} {% set clock_time, quarter = game_clock.split(' - ') %}

View File

@ -19,15 +19,15 @@
{% if type in ['alerts','full'] %} {% if type in ['alerts','full'] %}
{% if is_state('input_boolean.tornado_alarm','on') %} {% 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! 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) %} {% if state_attr('binary_sensor.tornado_warning','confirmed') == true %}
A tornado has been confirmed in the area. Please take shelter immediately! A tornado has been confirmed in the area. Please take shelter immediately!
{% endif %} {% endif %}
{% elif is_state('binary_sensor.severe_thunderstorm_warning','on') %} {% elif is_state('binary_sensor.severe_thunderstorm_warning','on') %}
We are under a severe thunderstorm warning. We are under a severe thunderstorm warning.
{% if state_attr('binary_sensor.severe_thunderstorm_warning','tornado_possible' == true) %} {% 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! The incoming storm has the potential to produce a tornado, so please pay attention and prepare to take shelter!
{% endif %} {% endif %}
{% if state_attr('binary_sensor.severe_thunderstorm_warning','considerable_destructive' == true) %} {% 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! This storm has the potential to cause considerable damage. Please take shelter and stay safe!
{% endif %} {% endif %}
{% elif states('sensor.weatheralerts_active_alerts') > '0' and method != 'dashboard' %} {% elif states('sensor.weatheralerts_active_alerts') > '0' and method != 'dashboard' %}
@ -39,9 +39,24 @@
There is lightning in the area. Nearest strike is {{ ltgdist }} miles away. There is lightning in the area. Nearest strike is {{ ltgdist }} miles away.
{% endif %} {% endif %}
{% if is_state('binary_sensor.raining','on') %} {% if is_state('binary_sensor.raining','on') %}
{% if states('sensor.home_tempest_cloud_sensors_precipitation_intensity') not in ['unavailable','unknown','no_rain'] %}
{% set intensity = states('sensor.home_tempest_cloud_sensors_precipitation_intensity') %}
{% if intensity == 'very_light' %}
There is currently a very light drizzle falling.
{% elif intensity == 'light' %}
There is currently light rain falling. Front porch windows should be okay, but other windows should be closed.
{% elif intensity == 'moderate' %}
It is raining pretty good outside, you should probably make sure all windows are closed.
{% elif intensity in ['heavy','very_heavy'] %}
There is heavy rain falling, please make sure all doors and windows are closed at this time.
{% elif intensity == 'extreme' %}
It is raining extremely hard outside. Make sure all doors and windows are closed, and I recommend staying inside until it calms down. Perhaps check for roof leaks as well.
{% endif %}
{% else %}
It is currently raining. Make sure all doors and windows are closed! It is currently raining. Make sure all doors and windows are closed!
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endif %}
{% if state_attr('weather.iron_nerd_weather_station','visibility') | int < 3 %} {% 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. Caution: Current outdoor visibility is {{ state_attr('weather.iron_nerd_weather_station','visibility') }} miles.
{% endif %} {% endif %}
@ -60,15 +75,15 @@
{% endif %} {% endif %}
{% if is_state('input_boolean.tornado_alarm','on') %} {% 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! " "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) %} {% if state_attr('binary_sensor.tornado_warning','confirmed') == true %}
"A tornado has been confirmed in the area. Please take shelter immediately! " "A tornado has been confirmed in the area. Please take shelter immediately! "
{% endif %} {% endif %}
{% elif is_state('binary_sensor.severe_thunderstorm_warning','on') %} {% elif is_state('binary_sensor.severe_thunderstorm_warning','on') %}
"We are under a severe thunderstorm warning. " "We are under a severe thunderstorm warning. "
{% if state_attr('binary_sensor.severe_thunderstorm_warning','tornado_possible' == true) %} {% 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! " "The incoming storm has the potential to produce a tornado, so please pay attention and prepare to take shelter! "
{% endif %} {% endif %}
{% if state_attr('binary_sensor.severe_thunderstorm_warning','considerable_destructive' == true) %} {% 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! " "This storm has the potential to cause considerable damage. Please take shelter and stay safe! "
{% endif %} {% endif %}
{% elif is_state('input_boolean.tornado_watch','on') %} {% elif is_state('input_boolean.tornado_watch','on') %}
@ -90,6 +105,42 @@
"The nearest lightning strike is {{ ltgdist }} miles away. " "The nearest lightning strike is {{ ltgdist }} miles away. "
{% endif %} {% endif %}
{% if is_state('binary_sensor.raining','on') %} {% if is_state('binary_sensor.raining','on') %}
{% if states('sensor.home_tempest_cloud_sensors_precipitation_intensity') not in ['unavailable','unknown','no_rain'] %}
{% set intensity = states('sensor.home_tempest_cloud_sensors_precipitation_intensity') %}
{% if intensity == 'very_light' %}
{{ [
"There is currently a very light drizzle falling. ",
"It is drizzling outside, but it is not too bad. ",
"The sky is spitting on us. That's not very nice, but a mild inconvenience at most. "
] | random }}
{% elif intensity == 'light' %}
{{ [
"There is currently light rain falling. ",
"It is raining lightly outside, but it is not too bad. ",
"It kinda wainin outside, but just a little. "
] | random }}
"Front porch windows should be okay, but other windows should be closed. "
{% elif intensity == 'moderate' %}
{{ [
"It is raining pretty good outside, you should probably make sure all windows are closed. ",
"It is raining at a decent rate outside, please make sure all windows are closed. "
"If you look outside, you will see that it wainin. "
] | random }}
{% elif intensity in ['heavy','very_heavy'] %}
{{ [
"There is heavy rain falling, please make sure all doors and windows are closed at this time. ",
"It is raining heavily outside, please make sure all doors and windows are closed. ",
"It wainin sideways! Please make sure all doors and windows are closed. "
] | random }}
{% elif intensity == 'extreme' %}
{{ [
"It is raining extremely hard outside. ",
"There is a torrential downpour outside. ",
"Holy crap, I have never seen it rain this hard before. "
] | random }}
"Make sure all doors and windows are closed, and I recommend staying inside until it calms down. Perhaps check for roof leaks as well. "
{% endif %}
{% else %}
{{ [ {{ [
"I have looked outside and determined that it is raining. ", "I have looked outside and determined that it is raining. ",
"If you look outside the window, you will notice, it wainin. ", "If you look outside the window, you will notice, it wainin. ",
@ -97,6 +148,7 @@
"There appears to be excessive moisture currently falling from the sky. Plan accordingly. ", "There appears to be excessive moisture currently falling from the sky. Plan accordingly. ",
] | random }} ] | random }}
{% endif %} {% endif %}
{% endif %}
{% if (state_attr('weather.iron_nerd_weather_station','visibility') | int ) < 3 %} {% if (state_attr('weather.iron_nerd_weather_station','visibility') | int ) < 3 %}
{{ [ {{ [
"It is foggy outside, please exercise caution when driving. ", "It is foggy outside, please exercise caution when driving. ",

View File

@ -239,6 +239,9 @@ script:
server_maintenance_annc: server_maintenance_annc:
alias: Server Maintenance Announcement alias: Server Maintenance Announcement
sequence: sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.server_maintenance
- service: script.status_annc - service: script.status_annc
data: data:
who: "{{ who|default('everywhere') }}" who: "{{ who|default('everywhere') }}"
@ -248,6 +251,9 @@ script:
server_maintenance_done_annc: server_maintenance_done_annc:
alias: Server Maintenance Done Announcement alias: Server Maintenance Done Announcement
sequence: sequence:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.server_maintenance
- service: script.status_annc - service: script.status_annc
data: data:
who: "{{ who|default('everywhere') }}" who: "{{ who|default('everywhere') }}"

View File

@ -68,6 +68,7 @@ weather:
{{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }} {{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }}
pressure_template: > pressure_template: >
{% set pressures = [ {% set pressures = [
states.sensor.home_tempest_local_slp,
states.sensor.home_tempest_cloud_sensors_sea_level_pressure, states.sensor.home_tempest_cloud_sensors_sea_level_pressure,
states.sensor.home_pressure, states.sensor.home_pressure,
states.sensor.kdfi_barometric_pressure states.sensor.kdfi_barometric_pressure
@ -173,6 +174,7 @@ weather:
{{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }} {{ forecasts | selectattr('forecast','defined') | map(attribute='forecast') | list | first }}
pressure_template: > pressure_template: >
{% set pressures = [ {% set pressures = [
states.sensor.home_tempest_local_slp,
states.sensor.home_tempest_cloud_sensors_sea_level_pressure, states.sensor.home_tempest_cloud_sensors_sea_level_pressure,
states.sensor.home_pressure, states.sensor.home_pressure,
states.sensor.kdfi_barometric_pressure states.sensor.kdfi_barometric_pressure

View File

@ -13,3 +13,10 @@ sensor:
state_characteristic: mean state_characteristic: mean
max_age: max_age:
hours: 24 hours: 24
binary_sensor:
- platform: trend
sensors:
local_average_gas_trend:
entity_id: sensor.local_average_gas_price
friendly_name: Local Average Gas Trend
unique_id: 3405a536-1e02-412f-916b-1a62c9cb8a2e

View File

@ -44,6 +44,9 @@ input_boolean:
adaptive_lighting_adjustments: adaptive_lighting_adjustments:
name: Adaptive Lighting Adjustments name: Adaptive Lighting Adjustments
icon: mdi:knob icon: mdi:knob
sunset_lights_triggered:
name: Sunset Lights Triggered
icon: mdi:weather-sunset
input_number: input_number:
upstairs_bathroom_motion_off_delay: upstairs_bathroom_motion_off_delay:
@ -215,6 +218,13 @@ input_number:
mode: box mode: box
unit_of_measurement: lx unit_of_measurement: lx
icon: mdi:sun-wireless icon: mdi:sun-wireless
sunset_lights_outdoor_lux_threshold:
name: Sunset Lights Outdoor Lux Threshold
min: 0
max: 10000
step: 100
unit_of_measurement: lx
icon: mdi:sun-wireless
# Settings for adaptive adjustments # Settings for adaptive adjustments
daytime_colortemp_front_porch: daytime_colortemp_front_porch:

View File

@ -602,26 +602,16 @@ script:
{% set low = states('sensor.overnight_lowest_temperature') | int %} {% set low = states('sensor.overnight_lowest_temperature') | int %}
{% set high = states('sensor.todays_high_temp') | int %} {% set high = states('sensor.todays_high_temp') | int %}
{% set kallen_bedtime = state_attr('input_datetime.kallen_bedtime','timestamp') | int %} {% set kallen_bedtime = state_attr('input_datetime.kallen_bedtime','timestamp') | int %}
{% set kallen_fantime = state_attr('input_datetime.kallen_fan','timestamp') | int %}
{% set bedroom_hot = is_state('binary_sensor.kallen_bedroom_hot','on') %}
{% set cutoff = 81000 %} {# Cutoff time is 22:30 #} {% 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') or bedroom_hot == true %}
{% if is_state('input_boolean.hot_day','on') %} {{ (kallen_fantime - 3600) | timestamp_custom('%H:%M',false) }}
{{ (kallen_bedtime - 3600) | timestamp_custom('%H:%M',false) }}
{% elif low >= 56 or high >= 75 %} {% elif low >= 56 or high >= 75 %}
{{ (kallen_bedtime - 1800) | timestamp_custom('%H:%M',false) }} {{ (kallen_bedtime - 1800) | timestamp_custom('%H:%M',false) }}
{% else %} {% else %}
{{ kallen_bedtime | timestamp_custom('%H:%M',false) }} {{ kallen_bedtime | timestamp_custom('%H:%M',false) }}
{% endif %} {% endif %}
{% elif low > 60 or high > 74 %}
{% if kallen_bedtime < cutoff %}
{{ kallen_bedtime | timestamp_custom('%H:%M',false) }}
{% else %}
22:00
{% endif %}
{% elif 56 <= low <= 60 %}
22:30
{% else %}
00:00
{% endif %}
- service: input_datetime.set_datetime - service: input_datetime.set_datetime
entity_id: input_datetime.master_bedroom_fan entity_id: input_datetime.master_bedroom_fan
data: data:

View File

@ -1,3 +1,8 @@
input_boolean:
server_maintenance:
name: Server Maintenance
icon: mdi:wrench-clock
input_select: input_select:
log_level: log_level:
name: Log Level name: Log Level

View File

@ -57,6 +57,7 @@ ## HACS Components
- [GasBuddy](https://github.com/firstof9/ha-gasbuddy) - [GasBuddy](https://github.com/firstof9/ha-gasbuddy)
- [Union Pacific Big Boy Tracker](https://github.com/jheizer/up_4014_tracker) - [Union Pacific Big Boy Tracker](https://github.com/jheizer/up_4014_tracker)
- [WeatherFlow Forecast](https://github.com/briis/weatherflow_forecast) - [WeatherFlow Forecast](https://github.com/briis/weatherflow_forecast)
- [NWS SPC Outlook](https://github.com/sedward5/nws_spc_outlook)
</details> </details>
@ -111,6 +112,7 @@ ## HACS Lovelace Cards
- [Weather Chart Card](https://github.com/mlamberts78/weather-chart-card) - [Weather Chart Card](https://github.com/mlamberts78/weather-chart-card)
- [Comfortable Environment Card](https://github.com/argaar/comfortable-environment-card) - [Comfortable Environment Card](https://github.com/argaar/comfortable-environment-card)
- [Versatile Thermostat UI Card](https://github.com/jmcollin78/versatile-thermostat-ui-card) - [Versatile Thermostat UI Card](https://github.com/jmcollin78/versatile-thermostat-ui-card)
- [Gauge Card Pro](https://github.com/benjamin-dcs/gauge-card-pro)
</details> </details>

View File

@ -854,6 +854,12 @@ adaptive_on_first_floor:
adaptive_on_second_floor: adaptive_on_second_floor:
alias: Adaptive on Second Floor alias: Adaptive on Second Floor
sequence: sequence:
- action: switch.turn_on
metadata: {}
data: {}
target:
entity_id: switch.adaptive_lighting_stairwell
alias: Turn on adaptive lighting in stairwell
- if: - if:
- condition: state - condition: state
entity_id: light.hallway_overhead entity_id: light.hallway_overhead