From dc821a5769a19052e0f920efb2d243cde19ddf08 Mon Sep 17 00:00:00 2001 From: Claus Dethlefsen Date: Sat, 20 Jun 2026 19:24:19 +0200 Subject: [PATCH] =?UTF-8?q?Ventilator:=20tilf=C3=B8j=20t=C3=A6nd/sluk=20+?= =?UTF-8?q?=20sluk-timer=20knapper=20for=20Andreas=20og=20Daniel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboards/views/01_home.yaml.bak | 913 ++++++++++++++++++ dashboards/views/03_andreas.yaml | 44 + dashboards/views/04_daniel.yaml | 44 + dashboards/views/06c_indkorsel_snapshots.yaml | 2 +- include/input/number/andreas.yaml | 9 + include/input/number/daniel.yaml | 9 + include/scripts/ventilator_timer.yaml | 21 + www/mealie.json | 2 +- 8 files changed, 1042 insertions(+), 2 deletions(-) create mode 100644 dashboards/views/01_home.yaml.bak create mode 100644 include/scripts/ventilator_timer.yaml diff --git a/dashboards/views/01_home.yaml.bak b/dashboards/views/01_home.yaml.bak new file mode 100644 index 0000000..5abee09 --- /dev/null +++ b/dashboards/views/01_home.yaml.bak @@ -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 => `
${r[0]}${r[1]}
`).join(''); + return `
+
Liter i dag
+
${total} L
+
${list}
+
`; + ]]] + 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 => `
${r[0]}${r[1]} min
`).join(''); + return `
+
Tid i dag
+
${total} min
+
${list}
+
`; + ]]] + 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 + diff --git a/dashboards/views/03_andreas.yaml b/dashboards/views/03_andreas.yaml index fab22b4..56e4c50 100644 --- a/dashboards/views/03_andreas.yaml +++ b/dashboards/views/03_andreas.yaml @@ -255,6 +255,50 @@ sections: - word-break: break-word - 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 cards: - type: heading diff --git a/dashboards/views/04_daniel.yaml b/dashboards/views/04_daniel.yaml index f99b73d..ba08738 100644 --- a/dashboards/views/04_daniel.yaml +++ b/dashboards/views/04_daniel.yaml @@ -255,6 +255,50 @@ sections: - word-break: break-word - 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 cards: - type: heading diff --git a/dashboards/views/06c_indkorsel_snapshots.yaml b/dashboards/views/06c_indkorsel_snapshots.yaml index c8f522a..86a677b 100644 --- a/dashboards/views/06c_indkorsel_snapshots.yaml +++ b/dashboards/views/06c_indkorsel_snapshots.yaml @@ -5,5 +5,5 @@ panel: true cards: - type: iframe - url: /local/snapshots/indkorsel_loader.html?v=20260619185107 + url: /local/snapshots/indkorsel_loader.html?v=20260620192035 aspect_ratio: 100% diff --git a/include/input/number/andreas.yaml b/include/input/number/andreas.yaml index b5df4b8..be87004 100644 --- a/include/input/number/andreas.yaml +++ b/include/input/number/andreas.yaml @@ -21,3 +21,12 @@ andreas_brightness: step: 1 unit_of_measurement: "%" 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 diff --git a/include/input/number/daniel.yaml b/include/input/number/daniel.yaml index a64050d..373e29c 100644 --- a/include/input/number/daniel.yaml +++ b/include/input/number/daniel.yaml @@ -21,3 +21,12 @@ daniel_brightness: step: 1 unit_of_measurement: "%" 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 diff --git a/include/scripts/ventilator_timer.yaml b/include/scripts/ventilator_timer.yaml new file mode 100644 index 0000000..506b42a --- /dev/null +++ b/include/scripts/ventilator_timer.yaml @@ -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 diff --git a/www/mealie.json b/www/mealie.json index 010b683..066af15 100644 --- a/www/mealie.json +++ b/www/mealie.json @@ -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"}}]} \ No newline at end of file +{"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"}}]} \ No newline at end of file