feat: badges origine centralisés, TOC masqué sur les index de catégorie
All checks were successful
Build & Deploy docs / build-deploy (push) Successful in 1m54s

- render_header_badges() fonction partagée pour canal + origine + stabilité
- Marqueur __badges_<plugin>__ dans les 9 fiches (5 manuelles + 4 auto)
- Marqueur __index_<cat>__ dans les 3 index manuels (compteurs, bornes, smart)
- Front matter hide: [toc] sur tous les index de catégorie
- .badge.experimental ajouté dans extra.css (waveshare)
- process() gère __badges_ keys via render_header_badges()
- build_category_index_page() inclut hide:toc front matter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Schurig 2026-06-03 15:42:04 +02:00
parent 0f2be2e000
commit a7dedb3366
19 changed files with 148 additions and 35 deletions

View File

@ -1,6 +1,9 @@
# Borne ABB Terra AC
<span class="badge testing">TESTING</span> <span class="badge consumer">CONSUMER</span>
<!-- BEGIN GENERATED: __badges_abbterra__ -->
<span class="badge testing">TESTING</span> <span class="badge origin-etm">ETM</span> <span class="badge consumer">CONSUMER</span>
<!-- END GENERATED -->
La borne de recharge ABB Terra AC existe en deux variantes de communication :
**Modbus TCP** (réseau Ethernet/LAN) et **Modbus RTU** (bus RS485).

View File

