Lovelace pour panneaux photovoltaïques

Sur des sites anglais j’en ai fais énormément je ne sais plus pourquoi ?

J’aurai voulu voir l’exemple car on est sur une animation complexe avec du dessin vectoriel dynamique, chose que je ne maitrise pas du tout, notamment la définition du path. La vague doit pouvoir être reproduite plus simplement avec une transition linéaire d’une image .png avec un positionnement en fonction de la valeur de production. L’inconvénient sera qu’il faudra ajouter l’image dans le répertoire www.

Désolé , je viens de voir la réponse. Maintenant . Il y a une partie sur ce site :

Voilà, je sais que j’avais récupéré ailleurs mais j’ai vraiment passé une journée à faire du copier-coller et à prendre sur plusieurs sites.
Recherche Google svg css wave

Ca OK pour obtenir le SVG des vagues, mais où as tu trouvé l’intégration dans custom:button-card ?

J’essaie de rechercher mon historique ce soir sa va être compliqué j’ai tellement fait de site et test :pensive:

T’embête pas je vais voir ce que j’arrive à faire avec une transition en boucle d’une image .png dans un custom_field et un autre custom_field pour le remplissage sous les vagues.

J’avais trouvé ce site pour le SVG : SVG Wave Generator – Create SVG waves for your designs

J’avais noté dans mes notes du téléphone :
SVG dans custom_fields
CSS dans extra_styles

Puis ce code :

<svg width="100%" height="100%" viewBox="0 0 1440 490" xmlns="http://www.w3.org/2000/svg" class="transition duration-300 ease-in-out delay-150">
  <defs>
    <linearGradient id="gradient" x1="6%" y1="26%" x2="94%" y2="74%">
      <stop offset="5%" stop-color="#fcb900"></stop>
      <stop offset="95%" stop-color="#fcb900"></stop>
    </linearGradient>
  </defs>
  <path d="M 0,500 L 0,125 C 36.62659329785079,154.7893472229357 73.25318659570158,184.57869444587143 109,161 C 144.74681340429842,137.42130555412857 179.61384691504446,60.47456943944994 217,64 C 254.38615308495554,67.52543056055006 294.29142574412043,151.52302779632876 338,176 C 381.70857425587957,200.47697220367124 429.2204501084738,165.43331937523496 460,135 C 490.7795498915262,104.56668062476504 504.82677382198403,78.74369470273136 538,74 C 571.173226178016,69.25630529726864 623.4724546035901,85.59190181383966 660,110 C 696.5275453964099,134.40809818616034 717.2834077636552,166.88869804190998 758,158 C 798.7165922363448,149.11130195809002 859.3939143417894,98.85330601852034 902,101 C 944.6060856582106,103.14669398147966 969.1409348691874,157.6980778840086 995,181 C 1020.8590651308126,204.3019221159914 1048.0423461814607,196.3543824454452 1090,179 C 1131.9576538185393,161.6456175545548 1188.6896804049693,134.88439233421056 1230,114 C 1271.3103195950307,93.11560766578944 1297.1989321986623,78.10804821771255 1335,82 C 1372.8010678013377,85.89195178228745 1422.5145908003824,108.68341479493927 1442,119 C 1461.4854091996176,129.31658520506073 1450.7427045998088,127.15829260253037 1440,125 L 1440,500 L 0,500 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="0.53"></path>
  <path d="M 0,500 L 0,291 C 26.37431852071593,300.5776664612242 52.74863704143186,310.1553329224484 96,317 C 139.25136295856814,323.8446670775516 199.37977035498852,327.95633477143076 238,312 C 276.6202296450115,296.04366522856924 293.73228153861396,260.0193279918285 329,271 C 364.26771846138604,281.9806720081715 417.6911034905557,339.9663532612554 456,332 C 494.3088965094443,324.0336467387446 517.5033044991634,250.11525896314998 555,253 C 592.4966955008366,255.88474103685002 644.2956785127907,335.57261088614484 677,352 C 709.7043214872093,368.42738911385516 723.3139814496736,321.5942974922707 760,305 C 796.6860185503264,288.4057025077293 856.4483956885146,302.05019914477236 896,300 C 935.5516043114854,297.94980085522764 954.8924357962678,280.2049059286398 985,274 C 1015.1075642037322,267.7950940713602 1055.9818611264145,273.1301771406683 1094,273 C 1132.0181388735855,272.8698228593317 1167.1801196980743,267.27438550868686 1207,266 C 1246.8198803019257,264.72561449131314 1291.2976600812876,267.7722808245843 1338,267 C 1384.7023399187124,266.2277191754157 1433.6292399767751,261.63649119297594 1451,265 C 1468.3707600232249,268.36350880702406 1454.1853800116123,279.68175440351206 1440,291 L 1440,500 L 0,500 Z" stroke="none" stroke-width="0" fill="url(#gradient)" fill-opacity="1"></path>
