Compare commits
1 Commits
2025.7.1
...
mb_climate
Author | SHA1 | Date | |
---|---|---|---|
183d2a2ae9
|
@ -1 +1 @@
|
||||
2025.7.1
|
||||
2025.6.0
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -20,7 +20,6 @@
|
||||
/glances/
|
||||
/downloads/
|
||||
/lightwand/
|
||||
/bubble/Scratchpad/
|
||||
|
||||
# ignore any of these files no matter where they are using double *
|
||||
**.DS_Store
|
||||
|
@ -5587,59 +5587,53 @@
|
||||
- id: '1722386174249'
|
||||
alias: Tina Meds Cleanup
|
||||
description: Handles the setting/clearing of medication configs for Tina
|
||||
triggers:
|
||||
- entity_id:
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id:
|
||||
- input_boolean.tina_morning_meds_reminder
|
||||
from: 'on'
|
||||
to: 'off'
|
||||
id: morning-reminders-off
|
||||
alias: Morning reminders off
|
||||
trigger: state
|
||||
- alias: Night reminders off
|
||||
platform: state
|
||||
entity_id:
|
||||
- input_boolean.tina_night_meds_reminder
|
||||
from: 'on'
|
||||
to: 'off'
|
||||
id: night-reminders-off
|
||||
trigger: state
|
||||
- event_type: ios.notification_action_fired
|
||||
- platform: event
|
||||
event_type: ios.notification_action_fired
|
||||
event_data:
|
||||
actionName: TINA_MORNING_MEDS_TAKEN
|
||||
id: morning-taken
|
||||
alias: Morning taken
|
||||
trigger: event
|
||||
- alias: Night taken
|
||||
platform: event
|
||||
event_type: ios.notification_action_fired
|
||||
event_data:
|
||||
actionName: TINA_NIGHT_MEDS_TAKEN
|
||||
id: night-taken
|
||||
trigger: event
|
||||
- alias: Morning skipped
|
||||
platform: event
|
||||
event_type: ios.notification_action_fired
|
||||
event_data:
|
||||
actionName: TINA_MORNING_MEDS_SKIPPED
|
||||
id: morning-skipped
|
||||
trigger: event
|
||||
- alias: Night skipped
|
||||
platform: event
|
||||
event_type: ios.notification_action_fired
|
||||
event_data:
|
||||
actionName: TINA_NIGHT_MEDS_SKIPPED
|
||||
id: night-skipped
|
||||
trigger: event
|
||||
- entity_id:
|
||||
- platform: state
|
||||
entity_id:
|
||||
- person.christina_stork
|
||||
from: home
|
||||
id: left
|
||||
alias: Left
|
||||
trigger: state
|
||||
- trigger: state
|
||||
entity_id:
|
||||
- person.christina_stork
|
||||
to: Bob Evans
|
||||
id: at-work
|
||||
alias: At Work
|
||||
conditions: []
|
||||
actions:
|
||||
condition: []
|
||||
action:
|
||||
- alias: Routing
|
||||
choose:
|
||||
- conditions:
|
||||
@ -5648,19 +5642,19 @@
|
||||
- morning-reminders-off
|
||||
alias: Morning Reminders Off
|
||||
sequence:
|
||||
- metadata: {}
|
||||
- service: counter.reset
|
||||
metadata: {}
|
||||
data: {}
|
||||
target:
|
||||
entity_id: counter.tina_morning_meds_reminder_count
|
||||
alias: Reset morning reminder count
|
||||
action: counter.reset
|
||||
- data:
|
||||
- service: script.text_notify
|
||||
data:
|
||||
type: alert
|
||||
who: tina
|
||||
message: clear_notification
|
||||
tag: tina-morning-meds
|
||||
alias: Clear morning notification
|
||||
action: script.text_notify
|
||||
- conditions:
|
||||
- condition: trigger
|
||||
id:
|
||||
@ -5668,66 +5662,66 @@
|
||||
alias: Night reminders off
|
||||
sequence:
|
||||
- alias: Reset night reminder count
|
||||
service: counter.reset
|
||||
metadata: {}
|
||||
data: {}
|
||||
target:
|
||||
entity_id: counter.tina_night_meds_reminder_count
|
||||
action: counter.reset
|
||||
- data:
|
||||
- service: script.text_notify
|
||||
data:
|
||||
type: alert
|
||||
who: tina
|
||||
message: clear_notification
|
||||
tag: tina-night-meds
|
||||
alias: Clear night notification
|
||||
action: script.text_notify
|
||||
- conditions:
|
||||
- condition: trigger
|
||||
id:
|
||||
- morning-taken
|
||||
alias: Morning taken
|
||||
sequence:
|
||||
- metadata: {}
|
||||
- service: input_boolean.turn_on
|
||||
metadata: {}
|
||||
data: {}
|
||||
target:
|
||||
entity_id: input_boolean.tina_morning_meds_taken
|
||||
alias: Turn on morning meds taken
|
||||
action: input_boolean.turn_on
|
||||
- conditions:
|
||||
- condition: trigger
|
||||
id:
|
||||
- night-taken
|
||||
alias: Night taken
|
||||
sequence:
|
||||
- metadata: {}
|
||||
- service: input_boolean.turn_on
|
||||
metadata: {}
|
||||
data: {}
|
||||
target:
|
||||
entity_id: input_boolean.tina_night_meds_taken
|
||||
alias: Turn on night meds taken
|
||||
action: input_boolean.turn_on
|
||||
- conditions:
|
||||
- condition: trigger
|
||||
id:
|
||||
- morning-skipped
|
||||
alias: Morning skipped
|
||||
sequence:
|
||||
- metadata: {}
|
||||
- service: input_boolean.turn_off
|
||||
metadata: {}
|
||||
data: {}
|
||||
target:
|
||||
entity_id: input_boolean.tina_morning_meds_reminder
|
||||
alias: Deactivate morning reminders
|
||||
action: input_boolean.turn_off
|
||||
- conditions:
|
||||
- condition: trigger
|
||||
id:
|
||||
- night-skipped
|
||||
alias: Night skipped
|
||||
sequence:
|
||||
- metadata: {}
|
||||
- service: input_boolean.turn_off
|
||||
metadata: {}
|
||||
data: {}
|
||||
target:
|
||||
entity_id: input_boolean.tina_night_meds_reminder
|
||||
alias: Deactivate night reminders
|
||||
action: input_boolean.turn_off
|
||||
- conditions:
|
||||
- condition: trigger
|
||||
id:
|
||||
@ -5749,6 +5743,7 @@
|
||||
alias: Night meds reminder active
|
||||
then:
|
||||
- alias: Send critical TTS notification
|
||||
service: script.text_notify
|
||||
metadata: {}
|
||||
data:
|
||||
type: critical
|
||||
@ -5756,19 +5751,6 @@
|
||||
title: HEY DUMBASS
|
||||
message: YOU FORGOT TO TAKE YOUR 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
|
||||
max: 10
|
||||
- id: '1722387020007'
|
||||
|
@ -1,42 +0,0 @@
|
||||
`${(() => {
|
||||
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 '';
|
||||
})()}`
|
@ -1,22 +0,0 @@
|
||||
- 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
|
@ -1,73 +0,0 @@
|
||||
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
|
@ -1,24 +0,0 @@
|
||||
`${(() => {
|
||||
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 '';
|
||||
})()}`
|
@ -1,10 +0,0 @@
|
||||
- type: expandable
|
||||
title: Entity Configuration
|
||||
icon: mdi:format-list-bulleted
|
||||
schema:
|
||||
- name: occupancy_entity
|
||||
label: Occupancy Entity
|
||||
selector:
|
||||
entity:
|
||||
device_class: occupancy
|
||||
required: false
|
@ -1,43 +0,0 @@
|
||||
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
|
@ -1,24 +0,0 @@
|
||||
`${(() => {
|
||||
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 '';
|
||||
})()}`
|
@ -1,33 +0,0 @@
|
||||
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: ''
|
@ -1,24 +0,0 @@
|
||||
`${(() => {
|
||||
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 '';
|
||||
})()}`
|
@ -1,33 +0,0 @@
|
||||
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: ''
|
@ -1,32 +0,0 @@
|
||||
`${(() => {
|
||||
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 '';
|
||||
})()}`
|
@ -1,14 +0,0 @@
|
||||
- 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
|
@ -1,55 +0,0 @@
|
||||
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
|
@ -1,92 +0,0 @@
|
||||
: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");
|
||||
}
|
||||
})()}
|
@ -1,101 +0,0 @@
|
||||
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: ''
|
@ -1,21 +0,0 @@
|
||||
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: ''
|
@ -1,34 +0,0 @@
|
||||
`${(() => {
|
||||
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 '';
|
||||
})()}`
|
@ -1,10 +0,0 @@
|
||||
- name: color
|
||||
label: Color (CSS Variable)
|
||||
selector:
|
||||
text: {}
|
||||
required: false
|
||||
- name: alt_entity
|
||||
label: Entity (Optional, overrides main config)
|
||||
selector:
|
||||
entity: {}
|
||||
required: false
|
@ -1,61 +0,0 @@
|
||||
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
|
@ -825,21 +825,7 @@
|
||||
'ottobre',
|
||||
'novembre',
|
||||
'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':{
|
||||
'_language': 'Português',
|
||||
@ -1055,21 +1041,7 @@
|
||||
'Październik',
|
||||
'Listopad',
|
||||
'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':{
|
||||
'_language': 'Русский',
|
||||
@ -1807,9 +1779,9 @@
|
||||
{%- else %}
|
||||
{%- set t = translate('ago', language=language) %}
|
||||
{%- if '%s' in t %}
|
||||
{{- t % items }}
|
||||
{{ t % items }}
|
||||
{%- else %}
|
||||
{{- items }} {{ t }}
|
||||
{{- items }} {{ translate('ago', language=language) }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
@ -2073,7 +2045,7 @@
|
||||
{%- if '%s' in t %}
|
||||
{{- t % ret }}
|
||||
{%- else %}
|
||||
{{- ret }} {{ t }}
|
||||
{{- ret }} {{ translate('ago', language=language) }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
@ -236,7 +236,7 @@
|
||||
'hour': ['ч', 'час', 'часа', 'часов'],
|
||||
'minute': ['м', 'минута', 'минуты', 'минут'],
|
||||
'second': ['с', 'секунда', 'секунды', 'секунд'],
|
||||
'millisecond': ['мс', 'миллисекунда', 'миллисекунды', 'миллисекунд'],
|
||||
'millisecond': ['мс', 'милисекунда', 'милисекунды', 'милисекунд'],
|
||||
'combine': 'и',
|
||||
'error': 'Неверная дата',
|
||||
}
|
||||
@ -337,22 +337,6 @@
|
||||
'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 #}
|
||||
|
@ -27,15 +27,8 @@
|
||||
{% set period_str = period_str(team) %}
|
||||
{% set game_clock = state_attr(team,'clock') | lower %}
|
||||
{% 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(' ') %}
|
||||
in the {{ inning_parts[0] ~ ' of the ' ~ inning_parts[1] ~ ' ' ~ period_str }}
|
||||
{% endif %}
|
||||
{% 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(' - ') %}
|
||||
|
@ -239,9 +239,6 @@ script:
|
||||
server_maintenance_annc:
|
||||
alias: Server Maintenance Announcement
|
||||
sequence:
|
||||
- service: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.server_maintenance
|
||||
- service: script.status_annc
|
||||
data:
|
||||
who: "{{ who|default('everywhere') }}"
|
||||
@ -251,9 +248,6 @@ script:
|
||||
server_maintenance_done_annc:
|
||||
alias: Server Maintenance Done Announcement
|
||||
sequence:
|
||||
- service: input_boolean.turn_off
|
||||
target:
|
||||
entity_id: input_boolean.server_maintenance
|
||||
- service: script.status_annc
|
||||
data:
|
||||
who: "{{ who|default('everywhere') }}"
|
||||
|
@ -273,6 +273,14 @@ input_select:
|
||||
- White Noise
|
||||
- N/A
|
||||
icon: mdi:home-thermometer
|
||||
current_climate_mode_master_bedroom:
|
||||
name: Current Climate Mode - Master Bedroom
|
||||
options:
|
||||
- None
|
||||
- Day Mode
|
||||
- Night Mode
|
||||
- Bedtime Mode
|
||||
- Shower Mode
|
||||
|
||||
input_number:
|
||||
master_bedroom_daytime_temp:
|
||||
|
@ -13,10 +13,3 @@ sensor:
|
||||
state_characteristic: mean
|
||||
max_age:
|
||||
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
|
||||
|
@ -1,8 +1,3 @@
|
||||
input_boolean:
|
||||
server_maintenance:
|
||||
name: Server Maintenance
|
||||
icon: mdi:wrench-clock
|
||||
|
||||
input_select:
|
||||
log_level:
|
||||
name: Log Level
|
||||
|
@ -57,7 +57,6 @@ ## HACS Components
|
||||
- [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)
|
||||
- [NWS SPC Outlook](https://github.com/sedward5/nws_spc_outlook)
|
||||
|
||||
</details>
|
||||
|
||||
@ -112,7 +111,6 @@ ## HACS Lovelace Cards
|
||||
- [Weather Chart Card](https://github.com/mlamberts78/weather-chart-card)
|
||||
- [Comfortable Environment Card](https://github.com/argaar/comfortable-environment-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>
|
||||
|
||||
|
Reference in New Issue
Block a user