Cloom
Juillet 16, 2026, 10:06
1
Bonjour,
Un petit retour d'expérience.
Dans mon immeuble on a une cogénération (on brule du gaz pour faire l'électricité et on réinjecte la chaleur dans le système d'eau chaude sanitaire et chauffage), des panneaux solaires, des bornes de recharges de voitures électriques et des compteurs MiD connecté en modbus TCP.
J'ai installé en Home Assistant dans la copro pour faire un BMS (Building Management System) et surveiller un peu tout ça.
Il y a quelques années j'ai passé pas mal de temps à potasser la doc d'HA et les tables modbus du compteur ULYS TT-M Modbus pour l'intégrer dans HA.
Pour tester plus rapidement et m'assurer que ça fonctionnait bien, j'ai écrit un petit script python pour interroger le compteur. Une fois que j'avais tout ce que je voulais correctement j'ai fait le fichier de config YAML pour que Home Assistant récupère les données directement.
Récemment on a mis un autre compteur: Eastron SDM630 Modbus v3 via une passerelle Waveshare RS485 to eth (B) et je me lance avec Gemini pour faire le fichier de config.
Je me rends compte que je fais des aller retour avec Gemini à copier les message d'erreur et là... l'illumination... utilisons https://antigravity.google/ !
Je me suis connecté sur le réseau de la copro, j'ai donné l'IP et le model du compteur/passerelle et demandé de faire un script python pour récupérer les données via modbus/TCP.
Antigravity a fait ce script pour tester et s'est auto corrigé en fonction des messages d'erreur reçus.
Une fois qu'il savait récupérer les valeurs via le script python, je lui ai demandé de faire la config YAML pour HA et voilà.... En même pas 5min c'était plié!
J'ai refait la même chose avec un autre compteur SOCOMEC Countis E27 et nickel... en 5min c'était plié également!
Ici je parle de compteurs modbus mais antigravity prend tout en input (media, texte, lien, etc) et (dangereusement ) vous demande s'il peut lancer telle ou telle commande ou script qu'il vient de fiare.
À utiliser à vos risques et péril mais c'est vraiment génial!
Cloom
Juillet 16, 2026, 5:18
2
Bon, j'ai jamais réussi à me connecter en modbus à la cogénération... du coup j'essaye avec ce prompt:
Avec la table modbus attachée en PDF et en sachant que l'IP de la cogénération est 192.168.1.150,
peux-tu écrire un script python pour lire les données en utilisant modbus?
N'hésite pas à tester différent slave id etc car je n'ai pas plus d'information
Donc un prompt pas terrible et bim... en même 5min il a réussi là où j'ai échoué pendant 1 an!!
Il a ensuite proposé le fichier yaml pour HA et j'ai demandé un dashboard:
Quelques valeurs à vérifier mais je suis bluffé...
Sympa comme réalisation, bravo.
Au niveau de l'affichage, tu peut utiliser custom:multiple-entity-row pour remplacer l'encart "SDM630 Power Meter":
Tu gagneras de la place et pour comparer des données similaire (comme la tension), c'est plus visuel.
Salut,
ou avec button-card, j'ai refait une carte au look de multiple -entity-row pour pas utiliser de card_mod.
Code
type: custom:button-card
show_name: false
show_icon: false
show_state: false
tap_action:
action: none
hold_action:
action: none
double_tap_action:
action: none
styles:
card:
- padding: 4px 6px 4px 6px
- box-shadow: none
grid:
- grid-template-areas: |
"title_ha abo_ha hp_ha hc_ha"
"title_edf abo_edf hp_edf hc_edf"
- grid-template-columns: minmax(145px, 1fr) repeat(3, 90px)
- grid-template-rows: auto auto
- column-gap: 6px
- row-gap: 0
- align-items: stretch
custom_fields:
title_ha:
- width: auto
- min-width: 0
- align-self: stretch
- justify-self: stretch
abo_ha:
- width: 100%
- align-self: stretch
hp_ha:
- width: 100%
- align-self: stretch
hc_ha:
- width: 100%
- align-self: stretch
title_edf:
- width: auto
- min-width: 0
- border-radius: 12px
- overflow: hidden
- align-self: stretch
- justify-self: stretch
abo_edf:
- width: 100%
- align-self: stretch
hp_edf:
- width: 100%
- align-self: stretch
hc_edf:
- width: 100%
- align-self: stretch
custom_fields:
title_ha:
card:
type: custom:button-card
name: Prix HA Zen Fixe
icon: mdi:currency-eur
color: var(--state-icon-color)
show_icon: true
show_name: true
show_state: false
show_label: true
label: " "
tap_action:
action: none
hold_action:
action: none
styles:
card:
- height: 100%
- min-height: 50px
- padding: 6px 4px
- overflow: visible
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
grid:
- grid-template-areas: |
"i n"
"i l"
- grid-template-columns: 38px minmax(0, 1fr)
- grid-template-rows: auto auto
- column-gap: 8px
- row-gap: 1px
- justify-content: start
- align-items: center
- overflow: visible
img_cell:
- width: 38px
- height: 38px
- min-width: 38px
- min-height: 38px
- box-sizing: border-box
- background: rgba(68, 115, 158, 0.15)
- border: 1px solid rgba(68, 115, 158, 0.25)
- border-radius: 50%
- justify-self: start
- align-self: center
- overflow: visible
icon:
- width: 25px
- height: 25px
- min-width: 25px
- min-height: 25px
- "--mdc-icon-size": 25px
- color: "#44739e"
name:
- justify-self: start
- align-self: end
- text-align: left
- font-size: 14px
- line-height: 16px
- font-weight: 500
- white-space: nowrap
- overflow: hidden
- text-overflow: ellipsis
label:
- justify-self: start
- align-self: start
- font-size: 11px
- line-height: 14px
- opacity: 0
abo_ha:
card:
type: custom:button-card
entity: input_number.prix_abonnement_mois
name: ABO 6kVA
color: DodgerBlue
show_icon: false
show_name: true
show_state: true
state_display: |
[[[[
if (
!entity ||
entity.state === "unknown" ||
entity.state === "unavailable"
) return "—";
const value = entity.state.replace(".", ",");
const unit =
entity.attributes.unit_of_measurement || "€/mois";
return `${value} ${unit} `;
]]]]
tap_action:
action: more-info
hold_action:
action: none
styles:
card:
- height: 100%
- width: auto
- padding: 10px 5px
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
grid:
- grid-template-areas: |
"n"
"s"
- grid-template-columns: 1fr
- grid-template-rows: min-content min-content
- row-gap: 1px
name:
- color: var(--secondary-text-color)
- font-size: 12px
- font-weight: 500
- white-space: nowrap
state:
- color: DodgerBlue
- font-size: 13px
- font-weight: 600
- white-space: nowrap
hp_ha:
card:
type: custom:button-card
entity: input_number.box_prix_hp
name: Prix HP
color: red
show_icon: false
show_name: true
show_state: true
units: €/kWh
tap_action:
action: more-info
hold_action:
action: none
styles:
card:
- height: 100%
- width: auto
- padding: 10px 2px
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
grid:
- grid-template-areas: |
"n"
"s"
- grid-template-columns: 1fr
- grid-template-rows: min-content min-content
- row-gap: 1px
name:
- color: var(--secondary-text-color)
- font-size: 12px
- font-weight: 500
- white-space: nowrap
state:
- color: red
- font-size: 13px
- font-weight: 800
- white-space: nowrap
hc_ha:
card:
type: custom:button-card
entity: input_number.box_prix_hc
name: Prix HC
color: green
show_icon: false
show_name: true
show_state: true
units: €/kWh
tap_action:
action: more-info
hold_action:
action: none
styles:
card:
- height: 100%
- padding: 10px 2px
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
grid:
- grid-template-areas: |
"n"
"s"
- grid-template-columns: 1fr
- grid-template-rows: min-content min-content
- row-gap: 1px
name:
- color: var(--secondary-text-color)
- font-size: 12px
- font-weight: 500
- white-space: nowrap
state:
- color: green
- font-size: 13px
- font-weight: 600
- white-space: nowrap
title_edf:
card:
type: custom:button-card
entity: sensor.pdf_tarif_zen_fixe_hp_hc_pdf_tarif_zen_fixe_hp_hc_last_modified
name: Prix EDF Zen Fixe PDF
icon: mdi:currency-eur
color: var(--state-icon-color)
show_icon: true
show_name: true
show_state: false
show_label: true
label: |
[[[[
if (
!entity ||
entity.state === "unknown" ||
entity.state === "unavailable"
) return "Date indisponible";
const date = new Date(entity.state);
if (Number.isNaN(date.getTime())) {
return entity.state;
}
return date.toLocaleString("fr-FR", {
dateStyle: "short",
timeStyle: "short"
});
]]]]
tap_action:
action: more-info
hold_action:
action: none
styles:
card:
- height: 100%
- min-height: 50px
- padding: 6px 4px
- overflow: visible
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
- overflow: hidden
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
grid:
- grid-template-areas: |
"i n"
"i l"
- grid-template-columns: 38px minmax(0, 1fr)
- grid-template-rows: auto auto
- column-gap: 8px
- row-gap: 1px
- justify-content: start
- align-items: center
- overflow: visible
img_cell:
- width: 38px
- height: 38px
- min-width: 38px
- min-height: 38px
- box-sizing: border-box
- background: rgba(68, 115, 158, 0.15)
- border: 1px solid rgba(68, 115, 158, 0.25)
- border-radius: 50%
- justify-self: start
- align-self: center
- overflow: visible
icon:
- width: 25px
- height: 25px
- min-width: 25px
- min-height: 25px
- "--mdc-icon-size": 25px
- color: "#44739e"
name:
- justify-self: start
- align-self: end
- text-align: left
- font-size: 14px
- line-height: 16px
- font-weight: 500
- white-space: nowrap
- overflow: hidden
- text-overflow: ellipsis
label:
- justify-self: start
- align-self: start
- text-align: left
- color: var(--secondary-text-color)
- font-size: 11px
- line-height: 14px
- white-space: nowrap
- overflow: hidden
- text-overflow: ellipsis
abo_edf:
card:
type: custom:button-card
entity: sensor.pdf_tarif_zen_fixe_hp_hc_prix_zen_fixe_abonnement_mensuel_6kva
name: ABO 6kVA
show_icon: false
show_name: true
show_state: true
color: DodgerBlue
tap_action:
action: more-info
hold_action:
action: none
styles:
card:
- height: 100%
- padding: 10px 2px
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
grid:
- grid-template-areas: |
"n"
"s"
- grid-template-columns: 1fr
- grid-template-rows: min-content min-content
- row-gap: 1px
name:
- color: var(--secondary-text-color)
- font-size: 12px
- font-weight: 500
- white-space: nowrap
state:
- color: DodgerBlue
- font-size: 13px
- font-weight: 600
- white-space: nowrap
hp_edf:
card:
type: custom:button-card
entity: sensor.pdf_tarif_zen_fixe_hp_hc_prix_zen_fix_heure_pleine
name: Prix HP
show_icon: false
show_name: true
show_state: true
color: red
tap_action:
action: more-info
hold_action:
action: none
styles:
card:
- height: 100%
- padding: 10px 2px
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
grid:
- grid-template-areas: |
"n"
"s"
- grid-template-columns: 1fr
- grid-template-rows: min-content min-content
- row-gap: 1px
name:
- color: var(--secondary-text-color)
- font-size: 12px
- font-weight: 500
- white-space: nowrap
state:
- color: red
- font-size: 13px
- font-weight: 800
- white-space: nowrap
hc_edf:
card:
type: custom:button-card
entity: sensor.pdf_tarif_zen_fixe_hp_hc_prix_zen_fix_heure_creuse
name: Prix HC
show_icon: false
show_name: true
show_state: true
color: green
tap_action:
action: more-info
hold_action:
action: none
styles:
card:
- height: 100%
- padding: 10px 2px
- background: none
- border: none
- box-shadow: none
- border-radius: 12px
- "--ha-card-border-width": 0px
- "--button-card-ripple-icon-hover-opacity": 0.2
- "--button-card-ripple-icon-pressed-opacity": 0.3
grid:
- grid-template-areas: |
"n"
"s"
- grid-template-columns: 1fr
- grid-template-rows: min-content min-content
- row-gap: 1px
name:
- color: var(--secondary-text-color)
- font-size: 12px
- font-weight: 500
- white-space: nowrap
state:
- color: green
- font-size: 13px
- font-weight: 600
- white-space: nowrap
grid_options:
columns: full
rows: auto