</svg>

Ensuite j’en ai trouvé d’autres et c’est là où mes notes ont disparu. Et ce matin j’ai dû faire un restaure de home assistant donc je n’ai même pas toutes les cartes testées.

Trouvé sur le net avec plein de test de ma part :

@keyframes wave {
    0% { transform: translateX(0); }
    100% { transform: translateX(-100%); }
  }
  .wave-container {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 50%;
    overflow: hidden;
  }

J’essaie encore, pour le moment j’ai triché dans le code, car je n’arrive pas à grandir les vagues…

1000778555

type: custom:button-card
entity: input_number.test
show_name: false
show_state: true
state_display: '[[[ return states[entity.entity_id].state + " W"; ]]]'
styles:
  card:
    - left: 130px
    - margin-bottom: 10px
    - height: 150px
    - width: 150px
    - font-size: 20px
    - font-weight: bold
    - line-height: 150px
    - border-radius: 75px
    - background-color: dimgrey
    - position: relative
    - overflow: hidden
    - display: flex
    - align-items: center
    - justify-content: center
    - background: |
        [[[
          var value = parseFloat(states['input_number.test'].state);
          var max = 6400;
          var color = 'orange';
          var percent = Math.min(100, (value/max*100)) -20;
          return `linear-gradient(to top, ${color} ${percent}%, transparent ${percent}%)`;
        ]]]
  state:
    - color: red
    - text-align: center
    - font-size: 20px
    - font-weight: bold
    - z-index: 2
extra_styles: |
  @keyframes wave {
    0% { transform: translateX(0); }
    100% { transform: translateX(-50%); }
  }
  .wave-container {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    align-items: flex-end;
    background-color: transparent;
  }
  .wave {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 200%;
    height: 200%;
    fill: rgba(255, 165, 0, 0.5);
    animation: wave 4s infinite linear;
    transform-origin: bottom;
  }
  .wave:nth-of-type(2) {
    fill: rgba(255, 165, 0, 0.7);
    animation: wave 4s infinite linear;
    animation-delay: -1.33s;
  }
  .wave:nth-of-type(3) {
    fill: rgba(255, 165, 0, 0.3);
    animation: wave 4s infinite linear;
    animation-delay: -2.66s;
  }
custom_fields:
  wave: |
    [[[ 
      var value = parseFloat(states['input_number.test'].state);
      var max = 6400;
      var percent = Math.min(100, (value / max * 100));
      var height = percent + "%";
      return `
        <div class="wave-container" style="height: ${height};">
          <svg class="wave" viewBox="0 0 1440 320"><path d="M0,224L48,213.3C96,203,192,181,288,165.3C384,149,480,139,576,144C672,149,768,171,864,197.3C960,224,1056,256,1152,250.7C1248,245,1344,203,1392,181.3L1440,160L1440,320L0,320Z"></path></svg>
          <svg class="wave" viewBox="0 0 1440 320"><path d="M0,288L48,272C96,256,192,224,288,208C384,192,480,192,576,213.3C672,235,768,277,864,288C960,299,1056,277,1152,250.7C1248,224,1344,192,1392,176L1440,320L0,320Z"></path></svg>
          <svg class="wave" viewBox="0 0 1440 320"><path d="M0,160L48,170.7C96,181,192,203,288,218.7C384,235,480,245,576,240C672,235,768,213,864,202.7C960,192,1056,192,1152,181.3C1248,171,1344,149,1392,138.7L1440,320L0,320Z"></path></svg>
        </div>
      `;
    ]]]

