Compare commits

...

22 Commits

Author SHA1 Message Date
claus 0b4fc7f2f4 fix presence 2026-03-25 21:06:57 +01:00
claus bef3fc5b4c slettes - redundant 2026-03-25 21:06:25 +01:00
claus 0416ec39de skift navn på dashboard 2026-03-25 20:59:47 +01:00
claus 4d6cd9fc58 commit besked 2026-03-25 07:35:30 +01:00
claus 34ad1c29ca small bug 2026-03-25 07:34:51 +01:00
claus cc42f93c51 feat(lovelace): refactor home dashboard layout and improve data grouping
- removed "antal hjemme" and standalone sunset card
- added weather forecast card with date, sunrise and sunset (template sensors)
- removed outdoor temperature gauge
- reorganized climate data into structured groups:
  - temperature (3 rooms)
  - CO2 (3 rooms)
  - humidity (3 rooms)
- compacted energy and dishwasher into horizontal stack
- simplified vacuum card (reduced noise)
- improved overall layout readability and consistency

focus: better UX, clearer grouping, reduced clutter, production-stable structure
2026-03-25 07:29:32 +01:00
claus 9a4efbcd6a kontekst 2026-03-25 07:19:21 +01:00
claus 40c78ed6af numeric opvasker 2026-03-25 07:15:29 +01:00
claus c91e669761 tesla 2026-03-24 20:45:05 +01:00
claus 98df2da6f9 feat(dashboard): Full Pro SnowyWhite Tesla Lovelace view
- Implemented numeric template sensors for battery, range, charging rate, energy added, and charging state
- Added gauges for battery and range
- Added tiles for charging status, rate, energy, charger power, and time to full charge
- Added Start/Stop charging buttons
- Added history-graph timeline for charging
- Added sections for doors & locks, temperature, arrival info, and maintenance/alerts
- Fully compatible with standard Lovelace (no Dwains Dashboard dependencies)
2026-03-24 20:44:38 +01:00
claus 04e89907cc støvsuger 2026-03-24 19:32:51 +01:00
claus 14548f9509 Fix: Replace roborock-map-card with static xiaomi-vacuum-map-card image
- Removed roborock-map-card causing calibration errors
- Use image.roborock_s8_pro_ultra_map_0 as a static map
- Keep vacuum status, mop, and automations functional
- Avoids "invalid calibration" errors while preserving dashboard functionality
2026-03-24 19:32:32 +01:00
claus 7f0859f446 tesla 2026-03-24 18:25:18 +01:00
claus 64032e6682 tesla charging 2026-03-24 18:24:58 +01:00
claus 6b6b69b766 vacation 2026-03-24 18:24:27 +01:00
claus cbeb832dd7 presence simulation 2026-03-24 18:22:52 +01:00
claus e542dc17c0 map 2026-03-24 18:21:56 +01:00
claus f81430d576 fix 2026-03-24 18:21:27 +01:00
claus 75928671d1 vacation 2026-03-24 18:21:13 +01:00
claus 6074dcac98 modules fixed 2026-03-24 18:20:47 +01:00
claus c979cdbf99 clean up inclusions 2026-03-24 18:20:17 +01:00
claus c60aa24576 tune 2026-03-22 20:02:40 +01:00
24 changed files with 839 additions and 407 deletions
+10 -10
View File
@@ -1,6 +1,11 @@
# --- Global ignores --- # Ignore everything globally
.DS_Store .DS_Store
custom_components/ custom_components/
blueprints/
dwains-dashboard/
tts/
www/
backups/
old* old*
# System / runtime folders # System / runtime folders
@@ -8,6 +13,7 @@ old*
.cloud/ .cloud/
.google.token/ .google.token/
.Rproj.user/ .Rproj.user/
.cache/
# Logs / DB / temp # Logs / DB / temp
*.log* *.log*
@@ -21,9 +27,6 @@ known_devices.yaml
configuration_full.yaml configuration_full.yaml
configuration_minimal.yaml configuration_minimal.yaml
# Specific ignore
include/automations/lys_have.yaml
# --- Whitelist core files --- # --- Whitelist core files ---
!*.yaml !*.yaml
!*.md !*.md
@@ -38,10 +41,7 @@ include/automations/lys_have.yaml
!include/ !include/
!themes/ !themes/
!python_scripts/ !python_scripts/
!view/ !dashboards/
# --- Allow structured YAML inside include/ --- # --- Explicitly include all YAML in dashboards subdirs ---
!include/**/*.yaml !dashboards/**/*.yaml
# --- Allow view YAML ---
!view/**/*.yaml
+4 -7
View File
@@ -53,13 +53,6 @@ recorder:
zone: !include include/zone/zones.yaml zone: !include include/zone/zones.yaml
input_boolean:
first_run:
initial: off
first_run_eve:
initial: off
first_run_stue:
initial: off
timer: timer:
indkorsel: indkorsel:
@@ -113,12 +106,16 @@ device_tracker: !include include/device_trackers.yaml
input_datetime: !include_dir_merge_named include/input/datetime/ input_datetime: !include_dir_merge_named include/input/datetime/
input_number: !include_dir_merge_named include/input/number/ input_number: !include_dir_merge_named include/input/number/
input_select: !include_dir_merge_named include/input/select/ input_select: !include_dir_merge_named include/input/select/
input_boolean: !include_dir_merge_named include/input/boolean/
light: !include_dir_merge_list include/lights/ light: !include_dir_merge_list include/lights/
panel_iframe: !include_dir_merge_named include/panels/ panel_iframe: !include_dir_merge_named include/panels/
script: !include_dir_merge_named include/scripts/ script: !include_dir_merge_named include/scripts/
shell_command: !include_dir_merge_named include/shell_commands/ shell_command: !include_dir_merge_named include/shell_commands/
switch: !include_dir_merge_list include/switches/ switch: !include_dir_merge_list include/switches/
browser_mod:
lovelace: lovelace:
mode: yaml mode: yaml
+133 -172
View File
@@ -1,17 +1,32 @@
title: Nørgårdsvej 22 title: Nørgårdsvej 22 (Main)
path: home path: hjem
icon: mdi:home icon: mdi:home
type: sections
sections: cards:
# 👨‍👩‍👧‍👦 Personer (overblik) # 🌤️ Vejr + dato + sol
- type: grid - type: vertical-stack
cards: cards:
- type: heading - type: weather-forecast
heading: Familien entity: weather.norgardsvej
show_forecast: true
- type: entities
show_header_toggle: false
entities:
- entity: sensor.n22_dato
name: Dato
icon: mdi:calendar
- entity: sensor.n22_solopgang
name: Solopgang
icon: mdi:weather-sunset-up
- entity: sensor.n22_solnedgang
name: Solnedgang
icon: mdi:weather-sunset-down
# 👨‍👩‍👧‍👦 Familien
- type: glance - type: glance
title: Familien
entities: entities:
- entity: person.daniel_schusler_dethlefsen - entity: person.daniel_schusler_dethlefsen
name: Daniel name: Daniel
@@ -23,12 +38,8 @@ sections:
name: Andreas name: Andreas
# 🗑️ Affald # 🗑️ Affald
- type: grid
cards:
- type: heading
heading: Affald
- type: entities - type: entities
title: Affald
entities: entities:
- entity: sensor.affalddk_norgardsvej_22_restaffald - entity: sensor.affalddk_norgardsvej_22_restaffald
name: Rest name: Rest
@@ -37,207 +48,157 @@ sections:
- entity: sensor.affalddk_norgardsvej_22_haveaffald - entity: sensor.affalddk_norgardsvej_22_haveaffald
name: Have name: Have
# 🏠 Hus kontrol # 🏠 Hus kontrol
- type: grid - type: entities
cards: title: Modes
- type: heading entities:
heading: Hus kontrol - entity: input_boolean.guests_mode
- type: tile
entity: input_boolean.guests_mode
name: Vi har gæster name: Vi har gæster
icon: mdi:account-group icon: mdi:account-group
- entity: input_boolean.vacation_mode
name: 🌴 Vacation Mode
- entity: input_datetime.vacation_end
name: Slutter
- type: button # 🌡️ Temperatur + CO2 + Fugt (grupperet pr type)
name: Godnat - type: vertical-stack
icon: mdi:weather-night
tap_action:
action: call-service
service: scene.turn_on
target:
entity_id: scene.godnat
- type: button
name: Morgen
icon: mdi:weather-sunset-up
tap_action:
action: call-service
service: scene.turn_on
target:
entity_id: scene.morgen
- type: button
name: Hjemme
icon: mdi:home
tap_action:
action: call-service
service: scene.turn_on
target:
entity_id: scene.hjemme
# 🧭 Navigation
- type: grid
cards: cards:
- type: heading
heading: Navigation
- type: button # Temperatur
name: Stue - type: horizontal-stack
icon: mdi:sofa
tap_action:
action: navigate
navigation_path: /lovelace/my-dashboard/stue
- type: button
name: Daniel
icon: mdi:bed
tap_action:
action: navigate
navigation_path: /lovelace/my-dashboard/daniel
- type: button
name: Andreas
icon: mdi:bed
tap_action:
action: navigate
navigation_path: /lovelace/my-dashboard/andreas
- type: button
name: Støvsuger
icon: mdi:robot-vacuum
tap_action:
action: navigate
navigation_path: /lovelace/my-dashboard/vacuum
- type: button
name: Energi
icon: mdi:flash
tap_action:
action: navigate
navigation_path: /lovelace/my-dashboard/energy
# 🌡️ Temperatur
- type: grid
cards: cards:
- type: heading - type: gauge
heading: Temperatur
- type: tile
entity: sensor.n22_temperatur
name: Ude
- type: tile
entity: sensor.sovevaerelse_temperatur entity: sensor.sovevaerelse_temperatur
name: Soveværelse name: Soveværelse
min: 15
- type: tile max: 30
unit: '°C'
- type: gauge
entity: sensor.sovevaerelse_stue_temperatur entity: sensor.sovevaerelse_stue_temperatur
name: Andreas name: Andreas
min: 15
- type: tile max: 30
unit: '°C'
- type: gauge
entity: sensor.sovevaerelse_daniel_temperatur entity: sensor.sovevaerelse_daniel_temperatur
name: Daniel name: Daniel
min: 15
max: 30
unit: '°C'
# CO2
# ⚡ Energi - type: horizontal-stack
- type: grid
cards: cards:
- type: heading - type: gauge
heading: Energi entity: sensor.sovevaerelse_carbon_dioxide
name: Soveværelse
min: 400
max: 2000
unit: 'ppm'
- type: gauge
entity: sensor.sovevaerelse_stue_carbon_dioxide
name: Andreas
min: 400
max: 2000
unit: 'ppm'
- type: gauge
entity: sensor.sovevaerelse_daniel_carbon_dioxide
name: Daniel
min: 400
max: 2000
unit: 'ppm'
- type: tile # Luftfugtighed
- type: horizontal-stack
cards:
- type: gauge
entity: sensor.sovevaerelse_luftfugtighed
name: Soveværelse
min: 20
max: 80
unit: '%'
- type: gauge
entity: sensor.sovevaerelse_stue_luftfugtighed
name: Andreas
min: 20
max: 80
unit: '%'
- type: gauge
entity: sensor.sovevaerelse_daniel_luftfugtighed
name: Daniel
min: 20
max: 80
unit: '%'
# ⚡ Energi + 🍽️ Opvaskemaskine (kompakt)
- type: horizontal-stack
cards:
- type: gauge
entity: sensor.energi_data_service entity: sensor.energi_data_service
name: Elpris name: Elpris
min: 0
max: 5
unit: 'kr/kWh'
severity:
green: 2
yellow: 3
red: 4.5
- type: gauge
entity: sensor.dishwasher_remaining_minutes
name: Opvask
min: 0
max: 180
unit: 'min'
# 🧹 Støvsuger # 🧹 Støvsuger (forenklet mindre støj)
- type: grid - type: entities
cards: title: Støvsuger
- type: heading entities:
heading: Støvsuger - vacuum.roborock_s8_pro_ultra
- sensor.roborock_s8_pro_ultra_status
- type: tile
entity: vacuum.roborock_s8_pro_ultra
- type: tile
entity: sensor.roborock_s8_pro_ultra_status
name: Status
- type: tile
entity: sensor.roborock_s8_pro_ultra_vacuum_error
name: Fejl
# 🍽️ Opvaskemaskine
- type: grid
cards:
- type: heading
heading: Opvaskemaskine
- type: tile
entity: sensor.dishwasher_remaining_time_2
name: Tid tilbage
- type: tile
entity: binary_sensor.dishwasher_svigt
name: Fejl
# 🎵 Sonos # 🎵 Sonos
- type: grid
cards:
- type: heading
heading: Sonos
- type: glance - type: glance
title: Sonos
entities: entities:
- media_player.stue - media_player.stue
- media_player.andreas - media_player.andreas
- media_player.daniel - media_player.daniel
- media_player.kokken - media_player.kokken
- media_player.alrum
- media_player.badevaerelse
- media_player.sovevaerelse
- media_player.lille_badevaerelse
# 📡 Kamera indikator # 📡 Kamera indikator
- type: grid
cards:
- type: heading
heading: Kamera
- type: glance - type: glance
title: Kamera
entities: entities:
- binary_sensor.indkoersel_person - binary_sensor.indkoersel_person
- binary_sensor.indkoersel_vehicle - binary_sensor.indkoersel_vehicle
- binary_sensor.terrasse_person - binary_sensor.terrasse_person
# 🌐 System (let trimmet)
# 🌐 System - type: horizontal-stack
- type: grid
cards: cards:
- type: heading - type: sensor
heading: System
- type: tile
entity: sensor.home_assistant_website entity: sensor.home_assistant_website
name: HA Version name: HA Version
- type: entity
- type: tile
entity: binary_sensor.home_assistant_website_update_available entity: binary_sensor.home_assistant_website_update_available
name: Opdatering name: Opdatering
icon: mdi:update
- type: tile - type: gauge
entity: sensor.speedtest_download entity: sensor.speedtest_download
name: Download name: Download
min: 0
- type: tile max: 1000
unit: 'Mbit/s'
- type: gauge
entity: sensor.speedtest_upload entity: sensor.speedtest_upload
name: Upload name: Upload
min: 0
- type: tile max: 500
entity: sensor.speedtest_ping unit: 'Mbit/s'
name: Ping
+47 -2
View File
@@ -2,12 +2,15 @@ title: Person Status
path: person-status path: person-status
icon: mdi:account-group icon: mdi:account-group
type: sections type: sections
max_columns: 1 # én kolonne for fuld bredde
sections: sections:
# 👨‍👩‍👧‍👦 Personer (2x2 grid)
- type: grid - type: grid
columns: 2
square: false
cards: cards:
- type: heading
heading: Person status
- type: entities - type: entities
title: Daniel title: Daniel
@@ -32,3 +35,45 @@ sections:
entities: entities:
- entity: person.andreas_schusler_dethlefsen - entity: person.andreas_schusler_dethlefsen
- entity: input_select.andreas_status - entity: input_select.andreas_status
# 🗺️ Popup kort nederst
- type: grid
cards:
- type: custom:button-card
name: Åbn kort
icon: mdi:map
show_state: false
styles:
card:
- border-radius: 16px
- padding: 14px
- background: linear-gradient(135deg, rgba(0,0,0,0.05), rgba(0,0,0,0.1))
icon:
- color: var(--primary-color)
name:
- font-size: 14px
- font-weight: 600
tap_action:
action: call-service
service: browser_mod.popup
service_data:
title: 📍 Familien
size: fullscreen
style:
--popup-border-radius: 20px
--popup-background-color: rgba(0,0,0,0.9)
content:
type: map
default_zoom: 12
hours_to_show: 6
aspect_ratio: 1
entities:
- entity: device_tracker.andreas_iphone_12
name: Andreas
- entity: device_tracker.daniels_iphone_7_3
name: Daniel
- entity: device_tracker.annes_iphone_xs_4
name: Anne
- entity: device_tracker.clausiphone
name: Claus
+3 -7
View File
@@ -11,13 +11,9 @@ sections:
- type: heading - type: heading
heading: Støvsuger heading: Støvsuger
- type: custom:roborock-map-card # Statisk kortbillede uden overlay
entity: vacuum.roborock_s8_pro_ultra - type: picture-entity
show_overlay: true entity: image.roborock_s8_pro_ultra_map_0
show_mop: true
show_vacuum: true
map_zoom: 1.0
map_size: 400
name: Kort name: Kort
- type: tile - type: tile
+93 -67
View File
@@ -1,86 +1,112 @@
title: Tesla title: Tesla
path: tesla path: tesla
icon: mdi:car-electric icon: mdi:car-electric
type: sections cards:
sections: # 🔋 Batteri & Opladning
- type: vertical-stack
# 🔋 Batteri og opladning
- type: grid
cards: cards:
- type: heading - type: gauge
heading: Batteri & Opladning entity: sensor.snowywhite_battery_numeric
name: Batteri
min: 0
max: 100
severity:
green: 50
yellow: 20
red: 0
unit: '%'
- type: tile - type: gauge
entity: sensor.snowywhite_battery_level entity: sensor.snowywhite_range_numeric
name: Batteri (%) name: Rækkevidde
min: 0
- type: tile max: 600
entity: sensor.snowywhite_battery_range severity:
name: Rækkevidde (km) green: 400
yellow: 150
- type: tile red: 0
entity: sensor.snowywhite_charge_state unit: 'km'
name: Opladningstilstand
- type: tile
entity: sensor.snowywhite_charge_rate
name: Ladehastighed (km/t)
# 🚗 Døre, låse og tilstand
- type: grid
cards:
- type: heading
heading: Døre & Lås
- type: entities - type: entities
entities: entities:
- lock.snowywhite_door_lock - entity: binary_sensor.snowywhite_charging
- binary_sensor.snowywhite_front_left_door name: Oplader nu?
- binary_sensor.snowywhite_front_right_door - entity: sensor.snowywhite_charging_rate_numeric
- binary_sensor.snowywhite_rear_left_door name: Ladehastighed (km/t)
- binary_sensor.snowywhite_rear_right_door - entity: sensor.snowywhite_energy_added_numeric
- binary_sensor.snowywhite_trunk name: Energi tilføjet (kWh)
- binary_sensor.snowywhite_frunk - entity: sensor.snowywhite_charger_power
name: Charger power (kW)
- entity: sensor.snowywhite_time_charge_complete
name: Forventet fuld opladning
- type: tile - type: horizontal-stack
entity: sensor.snowywhite_vehicle_state cards:
name: Tilstand - type: button
name: Start opladning
icon: mdi:flash-circle
tap_action:
action: call-service
service: switch.turn_on
target:
entity_id: switch.home_charging
- type: button
name: Stop opladning
icon: mdi:flash-off
tap_action:
action: call-service
service: switch.turn_off
target:
entity_id: switch.home_charging
# 🕒 Opladning Timeline (graf)
- type: history-graph
title: Ladeplan / Timeline
entities:
- entity: sensor.snowywhite_charging_numeric
name: Lader nu
- entity: sensor.snowywhite_charging_rate_numeric
name: Ladehastighed
- entity: sensor.snowywhite_energy_added_numeric
name: Energi tilføjet
hours_to_show: 24
refresh_interval: 60
# 🚗 Døre & Lås
- type: entities
title: Døre & Lås
entities:
- binary_sensor.snowywhite_doors
- binary_sensor.snowywhite_windows
- binary_sensor.snowywhite_parking_brake
- binary_sensor.snowywhite_user_present
- sensor.snowywhite_shift_state
# 🌡️ Temperatur # 🌡️ Temperatur
- type: grid - type: horizontal-stack
cards: cards:
- type: heading - type: sensor
heading: Temperatur entity: sensor.snowywhite_temperature_inside
- type: tile
entity: sensor.snowywhite_inside_temp
name: Inde (°C) name: Inde (°C)
- type: sensor
- type: tile entity: sensor.snowywhite_temperature_outside
entity: sensor.snowywhite_outside_temp
name: Ude (°C) name: Ude (°C)
# 📍 Lokation / Ankomst
# 📍 Lokation
- type: map
title: Lokation
default_zoom: 15
entities:
- device_tracker.snowywhite
show_state: true
# 🔧 Maintenance / alerts
- type: grid
cards:
- type: heading
heading: Vedligeholdelse / Alerts
- type: entities - type: entities
title: Ankomst / Distance
entities: entities:
- sensor.snowywhite_maintenance_required - sensor.snowywhite_arrival_time
- sensor.snowywhite_tire_pressure_alert - sensor.snowywhite_distance_to_arrival
- sensor.snowywhite_software_update
# 🔧 Vedligeholdelse / Alerts
- type: entities
title: Vedligeholdelse / Alerts
entities:
- sensor.snowywhite_tpms_front_left
- sensor.snowywhite_tpms_front_right
- sensor.snowywhite_tpms_rear_left
- sensor.snowywhite_tpms_rear_right
- sensor.snowywhite_data_last_update_time
+28
View File
@@ -0,0 +1,28 @@
title: Kort
path: map
icon: mdi:map
type: sections
max_columns: 1
sections:
- type: grid
cards:
- type: heading
heading: Familien live
- type: map
default_zoom: 12
hours_to_show: 6
aspect_ratio: 1
entities:
- entity: device_tracker.andreas_iphone_12
name: Andreas
- entity: device_tracker.daniels_iphone_7_3
name: Daniel
- entity: device_tracker.annes_iphone_xs_4
name: Anne
- entity: device_tracker.clausiphone
name: Claus
@@ -0,0 +1,166 @@
alias: Presence Simulation - Tidsblokke (robust)
mode: restart
trigger:
- platform: time
at: "07:00:00"
- platform: time
at: "12:00:00"
- platform: time
at: "18:00:00"
condition:
- condition: state
entity_id: input_boolean.presence_simulation
state: "on"
action:
- variables:
rand_delay: "{{ range(300,1200) | random }}" # 5-20 min
rand_music: "{{ range(0,100) | random }}"
- choose:
# 🌅 Morgen
- conditions:
- condition: time
after: "06:59:00"
before: "12:00:00"
sequence:
- service: light.turn_on
target:
entity_id:
- light.livingroom
- light.indkoersel_2
- light.andreas_vaerelse
- light.bedroom
- light.daniels_vaerelse
- light.forgang
- delay:
seconds: "{{ rand_delay }}"
- service: light.turn_off
target:
entity_id:
- light.livingroom
- light.indkoersel_2
- light.andreas_vaerelse
- light.bedroom
- light.daniels_vaerelse
- light.forgang
- choose:
- conditions:
- condition: template
value_template: "{{ rand_music < 20 }}"
sequence:
- service: media_player.play_media
target:
entity_id: media_player.kokken
data:
media_content_type: music
media_content_id: "spotify:playlist:37i9dQZF1EVHGWrwldPRtj"
- delay:
seconds: "{{ range(300,900) | random }}"
- service: media_player.media_stop
target:
entity_id: media_player.kokken
# 🌤️ Middag
- conditions:
- condition: time
after: "11:59:00"
before: "18:00:00"
sequence:
- service: light.turn_on
target:
entity_id:
- light.kokken
- light.indkoersel
- delay:
seconds: "{{ rand_delay }}"
- service: light.turn_off
target:
entity_id:
- light.livingroom
- light.indkoersel_2
- light.andreas_vaerelse
- light.bedroom
- light.daniels_vaerelse
- light.forgang
- choose:
- conditions:
- condition: template
value_template: "{{ rand_music < 30 }}"
sequence:
- service: media_player.play_media
target:
entity_id: media_player.kokken
data:
media_content_type: music
media_content_id: "spotify:playlist:37i9dQZF1EVHGWrwldPRtj"
- delay:
seconds: "{{ range(300,900) | random }}"
- service: media_player.media_stop
target:
entity_id: media_player.kokken
# 🌙 Aften
- conditions:
- condition: time
after: "17:59:00"
before: "22:30:00"
sequence:
- service: light.turn_on
target:
entity_id:
- light.livingroom
- light.indkoersel_2
- light.andreas_vaerelse
- light.bedroom
- light.daniels_vaerelse
- light.forgang
- delay:
seconds: "{{ rand_delay }}"
- service: light.turn_off
target:
entity_id:
- light.livingroom
- light.indkoersel_2
- light.andreas_vaerelse
- light.bedroom
- light.daniels_vaerelse
- light.forgang
- choose:
- conditions:
- condition: template
value_template: "{{ rand_music < 50 }}"
sequence:
- service: media_player.play_media
target:
entity_id: media_player.kokken
data:
media_content_type: music
media_content_id: "spotify:playlist:37i9dQZF1EVHGWrwldPRtj"
- delay:
seconds: "{{ range(300,1200) | random }}"
- service: media_player.media_stop
target:
entity_id: media_player.kokken
+15
View File
@@ -0,0 +1,15 @@
alias: Start Vacation Mode
description: Aktiverer presence simulation ved feriestart og planlægger slutdato
trigger:
- platform: time
at: "2026-03-28 14:00:00" # Ferie start
action:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.presence_simulation
# Planlæg slutdato automatisk
- delay:
days: 7
- service: input_boolean.turn_off
target:
entity_id: input_boolean.presence_simulation
+36 -33
View File
@@ -1,71 +1,74 @@
- alias: Tesla smart charging v4 - alias: Tesla smart charging PRO
id: tesla_smart_charging_v4 id: tesla_smart_charging_pro
mode: restart mode: restart
trigger: trigger:
# Kør hvert 5. min (responsiv)
- platform: time_pattern - platform: time_pattern
minutes: "/5" minutes: "/5"
# Sikrer re-evaluering ved ny time
- platform: time_pattern
minutes: "0"
condition: condition:
# Valid future deadline # Deadline gyldig
- condition: template - condition: template
value_template: > value_template: >
{% set deadline = states('input_datetime.tesla_charge_deadline') %} {% set deadline = states('input_datetime.tesla_charge_deadline') %}
{{ deadline not in ['unknown','unavailable',''] {{ deadline not in ['unknown','unavailable',''] and as_timestamp(deadline) > as_timestamp(now()) }}
and as_timestamp(deadline) > as_timestamp(now()) }}
# Car must be connected # Kun når bilen er tilsluttet
- condition: state - condition: template
entity_id: binary_sensor.snowywhite_charger value_template: >
state: "on" {{ states('binary_sensor.tesla_connected') == 'on' }}
action: action:
- variables: - variables:
charge_now: "{{ is_state('binary_sensor.tesla_charge_now', 'on') }}" should_charge: "{{ states('binary_sensor.tesla_charge_now') == 'on' }}"
charger_on: "{{ is_state('switch.home_charging', 'on') }}" last_start: "{{ states('input_datetime.tesla_last_start') }}"
last_start_ts: >
{% if last_start not in ['unknown','unavailable',''] %}
{{ as_timestamp(last_start) }}
{% else %}
0
{% endif %}
runtime: "{{ as_timestamp(now()) - last_start_ts }}"
- choose: - choose:
# ------------------------- # -------------------------
# START charging (cheap hour) # START / CONTINUE CHARGING
# ------------------------- # -------------------------
- conditions: - conditions:
- condition: template - condition: template
value_template: "{{ charge_now and not charger_on }}" value_template: "{{ should_charge }}"
sequence: sequence:
- service: system_log.write # Hvis ikke allerede i gang → registrer start
- condition: template
value_template: >
{{ states('switch.home_charging') != 'on' }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.tesla_last_start
data: data:
message: "Tesla: START charging (cheap hour)" datetime: "{{ now().isoformat() }}"
level: info
- service: switch.turn_on - service: switch.turn_on
target: target:
entity_id: switch.home_charging entity_id: switch.home_charging
# ------------------------- # -------------------------
# STOP charging (not cheap) # STOP CHARGING (med hysterese)
# ------------------------- # -------------------------
- conditions: - conditions:
- condition: template - condition: template
value_template: "{{ not charge_now and charger_on }}" value_template: >
{{ not should_charge and runtime > 3600 }}
sequence: sequence:
- service: system_log.write
data:
message: "Tesla: STOP charging (not cheap)"
level: info
- service: switch.turn_off - service: switch.turn_off
target: target:
entity_id: switch.home_charging entity_id: switch.home_charging
# -------------------------
# Default: do nothing
# -------------------------
- service: system_log.write
data:
message: >
Tesla: No action (charge_now={{ charge_now }},
charger_on={{ charger_on }})
level: debug
+26
View File
@@ -0,0 +1,26 @@
alias: Vacation Mode - Stop ved slutdato
trigger:
- platform: time_pattern
minutes: "/1"
condition:
- condition: state
entity_id: input_boolean.vacation_mode
state: "on"
- condition: template
value_template: >
{% set dt = states('input_datetime.vacation_end') %}
{{ dt not in ['unknown','unavailable',''] and
now() >= as_datetime(dt) }}
action:
- service: input_boolean.turn_off
target:
entity_id:
- input_boolean.vacation_mode
- input_boolean.presence_simulation
- service: media_player.media_stop
target:
entity_id: media_player.kokken
@@ -0,0 +1,26 @@
alias: Vacation Mode - Recovery efter restart
trigger:
- platform: homeassistant
event: start
condition:
- condition: state
entity_id: input_boolean.vacation_mode
state: "on"
action:
- choose:
- conditions:
- condition: template
value_template: >
{% set dt = states('input_datetime.vacation_end') %}
{{ dt not in ['unknown','unavailable',''] and
now() >= as_datetime(dt) }}
sequence:
- service: input_boolean.turn_off
target:
entity_id:
- input_boolean.vacation_mode
- input_boolean.presence_simulation
@@ -0,0 +1,15 @@
alias: Vacation Mode - Manuel stop
trigger:
- platform: state
entity_id: input_boolean.vacation_mode
to: "off"
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.presence_simulation
- service: media_player.media_stop
target:
entity_id: media_player.kokken
+6
View File
@@ -0,0 +1,6 @@
first_run:
initial: off
first_run_eve:
initial: off
first_run_stue:
initial: off
+6
View File
@@ -0,0 +1,6 @@
vacation_mode:
name: Vacation Mode
icon: mdi:beach
presence_simulation:
name: Presence Simulation
+4
View File
@@ -3,3 +3,7 @@ tesla_charge_deadline:
has_date: true has_date: true
has_time: true has_time: true
tesla_last_start:
name: Tesla last charge start
has_date: true
has_time: true
+5
View File
@@ -0,0 +1,5 @@
vacation_end:
name: Vacation End
has_date: true
has_time: true
+21
View File
@@ -0,0 +1,21 @@
- platform: template
sensors:
dishwasher_remaining_minutes:
friendly_name: "Opvask tid tilbage"
unit_of_measurement: "min"
value_template: >
{% set val = states('sensor.dishwasher_remaining_time_2') %}
{% if val in ['unknown','unavailable',''] %}
0
{% elif ':' in val %}
{% set parts = val.split(':') %}
{{ (parts[0] | int * 60) + (parts[1] | int) }}
{% elif 'min' in val %}
{{ val.replace('min','') | int }}
{% else %}
{{ val | int(0) }}
{% endif %}
+60
View File
@@ -0,0 +1,60 @@
# Konverterer batteri til float
- platform: template
sensors:
snowywhite_battery_numeric:
friendly_name: "Batteri (%)"
unit_of_measurement: "%"
value_template: >
{% set val = states('sensor.snowywhite_battery') %}
{% if val not in ['unknown','unavailable',''] %}
{{ val.replace('%','') | float }}
{% else %}
0
{% endif %}
# Konverterer range til float
snowywhite_range_numeric:
friendly_name: "Rækkevidde (km)"
unit_of_measurement: "km"
value_template: >
{% set val = states('sensor.snowywhite_range') %}
{% if val not in ['unknown','unavailable',''] %}
{{ val.replace(' km','') | float }}
{% else %}
0
{% endif %}
# include/sensors/tesla_timeline_numeric.yaml
- platform: template
sensors:
snowywhite_charging_numeric:
friendly_name: "Charging (numeric)"
unit_of_measurement: "1"
value_template: >
{% if is_state('binary_sensor.snowywhite_charging','on') %}
1
{% else %}
0
{% endif %}
# Dette sikrer altid numeric (0 eller 1)
snowywhite_energy_added_numeric:
friendly_name: "Energy Added (kWh)"
unit_of_measurement: "kWh"
value_template: >
{% set val = states('sensor.snowywhite_energy_added') %}
{% if val not in ['unknown','unavailable',''] %}
{{ val | float }}
{% else %}
0
{% endif %}
snowywhite_charging_rate_numeric:
friendly_name: "Charging Rate (km/h)"
unit_of_measurement: "km/h"
value_template: >
{% set val = states('sensor.snowywhite_charging_rate') %}
{% if val not in ['unknown','unavailable',''] %}
{{ val | float }}
{% else %}
0
{% endif %}
+25
View File
@@ -0,0 +1,25 @@
- platform: template
sensors:
n22_dato:
friendly_name: "Dato"
value_template: >
{{ now().strftime('%A %d %B') | replace('Monday','Mandag')
| replace('Tuesday','Tirsdag')
| replace('Wednesday','Onsdag')
| replace('Thursday','Torsdag')
| replace('Friday','Fredag')
| replace('Saturday','Lørdag')
| replace('Sunday','Søndag') }}
n22_solopgang:
friendly_name: "Solopgang"
value_template: >
{% set t = state_attr('sun.sun','next_rising') %}
{{ as_timestamp(t) | timestamp_custom('%H:%M') if t else '-' }}
n22_solnedgang:
friendly_name: "Solnedgang"
value_template: >
{% set t = state_attr('sun.sun','next_setting') %}
{{ as_timestamp(t) | timestamp_custom('%H:%M') if t else '-' }}
+41
View File
@@ -0,0 +1,41 @@
- binary_sensor:
- name: tesla_charge_now
state: >
{% set deadline_raw = states('input_datetime.tesla_charge_deadline') %}
{% set deadline_ts = as_timestamp(deadline_raw) if deadline_raw not in ['unknown','unavailable',''] else none %}
{% set hours_needed = states('sensor.tesla_charge_hours_needed') | float(0) | round(0, 'ceil') %}
{% set prices = (state_attr('sensor.energidataservice','today') or [])
+ (state_attr('sensor.energidataservice','tomorrow') or []) %}
{# Filter gyldige slots før deadline #}
{% set valid = [] %}
{% for p in prices %}
{% if p.hour %}
{% set ts = as_timestamp(p.hour) %}
{% if not deadline_ts or ts <= deadline_ts %}
{% set valid = valid + [p] %}
{% endif %}
{% endif %}
{% endfor %}
{# Sortér kronologisk #}
{% set valid = valid | sort(attribute='hour') %}
{# Find billigste sammenhængende blok #}
{% set best_block = [] %}
{% set best_price = 999 %}
{% for i in range(0, (valid | length) - hours_needed + 1) %}
{% set block = valid[i:i+hours_needed] %}
{% set total = block | map(attribute='price') | sum %}
{% if total < best_price %}
{% set best_price = total %}
{% set best_block = block %}
{% endif %}
{% endfor %}
{% set now_slot = now().replace(minute=0, second=0, microsecond=0).isoformat() %}
{{ best_block | selectattr('hour','equalto',now_slot) | list | count > 0 }}
-74
View File
@@ -1,74 +0,0 @@
sensors:
tesla_kwh_needed:
friendly_name: "Tesla kWh Needed"
unit_of_measurement: "kWh"
value_template: >
{% set capacity = 75 %}
{% set soc = states('sensor.snowywhite_battery') | float(0) %}
{% set limit = states('number.snowywhite_charge_limit') | float(100) %}
{{ [0, ((limit - soc)/100 * capacity)] | max | round(2) }}
tesla_charge_hours_needed:
friendly_name: "Tesla Charge Hours Needed"
unit_of_measurement: "h"
value_template: >
{% set power = 11 %}
{% set kwh = states('sensor.tesla_kwh_needed') | float(0) %}
{{ (kwh / power)|round(2) }}
tesla_charging_plan:
friendly_name: "Tesla Charging Plan"
value_template: >
{% set deadline_raw = states('input_datetime.tesla_charge_deadline') %}
{% set deadline_ts = as_timestamp(deadline_raw)
if deadline_raw not in ['unknown','unavailable',''] else none %}
{% set hours_needed = [1,
states('sensor.tesla_charge_hours_needed') | float(0) | round(0, 'ceil')
] | max %}
{% set prices = (state_attr('sensor.energidataservice','today') or [])
+ (state_attr('sensor.energidataservice','tomorrow') or []) %}
{% set valid = [] %}
{% for p in prices %}
{% if p.hour is defined and p.hour %}
{% set ts = as_timestamp(p.hour) %}
{% if not deadline_ts or ts <= deadline_ts %}
{% set valid = valid + [p] %}
{% endif %}
{% endif %}
{% endfor %}
{% set cheapest = (valid | sort(attribute='price'))[:hours_needed] %}
{% set times = cheapest
| map(attribute='hour')
| map('as_timestamp')
| map('timestamp_local')
| list %}
{{ times | join(', ') if times | count > 0 else 'none' }}
binary_sensors:
tesla_charge_now:
friendly_name: "Tesla Charge Now"
device_class: power
value_template: >
{% set hours_needed = [1, states('sensor.tesla_charge_hours_needed') | float(0) | round(0, 'ceil')] | max %}
{% set deadline_raw = states('input_datetime.tesla_charge_deadline') %}
{% set deadline_ts = as_timestamp(deadline_raw) if deadline_raw not in ['unknown','unavailable',''] else none %}
{% set prices = (state_attr('sensor.energidataservice','today') or []) + (state_attr('sensor.energidataservice','tomorrow') or []) %}
{% set valid_prices = [] %}
{% for p in prices %}
{% if p.hour is defined and p.hour %}
{% set ts = as_timestamp(p.hour) %}
{% if not deadline_ts or ts <= deadline_ts %}
{% set valid_prices = valid_prices + [p] %}
{% endif %}
{% endif %}
{% endfor %}
{% set cheapest = (valid_prices | sort(attribute='price'))[:hours_needed] %}
{% set now_ts = now().replace(minute=0, second=0, microsecond=0).timestamp() %}
{% set cheapest_ts = cheapest | map(attribute='hour') | map('as_timestamp') | list %}
{{ now_ts in cheapest_ts }}
+31
View File
@@ -0,0 +1,31 @@
Jeg arbejder med Home Assistant version 2026.3.3.
Min konfiguration er 100% YAML-baseret og opdelt via !include_dir_merge_* og !include i en struktureret mappestruktur (templates, sensors, automations, binary_sensors, input_*, osv.). Jeg forventer løsninger, der respekterer denne opdeling og er direkte kompatible med en splittet konfiguration.
Jeg bruger standard Lovelace (YAML mode) ikke UI editor og ikke Dwains Dashboard. Alle dashboards skal derfor leveres som valid Lovelace YAML.
Antag følgende:
- Jeg er erfaren HA-bruger
- Jeg ønsker robuste, produktionsegnet løsninger
- Jeg prioriterer stabilitet over “smart hacks”
- Jeg vil undgå unknown/unavailable states og template-fejl
- Jeg vil have korrekt datatype-håndtering (float/int/string)
- Jeg vil minimere race conditions og edge cases
Når du svarer:
- Giv altid copy-paste klar YAML
- Indiker hvor filer skal placeres (fx include/sensors/xxx.yaml)
- Brug defensive templates (default værdier, checks for unknown/unavailable)
- Undgå deprecated eller UI-only features
- Optimer for performance (undgå unødvendige loops / tunge templates)
- Forklar kort hvorfor løsningen er korrekt men vær præcis og teknisk
Hvis relevant:
- Foreslå forbedringer i arkitektur (ikke kun fixes)
- Identificér potentielle fejl før de opstår
- Prioritér simplicity + robustness over kompleksitet
Kort sagt: agér som en Home Assistant arkitekt/debugger og optimer min opsætning.
Skriv en commit besked som jeg kan bruge til git.
+4 -1
View File
@@ -2,8 +2,11 @@
# 1. Resources til custom cards # 1. Resources til custom cards
resources: resources:
- url: /hacsfiles/lovelace-xiaomi-vacuum-map-card/roborock-map-card.js - url: /hacsfiles/lovelace-xiaomi-vacuum-map-card/xiaomi-vacuum-map-card.js
type: module type: module
- url: /hacsfiles/button-card/button-card.js
type: module
# 2. Selve views # 2. Selve views
views: !include_dir_list dashboards/views views: !include_dir_list dashboards/views