Sauber umsetzen

Bevor du das YAML übernimmst

Nimm den Code als Vorlage, nicht als blind kopierbaren Endzustand. Die entscheidenden Stellen solltest du vor dem Speichern an dein eigenes Setup anpassen.

Voraussetzungen
  • Laufendes Home Assistant
  • Sections-Layout und benötigte Custom Cards
  • Eigene Kamera-, Temperatur- und Media-Entities
Hilft dir bei

Dashboard-Projekt mit YAML · Fortgeschritten · Eigene Werte anpassen

Bei YAML immer anpassen
  • Entity-IDs und Bereiche
  • Pfadnamen, Browser-IDs oder Helfer
  • Installierte Custom Cards und Integrationen

Diese View ist die Startseite unter /dashboard-haus/haus. Sie nutzt das moderne Sections-Layout mit bis zu drei Spalten und zeigt direkt die wichtigsten Zustände im Haus.

Was die Home View enthält

  • Temperatur-Badges für Kinderzimmer, Küche, Flur, Werkstatt und Garage.
  • Mehrere Live-Kamera-Kacheln über custom:webrtc-camera.
  • Ein fest positioniertes Radio/Musik-Widget unten rechts.
  • Navigation per Tap auf das Radio-Widget zur Radio-View.
  • Doppeltippen startet oder pausiert den hinterlegten Player media_player.kuche_2.

Wichtige Entities und Pfade

Code
sensor.temperatur_kinderzimmer_temperatur
sensor.ztemp104_temperature
sensor.ztemp101_temperature
sensor.ztemp102_temperature
sensor.ztemp103_temperature
media_player.kuche_2
/dashboard-haus/radio

Kompletter YAML-Code

YAML-Hilfe

Vor dem Einsetzen kurz prüfen

  • Ersetze Entity-IDs, Pfade und Namen durch deine eigenen Werte.
  • Prüfe, ob die genannte Card, Integration oder Erweiterung wirklich installiert ist.
  • Teste die Änderung zuerst in einem kleinen Bereich, bevor du das ganze Dashboard umbaust.