Bonjour , comme je n’arrive pas à grandir les vagues, j’ai décidé de faire varier la vitesse suivant les paliers de production (tous les 500w)

type: custom:button-card
entity: sensor.total_inverter_power
show_name: false
show_state: true
state_display: '[[[ return states[entity.entity_id].state + " W"; ]]]'
styles:
  card:
    - left: 125px
    - height: 150px
    - width: 150px
    - font-size: 20px
    - font-weight: bold
    - line-height: 150px
    - border-radius: 75px
    - position: relative
    - overflow: hidden
    - background-color: dimgrey
    - display: flex
    - align-items: center
    - justify-content: center
    - animation: pulse-grow 3s infinite ease-in-out
  state:
    - color: white
    - text-align: center
    - font-size: 20px
    - font-weight: bold
extra_styles: |
  @keyframes pulse-grow {
    0%, 100% {
      box-shadow: 0 0 0 0 rgba(255, 165, 0, 0.7);
      transform: scale(1);
    }
    50% {
      box-shadow: 0 0 0 10px rgba(255, 165, 0, 0);
      transform: scale(1.1);
    }
  }
  @keyframes wave {
    0% { transform: translateX(0); }
    100% { transform: translateX(-50%); }
  }
  .wave-container {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    align-items: flex-end;
  }
  .wave {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 200%;
    height: 44%;
    fill: rgba(255, 165, 0, 0.5);
    animation: wave infinite linear;
    transform-origin: bottom;
  }
  .wave:nth-of-type(2) {
    fill: rgba(255, 165, 0, 0.7);
    animation: wave infinite linear;
    animation-delay: -1s;
    transform-origin: bottom;
  }
  .wave:nth-of-type(3) {
    fill: rgba(255, 165, 0, 0.3);
    animation: wave infinite linear;
    animation-delay: -2s;
    transform-origin: bottom;
  }
custom_fields:
  wave: |
    [[[
      const value = parseFloat(states['sensor.total_inverter_power'].state);
      const max = 6400;
      let duration;

      if (value <= 500) {
        duration = '5s';
      } else if (value <= 1000) {
        duration = '4.5s';
      } else if (value <= 1500) {
        duration = '4s';
      } else if (value <= 2000) {
        duration = '3.5s';
      } else if (value <= 2500) {
        duration = '3s';
      } else if (value <= 3000) {
        duration = '2.8s';
      } else if (value <= 3500) {
        duration = '2.6s';
      } else if (value <= 4000) {
        duration = '2.5s';
      } else if (value <= 4500) {
        duration = '2s';
      } else if (value <= 5000) {
        duration = '1.5s';
      } else {
        duration = '1s';
      }

      const percent = Math.min(100, (value / max * 100));
      const scale = percent / 100;

      return `
        <div class="wave-container">
          <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,224L48,213.3C96,203,192,181,288,165.3C384,149,480,139,576,144C672,149,768,171,864,197.3C960,224,1056,256,1152,250.7C1248,245,1344,203,1392,181.3L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
          <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,288L48,272C96,256,192,224,288,208C384,192,480,192,576,213.3C672,235,768,277,864,288C960,299,1056,277,1152,250.7C1248,224,1344,192,1392,176L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
          <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,160L48,170.7C96,181,192,203,288,218.7C384,235,480,245,576,240C672,235,768,213,864,202.7C960,192,1056,192,1152,181.3C1248,171,1344,149,1392,138.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
        </div>
      `;
    ]]]

Très curieux de voir le résultat final. Je trouve que ça reprend l’esthétique de l’appli APSystems. J’aimerai pouvoir aider mais c’est au delà de mes connaissances.

J’ai encore changé, j’ai mis un fond blanc et écriture en noir.
j’ai créé un capteur pour tester les valeurs sa évite d’attendre le soleil

Bonjour voila un nouveau test

1000779098

Salut, tu peux partager ton code final du coup ?
Merci

Salut, pas de soucis. Voici le code complet :

