Dashboard views reorganized, mealie/roborock automations, indkorsel snapshots, wavin/sonoff docs, varme/sikkerhed updates

This commit is contained in:
2026-05-16 07:28:28 +02:00
parent bd134bafef
commit f2ac6064b5
214 changed files with 1812 additions and 675 deletions
+42 -405
View File
@@ -33,275 +33,19 @@ cards:
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
# 👨‍👩‍👧‍👦 Familien
- type: glance
entities:
- 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
- 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
- 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
- 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
- entity: binary_sensor.family_presence
name: Familie
# 🪟 Gardiner
- type: grid
@@ -389,71 +133,36 @@ cards:
icon: mdi:floor-plan
tap_action:
action: call-service
service: script.turn_on
service: button.press
target:
entity_id: script.roborock_manuelt_kokken
entity_id: button.roborock_s8_pro_ultra_kokken_bryggers
- type: button
name: Syd
icon: mdi:floor-plan
tap_action:
action: call-service
service: script.turn_on
service: button.press
target:
entity_id: script.roborock_manuelt_syd
entity_id: button.roborock_s8_pro_ultra_syd
- type: button
name: Mop
icon: mdi:floor-plan
tap_action:
action: call-service
service: script.turn_on
service: button.press
target:
entity_id: script.roborock_manuelt_mop
entity_id: button.roborock_s8_pro_ultra_vac_followed_by_mop
- type: custom:button-card
entity: vacuum.roborock_s8_pro_ultra
name: Start
icon: mdi:robot-vacuum
- type: button
name: Gå til dock
icon: mdi:home-import-outline
tap_action:
action: call-service
service: script.turn_on
service: vacuum.return_to_base
target:
entity_id: script.roborock_manuelt_start
state:
- value: cleaning
name: Dock
styles:
card:
- background-color: rgba(255, 200, 0, 0.25)
- border: 1px solid rgba(255, 200, 0, 0.8)
tap_action:
action: call-service
service: vacuum.return_to_base
target:
entity_id: vacuum.roborock_s8_pro_ultra
- value: returning
name: Dock
styles:
card:
- background-color: rgba(255, 200, 0, 0.25)
- border: 1px solid rgba(255, 200, 0, 0.8)
tap_action:
action: call-service
service: vacuum.return_to_base
target:
entity_id: vacuum.roborock_s8_pro_ultra
- value: paused
name: Dock
styles:
card:
- background-color: rgba(255, 200, 0, 0.25)
- border: 1px solid rgba(255, 200, 0, 0.8)
tap_action:
action: call-service
service: vacuum.return_to_base
target:
entity_id: vacuum.roborock_s8_pro_ultra
entity_id: vacuum.roborock_s8_pro_ultra
# 🏎️ Plæneklipper
- type: horizontal-stack
@@ -462,25 +171,8 @@ cards:
entity: input_datetime.ploeneklipper_sidst_koert
show_icon: false
show_name: true
show_state: false
show_label: true
show_state: true
name: Sidst klippet
label: >
[[[
const s = entity.state;
if (!s || s === 'unknown') return 'Ukendt';
const d = new Date(s.replace(' ', 'T'));
if (isNaN(d)) return s;
const now = new Date();
const isToday = d.toDateString() === now.toDateString();
const yesterday = new Date(now);
yesterday.setDate(now.getDate() - 1);
const isYesterday = d.toDateString() === yesterday.toDateString();
const t = d.toLocaleTimeString('da-DK', {hour: '2-digit', minute: '2-digit'});
if (isToday) return 'I dag ' + t;
if (isYesterday) return 'I g\u00e5r ' + t;
return d.toLocaleDateString('da-DK', {day: 'numeric', month: 'short'}) + ' ' + t;
]]]
tap_action:
action: none
styles:
@@ -490,34 +182,30 @@ cards:
- font-size: 11px
- color: var(--secondary-text-color)
- padding-bottom: 4px
label:
state:
- white-space: normal
- word-break: break-word
- line-height: 1.2
- font-size: 13px
- text-align: center
- type: custom:button-card
entity: lawn_mower.husqvarna_automower
- type: button
name: Klip
icon: mdi:robot-mower
tap_action:
action: call-service
service: script.turn_on
service: lawn_mower.start_mowing
target:
entity_id: script.ploeneklipper_manuelt_start
state:
- value: mowing
name: Stop
styles:
card:
- background-color: rgba(255, 200, 0, 0.25)
- border: 1px solid rgba(255, 200, 0, 0.8)
tap_action:
action: call-service
service: script.turn_on
target:
entity_id: script.ploeneklipper_manuelt_stop
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
# 💡 Lys kontrol
- type: horizontal-stack
@@ -542,60 +230,17 @@ cards:
action: more-info
show_state: true
- type: custom:button-card
- type: tile
entity: binary_sensor.garageport
name: Garage
show_name: true
show_state: false
show_label: true
label: >
[[[
const isOpen = entity.state === 'on';
const lastChanged = new Date(entity.last_changed);
const secsAgo = (Date.now() - lastChanged) / 1000;
const inMotion = secsAgo < 30;
if (inMotion) return isOpen ? 'Åbner...' : 'Lukker...';
return isOpen ? 'Åben' : 'Lukket';
]]]
icon: >
[[[
return entity.state === 'on'
? 'mdi:garage-open-variant'
: 'mdi:garage-variant';
]]]
extra_styles: |
@keyframes garage-pulse {
0% { opacity: 1; transform: scale(1); }
50% { opacity: 0.55; transform: scale(1.04); }
100% { opacity: 1; transform: scale(1); }
}
styles:
card:
- animation: >
[[[
const secsAgo = (Date.now() - new Date(entity.last_changed)) / 1000;
return secsAgo < 30 ? 'garage-pulse 0.8s ease-in-out infinite' : 'none';
]]]
icon:
- color: >
[[[
const isOpen = entity.state === 'on';
const secsAgo = (Date.now() - new Date(entity.last_changed)) / 1000;
if (secsAgo < 30) return 'dodgerblue';
return isOpen ? 'orange' : 'var(--primary-text-color)';
]]]
label:
- font-size: 11px
- color: >
[[[
const secsAgo = (Date.now() - new Date(entity.last_changed)) / 1000;
return secsAgo < 30 ? 'dodgerblue' : 'var(--secondary-text-color)';
]]]
features_position: bottom
vertical: false
tap_action:
action: call-service
service: cover.toggle
target:
entity_id: cover.anne
show_state: true
# 🎵 Sonos
- type: grid
@@ -741,18 +386,6 @@ cards:
action: call-service
service: script.tv_hygge_announcement
# 🏖️ Ferie
- type: entities
title: Ferie
icon: mdi:beach
entities:
- entity: input_datetime.vacation_start
name: Afrejse
- entity: input_datetime.vacation_end
name: Hjemkomst
- entity: input_boolean.vacation_mode
name: Ferietilstand aktiv
# 🗑️ Affald
- type: glance
columns: 3
@@ -897,6 +530,10 @@ cards:
- 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:
-18
View File
@@ -99,21 +99,3 @@ cards:
| --- | --- |
{{ ns.rows }}
# 🛒 Bilka ToGo - opdater og vis kryds-af liste
- type: vertical-stack
cards:
- type: markdown
content: |
## Bilka ToGo - kryds-af
Tryk på knappen for at hente ingredienser fra ugeplanen (fredagtorsdag).
- type: button
name: Opdater Bilka ToGo-liste nu
icon: mdi:cart-check
tap_action:
action: call-service
service: script.mealie_shopping_refresh
- type: iframe
url: /local/bilka_togo_checklist.html
aspect_ratio: 100%
+215
View File
@@ -0,0 +1,215 @@
title: Vanding
path: vanding
icon: mdi:sprinkler-variant
type: sections
max_columns: 2
sections:
# 💧 Jordfugt målere
- type: grid
cards:
- type: heading
heading: Jordfugt
icon: mdi:water-percent
- type: gauge
entity: sensor.annes_havesensor_soil_moisture_1
name: Højbed 1 Ærter
min: 0
max: 100
needle: true
severity:
green: 40
yellow: 20
red: 0
- type: gauge
entity: sensor.annes_havesensor_soil_moisture_2
name: Højbed 2 Kartofler
min: 0
max: 100
needle: true
severity:
green: 40
yellow: 20
red: 0
- type: gauge
entity: sensor.annes_havesensor_soil_moisture_3
name: Højbed 3 Rabarber
min: 0
max: 100
needle: true
severity:
green: 40
yellow: 20
red: 0
- type: gauge
entity: sensor.annes_havesensor_soil_moisture_4
name: Drivhus
min: 0
max: 100
needle: true
severity:
green: 45
yellow: 25
red: 0
# 📈 Jordfugt historik
- type: grid
cards:
- type: heading
heading: Jordfugt 7 dage
icon: mdi:chart-line
- type: history-graph
title: Højbede (%)
entities:
- entity: sensor.annes_havesensor_soil_moisture_1
name: HB1 Ærter
- entity: sensor.annes_havesensor_soil_moisture_2
name: HB2 Kartofler
- entity: sensor.annes_havesensor_soil_moisture_3
name: HB3 Rabarber
hours_to_show: 168
refresh_interval: 900
- type: history-graph
title: Drivhus (%)
entities:
- entity: sensor.annes_havesensor_soil_moisture_4
name: Drivhus
hours_to_show: 168
refresh_interval: 900
# 🌧️ Regn & vejr
- type: grid
cards:
- type: heading
heading: Regn (Netatmo)
icon: mdi:weather-rainy
- type: tile
entity: sensor.n22_nedbor
name: Nedbør nu
- type: tile
entity: sensor.n22_precipitation_today
name: Nedbør i dag
- type: history-graph
title: Nedbør 7 dage
entities:
- entity: sensor.n22_precipitation_today
name: Nedbør
hours_to_show: 168
refresh_interval: 1800
- type: custom:apexcharts-card
header:
show: true
title: Forventet nedbør næste 7 dage
graph_span: 7d
span:
start: day
apex_config:
chart:
type: bar
height: 200
dataLabels:
enabled: true
formatter: |
EVAL:function(val) { return val ? val + ' mm' : ''; }
xaxis:
type: datetime
labels:
datetimeFormatter:
day: "dd/MM"
yaxis:
min: 0
title:
text: mm
series:
- entity: weather.norgardsvej
name: Nedbør
color: "#4fc3f7"
data_generator: |
return entity.attributes.forecast.map(f => ({
x: new Date(f.datetime).getTime(),
y: f.precipitation ?? 0
}));
# ⏸️ Rain Bird RC2
- type: grid
cards:
- type: heading
heading: Rain Bird RC2
icon: mdi:sprinkler-fire
- type: tile
entity: sensor.annes_vanding_raindelay
name: Regn-forsinkelse status
- type: tile
entity: number.annes_vanding_rain_delay
name: Sæt forsinkelse (dage)
- type: tile
entity: calendar.annes_vanding
name: Vandingsplan
# 🌿 Zonekontrol
- type: grid
cards:
- type: heading
heading: Zoner manuel styring
icon: mdi:water-pump
- type: tile
entity: switch.hojbed_1
name: Højbed 1 Ærter
icon: mdi:sprinkler
- type: tile
entity: switch.hojbed_2
name: Højbed 2 Kartofler
icon: mdi:sprinkler
- type: tile
entity: switch.hojbed_3
name: Højbed 3 Rabarber
icon: mdi:sprinkler
- type: tile
entity: switch.drivhus_drypvanding
name: Drivhus
icon: mdi:greenhouse
# 🔋 Sensorbatterier
- type: grid
cards:
- type: heading
heading: Sensor batterier
icon: mdi:battery
- type: glance
show_name: true
show_icon: true
show_state: true
columns: 4
entities:
- entity: sensor.annes_havesensor_soil_battery_1
name: HB1
icon: mdi:battery
- entity: sensor.annes_havesensor_soil_battery_2
name: HB2
icon: mdi:battery
- entity: sensor.annes_havesensor_soil_battery_3
name: HB3
icon: mdi:battery
- entity: sensor.annes_havesensor_soil_battery_4
name: Drivhus
icon: mdi:battery
+6 -4
View File
@@ -393,8 +393,8 @@ sections:
- type: grid
cards:
- type: gauge
entity: sensor.fjernvarme_ventil_anbefalet
name: Anbefalet ventilposition (15)
entity: sensor.fjernvarme_ventil_3_ugers_gennemsnit
name: Anbefalet ventilposition 3 ugers snit (15)
min: 1
max: 5
needle: true
@@ -412,9 +412,11 @@ sections:
- type: markdown
content: |-
**{{ state_attr('sensor.fjernvarme_ventil_anbefalet', 'anbefaling') }}**
**Anbefalet stilling (3 ugers snit): {{ states('sensor.fjernvarme_ventil_3_ugers_gennemsnit') | float(0) | round(1) }}**
Udetemperatur: {{ state_attr('sensor.fjernvarme_ventil_anbefalet', 'udetemperatur') }}°C
Øjeblikkelig (vejrbaseret): {{ states('sensor.fjernvarme_ventil_anbefalet') }} {{ state_attr('sensor.fjernvarme_ventil_anbefalet', 'anbefaling') }}
Udetemperatur nu: {{ state_attr('sensor.fjernvarme_ventil_anbefalet', 'udetemperatur') }}°C
Gælder for begge manuelle hoveddrejehaner:
- Roth-fordeler (sauna)
+352
View File
@@ -0,0 +1,352 @@
title: Sikkerhed
path: sikkerhed
icon: mdi:shield-home
cards:
# ─────────────────────────────────────────────────────────────
# 📷 KAMERAER
# ─────────────────────────────────────────────────────────────
- type: grid
columns: 2
square: false
cards:
- type: picture-entity
entity: camera.terrasse_sub
name: Terasse
camera_view: live
show_state: false
show_name: true
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Terasse Live
content:
type: vertical-stack
cards:
- type: picture-entity
entity: camera.terrasse_sub
camera_view: live
show_name: false
show_state: false
tap_action:
action: none
- type: tile
entity: number.terrasse_focus
name: Fokus
icon: mdi:focus-field
features:
- type: numeric-input
style: slider
- type: tile
entity: number.terrasse_zoom
name: Zoom
icon: mdi:magnify
features:
- type: numeric-input
style: slider
- type: picture-entity
entity: camera.indkoersel_sub
name: Indkørsel
camera_view: live
show_state: false
show_name: true
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Indkørsel Live
content:
type: vertical-stack
cards:
- type: picture-entity
entity: camera.indkoersel_sub
camera_view: live
show_name: false
show_state: false
tap_action:
action: none
- type: tile
entity: number.indkoersel_focus
name: Fokus
icon: mdi:focus-field
features:
- type: numeric-input
style: slider
- type: tile
entity: number.indkoersel_zoom
name: Zoom
icon: mdi:magnify
features:
- type: numeric-input
style: slider
# ─────────────────────────────────────────────────────────────
# 🛡️ SIKKERHEDSSTATUS
# ─────────────────────────────────────────────────────────────
- type: heading
heading: Sikkerhedsstatus
heading_style: title
- type: grid
columns: 2
square: false
cards:
# 👥 Tilstedeværelse
- type: custom:mushroom-template-card
entity: binary_sensor.family_presence
primary: >
{{ 'Nogen hjemme' if is_state('binary_sensor.family_presence', 'on') else 'Ingen hjemme' }}
secondary: >
{% set persons = [
('Claus', 'person.claus_dethlefsen'),
('Anne', 'person.anne_schusler_dethlefsen'),
('Andreas', 'person.andreas_schusler_dethlefsen'),
('Daniel', 'person.daniel_schusler_dethlefsen')
] %}
{% set ns = namespace(home=[]) %}
{% for name, eid in persons %}
{% if is_state(eid, 'home') %}{% set ns.home = ns.home + [name] %}{% endif %}
{% endfor %}
{{ ns.home | join(', ') if ns.home else 'Alle ude' }}
icon: >
{{ 'mdi:home-account' if is_state('binary_sensor.family_presence', 'on') else 'mdi:home-outline' }}
icon_color: >
{{ 'green' if is_state('binary_sensor.family_presence', 'on') else 'blue' }}
tap_action:
action: none
# 💡 Lys
- type: custom:mushroom-template-card
entity: light.alle_lys
primary: >
{{ 'Lys er tændt' if is_state('light.alle_lys', 'on') else 'Alt lys slukket' }}
secondary: ""
icon: >
{{ 'mdi:lightbulb-on' if is_state('light.alle_lys', 'on') else 'mdi:lightbulb-off' }}
icon_color: >
{{ 'yellow' if is_state('light.alle_lys', 'on') else 'grey' }}
tap_action:
action: navigate
navigation_path: /lovelace/lys
# 🪟 Vinduer og terrassedør
- type: custom:mushroom-template-card
multiline_secondary: true
primary: >
{% set sensors = [
'binary_sensor.andreas_vindue',
'binary_sensor.daniel_vindue',
'binary_sensor.sovevaerelse_vindue',
'binary_sensor.badevaerelse_vindue',
'binary_sensor.lille_bad_vindue',
'binary_sensor.terrassedor'
] %}
{% set ns = namespace(open=0) %}
{% for s in sensors %}{% if is_state(s, 'on') %}{% set ns.open = ns.open + 1 %}{% endif %}{% endfor %}
{{ 'Alle vinduer lukket' if ns.open == 0 else ns.open | string + ' vindue(r) åben' }}
secondary: >
{% set sensor_map = {
'binary_sensor.andreas_vindue': 'Andreas',
'binary_sensor.daniel_vindue': 'Daniel',
'binary_sensor.sovevaerelse_vindue': 'Soveværelse',
'binary_sensor.badevaerelse_vindue': 'Badeværelse',
'binary_sensor.lille_bad_vindue': 'Lille bad',
'binary_sensor.terrassedor': 'Terrassedør'
} %}
{% set ns = namespace(aabne=[]) %}
{% for s, n in sensor_map.items() %}{% if is_state(s, 'on') %}{% set ns.aabne = ns.aabne + [n] %}{% endif %}{% endfor %}
{{ ns.aabne | join(', ') if ns.aabne else '' }}
icon: >
{% set sensors = [
'binary_sensor.andreas_vindue',
'binary_sensor.daniel_vindue',
'binary_sensor.sovevaerelse_vindue',
'binary_sensor.badevaerelse_vindue',
'binary_sensor.lille_bad_vindue',
'binary_sensor.terrassedor'
] %}
{% set ns = namespace(open=0) %}
{% for s in sensors %}{% if is_state(s, 'on') %}{% set ns.open = ns.open + 1 %}{% endif %}{% endfor %}
{{ 'mdi:window-open-variant' if ns.open > 0 else 'mdi:window-closed-variant' }}
icon_color: >
{% set sensors = [
'binary_sensor.andreas_vindue',
'binary_sensor.daniel_vindue',
'binary_sensor.sovevaerelse_vindue',
'binary_sensor.badevaerelse_vindue',
'binary_sensor.lille_bad_vindue',
'binary_sensor.terrassedor'
] %}
{% set ns = namespace(open=0) %}
{% for s in sensors %}{% if is_state(s, 'on') %}{% set ns.open = ns.open + 1 %}{% endif %}{% endfor %}
{{ 'red' if ns.open > 0 else 'green' }}
tap_action:
action: none
# 🚗 Garage
- type: custom:mushroom-template-card
entity: binary_sensor.garageport
primary: >
{{ 'Garage åben' if is_state('binary_sensor.garageport', 'on') else 'Garage lukket' }}
secondary: >
Sidst ændret: {{ relative_time(states.binary_sensor.garageport.last_changed) }} siden
icon: >
{{ 'mdi:garage-open-variant' if is_state('binary_sensor.garageport', 'on') else 'mdi:garage-variant' }}
icon_color: >
{{ 'orange' if is_state('binary_sensor.garageport', 'on') else 'green' }}
tap_action:
action: call-service
service: cover.toggle
target:
entity_id: cover.anne
# 🏖️ Ferietilstand
- type: custom:mushroom-template-card
entity: input_boolean.vacation_mode
primary: >
{{ 'Ferie aktiv' if is_state('input_boolean.vacation_mode', 'on') else 'Normal tilstand' }}
secondary: >
{% if is_state('input_boolean.vacation_mode', 'on') %}
{% set end = states('input_datetime.vacation_end') %}
{% if end not in ['unknown', 'unavailable', ''] %}Slutter {{ as_datetime(end).strftime('%-d. %b') }}{% endif %}
{% endif %}
icon: >
{{ 'mdi:beach' if is_state('input_boolean.vacation_mode', 'on') else 'mdi:home' }}
icon_color: >
{{ 'cyan' if is_state('input_boolean.vacation_mode', 'on') else 'grey' }}
tap_action:
action: more-info
# 🤖 AI-overvågning (indkørsel)
- type: custom:mushroom-template-card
primary: >
{% set pause = states('input_datetime.ai_indkorsel_ai_pause_until') %}
{% set paused = pause not in ['unknown', 'unavailable', ''] and as_timestamp(pause) > as_timestamp(now()) %}
{{ 'AI-overvågning pauset' if paused else 'AI-overvågning aktiv' }}
secondary: >
{% set pause = states('input_datetime.ai_indkorsel_ai_pause_until') %}
{% set paused = pause not in ['unknown', 'unavailable', ''] and as_timestamp(pause) > as_timestamp(now()) %}
{% if paused %}Genoptages kl. {{ as_datetime(pause).strftime('%H:%M') }}{% else %}Indkørsel overvåges{% endif %}
icon: >
{% set pause = states('input_datetime.ai_indkorsel_ai_pause_until') %}
{% set paused = pause not in ['unknown', 'unavailable', ''] and as_timestamp(pause) > as_timestamp(now()) %}
{{ 'mdi:robot-off' if paused else 'mdi:robot' }}
icon_color: >
{% set pause = states('input_datetime.ai_indkorsel_ai_pause_until') %}
{% set paused = pause not in ['unknown', 'unavailable', ''] and as_timestamp(pause) > as_timestamp(now()) %}
{{ 'orange' if paused else 'green' }}
tap_action:
action: more-info
entity: input_datetime.ai_indkorsel_ai_pause_until
# 🔒 Terrassedør (separat overblik)
- type: custom:mushroom-template-card
entity: binary_sensor.terrassedor
primary: >
{{ 'Terrassedør åben' if is_state('binary_sensor.terrassedor', 'on') else 'Terrassedør lukket' }}
secondary: >
Sidst ændret: {{ relative_time(states.binary_sensor.terrassedor.last_changed) }} siden
icon: >
{{ 'mdi:door-open' if is_state('binary_sensor.terrassedor', 'on') else 'mdi:door-closed' }}
icon_color: >
{{ 'red' if is_state('binary_sensor.terrassedor', 'on') else 'green' }}
tap_action:
action: more-info
# 📡 Bevægelse i indkørslen lige nu
- type: custom:mushroom-template-card
entity: binary_sensor.indkorsel_sensor_motion
primary: >
{{ 'Bevægelse registreret!' if is_state('binary_sensor.indkorsel_sensor_motion', 'on') else 'Ingen bevægelse' }}
secondary: >
Sidst: {{ relative_time(states.binary_sensor.indkorsel_sensor_motion.last_changed) }} siden
icon: >
{{ 'mdi:motion-sensor' if is_state('binary_sensor.indkorsel_sensor_motion', 'on') else 'mdi:motion-sensor-off' }}
icon_color: >
{{ 'red' if is_state('binary_sensor.indkorsel_sensor_motion', 'on') else 'grey' }}
tap_action:
action: none
# ─────────────────────────────────────────────────────────────
# 📋 SENESTE BEVÆGELSE INDKØRSEL (AI-log)
# ─────────────────────────────────────────────────────────────
- type: heading
heading: Seneste bevægelse Indkørsel
heading_style: title
# Seneste snapshot gemt af AI-overvågningsscriptet
- type: picture-entity
entity: camera.indkorsel_snapshot
show_name: false
show_state: false
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Seneste bevægelse Indkørsel
content:
type: picture-entity
entity: camera.indkorsel_snapshot
show_name: false
show_state: false
tap_action:
action: none
# Seneste AI-beskrivelse
- type: custom:button-card
entity: input_text.last_notification_message
show_name: false
show_icon: true
show_state: true
icon: mdi:robot
styles:
card:
- padding: 14px 16px
- text-align: left
grid:
- grid-template-areas: '"i s"'
- grid-template-columns: 44px 1fr
- grid-template-rows: auto
icon:
- width: 32px
- height: 32px
- color: var(--primary-color)
- align-self: flex-start
- margin-top: 2px
state:
- white-space: normal
- word-break: break-word
- font-size: 13px
- text-align: left
- line-height: "1.5"
tap_action:
action: none
# ─────────────────────────────────────────────────────────────
# 📸 SENESTE PERSON-SNAPSHOT INDKØRSEL
# ─────────────────────────────────────────────────────────────
- type: heading
heading: Seneste person i indkørsel
heading_style: subtitle
# Klik åbner galleri med alle tidligere snapshots
- type: picture
image: /local/snapshots/indkorsel/latest.jpg
tap_action:
action: navigate
navigation_path: /lovelace/indkorsel-snapshots
# Logbog over bevægelseshændelser (48 timer)
- type: logbook
entities:
- binary_sensor.indkorsel_sensor_motion
hours_to_show: 48
title: Bevægelseslog (48 timer)
@@ -0,0 +1,9 @@
title: Snapshots Indkørsel
path: indkorsel-snapshots
icon: mdi:camera-burst
panel: true
cards:
- type: iframe
url: /local/snapshots/indkorsel_loader.html
aspect_ratio: 100%