YAML
- title: Home
    path: haus
    type: sections
    max_columns: 3
    cards: []
    background:
      opacity: 40
      alignment: center
      size: cover
      repeat: repeat
      attachment: fixed
    badges:
      - type: entity
        entity: sensor.temperatur_kinderzimmer_temperatur
        name: Hanna
        color: teal
        show_name: true
        show_state: true
        show_icon: true
      - type: entity
        entity: sensor.ztemp104_temperature
        name: Küche 2. OG
        color: teal
        show_name: true
        show_state: true
        show_icon: true
      - type: entity
        entity: sensor.ztemp101_temperature
        name: Flur 1. OG
        color: teal
        show_name: true
        show_state: true
        show_icon: true
      - type: entity
        entity: sensor.ztemp102_temperature
        name: Werkstatt
        color: teal
        show_name: true
        show_state: true
        show_icon: true
      - type: entity
        entity: sensor.ztemp103_temperature
        name: Garage
        color: teal
        show_name: true
        show_state: true
        show_icon: true
    sections:
      - type: grid
        cards:
          - type: custom:webrtc-camera
            url: vorplatz
            server: http://DEIN-GO2RTC-SERVER:1984/
            muted: true
            mode: mse
      - type: grid
        cards:
          - type: custom:webrtc-camera
            url: vorplatz2
            server: http://DEIN-GO2RTC-SERVER:1984/
            muted: true
      - type: grid
        cards:
          - type: custom:webrtc-camera
            url: garten_eingang
            server: http://DEIN-GO2RTC-SERVER:1984/
            muted: true
      - type: grid
        cards:
          - type: custom:webrtc-camera
            url: garten
            server: http://DEIN-GO2RTC-SERVER:1984/
            muted: true
            mode: mse
      - type: grid
        cards:
          - type: custom:webrtc-camera
            url: werkstatt
            server: http://DEIN-GO2RTC-SERVER:1984/
            muted: true
            mode: mse
      - type: grid
        cards:
          - type: custom:webrtc-camera
            url: garage
            server: http://DEIN-GO2RTC-SERVER:1984/
            muted: true
            mode: mse
          - type: custom:button-card
            entity: media_player.kuche_2
            show_name: false
            show_state: false
            show_icon: false
            view_layout:
              position: sidebar
            variables:
              card_width: 320px
              card_height: 120px
              card_bottom: 18px
              card_right: 18px
              card_radius: 22px
              logo_size: 79px
              logo_left: 12px
              text_left: 110px
              font_size_title: 15px
              font_size_artist: 12px
              font_size_hint: 11px
            tap_action:
              action: navigate
              navigation_path: /dashboard-haus/radio
            double_tap_action:
              action: call-service
              service: >-
                [[[ return entity.state === 'playing' ?
                'media_player.media_pause' : 'media_player.play_media'; ]]]
              target:
                entity_id: media_player.kuche_2
              data: >-
                [[[ return entity.state === 'playing' ? {} : {
                media_content_type: 'url', media_content_id:
                'tunein--kqdEaHjB://radio/s15496' }; ]]]
            hold_action:
              action: call-service
              service: media_player.media_play_pause
              target:
                entity_id: media_player.kuche_2
            styles:
              card:
                - position: fixed
                - bottom: "[[[ return variables.card_bottom; ]]]"
                - right: "[[[ return variables.card_right; ]]]"
                - width: "[[[ return variables.card_width; ]]]"
                - height: "[[[ return variables.card_height; ]]]"
                - z-index: 999
                - background: >-
                    linear-gradient(135deg, rgba(0,161,136,.28) 0%,
                    rgba(17,17,20,.98) 48%, rgba(17,17,20,.98) 100%)
                - border-radius: "[[[ return variables.card_radius; ]]]"
                - border: 1px solid rgba(255,255,255,.09)
                - box-shadow: 0 16px 45px rgba(0,0,0,.45)
                - overflow: hidden
              custom_fields:
                logo:
                  - position: absolute
                  - left: "[[[ return variables.logo_left; ]]]"
                  - top: 10px
                  - width: "[[[ return variables.logo_size; ]]]"
                  - height: "[[[ return variables.logo_size; ]]]"
                badge:
                  - position: absolute
                  - left: "[[[ return variables.logo_left; ]]]"
                  - bottom: 6px
                title:
                  - position: absolute
                  - top: calc(50% - 20px)
                  - left: "[[[ return variables.text_left; ]]]"
                  - right: 16px
                  - font-size: "[[[ return variables.font_size_title; ]]]"
                  - font-weight: 600
                  - color: white
                  - text-align: left
                  - white-space: nowrap
                  - overflow: hidden
                  - text-overflow: ellipsis
                artist:
                  - position: absolute
                  - top: calc(50% + 4px)
                  - left: "[[[ return variables.text_left; ]]]"
                  - right: 16px
                  - font-size: "[[[ return variables.font_size_artist; ]]]"
                  - font-weight: 300
                  - color: rgba(255,255,255,0.65)
                  - text-align: left
                  - white-space: nowrap
                  - overflow: hidden
                  - text-overflow: ellipsis
                hint:
                  - position: absolute
                  - top: 50%
                  - transform: translateY(-50%)
                  - left: "[[[ return variables.text_left; ]]]"
                  - right: 16px
                  - font-size: "[[[ return variables.font_size_hint; ]]]"
                  - color: rgba(0,220,180,0.9)
                  - text-align: left
            custom_fields:
              logo: |
                [[[
                  const isPaused = entity.state !== 'playing';
                  const albumName = entity.attributes.media_album_name || '';
                  const entityPicture = entity.attributes.entity_picture || '';
                  const mediaContentId = entity.attributes.media_content_id || '';
                  if (mediaContentId.includes('spotify:')) {
                    return `<img src="${entityPicture}" style="width:100%;height:100%;object-fit:cover;border-radius:14px;${isPaused ? 'filter:blur(3px);opacity:0.5;' : ''}">`;
                  }
                  const isMunot = albumName.includes('Munot') || mediaContentId.includes('s15496') || entityPicture.includes('s15496');
                  const isRadio24 = albumName.includes('Radio 24') || mediaContentId.includes('s2773') || entityPicture.includes('s2773');
                  let logoSrc = '/local/radio-logos/flashbackfm.png';
                  if (isMunot) logoSrc = '/local/radio-logos/radiomunot.png';
                  else if (isRadio24) logoSrc = '/local/radio-logos/radio24.png';
                  return `<img src="${logoSrc}" style="width:100%;height:100%;object-fit:contain;${isPaused ? 'filter:blur(3px);opacity:0.5;' : ''}">`;
                ]]]
              badge: |
                [[[
                  const isPlaying = entity.state === 'playing';
                  if (isPlaying) {
                    return `
                      <style>
                        @keyframes _p2{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.7)}}
                        @keyframes _e2{0%,100%{transform:scaleY(1)}50%{transform:scaleY(.2)}}
                        ._d2{animation:_p2 1.4s ease-in-out infinite}
                        ._c1{animation:_e2 .9s linear infinite}._c2{animation:_e2 .7s linear infinite}
                        ._c3{animation:_e2 1.1s linear infinite}._c4{animation:_e2 .8s linear infinite}
                      </style>
                      <div style="display:flex;align-items:center;gap:4px;background:rgba(0,0,0,.4);border:1px solid rgba(0,220,180,.28);border-radius:20px;padding:3px 8px;">
                        <div class="_d2" style="width:5px;height:5px;border-radius:50%;background:#00dcb4;flex-shrink:0;"></div>
                        <span style="font-size:9px;font-weight:700;letter-spacing:1.2px;color:#00dcb4;">LÄUFT</span>
                        <div style="display:flex;align-items:flex-end;gap:2px;height:10px;margin-left:2px;">
                          <div class="_c1" style="width:2px;height:5px;border-radius:1px;background:#00dcb4;transform-origin:bottom;"></div>
                          <div class="_c2" style="width:2px;height:9px;border-radius:1px;background:#00dcb4;transform-origin:bottom;"></div>
                          <div class="_c3" style="width:2px;height:6px;border-radius:1px;background:#00dcb4;transform-origin:bottom;"></div>
                          <div class="_c4" style="width:2px;height:10px;border-radius:1px;background:#00dcb4;transform-origin:bottom;"></div>
                        </div>
                      </div>`;
                  } else {
                    return `
                      <div style="display:flex;align-items:center;background:rgba(0,0,0,.4);border:1px solid rgba(255,255,255,.12);border-radius:20px;padding:3px 8px;">
                        <span style="font-size:9px;font-weight:700;letter-spacing:1.2px;color:rgba(255,255,255,.4);">PAUSIERT</span>
                      </div>`;
                  }
                ]]]
              title: |
                [[[
                  if (entity.state !== 'playing') return '';

                  const isMunot =
                    (entity.attributes.media_album_name || '').includes('Munot') ||
                    (entity.attributes.media_content_id || '').includes('s15496');

                  const text = isMunot
                    ? (entity.attributes.media_artist || '')
                    : (entity.attributes.media_title || 'Radio');

                  if (text.length <= 18) {
                    return `<div style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">${text}</div>`;
                  }

                  return `
                  <style>
                    @keyframes marquee_title {
                      0% { transform: translateX(0); }
                      12% { transform: translateX(0); }
                      88% { transform: translateX(calc(-100% + 190px)); }
                      100% { transform: translateX(calc(-100% + 190px)); }
                    }
                  </style>
                  <div style="overflow:hidden;white-space:nowrap;width:100%;">
                    <div style="
                      display:inline-block;
                      padding-right:40px;
                      animation:marquee_title 11s linear infinite;
                    ">
                      ${text}
                    </div>
                  </div>`;
                ]]]
              artist: |
                [[[
                  if (entity.state !== 'playing') return '';

                  const isMunot =
                    (entity.attributes.media_album_name || '').includes('Munot') ||
                    (entity.attributes.media_content_id || '').includes('s15496');

                  const text = isMunot
                    ? (entity.attributes.media_title || '')
                    : (entity.attributes.media_artist || entity.attributes.media_album_name || '');

                  if (text.length <= 22) {
                    return `<div style="overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">${text}</div>`;
                  }

                  return `
                  <style>
                    @keyframes marquee_artist {
                      0% { transform: translateX(0); }
                      12% { transform: translateX(0); }
                      88% { transform: translateX(calc(-100% + 190px)); }
                      100% { transform: translateX(calc(-100% + 190px)); }
                    }
                  </style>
                  <div style="overflow:hidden;white-space:nowrap;width:100%;">
                    <div style="
                      display:inline-block;
                      padding-right:40px;
                      animation:marquee_artist 12s linear infinite;
                    ">
                      ${text}
                    </div>
                  </div>`;
                ]]]
              hint: |
                [[[
                  if (entity.state !== 'playing') return 'Doppelklick um Radio zu starten';
                  return '';
                ]]]
    footer:
      max_width: 360
    dense_section_placement: true