type: vertical-stack
title: Panneaux photovoltaïques
cards:
  - type: custom:button-card
    entity: sensor.ecu_current_power
    show_name: false
    show_state: true
    state_display: '[[[ return states[entity.entity_id].state + " W"; ]]]'
    styles:
      card:
        - left: 125px
        - height: 150px
        - width: 150px
        - font-size: 20px
        - font-weight: bold
        - line-height: 150px
        - border-radius: 75px
        - position: relative
        - overflow: hidden
        - background-color: whitesnow
        - display: flex
        - align-items: center
        - justify-content: center
        - margin: 0 auto
        - display: block
      state:
        - color: black
        - text-align: center
        - font-size: 20px
        - font-weight: bold
        - z-index: 2
    extra_styles: |
      @keyframes pulse-grow {
        0%, 100% {
          box-shadow: 0 0 0 0 rgba(255, 165, 0, 0.7);
          transform: scale(1);
        }
        50% {
          box-shadow: 0 0 0 10px rgba(255, 165, 0, 0);
          transform: scale(1.1);
        }
      }
      @keyframes spin {
        from { transform: rotate(0deg); }
        to { transform: rotate(360deg); }
      }
      @keyframes wave {
        0% { transform: translateX(0); }
        100% { transform: translateX(-50%); }
      }
      .wave-container {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        display: flex;
        align-items: flex-end;
      }
      .wave {
        position: absolute;
        bottom: 0;
        left: 0;
        width: 200%;
        height: 44%;
        fill: rgba(255, 165, 0, 0.5);
        animation: wave infinite linear;
        transform-origin: bottom;
      }
      .wave:nth-of-type(2) {
        fill: rgba(255, 165, 0, 0.7);
        animation: wave infinite linear;
        animation-delay: -1s;
        transform-origin: bottom;
      }
      .wave:nth-of-type(3) {
        fill: rgba(255, 165, 0, 0.3);
        animation: wave infinite linear;
        animation-delay: -2s;
        transform-origin: bottom;
      }
    custom_fields:
      outer_circle: >
        [[[ return `<div class="outer_circle" style="position: absolute; top:
        0px; left: 0px; right: 0px; bottom: 0px; border-radius: 50%; border: 4px
        solid transparent; background: conic-gradient(orange 0%, orange 90%,
        yellow 90% 100%); box-shadow: 0 0 10px rgba(255, 165, 0, 0.5);
        animation: spin 5s linear infinite; z-index: 0;"></div>`; ]]]
      highlight: >
        [[[ return `

        <style>

        .highlight {
          animation: spin 5s linear infinite reverse;
          z-index: 0;
        }

        </style>

        <div class="highlight" style="position: absolute; top: -4px; left: -4px;
        width: 100%; height: 100%; border-radius: 50%; border: 4px solid
        transparent; border-top-color: yellow;"></div>`; ]]]
      inner_circle: >
        [[[ return `<div class="inner_circle" style="position: absolute; top:
        4px; left: 4px; right: 4px; bottom: 4px; border-radius: 50%;
        background-color: white; border: 2px solid rgba(255, 165, 0, 0.3);
        z-index: 0;"></div>`; ]]]
      wave: |
        [[[
          const value = parseFloat(states['sensor.ecu_current_power'].state);
          const max = 6400;
          let duration;

          if (value <= 500) {
            duration = '4.6s';
          } else if (value <= 1000) {
            duration = '4s';
          } else if (value <= 1500) {
            duration = '3.6s';
          } else if (value <= 2000) {
            duration = '3.3s';
          } else if (value <= 2500) {
            duration = '2.8s';
          } else if (value <= 3000) {
            duration = '2.6s';
          } else if (value <= 3500) {
            duration = '2.4s';
          } else if (value <= 4000) {
            duration = '2.2s';
          } else if (value <= 4500) {
            duration = '1.8s';
          } else if (value <= 5000) {
            duration = '1.5s';
          } else {
            duration = '1s';
          }

          const percent = Math.min(100, (value / max * 100));
          const scale = percent / 100;

          return `
            <div class="wave-container" style="z-index: 1;">
              <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,224L48,213.3C96,203,192,181,288,165.3C384,149,480,139,576,144C672,149,768,171,864,197.3C960,224,1056,256,1152,250.7C1248,245,1344,203,1392,181.3L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
              <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,288L48,272C96,256,192,224,288,208C384,192,480,192,576,213.3C672,235,768,277,864,288C960,299,1056,277,1152,250.7C1248,224,1344,192,1392,176L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
              <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,160L48,170.7C96,181,192,203,288,218.7C384,235,480,245,576,240C672,235,768,213,864,202.7C960,192,1056,192,1152,181.3C1248,171,1344,149,1392,138.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
            </div>
          `;
        ]]]
  - square: true
    type: grid
    columns: 8
    cards:
      - type: custom:button-card
        entity: sensor.inverter_703000023945_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000023945_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000023945_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000023945_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000026082_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000026082_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000026082_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000026082_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000028507_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000028507_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000028507_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000028507_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000025629_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000025629_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000025629_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000025629_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
  - square: true
    type: grid
    cards:
      - type: custom:button-card
        entity: sensor.inverter_703000023929_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000023929_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000023929_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000023929_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
    columns: 8
  - square: true
    type: grid
    cards:
      - type: custom:button-card
        entity: sensor.inverter_703000027801_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000027801_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000027801_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000027801_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000027698_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000027698_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000027698_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000027698_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000027765_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000027765_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000027765_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000027765_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
    columns: 8
  - type: custom:apexcharts-card
    graph_span: 12h
    span:
      start: day
      offset: +6h
    apex_config:
      yaxis:
        - id: first
          opposite: false
          show: true
          decimalsInFloat: 0
          title:
            text: Puissance (W)
        - id: second
          opposite: true
          show: true
          decimalsInFloat: 2
          title:
            text: Énergie (kWh)
    series:
      - entity: sensor.ecu_current_power
        name: Puissance (W)
        type: column
        stroke_width: 2
        curve: smooth
        group_by:
          duration: 5min
          func: avg
        yaxis_id: first
      - entity: sensor.ecu_today_energy
        name: Énergie (kWh)
        type: line
        stroke_width: 2
        curve: smooth
        group_by:
          duration: 5min
          func: avg
        yaxis_id: second
