Ventilator: tilføj tænd/sluk + sluk-timer knapper for Andreas og Daniel
This commit is contained in:
@@ -0,0 +1,913 @@
|
|||||||
|
title: Overblik
|
||||||
|
path: home
|
||||||
|
icon: mdi:home
|
||||||
|
|
||||||
|
cards:
|
||||||
|
|
||||||
|
# 🌤️ Vejr + dato + sol
|
||||||
|
- type: vertical-stack
|
||||||
|
cards:
|
||||||
|
- type: weather-forecast
|
||||||
|
entity: weather.norgardsvej
|
||||||
|
show_forecast: true
|
||||||
|
|
||||||
|
- type: glance
|
||||||
|
columns: 5
|
||||||
|
show_icon: true
|
||||||
|
show_name: true
|
||||||
|
show_state: true
|
||||||
|
entities:
|
||||||
|
- entity: sensor.dato
|
||||||
|
name: Dato
|
||||||
|
icon: mdi:calendar
|
||||||
|
- entity: sensor.solopgang
|
||||||
|
name: Sol op
|
||||||
|
icon: mdi:weather-sunset-up
|
||||||
|
- entity: sensor.solnedgang
|
||||||
|
name: Sol ned
|
||||||
|
icon: mdi:weather-sunset-down
|
||||||
|
- entity: binary_sensor.arbejdsdag
|
||||||
|
name: I dag
|
||||||
|
icon: mdi:briefcase
|
||||||
|
- entity: binary_sensor.arbejdsdagimorgen
|
||||||
|
name: I morgen
|
||||||
|
icon: mdi:briefcase-outline
|
||||||
|
|
||||||
|
# 👨👩👧👦 Familien – tryk for at toggle syg/rask
|
||||||
|
- type: grid
|
||||||
|
columns: 4
|
||||||
|
square: false
|
||||||
|
cards:
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: person.daniel_schusler_dethlefsen
|
||||||
|
name: Daniel
|
||||||
|
show_name: true
|
||||||
|
show_state: false
|
||||||
|
show_label: true
|
||||||
|
show_icon: false
|
||||||
|
show_entity_picture: true
|
||||||
|
label: >
|
||||||
|
[[[
|
||||||
|
const s = entity.state;
|
||||||
|
const sick = states['input_select.daniel_status'] &&
|
||||||
|
states['input_select.daniel_status'].state === 'syg';
|
||||||
|
const loc = s === 'home' ? 'Hjemme' : s === 'not_home' ? 'Ude' : s;
|
||||||
|
return sick ? loc + ' · Syg' : loc;
|
||||||
|
]]]
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 4px
|
||||||
|
- border: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.daniel_status'] &&
|
||||||
|
states['input_select.daniel_status'].state === 'syg'
|
||||||
|
? '2px solid rgba(220,50,50,0.8)' : '2px solid transparent';
|
||||||
|
]]]
|
||||||
|
- border-radius: 12px
|
||||||
|
entity_picture:
|
||||||
|
- width: 60px
|
||||||
|
- height: 60px
|
||||||
|
- border-radius: 50%
|
||||||
|
- object-fit: cover
|
||||||
|
- filter: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.daniel_status'] &&
|
||||||
|
states['input_select.daniel_status'].state === 'syg'
|
||||||
|
? 'grayscale(100%)' : 'none';
|
||||||
|
]]]
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
- font-weight: 600
|
||||||
|
- padding-top: 6px
|
||||||
|
- color: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.daniel_status'] &&
|
||||||
|
states['input_select.daniel_status'].state === 'syg'
|
||||||
|
? 'rgb(220,50,50)' : 'var(--primary-text-color)';
|
||||||
|
]]]
|
||||||
|
label:
|
||||||
|
- font-size: 10px
|
||||||
|
- color: var(--secondary-text-color)
|
||||||
|
- padding-bottom: 2px
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: input_select.select_option
|
||||||
|
service_data:
|
||||||
|
entity_id: input_select.daniel_status
|
||||||
|
option: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.daniel_status'] &&
|
||||||
|
states['input_select.daniel_status'].state === 'syg'
|
||||||
|
? 'hjemme' : 'syg';
|
||||||
|
]]]
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
entity: person.daniel_schusler_dethlefsen
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: person.claus_dethlefsen
|
||||||
|
name: Claus
|
||||||
|
show_name: true
|
||||||
|
show_state: false
|
||||||
|
show_label: true
|
||||||
|
show_icon: false
|
||||||
|
show_entity_picture: true
|
||||||
|
label: >
|
||||||
|
[[[
|
||||||
|
const s = entity.state;
|
||||||
|
const sick = states['input_select.claus_status'] &&
|
||||||
|
states['input_select.claus_status'].state === 'syg';
|
||||||
|
const loc = s === 'home' ? 'Hjemme' : s === 'not_home' ? 'Ude' : s;
|
||||||
|
return sick ? loc + ' · Syg' : loc;
|
||||||
|
]]]
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 4px
|
||||||
|
- border: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.claus_status'] &&
|
||||||
|
states['input_select.claus_status'].state === 'syg'
|
||||||
|
? '2px solid rgba(220,50,50,0.8)' : '2px solid transparent';
|
||||||
|
]]]
|
||||||
|
- border-radius: 12px
|
||||||
|
entity_picture:
|
||||||
|
- width: 60px
|
||||||
|
- height: 60px
|
||||||
|
- border-radius: 50%
|
||||||
|
- object-fit: cover
|
||||||
|
- filter: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.claus_status'] &&
|
||||||
|
states['input_select.claus_status'].state === 'syg'
|
||||||
|
? 'grayscale(100%)' : 'none';
|
||||||
|
]]]
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
- font-weight: 600
|
||||||
|
- padding-top: 6px
|
||||||
|
- color: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.claus_status'] &&
|
||||||
|
states['input_select.claus_status'].state === 'syg'
|
||||||
|
? 'rgb(220,50,50)' : 'var(--primary-text-color)';
|
||||||
|
]]]
|
||||||
|
label:
|
||||||
|
- font-size: 10px
|
||||||
|
- color: var(--secondary-text-color)
|
||||||
|
- padding-bottom: 2px
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: input_select.select_option
|
||||||
|
service_data:
|
||||||
|
entity_id: input_select.claus_status
|
||||||
|
option: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.claus_status'] &&
|
||||||
|
states['input_select.claus_status'].state === 'syg'
|
||||||
|
? 'hjemme' : 'syg';
|
||||||
|
]]]
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
entity: person.claus_dethlefsen
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: person.anne_schusler_dethlefsen
|
||||||
|
name: Anne
|
||||||
|
show_name: true
|
||||||
|
show_state: false
|
||||||
|
show_label: true
|
||||||
|
show_icon: false
|
||||||
|
show_entity_picture: true
|
||||||
|
label: >
|
||||||
|
[[[
|
||||||
|
const s = entity.state;
|
||||||
|
const sick = states['input_select.anne_status'] &&
|
||||||
|
states['input_select.anne_status'].state === 'syg';
|
||||||
|
const loc = s === 'home' ? 'Hjemme' : s === 'not_home' ? 'Ude' : s;
|
||||||
|
return sick ? loc + ' · Syg' : loc;
|
||||||
|
]]]
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 4px
|
||||||
|
- border: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.anne_status'] &&
|
||||||
|
states['input_select.anne_status'].state === 'syg'
|
||||||
|
? '2px solid rgba(220,50,50,0.8)' : '2px solid transparent';
|
||||||
|
]]]
|
||||||
|
- border-radius: 12px
|
||||||
|
entity_picture:
|
||||||
|
- width: 60px
|
||||||
|
- height: 60px
|
||||||
|
- border-radius: 50%
|
||||||
|
- object-fit: cover
|
||||||
|
- filter: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.anne_status'] &&
|
||||||
|
states['input_select.anne_status'].state === 'syg'
|
||||||
|
? 'grayscale(100%)' : 'none';
|
||||||
|
]]]
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
- font-weight: 600
|
||||||
|
- padding-top: 6px
|
||||||
|
- color: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.anne_status'] &&
|
||||||
|
states['input_select.anne_status'].state === 'syg'
|
||||||
|
? 'rgb(220,50,50)' : 'var(--primary-text-color)';
|
||||||
|
]]]
|
||||||
|
label:
|
||||||
|
- font-size: 10px
|
||||||
|
- color: var(--secondary-text-color)
|
||||||
|
- padding-bottom: 2px
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: input_select.select_option
|
||||||
|
service_data:
|
||||||
|
entity_id: input_select.anne_status
|
||||||
|
option: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.anne_status'] &&
|
||||||
|
states['input_select.anne_status'].state === 'syg'
|
||||||
|
? 'hjemme' : 'syg';
|
||||||
|
]]]
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
entity: person.anne_schusler_dethlefsen
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: person.andreas_schusler_dethlefsen
|
||||||
|
name: Andreas
|
||||||
|
show_name: true
|
||||||
|
show_state: false
|
||||||
|
show_label: true
|
||||||
|
show_icon: false
|
||||||
|
show_entity_picture: true
|
||||||
|
label: >
|
||||||
|
[[[
|
||||||
|
const s = entity.state;
|
||||||
|
const sick = states['input_select.andreas_status'] &&
|
||||||
|
states['input_select.andreas_status'].state === 'syg';
|
||||||
|
const loc = s === 'home' ? 'Hjemme' : s === 'not_home' ? 'Ude' : s;
|
||||||
|
return sick ? loc + ' · Syg' : loc;
|
||||||
|
]]]
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 4px
|
||||||
|
- border: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.andreas_status'] &&
|
||||||
|
states['input_select.andreas_status'].state === 'syg'
|
||||||
|
? '2px solid rgba(220,50,50,0.8)' : '2px solid transparent';
|
||||||
|
]]]
|
||||||
|
- border-radius: 12px
|
||||||
|
entity_picture:
|
||||||
|
- width: 60px
|
||||||
|
- height: 60px
|
||||||
|
- border-radius: 50%
|
||||||
|
- object-fit: cover
|
||||||
|
- filter: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.andreas_status'] &&
|
||||||
|
states['input_select.andreas_status'].state === 'syg'
|
||||||
|
? 'grayscale(100%)' : 'none';
|
||||||
|
]]]
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
- font-weight: 600
|
||||||
|
- padding-top: 6px
|
||||||
|
- color: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.andreas_status'] &&
|
||||||
|
states['input_select.andreas_status'].state === 'syg'
|
||||||
|
? 'rgb(220,50,50)' : 'var(--primary-text-color)';
|
||||||
|
]]]
|
||||||
|
label:
|
||||||
|
- font-size: 10px
|
||||||
|
- color: var(--secondary-text-color)
|
||||||
|
- padding-bottom: 2px
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: input_select.select_option
|
||||||
|
service_data:
|
||||||
|
entity_id: input_select.andreas_status
|
||||||
|
option: >
|
||||||
|
[[[
|
||||||
|
return states['input_select.andreas_status'] &&
|
||||||
|
states['input_select.andreas_status'].state === 'syg'
|
||||||
|
? 'hjemme' : 'syg';
|
||||||
|
]]]
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
entity: person.andreas_schusler_dethlefsen
|
||||||
|
|
||||||
|
# 🪟 Gardiner
|
||||||
|
- type: grid
|
||||||
|
columns: 6
|
||||||
|
square: false
|
||||||
|
cards:
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:blinds-open
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: scene.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: scene.alle_lidt_nede
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:blinds
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: scene.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: scene.n22_alt_ned
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:blinds-horizontal
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: scene.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: scene.morgen
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:window-shutter
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: scene.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: scene.syd_ned_venstre_halvt_ned
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:television-ambient-light
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: scene.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: scene.n22_tv
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:silverware-fork-knife
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: scene.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: scene.n22_spisetid
|
||||||
|
|
||||||
|
# 🧹 Støvsuger
|
||||||
|
- type: horizontal-stack
|
||||||
|
cards:
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: sensor.roborock_last_clean_end_compact
|
||||||
|
show_icon: false
|
||||||
|
show_name: true
|
||||||
|
show_state: true
|
||||||
|
name: Sidst kørt
|
||||||
|
tap_action:
|
||||||
|
action: none
|
||||||
|
hold_action:
|
||||||
|
action: none
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px
|
||||||
|
name:
|
||||||
|
- font-size: 11px
|
||||||
|
- color: var(--secondary-text-color)
|
||||||
|
- padding-bottom: 4px
|
||||||
|
state:
|
||||||
|
- white-space: normal
|
||||||
|
- word-break: break-word
|
||||||
|
- line-height: 1.2
|
||||||
|
- font-size: 13px
|
||||||
|
- text-align: center
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Køkken
|
||||||
|
icon: mdi:floor-plan
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: button.press
|
||||||
|
target:
|
||||||
|
entity_id: button.roborock_s8_pro_ultra_kokken_bryggers
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Syd
|
||||||
|
icon: mdi:floor-plan
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: button.press
|
||||||
|
target:
|
||||||
|
entity_id: button.roborock_s8_pro_ultra_syd
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Mop
|
||||||
|
icon: mdi:floor-plan
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: button.press
|
||||||
|
target:
|
||||||
|
entity_id: button.roborock_s8_pro_ultra_vac_followed_by_mop
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Gå til dock
|
||||||
|
icon: mdi:home-import-outline
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: vacuum.return_to_base
|
||||||
|
target:
|
||||||
|
entity_id: vacuum.roborock_s8_pro_ultra
|
||||||
|
|
||||||
|
# 🏎️ Plæneklipper
|
||||||
|
- type: horizontal-stack
|
||||||
|
cards:
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: input_datetime.ploeneklipper_sidst_koert
|
||||||
|
show_icon: false
|
||||||
|
show_name: true
|
||||||
|
show_state: true
|
||||||
|
name: Sidst klippet
|
||||||
|
tap_action:
|
||||||
|
action: none
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px
|
||||||
|
name:
|
||||||
|
- font-size: 11px
|
||||||
|
- color: var(--secondary-text-color)
|
||||||
|
- padding-bottom: 4px
|
||||||
|
state:
|
||||||
|
- white-space: normal
|
||||||
|
- word-break: break-word
|
||||||
|
- line-height: 1.2
|
||||||
|
- font-size: 13px
|
||||||
|
- text-align: center
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Klip
|
||||||
|
icon: mdi:robot-mower
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: lawn_mower.start_mowing
|
||||||
|
target:
|
||||||
|
entity_id: lawn_mower.husqvarna_automower
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Stop
|
||||||
|
icon: mdi:home-import-outline
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: lawn_mower.dock
|
||||||
|
target:
|
||||||
|
entity_id: lawn_mower.husqvarna_automower
|
||||||
|
|
||||||
|
# � Vanding
|
||||||
|
- type: horizontal-stack
|
||||||
|
cards:
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: sensor.vanding_sidst_vandet_compact
|
||||||
|
show_icon: false
|
||||||
|
show_name: true
|
||||||
|
show_state: true
|
||||||
|
name: Sidst vandet
|
||||||
|
tap_action:
|
||||||
|
action: none
|
||||||
|
hold_action:
|
||||||
|
action: none
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px
|
||||||
|
name:
|
||||||
|
- font-size: 11px
|
||||||
|
- color: var(--secondary-text-color)
|
||||||
|
- padding-bottom: 4px
|
||||||
|
state:
|
||||||
|
- white-space: normal
|
||||||
|
- word-break: break-word
|
||||||
|
- line-height: 1.2
|
||||||
|
- font-size: 13px
|
||||||
|
- text-align: center
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Smart vanding
|
||||||
|
icon: mdi:sprinkler-variant
|
||||||
|
entity: script.vanding_hojbed_skiftevis
|
||||||
|
tap_action:
|
||||||
|
action: toggle
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: sensor.vanding_liter_i_dag_total
|
||||||
|
show_icon: false
|
||||||
|
show_name: false
|
||||||
|
show_state: false
|
||||||
|
tap_action:
|
||||||
|
action: none
|
||||||
|
hold_action:
|
||||||
|
action: none
|
||||||
|
custom_fields:
|
||||||
|
info: |
|
||||||
|
[[[
|
||||||
|
const n = (id) => { const s = states[id]; return s ? Math.round(parseFloat(s.state) || 0) : 0; };
|
||||||
|
const total = n('sensor.vanding_liter_i_dag_total');
|
||||||
|
const rows = [
|
||||||
|
['Ærter', n('sensor.vanding_liter_hb1')],
|
||||||
|
['Kartofler', n('sensor.vanding_liter_hb2')],
|
||||||
|
['Rabarber', n('sensor.vanding_liter_hb3')],
|
||||||
|
['Drivhus', n('sensor.vanding_liter_drivhus')],
|
||||||
|
['Kapillær', n('sensor.vanding_liter_kapillaer')],
|
||||||
|
];
|
||||||
|
const list = rows.map(r => `<div style="display:flex;justify-content:space-between;gap:6px"><span>${r[0]}</span><span style="font-variant-numeric:tabular-nums">${r[1]}</span></div>`).join('');
|
||||||
|
return `<div style="display:flex;flex-direction:column;width:100%;text-align:left">
|
||||||
|
<div style="font-size:11px;color:var(--secondary-text-color)">Liter i dag</div>
|
||||||
|
<div style="font-size:20px;font-weight:bold;line-height:1.1;margin:1px 0 4px">${total} L</div>
|
||||||
|
<div style="font-size:10.5px;color:var(--secondary-text-color);line-height:1.5">${list}</div>
|
||||||
|
</div>`;
|
||||||
|
]]]
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 10px
|
||||||
|
grid:
|
||||||
|
- grid-template-areas: '"info"'
|
||||||
|
custom_fields:
|
||||||
|
info:
|
||||||
|
- width: 100%
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: sensor.vanding_tid_i_dag_total
|
||||||
|
show_icon: false
|
||||||
|
show_name: false
|
||||||
|
show_state: false
|
||||||
|
tap_action:
|
||||||
|
action: none
|
||||||
|
hold_action:
|
||||||
|
action: none
|
||||||
|
custom_fields:
|
||||||
|
info: |
|
||||||
|
[[[
|
||||||
|
const m = (id) => { const s = states[id]; return s ? Math.round((parseFloat(s.state) || 0) * 60) : 0; };
|
||||||
|
const cap = () => { const s = states['sensor.vanding_kapillaer_tid_i_dag']; return s ? Math.round(parseFloat(s.state) || 0) : 0; };
|
||||||
|
const total = (() => { const s = states['sensor.vanding_tid_i_dag_total']; return s ? Math.round(parseFloat(s.state) || 0) : 0; })();
|
||||||
|
const rows = [
|
||||||
|
['Ærter', m('sensor.vanding_hojbed_1_i_dag')],
|
||||||
|
['Kartofler', m('sensor.vanding_hojbed_2_i_dag')],
|
||||||
|
['Rabarber', m('sensor.vanding_hojbed_3_i_dag')],
|
||||||
|
['Drivhus', m('sensor.vanding_drivhus_i_dag')],
|
||||||
|
['Kapillær', cap()],
|
||||||
|
];
|
||||||
|
const list = rows.map(r => `<div style="display:flex;justify-content:space-between;gap:6px"><span>${r[0]}</span><span style="font-variant-numeric:tabular-nums">${r[1]} min</span></div>`).join('');
|
||||||
|
return `<div style="display:flex;flex-direction:column;width:100%;text-align:left">
|
||||||
|
<div style="font-size:11px;color:var(--secondary-text-color)">Tid i dag</div>
|
||||||
|
<div style="font-size:20px;font-weight:bold;line-height:1.1;margin:1px 0 4px">${total} min</div>
|
||||||
|
<div style="font-size:10.5px;color:var(--secondary-text-color);line-height:1.5">${list}</div>
|
||||||
|
</div>`;
|
||||||
|
]]]
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 10px
|
||||||
|
grid:
|
||||||
|
- grid-template-areas: '"info"'
|
||||||
|
custom_fields:
|
||||||
|
info:
|
||||||
|
- width: 100%
|
||||||
|
|
||||||
|
# �💡 Lys kontrol
|
||||||
|
- type: horizontal-stack
|
||||||
|
cards:
|
||||||
|
- type: tile
|
||||||
|
entity: light.indendorslamper
|
||||||
|
name: Indenfor
|
||||||
|
icon: mdi:lightbulb-group
|
||||||
|
tap_action:
|
||||||
|
action: toggle
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
show_state: true
|
||||||
|
|
||||||
|
- type: tile
|
||||||
|
entity: light.udendorslamper
|
||||||
|
name: Udenfor
|
||||||
|
icon: mdi:outdoor-lamp
|
||||||
|
tap_action:
|
||||||
|
action: toggle
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
show_state: true
|
||||||
|
|
||||||
|
- type: tile
|
||||||
|
entity: binary_sensor.garageport
|
||||||
|
name: Garage
|
||||||
|
features_position: bottom
|
||||||
|
vertical: false
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: cover.toggle
|
||||||
|
target:
|
||||||
|
entity_id: cover.anne
|
||||||
|
show_state: true
|
||||||
|
|
||||||
|
# 🎵 Sonos
|
||||||
|
- type: grid
|
||||||
|
columns: 3
|
||||||
|
square: false
|
||||||
|
cards:
|
||||||
|
- type: button
|
||||||
|
name: Stop alt
|
||||||
|
icon: mdi:stop-circle-outline
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: media_player.media_stop
|
||||||
|
target:
|
||||||
|
entity_id:
|
||||||
|
- media_player.stue
|
||||||
|
- media_player.andreas
|
||||||
|
- media_player.daniel
|
||||||
|
- media_player.kokken
|
||||||
|
- media_player.alrum
|
||||||
|
- media_player.badevaerelse
|
||||||
|
- media_player.sovevaerelse
|
||||||
|
- media_player.lille_badevaerelse
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: P3 i bad
|
||||||
|
icon: mdi:radio
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: media_player.select_source
|
||||||
|
target:
|
||||||
|
entity_id: media_player.badevaerelse
|
||||||
|
data:
|
||||||
|
source: "0 DR P3"
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: P3 i alrum
|
||||||
|
icon: mdi:radio
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: media_player.select_source
|
||||||
|
target:
|
||||||
|
entity_id: media_player.alrum
|
||||||
|
data:
|
||||||
|
source: "0 DR P3"
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Daily Mix bad
|
||||||
|
icon: mdi:music-circle-outline
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: media_player.select_source
|
||||||
|
target:
|
||||||
|
entity_id: media_player.badevaerelse
|
||||||
|
data:
|
||||||
|
source: "Andreas Daily Mix 1"
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Daily Mix køkken
|
||||||
|
icon: mdi:music-circle-outline
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: media_player.select_source
|
||||||
|
target:
|
||||||
|
entity_id: media_player.kokken
|
||||||
|
data:
|
||||||
|
source: "Andreas Daily Mix 1"
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: Family Mix køkken
|
||||||
|
icon: mdi:music-note-outline
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: media_player.select_source
|
||||||
|
target:
|
||||||
|
entity_id: media_player.kokken
|
||||||
|
data:
|
||||||
|
source: "1 Family Mix"
|
||||||
|
|
||||||
|
# 🔊 Receiver presets
|
||||||
|
- type: grid
|
||||||
|
columns: 4
|
||||||
|
square: false
|
||||||
|
cards:
|
||||||
|
- type: button
|
||||||
|
name: Sonos
|
||||||
|
icon: mdi:speaker-multiple
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: script.receiver_sonos_mch_stereo
|
||||||
|
- type: button
|
||||||
|
name: TV Dolby
|
||||||
|
icon: mdi:television-speaker
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: script.receiver_tv_dolby_digital
|
||||||
|
- type: button
|
||||||
|
name: TV Stereo
|
||||||
|
icon: mdi:surround-sound
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: script.receiver_tv_mch_stereo
|
||||||
|
- type: horizontal-stack
|
||||||
|
cards:
|
||||||
|
- type: vertical-stack
|
||||||
|
cards:
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:power
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: media_player.turn_off
|
||||||
|
target:
|
||||||
|
entity_id: media_player.denon_avr_x2300w
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:volume-plus
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: script.receiver_volume_up_5
|
||||||
|
- type: button
|
||||||
|
name: ""
|
||||||
|
icon: mdi:volume-minus
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: script.receiver_volume_down_5
|
||||||
|
|
||||||
|
# 🍽️ Hjemmeknapper
|
||||||
|
- type: grid
|
||||||
|
columns: 2
|
||||||
|
square: false
|
||||||
|
cards:
|
||||||
|
- type: button
|
||||||
|
name: Der er mad
|
||||||
|
icon: mdi:silverware-fork-knife
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: script.mad_announcement
|
||||||
|
|
||||||
|
- type: button
|
||||||
|
name: TV hygge
|
||||||
|
icon: mdi:television-ambient-light
|
||||||
|
tap_action:
|
||||||
|
action: call-service
|
||||||
|
service: script.tv_hygge_announcement
|
||||||
|
|
||||||
|
# 🗑️ Affald
|
||||||
|
- type: glance
|
||||||
|
columns: 3
|
||||||
|
show_icon: true
|
||||||
|
show_name: false
|
||||||
|
show_state: true
|
||||||
|
entities:
|
||||||
|
- entity: sensor.affalddk_norgardsvej_22_restaffald
|
||||||
|
icon: mdi:trash-can-outline
|
||||||
|
- entity: sensor.affalddk_norgardsvej_22_papir_plast
|
||||||
|
icon: mdi:recycle
|
||||||
|
- entity: sensor.affalddk_norgardsvej_22_haveaffald
|
||||||
|
icon: mdi:leaf
|
||||||
|
|
||||||
|
# ⚡ El-priser
|
||||||
|
- type: vertical-stack
|
||||||
|
cards:
|
||||||
|
- type: custom:apexcharts-card
|
||||||
|
graph_span: 24h
|
||||||
|
span:
|
||||||
|
start: hour
|
||||||
|
stacked: false
|
||||||
|
header:
|
||||||
|
show: true
|
||||||
|
title: El-priser næste 24 timer
|
||||||
|
show_states: true
|
||||||
|
colorize_states: true
|
||||||
|
now:
|
||||||
|
show: true
|
||||||
|
label: Nu
|
||||||
|
all_series_config:
|
||||||
|
stroke_width: 0
|
||||||
|
apex_config:
|
||||||
|
chart:
|
||||||
|
height: 260
|
||||||
|
grid:
|
||||||
|
strokeDashArray: 2
|
||||||
|
xaxis:
|
||||||
|
type: datetime
|
||||||
|
labels:
|
||||||
|
datetimeFormatter:
|
||||||
|
hour: HH:mm
|
||||||
|
yaxis:
|
||||||
|
decimalsInFloat: 2
|
||||||
|
tickAmount: 5
|
||||||
|
plotOptions:
|
||||||
|
bar:
|
||||||
|
columnWidth: 82%
|
||||||
|
borderRadius: 3
|
||||||
|
series:
|
||||||
|
- entity: sensor.energi_data_service
|
||||||
|
name: Pris
|
||||||
|
type: column
|
||||||
|
float_precision: 2
|
||||||
|
unit: ' kr/kWh'
|
||||||
|
show:
|
||||||
|
in_header: raw
|
||||||
|
in_chart: true
|
||||||
|
data_generator: |
|
||||||
|
const startOfHour = new Date();
|
||||||
|
startOfHour.setMinutes(0, 0, 0);
|
||||||
|
const endTime = startOfHour.getTime() + (24 * 60 * 60 * 1000);
|
||||||
|
|
||||||
|
const rawToday = entity.attributes.raw_today || [];
|
||||||
|
const rawTomorrow = entity.attributes.tomorrow_valid ? (entity.attributes.raw_tomorrow || []) : [];
|
||||||
|
const forecast = entity.attributes.forecast || [];
|
||||||
|
|
||||||
|
const allKnown = [...rawToday, ...rawTomorrow];
|
||||||
|
const data = [];
|
||||||
|
const seen = new Set();
|
||||||
|
|
||||||
|
const pushPoint = (item) => {
|
||||||
|
const timestamp = new Date(item.hour).getTime();
|
||||||
|
if (Number.isNaN(timestamp) || timestamp < startOfHour.getTime() || timestamp >= endTime || seen.has(timestamp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const price = Number(item.price);
|
||||||
|
if (Number.isNaN(price)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
seen.add(timestamp);
|
||||||
|
data.push({ x: timestamp, y: price });
|
||||||
|
};
|
||||||
|
|
||||||
|
allKnown.forEach(pushPoint);
|
||||||
|
|
||||||
|
if (data.length < 24) {
|
||||||
|
forecast.forEach(pushPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.sort((left, right) => left.x - right.x);
|
||||||
|
|
||||||
|
const trimmed = data.slice(0, 24);
|
||||||
|
if (!trimmed.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const prices = trimmed.map((item) => item.y);
|
||||||
|
const minPrice = Math.min(...prices);
|
||||||
|
const maxPrice = Math.max(...prices);
|
||||||
|
|
||||||
|
const mix = (start, end, ratio) => Math.round(start + ((end - start) * ratio));
|
||||||
|
const toHex = (value) => value.toString(16).padStart(2, '0');
|
||||||
|
const rgbToHex = (red, green, blue) => `#${toHex(red)}${toHex(green)}${toHex(blue)}`;
|
||||||
|
|
||||||
|
const colorByValue = (value) => {
|
||||||
|
if (maxPrice === minPrice) {
|
||||||
|
return '#16a34a';
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalized = (value - minPrice) / (maxPrice - minPrice);
|
||||||
|
|
||||||
|
if (normalized <= 0.5) {
|
||||||
|
const ratio = normalized / 0.5;
|
||||||
|
return rgbToHex(
|
||||||
|
mix(22, 250, ratio),
|
||||||
|
mix(163, 204, ratio),
|
||||||
|
mix(74, 21, ratio)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ratio = (normalized - 0.5) / 0.5;
|
||||||
|
return rgbToHex(
|
||||||
|
mix(250, 220, ratio),
|
||||||
|
mix(204, 38, ratio),
|
||||||
|
mix(21, 38, ratio)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return trimmed.map((item) => ({
|
||||||
|
x: item.x,
|
||||||
|
y: item.y,
|
||||||
|
fillColor: colorByValue(item.y)
|
||||||
|
}));
|
||||||
|
|
||||||
|
# 🏠 Hus kontrol
|
||||||
|
- type: entities
|
||||||
|
title: Modes
|
||||||
|
entities:
|
||||||
|
- entity: input_boolean.guests_mode
|
||||||
|
name: Vi har gæster
|
||||||
|
icon: mdi:account-group
|
||||||
|
- entity: input_boolean.vacation_mode
|
||||||
|
name: 🌴 Vacation Mode
|
||||||
|
- entity: input_datetime.vacation_end
|
||||||
|
name: Slutter
|
||||||
|
|
||||||
|
- type: conditional
|
||||||
|
conditions:
|
||||||
|
- condition: numeric_state
|
||||||
|
entity: sensor.antal_vedligeholdskort
|
||||||
|
above: 0
|
||||||
|
card:
|
||||||
|
type: tile
|
||||||
|
entity: sensor.antal_vedligeholdskort
|
||||||
|
name: Vedligehold
|
||||||
|
icon: mdi:wrench-cog
|
||||||
|
|
||||||
@@ -255,6 +255,50 @@ sections:
|
|||||||
- word-break: break-word
|
- word-break: break-word
|
||||||
- line-height: 1.15
|
- line-height: 1.15
|
||||||
|
|
||||||
|
- type: grid
|
||||||
|
cards:
|
||||||
|
- type: heading
|
||||||
|
heading: Ventilator
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: light.indkorsel_plug
|
||||||
|
name: Ventilator
|
||||||
|
icon: mdi:fan
|
||||||
|
show_state: true
|
||||||
|
tap_action:
|
||||||
|
action: toggle
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 6px
|
||||||
|
- height: 72px
|
||||||
|
icon:
|
||||||
|
- width: 26px
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
|
||||||
|
- type: entities
|
||||||
|
entities:
|
||||||
|
- entity: input_number.andreas_ventilator_timer
|
||||||
|
name: Sluk-timer (min)
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
icon: mdi:fan-off
|
||||||
|
name: |
|
||||||
|
[[[ return 'Sluk om ' + Math.round(states['input_number.andreas_ventilator_timer'].state) + ' min'; ]]]
|
||||||
|
tap_action:
|
||||||
|
action: perform-action
|
||||||
|
perform_action: script.andreas_ventilator_sluk_timer
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 6px
|
||||||
|
- height: 56px
|
||||||
|
icon:
|
||||||
|
- width: 22px
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
|
||||||
- type: grid
|
- type: grid
|
||||||
cards:
|
cards:
|
||||||
- type: heading
|
- type: heading
|
||||||
|
|||||||
@@ -255,6 +255,50 @@ sections:
|
|||||||
- word-break: break-word
|
- word-break: break-word
|
||||||
- line-height: 1.15
|
- line-height: 1.15
|
||||||
|
|
||||||
|
- type: grid
|
||||||
|
cards:
|
||||||
|
- type: heading
|
||||||
|
heading: Ventilator
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
entity: switch.stik_daniel
|
||||||
|
name: Ventilator
|
||||||
|
icon: mdi:fan
|
||||||
|
show_state: true
|
||||||
|
tap_action:
|
||||||
|
action: toggle
|
||||||
|
hold_action:
|
||||||
|
action: more-info
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 6px
|
||||||
|
- height: 72px
|
||||||
|
icon:
|
||||||
|
- width: 26px
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
|
||||||
|
- type: entities
|
||||||
|
entities:
|
||||||
|
- entity: input_number.daniel_ventilator_timer
|
||||||
|
name: Sluk-timer (min)
|
||||||
|
|
||||||
|
- type: custom:button-card
|
||||||
|
icon: mdi:fan-off
|
||||||
|
name: |
|
||||||
|
[[[ return 'Sluk om ' + Math.round(states['input_number.daniel_ventilator_timer'].state) + ' min'; ]]]
|
||||||
|
tap_action:
|
||||||
|
action: perform-action
|
||||||
|
perform_action: script.daniel_ventilator_sluk_timer
|
||||||
|
styles:
|
||||||
|
card:
|
||||||
|
- padding: 8px 6px
|
||||||
|
- height: 56px
|
||||||
|
icon:
|
||||||
|
- width: 22px
|
||||||
|
name:
|
||||||
|
- font-size: 12px
|
||||||
|
|
||||||
- type: grid
|
- type: grid
|
||||||
cards:
|
cards:
|
||||||
- type: heading
|
- type: heading
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ panel: true
|
|||||||
|
|
||||||
cards:
|
cards:
|
||||||
- type: iframe
|
- type: iframe
|
||||||
url: /local/snapshots/indkorsel_loader.html?v=20260619185107
|
url: /local/snapshots/indkorsel_loader.html?v=20260620192035
|
||||||
aspect_ratio: 100%
|
aspect_ratio: 100%
|
||||||
|
|||||||
@@ -21,3 +21,12 @@ andreas_brightness:
|
|||||||
step: 1
|
step: 1
|
||||||
unit_of_measurement: "%"
|
unit_of_measurement: "%"
|
||||||
initial: 100
|
initial: 100
|
||||||
|
|
||||||
|
andreas_ventilator_timer:
|
||||||
|
name: Andreas ventilator sluk-timer
|
||||||
|
min: 5
|
||||||
|
max: 120
|
||||||
|
step: 5
|
||||||
|
unit_of_measurement: min
|
||||||
|
initial: 30
|
||||||
|
icon: mdi:fan-off
|
||||||
|
|||||||
@@ -21,3 +21,12 @@ daniel_brightness:
|
|||||||
step: 1
|
step: 1
|
||||||
unit_of_measurement: "%"
|
unit_of_measurement: "%"
|
||||||
initial: 100
|
initial: 100
|
||||||
|
|
||||||
|
daniel_ventilator_timer:
|
||||||
|
name: Daniel ventilator sluk-timer
|
||||||
|
min: 5
|
||||||
|
max: 120
|
||||||
|
step: 5
|
||||||
|
unit_of_measurement: min
|
||||||
|
initial: 30
|
||||||
|
icon: mdi:fan-off
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
andreas_ventilator_sluk_timer:
|
||||||
|
alias: Andreas ventilator sluk efter timer
|
||||||
|
icon: mdi:fan-off
|
||||||
|
mode: restart
|
||||||
|
sequence:
|
||||||
|
- delay:
|
||||||
|
minutes: "{{ states('input_number.andreas_ventilator_timer') | int(30) }}"
|
||||||
|
- service: light.turn_off
|
||||||
|
target:
|
||||||
|
entity_id: light.indkorsel_plug
|
||||||
|
|
||||||
|
daniel_ventilator_sluk_timer:
|
||||||
|
alias: Daniel ventilator sluk efter timer
|
||||||
|
icon: mdi:fan-off
|
||||||
|
mode: restart
|
||||||
|
sequence:
|
||||||
|
- delay:
|
||||||
|
minutes: "{{ states('input_number.daniel_ventilator_timer') | int(30) }}"
|
||||||
|
- service: switch.turn_off
|
||||||
|
target:
|
||||||
|
entity_id: switch.stik_daniel
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"count": 8, "items": [{"date": "2026-06-19", "recipe": {"name": "Okse tacos", "slug": "okse-tacos"}}, {"date": "2026-06-20", "recipe": {"name": "Bagte s\u00f8de kartofler med fyld", "slug": "bagte-sode-kartofler-med-fyld"}}, {"date": "2026-06-20", "recipe": {"name": "Engelsk b\u00f8f ", "slug": ""}}, {"date": "2026-06-25", "recipe": {"name": "Macaroni and cheese", "slug": "macaroni-and-cheese"}}, {"date": "2026-06-24", "recipe": {"name": "Rester fra mandag (Tortellini i fad)", "slug": ""}}, {"date": "2026-06-23", "recipe": {"name": "Rester fra s\u00f8ndag (Kylling med cornflakes)", "slug": ""}}, {"date": "2026-06-22", "recipe": {"name": "Tortellini i fad", "slug": "tortellini-i-fad"}}, {"date": "2026-06-21", "recipe": {"name": "Kylling med cornflakes", "slug": "kylling-med-cornflakes"}}]}
|
{"count": 8, "items": [{"date": "2026-06-20", "recipe": {"name": "Bagte s\u00f8de kartofler med fyld", "slug": "bagte-sode-kartofler-med-fyld"}}, {"date": "2026-06-20", "recipe": {"name": "Engelsk b\u00f8f ", "slug": ""}}, {"date": "2026-06-26", "recipe": {"name": "M\u00f8rbradb\u00f8ffer med bl\u00f8de l\u00f8g og fl\u00f8desauce", "slug": "morbradboffer-med-blode-log-og-flodesauce"}}, {"date": "2026-06-25", "recipe": {"name": "Macaroni and cheese", "slug": "macaroni-and-cheese"}}, {"date": "2026-06-24", "recipe": {"name": "Rester fra mandag (Tortellini i fad)", "slug": ""}}, {"date": "2026-06-23", "recipe": {"name": "Rester fra s\u00f8ndag (Kylling med cornflakes)", "slug": ""}}, {"date": "2026-06-22", "recipe": {"name": "Tortellini i fad", "slug": "tortellini-i-fad"}}, {"date": "2026-06-21", "recipe": {"name": "Kylling med cornflakes", "slug": "kylling-med-cornflakes"}}]}
|
||||||
Reference in New Issue
Block a user