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
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…
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
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
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 é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