view_layout:
  position: sidebar

1 « J'aime »

Merci pour le partage.
J’ai cherché une astuce pour que la première carte soit toujours centrée, quelle que soit la largeur de colonne ou le type de consultation (iphone, tablette ou navigateur) avec du horizontal-stack, 3 colonnes et des boutons vides transparents et sans bordures.

type: vertical-stack
cards:
  - square: false
    type: horizontal-stack
    columns: 3
    cards:
      - type: button
        card_mod:
          style: |
            ha-card {
              border: none;
              background: transparent;
            }
      - type: custom:button-card
        entity: sensor.ecu_current_power
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state + " W"; ]]]'
        styles:
          card:
            - height: 150px
            - width: 150px
            - font-size: 20px
            - font-weight: bold
            - line-height: 150px
            - border-radius: 75px
            - position: relative
            - overflow: hidden
            - background-color: whitesnow
            - display: flex
            - align-items: center
            - justify-content: center
            - margin: 0 auto
            - display: block
          state:
            - color: black
            - text-align: center
            - font-size: 20px
            - font-weight: bold
            - z-index: 2
        extra_styles: |
          @keyframes pulse-grow {
            0%, 100% {
              box-shadow: 0 0 0 0 rgba(255, 165, 0, 0.7);
              transform: scale(1);
            }
            50% {
              box-shadow: 0 0 0 10px rgba(255, 165, 0, 0);
              transform: scale(1.1);
            }
          }
          @keyframes spin {
            from { transform: rotate(0deg); }
            to { transform: rotate(360deg); }
          }
          @keyframes wave {
            0% { transform: translateX(0); }
            100% { transform: translateX(-50%); }
          }
          .wave-container {
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            display: flex;
            align-items: flex-end;
          }
          .wave {
            position: absolute;
            bottom: 0;
            left: 0;
            width: 200%;
            height: 44%;
            fill: rgba(255, 165, 0, 0.5);
            animation: wave infinite linear;
            transform-origin: bottom;
          }
          .wave:nth-of-type(2) {
            fill: rgba(255, 165, 0, 0.7);
            animation: wave infinite linear;
            animation-delay: -1s;
            transform-origin: bottom;
          }
          .wave:nth-of-type(3) {
            fill: rgba(255, 165, 0, 0.3);
            animation: wave infinite linear;
            animation-delay: -2s;
            transform-origin: bottom;
          }
        custom_fields:
          outer_circle: >
            [[[ return `<div class="outer_circle" style="position: absolute;
            top: 0px; left: 0px; right: 0px; bottom: 0px; border-radius: 50%;
            border: 4px solid transparent; background: conic-gradient(orange 0%,
            orange 90%, yellow 90% 100%); box-shadow: 0 0 10px rgba(255, 165, 0,
            0.5); animation: spin 5s linear infinite; z-index: 0;"></div>`; ]]]
          highlight: >
            [[[ return `

            <style>

            .highlight {
              animation: spin 5s linear infinite reverse;
              z-index: 0;
            }

            </style>

            <div class="highlight" style="position: absolute; top: -4px; left:
            -4px; width: 100%; height: 100%; border-radius: 50%; border: 4px
            solid transparent; border-top-color: yellow;"></div>`; ]]]
          inner_circle: >
            [[[ return `<div class="inner_circle" style="position: absolute;
            top: 4px; left: 4px; right: 4px; bottom: 4px; border-radius: 50%;
            background-color: white; border: 2px solid rgba(255, 165, 0, 0.3);
            z-index: 0;"></div>`; ]]]
          wave: |
            [[[
              const value = parseFloat(states['sensor.ecu_current_power'].state);
              const max = 800;
              let duration;

              if (value <= 100) {
                duration = '4.6s';
              } else if (value <= 200) {
                duration = '4s';
              } else if (value <= 300) {
                duration = '3.6s';
              } else if (value <= 400) {
                duration = '3.3s';
              } else if (value <= 500) {
                duration = '2.8s';
              } else if (value <= 600) {
                duration = '2.6s';
              } else if (value <= 700) {
                duration = '2.4s';
              } else if (value <= 800) {
                duration = '2.2s';
              } else if (value <= 900) {
                duration = '1.8s';
              } else if (value <= 1000) {
                duration = '1.5s';
              } else {
                duration = '1s';
              }

              const percent = Math.min(100, (value / max * 100));
              const scale = percent / 100;

              return `
                <div class="wave-container" style="z-index: 1;">
                  <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,224L48,213.3C96,203,192,181,288,165.3C384,149,480,139,576,144C672,149,768,171,864,197.3C960,224,1056,256,1152,250.7C1248,245,1344,203,1392,181.3L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
                  <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,288L48,272C96,256,192,224,288,208C384,192,480,192,576,213.3C672,235,768,277,864,288C960,299,1056,277,1152,250.7C1248,224,1344,192,1392,176L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
                  <svg class="wave" style="transform: scaleY(${scale}); animation-duration: ${duration};" viewBox="0 0 1440 320"><path d="M0,160L48,170.7C96,181,192,203,288,218.7C384,235,480,245,576,240C672,235,768,213,864,202.7C960,192,1056,192,1152,181.3C1248,171,1344,149,1392,138.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path></svg>
                </div>
              `;
            ]]]
      - type: button
        card_mod:
          style: |
            ha-card {
              border: none;
              background: transparent;
            }
  - square: false
    type: grid
    columns: 2
    cards:
      - type: custom:button-card
        entity: sensor.inverter_703000573416_power_ch_1
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000573416_power_ch_1'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.inverter_703000573416_power_ch_2
        show_name: false
        show_state: true
        state_display: '[[[ return states[entity.entity_id].state; ]]]'
        styles:
          card:
            - height: 70px
            - font-size: 15px
            - font-weight: bold
            - line-height: 70px
            - background: |
                [[[
                  var value = parseFloat(states['sensor.inverter_703000573416_power_ch_2'].state);
                  var max = 400;
                  var color = 'orange';
                  return `linear-gradient(to top, ${color} ${value/max*100}%, transparent 0%)`;
                ]]]
            - background-color: dimgrey
          state:
            - color: white
            - text-align: center
            - font-size: 15px
            - font-weight: bold
  - type: custom:apexcharts-card
    graph_span: 12h
    span:
      start: day
      offset: +6h
    apex_config:
      yaxis:
        - id: first
          opposite: false
          show: true
          decimalsInFloat: 0
          title:
            text: Puissance (W)
        - id: second
          opposite: true
          show: true
          decimalsInFloat: 2
          title:
            text: Énergie (kWh)
    series:
      - entity: sensor.ecu_current_power
        name: Puissance (W)
        type: column
        stroke_width: 2
        curve: smooth
        group_by:
          duration: 5min
          func: avg
        yaxis_id: first
      - entity: sensor.ecu_today_energy
        name: Énergie (kWh)
        type: line
        stroke_width: 2
        curve: smooth
        group_by:
          duration: 5min
          func: avg
        yaxis_id: second