@ -1,8 +1,27 @@
---
hide:
- toc
---
# Bornes de recharge
Bornes EVSE intégrées dans ETM PowerSync pour la recharge pilotée des véhicules électriques.
| Appareil | Protocole | Canal | Stabilité |
|---|---|---|---|
| [Borne ABB Terra AC](abb-terra.md) | Modbus TCP / RTU | <span class="badge testing">TESTING</span> | <span class="badge consumer">CONSUMER</span> |
| [Keba](keba.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge community">COMMUNITY</span> |
<!-- BEGIN GENERATED: __index_irve__ -->
| Appareil | Protocole | Canal | Origine | Stabilité |
| --- | --- | --- | --- | --- |
| [Borne ABB Terra AC](abb-terra.md) | Modbus TCP | <span class="badge testing">TESTING</span> | <span class="badge origin-etm">ETM</span> | <span class="badge consumer">CONSUMER</span> |
| [Keba](keba.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [Easeex](easee.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [go-eCharger](goecharger.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [EVBox](evbox.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [EVerest](everest.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [v2xeamberelectric](v2xeamberelectric.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | — |
| [Amperfied](amperfied.md) | Modbus RTU | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [MENNEKES](mennekes.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [webasto](webasto.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [PC Electric](pcelectric.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [PhoenixConnect](phoenixconnect.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [INRO](inro.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
<!-- END GENERATED -->

View File

@ -1,6 +1,9 @@
# Keba
<span class="badge nightly">NIGHTLY</span> <span class="badge community">COMMUNITY</span>
<!-- BEGIN GENERATED: __badges_keba__ -->
<span class="badge nightly">NIGHTLY</span> <span class="badge origin-nymea">NYMEA</span> <span class="badge consumer">CONSUMER</span>
<!-- END GENERATED -->
Bornes de recharge Keba (séries P30, P31), communication **Modbus TCP** via réseau local.

View File

@ -64,7 +64,7 @@ Chaque appareil porte trois badges indépendants :
| Marque / Modèle | Protocole | Canal | Origine | Stabilité |
|---|---|---|---|---|
| Waveshare relais | Modbus RTU | <span class="badge testing">TESTING</span> | <span class="badge origin-etm">ETM</span> | |
| Waveshare relais | Modbus RTU | <span class="badge testing">TESTING</span> | <span class="badge origin-etm">ETM</span> | <span class="badge experimental">EXPERIMENTAL</span> |
| Shelly | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| Tasmota | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge community">COMMUNITY</span> |
| Tuya | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge community">COMMUNITY</span> |

View File

@ -1,6 +1,9 @@
# Compteur ABB B2x
<span class="badge testing">TESTING</span> <span class="badge consumer">CONSUMER</span>
<!-- BEGIN GENERATED: __badges_abbb2x__ -->
<span class="badge testing">TESTING</span> <span class="badge origin-etm">ETM</span> <span class="badge consumer">CONSUMER</span>
<!-- END GENERATED -->
Le compteur d'énergie ABB B2x communique en **Modbus RTU** sur le bus RS485 du
hub. Mesure triphasée (tensions, courants et puissances par phase).

View File

@ -1,6 +1,9 @@
# Compteurs Eastron (SDM)
<span class="badge stable">STABLE</span> <span class="badge consumer">CONSUMER</span>
<!-- BEGIN GENERATED: __badges_eastron__ -->
<span class="badge stable">STABLE</span> <span class="badge origin-etm">ETM</span> <span class="badge consumer">CONSUMER</span>
<!-- END GENERATED -->
Les compteurs Eastron de la série SDM (SDM72, SDM120, SDM220, SDM230, SDM630)
communiquent en **Modbus RTU** sur le bus RS485 du hub. Selon le modèle, ils

View File

@ -1,8 +1,22 @@
---
hide:
- toc
---
# Compteurs
Compteurs d'énergie supportés par ETM PowerSync via Modbus RTU.
| Appareil | Protocole | Canal | Stabilité |
|---|---|---|---|
| [Eastron SDM](eastron.md) | Modbus RTU | <span class="badge stable">STABLE</span> | <span class="badge consumer">CONSUMER</span> |
| [Compteur ABB B2x](abb-b2x.md) | Modbus RTU | <span class="badge testing">TESTING</span> | <span class="badge consumer">CONSUMER</span> |
<!-- BEGIN GENERATED: __index_compteur__ -->
| Appareil | Protocole | Canal | Origine | Stabilité |
| --- | --- | --- | --- | --- |
| [Eastron SDM](eastron.md) | Modbus RTU | <span class="badge stable">STABLE</span> | <span class="badge origin-etm">ETM</span> | <span class="badge consumer">CONSUMER</span> |
| [Compteur ABB B2x](abb-b2x.md) | Modbus RTU | <span class="badge testing">TESTING</span> | <span class="badge origin-etm">ETM</span> | <span class="badge consumer">CONSUMER</span> |
| [powerfox](powerfox.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [B+G E-Tech](bgetech.md) | Modbus RTU | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [inepro Metering](inepro.md) | Modbus RTU | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [Schrack](schrack.md) | Modbus RTU | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [Bestel](vestel.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [Senseair](senseair.md) | Modbus RTU | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
<!-- END GENERATED -->

View File

@ -1,3 +1,8 @@
---
hide:
- toc
---
# Types génériques
<!-- BEGIN GENERATED: __index_generic__ -->

View File

@ -1,6 +1,9 @@
# Daikin
<span class="badge nightly">NIGHTLY</span>
<!-- BEGIN GENERATED: __badges_daikinairco__ -->
<span class="badge nightly">NIGHTLY</span> <span class="badge origin-nymea">NYMEA</span> <span class="badge community">COMMUNITY</span>
<!-- END GENERATED -->
<!-- BEGIN GENERATED: integrationplugindaikinairco.json -->
**Fabricant :** Daikin

View File

@ -1,3 +1,8 @@
---
hide:
- toc
---
# HVAC
<!-- BEGIN GENERATED: __index_hvac__ -->

View File

@ -1,6 +1,9 @@
# SG-Ready
<span class="badge nightly">NIGHTLY</span>
<!-- BEGIN GENERATED: __badges_sgready__ -->
<span class="badge nightly">NIGHTLY</span> <span class="badge origin-nymea">NYMEA</span> <span class="badge community">COMMUNITY</span>
<!-- END GENERATED -->
<!-- BEGIN GENERATED: integrationpluginsgready.json -->
**Fabricant :** nymea

View File

@ -1,6 +1,9 @@
# SimpleHeatpump
<span class="badge nightly">NIGHTLY</span>
<!-- BEGIN GENERATED: __badges_simpleheatpump__ -->
<span class="badge nightly">NIGHTLY</span> <span class="badge origin-nymea">NYMEA</span> <span class="badge community">COMMUNITY</span>
<!-- END GENERATED -->
<!-- BEGIN GENERATED: integrationpluginsimpleheatpump.json -->
**Fabricant :** nymea

View File

@ -1,6 +1,9 @@
# Fronius
<span class="badge nightly">NIGHTLY</span>
<!-- BEGIN GENERATED: __badges_fronius__ -->
<span class="badge nightly">NIGHTLY</span> <span class="badge origin-nymea">NYMEA</span> <span class="badge consumer">CONSUMER</span>
<!-- END GENERATED -->
<!-- BEGIN GENERATED: integrationpluginfronius.json -->
**Fabricant :** Fronius

View File

@ -1,3 +1,8 @@
---
hide:
- toc
---
# Onduleurs / PV
<!-- BEGIN GENERATED: __index_onduleur__ -->

View File

@ -1,7 +1,24 @@
---
hide:
- toc
---
# SmartDevices
Modules de pilotage de charges supportés par ETM PowerSync.
| Appareil | Protocole | Canal | Stabilité |
|---|---|---|---|
| [Waveshare relais](waveshare.md) | Modbus RTU | <span class="badge testing">TESTING</span> | <span class="badge consumer">CONSUMER</span> |
<!-- BEGIN GENERATED: __index_smartdevice__ -->
| Appareil | Protocole | Canal | Origine | Stabilité |
| --- | --- | --- | --- | --- |
| [Waveshare relais](waveshare.md) | Modbus RTU | <span class="badge testing">TESTING</span> | <span class="badge origin-etm">ETM</span> | <span class="badge experimental">EXPERIMENTAL</span> |
| [Shelly](shelly.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [Tasmota](tasmota.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge community">COMMUNITY</span> |
| [Tuya](tuya.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge community">COMMUNITY</span> |
| [GPIO](gpio.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge community">COMMUNITY</span> |
| [USB Relay](usbrelay.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [USB-RLY82](usbrly82.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
| [MQTT client](mqttclient.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge community">COMMUNITY</span> |
| [Modbus Commander](modbuscommander.md) | Modbus TCP | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge community">COMMUNITY</span> |
| [UniPi](unipi.md) | — | <span class="badge nightly">NIGHTLY</span> | <span class="badge origin-nymea">NYMEA</span> | <span class="badge consumer">CONSUMER</span> |
<!-- END GENERATED -->

View File

@ -1,6 +1,9 @@
# Waveshare relais
<span class="badge testing">TESTING</span> <span class="badge consumer">CONSUMER</span>
<!-- BEGIN GENERATED: __badges_waveshare-relay-d8__ -->
<span class="badge testing">TESTING</span> <span class="badge origin-etm">ETM</span> <span class="badge experimental">EXPERIMENTAL</span>
<!-- END GENERATED -->
Module de relais Waveshare (modèle 8 canaux RS485), pilotage via **Modbus RTU**.

View File

@ -1,3 +1,8 @@
---
hide:
- toc
---
# Tarifs & prévisions
<!-- BEGIN GENERATED: __index_tarif__ -->

View File

@ -22,8 +22,9 @@
.badge.nightly {color:#8fa9b5;background:rgba(143,169,181,.1);border:1px solid rgba(143,169,181,.3)}
/* stabilité plugin (meta.json) */
.badge.consumer {color:#31a3dd;background:rgba(49,163,221,.1);border:1px solid rgba(49,163,221,.3)}
.badge.community {color:#a78bfa;background:rgba(167,139,250,.1);border:1px solid rgba(167,139,250,.3)}
.badge.consumer {color:#31a3dd;background:rgba(49,163,221,.1);border:1px solid rgba(49,163,221,.3)}
.badge.community {color:#a78bfa;background:rgba(167,139,250,.1);border:1px solid rgba(167,139,250,.3)}
.badge.experimental {color:#fb923c;background:rgba(251,146,60,.1);border:1px solid rgba(251,146,60,.3)}
/* origine plugin (PORTING_STATUS.repo ou champ origin:) */
.badge.origin-nymea {color:#94a3b8;background:rgba(148,163,184,.1);border:1px solid rgba(148,163,184,.3)}

View File

@ -78,8 +78,9 @@ CHANNEL_BADGES = {
}
STABILITY_BADGES = {
"consumer": '<span class="badge consumer">CONSUMER</span>',
"community": '<span class="badge community">COMMUNITY</span>',
"consumer": '<span class="badge consumer">CONSUMER</span>',
"community": '<span class="badge community">COMMUNITY</span>',
"experimental": '<span class="badge experimental">EXPERIMENTAL</span>',
}
ORIGIN_BADGES = {
@ -100,6 +101,16 @@ def resolve_origin(e: dict) -> str:
return "etm"
return "tiers"
def render_header_badges(e: dict, meta: dict) -> str:
"""Rendu de la ligne de badges d'en-tête : canal, origine, stabilité."""
channel_badge = CHANNEL_BADGES.get(e["channel"], e["channel"])
origin_badge = ORIGIN_BADGES.get(resolve_origin(e), "")
stability = meta.get("stability", "")
stability_badge = STABILITY_BADGES.get(stability, "") if stability else ""
parts = [b for b in [channel_badge, origin_badge, stability_badge] if b]
return " ".join(parts) + "\n"
MARKER_RE = re.compile(
r"(<!-- BEGIN GENERATED: (?P<key>[^\s]+) -->)(?P<body>.*?)(<!-- END GENERATED -->)",
re.DOTALL,
@ -434,12 +445,10 @@ def build_device_page(e: dict, plugin_data: dict | None, meta: dict) -> str:
plugin = e["plugin"]
fname = f"integrationplugin{plugin}.json"
channel_badge = CHANNEL_BADGES.get(e["channel"], e["channel"])
origin_badge = ORIGIN_BADGES.get(resolve_origin(e), "")
stability = meta.get("stability", "")
stability_badge = STABILITY_BADGES.get(stability, "") if stability else ""
badges_parts = [b for b in [channel_badge, origin_badge, stability_badge] if b]
badges_line = " ".join(badges_parts)
badges_gen = render_header_badges(e, meta)
badges_block = (
f"<!-- BEGIN GENERATED: __badges_{plugin}__ -->\n{badges_gen}\n<!-- END GENERATED -->"
)
tagline = meta.get("tagline", "")
if plugin_data:
@ -449,11 +458,9 @@ def build_device_page(e: dict, plugin_data: dict | None, meta: dict) -> str:
file=sys.stderr)
gen = render_nightly_stub(e, meta)
# Bloc BEGIN/END au format exact produit par process() :
# f"{m.group(1)}\n{gen}\n{m.group(4)}" avec gen qui se termine par \n
block = f"<!-- BEGIN GENERATED: {fname} -->\n{gen}\n<!-- END GENERATED -->"
header_parts = [f"# {title}", "", badges_line]
header_parts = [f"# {title}", "", badges_block]
if tagline:
header_parts += ["", tagline]
header_parts.append("") # ligne vide avant le bloc BEGIN
@ -468,7 +475,7 @@ def build_category_index_page(cat: str, entries: list, plugins: dict, src: Path)
gen = render_category_index(cat, entries, plugins, src)
# Même format que process() : f"{m.group(1)}\n{gen}\n{m.group(4)}"
block = f"<!-- BEGIN GENERATED: __index_{cat}__ -->\n{gen}\n<!-- END GENERATED -->"
return f"# {label}\n\n{block}\n"
return f"---\nhide:\n - toc\n---\n\n# {label}\n\n{block}\n"
# ── Création des fichiers manquants ───────────────────────────────────────────
@ -543,6 +550,14 @@ def process(docs: Path, entries: list, plugins: dict, src: Path, check: bool) ->
key = m.group("key")
if key == "__matrix__":
gen = render_matrix(entries, plugins, src)
elif key.startswith("__badges_"):
plugin_name = key.removeprefix("__badges_").removesuffix("__")
entry = entry_by_plugin.get(plugin_name)
if not entry:
print(f" ! {md.name}: clé '{key}' plugin '{plugin_name}' inconnu",
file=sys.stderr)
return m.group(0)
gen = render_header_badges(entry, load_meta(src, plugin_name))
elif key.startswith("__index_"):
# key = "__index_<cat>__" → strip prefix "__index_" et suffix "__"
cat = key.removeprefix("__index_").removesuffix("__")