Salut à tous ![]()
Je partage une deuxième petite carte que j'ai réalisée pour mon dashboard Home Assistant.
Cette fois, l'idée était d'avoir un affichage simple pour suivre la recharge de ma voiture hybride rechargeable, une Cupra Formentor, et de pouvoir allumer et éteindre la prise en cliquant sur la carte.
Je suis frustré depuis un moment de ne pas avoir littéralement le contrôle de mon app mobile Cupra. Donc j'ai essayé de faire quelque chose qui correspond à la voiture mais qui reste adaptable pour tous.
La carte permet de voir en un coup d'œil :
si la prise est allumée ou éteinte
la puissance instantanée consommée
l'état de la recharge
l'énergie totale consommée
et surtout, de piloter directement la prise depuis la carte
Le tout avec un affichage assez minimaliste pour rester cohérent avec le reste de mon dashboard.
Comment ça fonctionne ?
Dans mon installation, la voiture est branchée sur une prise connectée, qui me remonte la consommation et peut être pilotée dans Home Assistant :
- l'état ON/OFF de la prise
- la puissance instantanée en watts
- l'énergie consommée en kWh
La carte utilise ces trois informations pour déterminer automatiquement l'état de la recharge.
Les trois états affichés
Lorsque la prise est désactivée :
- ÉTEINTE
PRISE ALLUMÉE mais consommation faible
Lorsque la prise est allumée mais que la consommation est inférieure à 100 W :
- CHARGÉ
Cela permet notamment de considérer que la voiture a terminé sa charge.
PRISE ALLUMÉE avec une consommation supérieure à 100 W
La carte affiche :
- EN CHARGE
avec la couleur orange correspondante.
Les éléments à modifier
C'est probablement la partie la plus importante si vous souhaitez adapter la carte à votre installation.
Au début du code, j'ai regroupé les trois entités utilisées :
const switchEntity =
'switch.0x705464fffe445e61';
const powerEntity =
'sensor.0x705464fffe445e61_power';
const energyEntity =
'sensor.0x705464fffe445e61_energy';
1. Entité de la prise
Remplacez :
switch.0x705464fffe445e61
par l'entité de votre prise connectée.
Par exemple :
switch.prise_garage
Cette entité sert à connaître l'état de la prise et permet également de l'allumer/éteindre directement depuis le petit bouton en haut à droite.
2. Entité de puissance
Remplacez :
sensor.0x705464fffe445e61_power
par votre capteur de puissance.
Celui-ci doit idéalement remonter une valeur en watts (W).
C'est cette valeur qui est affichée en gros au centre de la carte.
3. Entité d'énergie
Remplacez :
sensor.0x705464fffe445e61_energy
par votre capteur d'énergie.
La valeur est affichée en kWh en bas de la carte.
4. Modifier le seuil "CHARGÉ"
Par défaut, j'ai choisi 100 W comme seuil :
} else if (power < 100) {
chargeStatus = 'CHARGÉ';
chargeClass = 'charged';
} else {
chargeStatus = 'EN CHARGE';
chargeClass = 'charging';
}
Donc :
Situation Affichage
Prise OFF ÉTEINTE
Prise ON + < 100 W CHARGÉ
Prise ON + ≥ 100 W EN CHARGE
Ce seuil est évidemment à adapter à votre véhicule et à votre prise.
Par exemple, si votre voiture consomme toujours quelques dizaines de watts même lorsqu'elle a terminé sa charge, 100 W peut être un seuil intéressant.
Si vous souhaitez être plus ou moins sensible, il suffit de modifier :
power < 100
par exemple en :
power < 50
ou :
power < 200
5. Modifier les couleurs
La couleur principale de la carte est actuellement Cuivre :
#c87941
Elle est utilisée notamment pour :
la bordure
le logo
le toggle
le texte EN CHARGE
Vous pouvez donc facilement remplacer cette couleur par celle de votre choix.
Par exemple, pour quelque chose de plus "électrique", vous pouvez remplacer #c87941 par une couleur bleue ou verte.
6. Modifier le nom de la voiture
Le nom est simplement écrit en dur dans la carte :
<div class="cname">
Cupra Formentor
</div>
Vous pouvez donc mettre ce que vous voulez :
<div class="cname">
Tesla Model 3
</div>
ou :
<div class="cname">
Peugeot 308 Hybrid
</div>
Même chose pour le petit sous-titre :
<div class="csub">
GARAGE · PRISE DÉDIÉE
</div>
7. Le bouton en haut à droite
Le petit interrupteur n'est pas simplement décoratif.
Il permet réellement de basculer la prise ON/OFF.
La carte utilise :
hass.callService(
'switch',
'toggle',
{
entity_id: switchEntity
}
);
Il faut donc que l'entité définie dans switchEntity soit bien une entité de type switch.
Pré-requis
Comme pour ma précédente carte, celle-ci utilise :
custom:button-card
card-mod
Il suffit ensuite de créer une carte manuelle dans votre dashboard Lovelace et de coller le code.
type: custom:button-card
show_name: false
show_icon: false
show_state: false
# ============================================================
# ENTITÉ PRINCIPALE : PRISE / CHARGEUR
# ============================================================
entity: switch.0x705464fffe445e61
tap_action:
action: toggle
# ============================================================
# STYLE DE LA CARTE
# ============================================================
card_mod:
style: |
ha-card {
border: 1.5px solid #c87941 !important;
border-radius: 16px !important;
}
styles:
card:
- padding: 0
- background: '#ffffff'
- border-radius: 16px
- overflow: hidden
- text-align: left
- height: 285px
grid:
- grid-template-areas: '"content"'
- grid-template-columns: 1fr
- grid-template-rows: auto
custom_fields:
content:
- width: 100%
- display: block
- padding: 0
- margin: 0
- text-align: left
custom_fields:
content: |
[[[
// ==========================================================
// ENTITÉS À ADAPTER À VOTRE INSTALLATION
// ==========================================================
//
// Prise / chargeur :
// switch.0x705464fffe445e61
//
// Puissance instantanée :
// sensor.0x705464fffe445e61_power
//
// Énergie totale :
// sensor.0x705464fffe445e61_energy
//
// ==========================================================
const switchEntity =
'switch.0x705464fffe445e61';
const powerEntity =
'sensor.0x705464fffe445e61_power';
const energyEntity =
'sensor.0x705464fffe445e61_energy';
// ==========================================================
// VALEURS
// ==========================================================
const switchState =
states[switchEntity].state;
const power =
parseFloat(
states[powerEntity].state
) || 0;
const energy =
parseFloat(
states[energyEntity].state
) || 0;
// ==========================================================
// STATUT DE CHARGE
// ==========================================================
//
// Prise éteinte → ÉTEINTE
// Prise allumée + <100W → CHARGÉ
// Prise allumée + ≥100W → EN CHARGE
//
// Le seuil de 100 W peut être modifié ci-dessous.
// ==========================================================
let chargeStatus;
let chargeClass;
if (switchState !== 'on') {
chargeStatus = 'ÉTEINTE';
chargeClass = 'off';
} else if (power < 100) {
chargeStatus = 'CHARGÉ';
chargeClass = 'charged';
} else {
chargeStatus = 'EN CHARGE';
chargeClass = 'charging';
}
// ==========================================================
// HTML
// ==========================================================
return `
<style>
/* ======================================================
RESET
====================================================== */
.cw * {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cw {
font-family: sans-serif;
color: #1a1917;
width: 100%;
display: block;
}
/* ======================================================
PARTIE HAUTE
====================================================== */
.ch {
padding: 1rem 1.25rem 2rem;
}
/* ======================================================
EN-TÊTE
====================================================== */
.cht {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 2.9rem;
}
.cbrand {
display: flex;
align-items: center;
gap: 10px;
}
/* Cercle contenant le logo */
.cmark {
width: 38px;
height: 38px;
border-radius: 50%;
background: #fdf6ee;
border: 1px solid #c87941;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
/* Nom de la voiture */
.cname {
font-size: 14px;
font-weight: 500;
color: #1a1917;
letter-spacing: 0.03em;
}
/* Sous-titre */
.csub {
font-size: 10px;
color: #9a9590;
letter-spacing: 0.06em;
margin-top: 2px;
}
/* ======================================================
TOGGLE
====================================================== */
.ctrow {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8px;
}
.ctoggle {
position: relative;
width: 38px;
height: 20px;
cursor: pointer;
flex-shrink: 0;
z-index: 999;
}
.cslider {
position: absolute;
inset: 0;
border-radius: 20px;
transition: 0.2s;
}
.cthumb {
position: absolute;
width: 14px;
height: 14px;
border-radius: 50%;
top: 3px;
transition: 0.2s;
}
/* ======================================================
PUISSANCE + STATUT
====================================================== */
.cpwr-row {
display: flex;
align-items: baseline;
justify-content: space-between;
}
.cprow {
display: flex;
align-items: baseline;
gap: 5px;
}
/* Valeur de puissance */
.cpval {
font-size: 48px;
font-weight: 500;
color: #1a1917;
line-height: 1;
letter-spacing: -0.02em;
}
/* Unité W */
.cpunit {
font-size: 20px;
color: #9a9590;
}
/* Statut de charge */
.ccharge-status {
font-size: 20px;
line-height: 1;
font-weight: 500;
letter-spacing: 0.06em;
white-space: nowrap;
text-align: right;
}
/* En charge */
.ccharge-status.charging {
color: #c87941;
}
/* Batterie chargée */
.ccharge-status.charged {
color: #9a9590;
}
/* Prise éteinte */
.ccharge-status.off {
color: #9a9590;
}
/* Libellé sous la puissance */
.cplbl {
font-size: 10px;
color: #c87941;
letter-spacing: 0.12em;
margin-top: 6px;
}
/* ======================================================
PARTIE BASSE : ÉNERGIE TOTALE
====================================================== */
.cmets {
border-top: 0.5px solid #e0ddd8;
padding: 1rem 1.25rem 1.2rem;
}
.cmlbl {
font-size: 10px;
color: #9a9590;
letter-spacing: 0.1em;
margin-bottom: 6px;
}
.cmval {
font-size: 24px;
font-weight: 500;
color: #1a1917;
}
.cmunit {
font-size: 13px;
color: #9a9590;
margin-left: 2px;
}
</style>
<div class="cw">
<!-- ====================================================
EN-TÊTE
==================================================== -->
<div class="ch">
<div class="cht">
<!-- Marque + nom -->
<div class="cbrand">
<div class="cmark">
<!-- Logo Cupra -->
<svg
width="26"
height="17"
viewBox="64 0 182 140"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="#c87941"
d="M208.415,28.817c-9.839,4.816-19.677,9.632-29.516,14.445h-0.007c5.999,2.295,11.995,4.599,17.988,6.911c3.712,1.431,8.115,3.227,9.735,7.613c1.665,4.503-0.784,8.521-2.948,11.909c-3.275,5.129-6.55,10.258-9.825,15.384c-11.651,18.246-23.31,36.492-35.006,54.711c-0.021-5.624-0.034-11.252-0.045-16.877v-0.01c4.472-14.066,8.837-28.164,13.048-42.313c1.194-4.018,2.377-8.039,3.543-12.064c0.702-2.425,0.248-3.877-2.085-5.033c-5.958-2.941-11.92-5.879-17.885-8.813c-5.962,2.934-11.923,5.872-17.885,8.813c-2.332,1.156-2.786,2.608-2.085,5.033c1.17,4.025,2.35,8.046,3.547,12.064c4.207,14.149,8.573,28.246,13.048,42.313l-0.003,0.01c-0.01,5.624-0.024,11.252-0.045,16.877c-11.696-18.219-23.351-36.465-35.006-54.711c-3.275-5.126-6.55-10.255-9.821-15.384c-2.164-3.388-4.617-7.406-2.952-11.909c1.624-4.386,6.024-6.182,9.735-7.613c5.993-2.312,11.989-4.617,17.988-6.911h-0.003c-9.842-4.813-19.681-9.629-29.519-14.445l-0.014-0.014c3.072,5.139,6.137,10.282,9.202,15.425c-5.074,1.947-10.145,3.894-15.215,5.848C85.732,33.393,75.072,16.712,64.456,0c30.286,10.743,60.545,21.569,90.958,31.951C185.831,21.569,216.086,10.743,246.376,0c-10.616,16.712-21.28,33.393-31.934,50.077c-5.067-1.954-10.141-3.901-15.215-5.848c3.065-5.143,6.134-10.286,9.202-15.425"
/>
</svg>
</div>
<div>
<div class="cname">
Cupra Formentor
</div>
<div class="csub">
GARAGE · PRISE DÉDIÉE
</div>
</div>
</div>
<!-- ==================================================
TOGGLE DE LA PRISE
================================================== -->
<div class="ctrow">
<div
class="ctoggle"
id="cupra-toggle"
>
<span
class="cslider"
style="
background:${switchState === 'on'
? '#fdf0e0'
: '#f0ede8'};
border:0.5px solid ${switchState === 'on'
? '#c87941'
: '#d0cdc8'}
"
>
</span>
<span
class="cthumb"
style="
left:${switchState === 'on'
? '21'
: '3'}px;
background:${switchState === 'on'
? '#c87941'
: '#b0ada8'}
"
>
</span>
</div>
</div>
</div>
<!-- ==================================================
PUISSANCE + STATUT DE CHARGE
================================================== -->
<div class="cpwr-row">
<div class="cprow">
<span class="cpval">
${Math.round(power)}
</span>
<span class="cpunit">
W
</span>
</div>
<div class="ccharge-status ${chargeClass}">
${chargeStatus}
</div>
</div>
<div class="cplbl">
PUISSANCE INSTANTANÉE
</div>
</div>
<!-- ====================================================
ÉNERGIE TOTALE
==================================================== -->
<div class="cmets">
<div class="cmlbl">
⚡ ÉNERGIE TOTALE
</div>
<div class="cmval">
${energy.toFixed(1)}
<span class="cmunit">
kWh
</span>
</div>
</div>
</div>
<!-- ======================================================
GESTION DU BOUTON TOGGLE
====================================================== -->
<script>
(function() {
const toggle =
document.getElementById(
'cupra-toggle'
);
if (
toggle &&
!toggle.dataset.bound
) {
toggle.dataset.bound = '1';
toggle.addEventListener(
'click',
function(e) {
e.preventDefault();
e.stopImmediatePropagation();
hass.callService(
'switch',
'toggle',
{
entity_id:
switchEntity
}
);
}
);
}
})();
</script>
`;
]]]