view_layout:
  position: sidebar

Oui cela est possible, moi j’étais parti sur la disposition des panneaux du toit c’est pour cela que je n’ai pas voulu les grandir et que je leurs ai donné une taille identique à tous. Mais si tu préfères comme tu as fait et que le code te convienne s’est génial

Bonjour, encore une petite évolution

Bonjour encore une évolution du code. Si quelqu’un sait comment enlever le trait vert tout en gardant le résultat dans la légende du graphique je suis preneur.

- type: custom:apexcharts-card
    graph_span: 12h
    span:
      start: day
      offset: +6h
    apex_config:
      yaxis:
        - id: first
          opposite: false
          show: true
          decimalsInFloat: 2
          title:
            text: Énergie (kWh)
        - id: second
          opposite: true
          show: true
          decimalsInFloat: 0
          title:
            text: Puissance (W)
      stroke:
        width: 2
      fill:
        type: gradient
        gradient:
          shade: light
          type: vertical
          shadeIntensity: 0.5
          gradientToColors:
            - rgba(0, 255, 0, 0.6)
          inverseColors: false
          opacityFrom: 0.8
          opacityTo: 0.2
          stops:
            - 0
            - 100
    series:
      - entity: sensor.ecu_current_power
        name: Puissance (W)
        type: area
        stroke_width: 3
        curve: smooth
        group_by:
          duration: 5min
          func: avg
        yaxis_id: second
        color: rgba(255, 165, 0, 1)
      - entity: sensor.ecu_today_energy
        name: Énergie (kWh)
        type: line
        yaxis_id: first
        color: rgba(0, 255, 0, 0) ;
        opacity: 0
        group_by:
          duration: 5min
          func: last
        show:
          in_header: true
    view_layout:
      position: sidebar

Salut

Je ne sais pas si c’est possible mais tu dois pouvoir feinter comme ça :

- type: custom:apexcharts-card
    graph_span: 12h
    span:
      start: day
      offset: +6h
    apex_config:
      yaxis:
        - id: first
          opposite: false
          show: true
          decimalsInFloat: 2
          title:
            text: Énergie (kWh)
        - id: second
          opposite: true
          show: true
          decimalsInFloat: 0
          title:
            text: Puissance (W)
      stroke:
        width: 2
      fill:
        type: gradient
        gradient:
          shade: light
          type: vertical
          shadeIntensity: 0.5
          gradientToColors:
            - rgba(0, 255, 0, 0.6)
          inverseColors: false
          opacityFrom: 0.8
          opacityTo: 0.2
          stops:
            - 0
            - 100
########
      experimental:
        hidden_by_default: true
########
    series:
      - entity: sensor.ecu_current_power
        name: Puissance (W)
        type: area
        stroke_width: 3
        curve: smooth
        group_by:
          duration: 5min
          func: avg
        yaxis_id: second
        color: rgba(255, 165, 0, 1)
      - entity: sensor.ecu_today_energy
        name: Énergie (kWh)
        type: line
        yaxis_id: first
        color: rgba(0, 255, 0, 0) ;
        opacity: 0
        group_by:
          duration: 5min
          func: last
        show:
########
          legend_value: true
          hidden_by_default: true
########
          in_header: true
    view_layout:
      position: sidebar

Regardes les lignes entre ####

Bonjour, n’a pas fonctionné pour moi