26 Commits

Author SHA1 Message Date
Patrick Schurig
0ae23ce2db docs: suppression de la fiche orpheline homeconnect
Elle n'avait plus d'entrée dans PORTING_STATUS : donc pas de badges générés
(les siens étaient du HTML figé annonçant NIGHTLY), pas de traduction, pas
d'entrée de nav. Elle était rendue et servie sans que rien ne la pilote.

Ce n'était pas un oubli de cadrage mais le reliquat d'une décision déjà prise et
consignée : `PORTING_STATUS.yaml:420` porte l'entrée `homeconnect` COMMENTÉE, au
milieu du bloc des plugins nymea amont volontairement hors périmètre — sonos,
telegram, wakeonlan, yamahaavr. Des fours, lave-vaisselle et cafetières
connectés appartiennent à cette même famille « hors énergie ». La fiche avait
survécu au commentaire de son entrée.

Rien de rédigé n'est perdu : la page était à 100 % du bloc généré, plus un titre
et un tagline amont reproductibles. La ligne commentée de PORTING_STATUS est
laissée telle quelle — c'est la trace de la décision.

Vérifié : build --strict sans avertissement, contrôle d'idempotence « Doc à
jour », catégorie HVAC toujours à 9 appareils.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-13 09:09:26 +02:00
Patrick Schurig
846c0c7525 feat(i18n): traduire ce qu'on écrit, garder verbatim ce que la machine affiche
Signalé sur /de/appareils/bornes/goecharger/ : la page était allemande sur deux
lignes et anglaise sur tout le reste. Le diagnostic a séparé deux choses que
j'avais mises dans le même sac le 2026-10-12.

LA LIGNE DE PARTAGE, écrite en tête du générateur :

  • les LIBELLÉS QUE NOUS ÉCRIVONS (en-têtes de colonnes, titres de section,
    oui/non, « Documentation fabricant ») → TRADUITS. Ils ne désignent rien à
    l'écran, l'anglais n'y était qu'une friction. REF devient REF_I18N, trois
    jeux de 20 libellés.

  • le CONTENU VENANT DE NYMEA (noms de modèles, clés de registres, libellés de
    champs comme « MAC address », unités) → VERBATIM, en anglais. Ce sont
    exactement les chaînes que l'installateur lit DANS L'APP, qui tourne en
    en_US. Les traduire rendrait la doc inutilisable pour retrouver un champ à
    l'écran.

Et la pièce qui change l'expérience plus que la traduction elle-même : une note
`verbatim`, générée dans la langue de la page, en tête du bloc de référence.
Sans elle le mélange FR/EN passe pour une traduction bâclée ; avec elle c'est
une convention que le lecteur comprend.

L'injection devient sensible à la langue : `locale_of()` déduit la langue du
suffixe du fichier et `process()` rend le bloc en conséquence. Sans ça le même
bloc partait à l'identique dans les trois versions.

TAGLINES ET TITRES — i18n/devices.yaml, 52 entrées

Le tagline vivait en paragraphe libre, écrit UNE SEULE FOIS à la création de la
page : il restait donc en anglais sur les trois versions, y compris la
FRANÇAISE. Il entre dans le bloc badges, donc il est régénéré, donc traduisible
pour toujours. 52 taglines en fr et de ; l'anglais retombe sur l'amont.

Les traductions vivent dans le dépôt de DOC et pas dans les meta.json : trois
des cinq dépôts plugins sont des dépôts nymea amont que l'AGENTS.md interdit de
modifier. Repli sur l'amont pour toute entrée absente.

Deux titres s'affichaient en FRANÇAIS sous /de/ et /en/ — « Compteur ABB B2x »,
« Borne ABB Terra AC » : corrigés, dans la page et dans la nav.

Deux coquilles AMONT corrigées au passage, repérées en relisant les 57 entrées :
meta.json annonçait « Bestel » pour Vestel et « Easeex » pour Easee. Signalées
comme corrections, pas comme traductions, dans i18n/devices.yaml.

48 FICHES FR ÉTAIENT DANS UN ANCIEN FORMAT, ET MENTAIENT

Trouvé en vérifiant : 48 fiches FR n'avaient pas de marqueur `__badges_*__`.
Leurs badges étaient du HTML figé, écrit une fois — goecharger affichait
« NIGHTLY » alors que PORTING_STATUS dit `stable` depuis. Elles sont migrées au
format canonique : badges générés, donc exacts, plus titre localisé, tagline et
intertitre. Reste `hvac/homeconnect.md`, orpheline (plugin hors PORTING_STATUS).

NAV : UN CONSTAT QUI ÉVITE DE REFAIRE L'ESSAI

`literate-nav` ne lit que son `nav_file` : la substitution par suffixe de
mkdocs-static-i18n ne s'y applique PAS. Un `SUMMARY.de.md` généré n'était lu par
personne et la barre latérale allemande gardait les noms français. Testé, puis
retiré — et la raison est écrite dans le générateur pour que personne n'y
revienne. Les libellés de nav passent par `nav_translations` : 31 éléments
traduits par langue au lieu de 29.

RÉFÉRENCE API : LAISSÉE EN ANGLAIS, DÉLIBÉRÉMENT

Les 23 pages de l'API n'ont pas de variante par langue. Leur traduire les
libellés aurait fait voir du FRANÇAIS aux lecteurs /de/ et /en/ par le repli —
une régression. Créer 46 variantes pour traduire dix libellés aurait triplé
28 000 mots de contenu généré pour un gain nul : le reste de la page (noms de
méthodes, de champs, de types, descriptions) est l'API elle-même, et ce sont les
chaînes qu'on écrit dans ses requêtes. À la place, une note explique dans les
trois langues POURQUOI cette référence est en anglais.

Vérifié : build --strict sans avertissement, les deux générateurs rendent « Doc à
jour » en --check, et la fiche goecharger relue dans les trois langues.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-13 08:42:21 +02:00
Patrick Schurig
be0cbcf42d fix(i18n): drapeaux dans le sélecteur de langue de la doc
Material rend son sélecteur en liste déroulante, chaque entrée portant un
`hreflang` : on l'habille donc en CSS pure, sans toucher au gabarit du thème ni
surcharger de template. Vérifié sur le HTML produit : les trois entrées ont bien
`hreflang="fr|de|en"` et la classe `md-select__link`.

Mêmes choix que sur le site vitrine, et pour les mêmes raisons : SVG inline en
data-URI plutôt qu'emoji (🇫🇷 ne s'affiche pas sous Windows), et le NOM de la
langue conservé à côté du drapeau (un drapeau désigne un pays, pas une langue —
et l'anglais sert ici les deux marchés plus la communauté).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-13 08:19:53 +02:00
Patrick Schurig
0c8c814f75 fix(ci): l'entrée Waveshare bloquait toute la chaîne — retirée, CI débloquée
validate_entries() arrête la génération quand une entrée de PORTING_STATUS d'un
canal autre que nightly n'a pas son integrationplugin*.json dans --src. L'entrée
waveshare-relay-d8 était en `channel: testing` pour un plugin qui n'a JAMAIS été
livré : la CI a donc échoué chaque nuit du 2026-08-02 au 2026-10-13, et le site de
doc est resté gelé au build du 1er août. Dix semaines, en silence.

Le garde-fou avait raison. C'est l'entrée qui était fausse, pas le contrôle — d'où
le choix de retirer l'entrée plutôt que de la basculer en nightly (ce qui aurait
publié « portage en cours » là où il n'y a pas de portage) ou d'assouplir
validate_entries() (ce qui aurait échangé un échec visible contre une doc
silencieusement incomplète).

Retirés : l'entrée de PORTING_STATUS — remplacée par le motif complet, sur place,
pour que personne ne la réintroduise sans savoir — et les trois fiches
smart/waveshare.{md,de.md,en.md}. Le reste des mentions vivait dans du contenu
généré (SUMMARY.md, index de catégorie, matrice de compatibilité) et a disparu à
la régénération.

Au passage, deux choses trouvées en nettoyant :
- `appareils/index.md` citait « SmartDevices — Waveshare » comme exemple de la
  catégorie ; remplacé par Shelly, Tasmota, GPIO, qui sont en canal stable.
- cette même page n'avait AUCUNE variante traduite : une entrée de nav de premier
  niveau servie en français sous /de/ et /en/. Traduite.

Chaîne CI rejouée en entier dans l'ordre, après correction : génération appareils
OK, génération API OK, `mkdocs build --strict` sans aucun avertissement,
contrôle d'idempotence OK.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-13 07:43:31 +02:00
Patrick Schurig
325409dd3f feat(i18n): prose traduite DE/EN et référence régénérée en anglais
82 pages .de.md et 82 .en.md. La volumétrie explique la forme : 95 % du volume
est GÉNÉRÉ (74 013 mots contre 3 506 rédigés, mesuré sur 107 pages). On ne
traduisait donc pas 77 500 mots — on traduit la prose, et le vocabulaire des
générateurs fait le reste.

Prose traduite à la main : accueil, installation (4), fonctionnalités (4),
tarifs, référence, dépannage, FAQ, intégrations (2), api/index, et les 6 fiches
appareils qui portent une vraie prose + compatibilite.md. Les blocs générés ne
sont JAMAIS recopiés dans une traduction : le script de pose les reprend
verbatim du fichier français via des placeholders, pour qu'une traduction ne
puisse pas désynchroniser un bloc généré.

Les 49 fiches légères n'ont rien à traduire : leur tagline vient d'amont et est
DÉJÀ en anglais (« Connects nymea to powerfox. »). Constat, pas renoncement.

Localisation ≠ traduction, et tarifs.md en est l'exemple à connaître : la
version FR parle de Tempo et du signal RTE, la DE de §14a EnWG et de SMARD,
l'EN des deux. Ce ne sont pas des traductions l'une de l'autre, et c'est
volontaire — les signaux tarifaires sont nationaux. Aucune des deux n'est
annoncée comme livrée : les deux sont Roadmap, et les pages le disent.

Référence régénérée : en-têtes et libellés en anglais (Field/Type/Notes,
Supported models, Settings, Read-only, Brand / Model…). Conséquence assumée et
signalée : les pages FR en ligne changent aussi.

README.md (il était VIDE) : la règle du 95 % généré en tête, la frontière de
décision du multi-langue avec sa mesure, pourquoi SCAFFOLD existe, et le piège
--strict/navigation.instant.

TODO : multi-langue clos, et trois points ouverts qui en restent — les tagline
vivent dans les meta.json de 5 autres dépôts (forme à ajouter : tagline_de /
tagline_en), les stubs traduits restent des stubs (la dette éditoriale a triplé
en surface, pas en fond), api/types.md n'a pas besoin de variante. Le P1
openmeteo est corrigé sur constat : il EST dans PORTING_STATUS depuis, et une
ligne commentée contradictoire y traîne encore.

Vérifié : mkdocs build --strict vert sur les trois langues, 322 pages HTML,
contenu traduit relu dans le HTML produit, et les deux générateurs rendent
« Doc à jour » en --check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-13 06:39:20 +02:00
Patrick Schurig
b2b92e7ce1 feat(i18n): mkdocs-static-i18n, trois langues construites en une passe
mkdocs.yml : plugin i18n en mode `suffix` (page.md = fr, page.de.md,
page.en.md), fr par défaut, fallback_to_default, un index de recherche par
langue, et nav_translations — 29 éléments traduits par langue, vérifié au
build. i18n est placé AVANT literate-nav et search : il réécrit l'arbre des
fichiers par langue, les autres doivent voir l'arbre déjà localisé.

navigation.instant est RETIRÉ de theme.features. Ce n'est pas un arbitrage de
confort : il est incompatible avec le lien contextuel du sélecteur de langue de
mkdocs-static-i18n, et l'avertissement fait ÉCHOUER `mkdocs build --strict`.
Le sélecteur l'emporte — atterrir sur la même page dans l'autre langue vaut
plus qu'un chargement instantané qui renvoie à l'accueil. Le commentaire est à
l'endroit du retrait, pas ailleurs.

Vérifié que literate-nav et static-i18n cohabitent, plutôt que supposé : build
construit, nav de /de/ relue dans le HTML produit (« Geräte », « Kompatibilität »,
liste des appareils bien dépliée).

CI : --locales fr,de,en sur la génération ET sur le contrôle d'idempotence. Et
une étape qui manquait — gen_api_reference.py n'était pas dans le pipeline, sa
sortie ne se propageait donc qu'au prochain passage manuel.

requirements.txt : mkdocs-static-i18n >= 1.3.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-13 06:39:19 +02:00
Patrick Schurig
e88c283243 feat(i18n): le bloc de référence passe en anglais, et --lang devient réel
Le vocabulaire des deux générateurs sortait en français en dur. Il est
externalisé dans un dict REF par générateur, EN ANGLAIS, un seul jeu servi
identique dans les trois langues.

La raison est une MESURE, pas un goût : nymea ne sert aucune traduction sur
notre parc. Vérifié le 2026-10-12 sur le banc `hems` —
Integrations.GetThingClasses rend la MÊME charge utile au sha256 près
(243 340 octets) pour fr_FR, de_DE et en_US, et nymea-plugins-translations
n'est pas installé. Les noms de modèles, de registres et d'unités sont donc
déjà en anglais ; traduire les seuls en-têtes de colonnes autour aurait
fabriqué des pages bilingues sans rien gagner. Côté API c'est plus direct
encore : méthodes, champs, types et `description` viennent d'introspect.json.

Ce qui se TRADUIT, en revanche, c'est la prose et la navigation. D'où deux
ajouts côté fiches appareils :

- SCAFFOLD : l'échafaudage de prose par langue (titre de catégorie, intertitre
  « Référence », mention de guide à venir). Sans lui, chaque nouvel appareil
  créerait sa fiche dans la seule langue par défaut, et fallback_to_default la
  servirait EN FRANÇAIS sous /de/ et /en/ — par le simple fait d'être créée.
- CATEGORY_LABELS_I18N pour les titres de pages d'index de catégorie.

`--lang` existait depuis la CI mais n'était PAS lu (« Conservé pour
compatibilité CI »). Il désigne maintenant la langue par défaut — celle dont
les fichiers n'ont pas de suffixe — et `--locales` dit lesquelles générer.
ensure_device_pages() et ensure_category_indexes() bouclent dessus, et ne
réécrivent JAMAIS une page existante : la prose traduite à la main survit aux
régénérations. Vérifié : second passage, « Doc à jour », 0 page régénérée.

Les messages de diagnostic (ERREUR, AVERTISSEMENT, BLOQUANT) restent en
français : ils s'adressent au mainteneur, pas au site.

Note de méthode : la validation par ast.parse() ne voit pas une erreur de table
des symboles (`global` après usage). compile() la voit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-13 06:38:45 +02:00
ec3dbd9650 Téléverser les fichiers vers "/" 2026-06-29 06:20:12 +02:00
827de2c4d8 mise a jour 2026-06-06 09:51:43 +02:00
b26274595c feat: référence API JsonRPC générée depuis introspect.json
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 10m17s
- Nouveau générateur scripts/gen_api_reference.py : 19 namespaces →
  docs/api/metier/ (10) + docs/api/systeme/ (9) + notifications.md +
  types.md (96 types · 55 enums · 4 flags) + SUMMARY.md literate-nav
- Badges permissionScope (perm-none/control/configure/admin) dans extra.css
- Guide docs/integrations/jsonrpc-api.md (connexion TCP/WS, auth, conventions énergie)
- mkdocs.yml : Référence API dans la nav, REST→JsonRPC renommé
- mkdocs build --strict : 0 warnings · --check idempotent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 08:15:37 +02:00
f3b254c5af feat: canal stable pour nymea upstream, Keba fork ETM, cohérence badges
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 11m56s
Correction 2 — canal par défaut selon l'origine :
- Tous les plugins origin:nymea passent de nightly→stable (upstream redistribué tel quel)
- Plugins ETM conservent leur canal manuel (eastron=stable, abb-b2x/abb-terra/waveshare=testing)
- Ajout name: sur 5 plugins sans meta.json (v2xeamberelectric→Amber Electric, mtec,
  genericenergy, genericheatingcooling, genericcar)

Correction 3 — Keba fork ETM :
- repo: etm-powersync-plugins (fork corrigé KC-P30), channel: testing, origin: etm
- La version nymea-plugins (bugguée) n'est plus déclarée → écartée de facto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 16:09:03 +02:00
a7dedb3366 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>
2026-06-03 15:42:04 +02:00
0f2be2e000 feat: badge origine + catalogue complet PORTING_STATUS (60 plugins)
All checks were successful
Build & Deploy docs / build-deploy (push) Successful in 1m47s
Partie 1 — Dimension « origine » (3ème badge)
- gen_device_reference.py : ORIGIN_BADGES dict, resolve_origin() déduit
  l'origine depuis repo: (nymea-* → NYMEA, etm-* → ETM) ou champ origin:
  explicite ; colonne Origine ajoutée dans matrice et index de catégorie ;
  badge origine dans l'en-tête des fiches générées
- extra.css : styles .badge.origin-nymea (gris-bleu), .badge.origin-etm
  (vert), .badge.origin-tiers (orange)
- compatibilite.md : légende étendue aux 3 dimensions (canal, origine, stab.)
- Catégorie « generic » ajoutée (Types génériques nymea)

Partie 2 — Catalogue complet PORTING_STATUS.yaml
- 9 entrées validées conservées avec leurs canaux (stable/testing/nightly)
- 41 nouveaux plugins énergie activés (channel: nightly) : onduleurs PV
  (sma, solax, sungrow, huawei, kostal, mtec, wattsonic, sunspec, bosswerk,
  solarlog), IRVE (easee, goecharger, evbox, everest, v2xeamberelectric,
  amperfied, mennekes, webasto, pcelectric, phoenixconnect, inro),
  HVAC (tado, homeconnect, stiebeleltron, idm, drexelundweiss, alphainnotec,
  mypv), compteurs (powerfox, bgetech, inepro, schrack, vestel, senseair),
  smartdevices (shelly, tasmota, tuya, gpio, usbrelay, usbrly82, mqttclient,
  modbuscommander, unipi), tarifs (awattar, tempo, spothinta),
  generic (genericenergy, genericheatingcooling, genericcar)
- 60 plugins domotique/hors-périmètre commentés (réactivables via # → -)
- 50 fiches générées + 2 index créés (tarifs/, generic/)
- mkdocs build --strict OK, --check exit 0 (idempotent)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 15:02:25 +02:00
e6d9225a4a feat: génération complète des fiches appareils depuis PORTING_STATUS + JSON
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 13m43s
Le générateur crée désormais entièrement les fiches inexistantes (titre,
badges, section générée BEGIN/END) et les index.md de catégorie manquants.
Les fiches rédigées manuellement (eastron, abb-b2x, abb-terra, keba,
waveshare) sont préservées — seul le contenu entre marqueurs est réinjecté.

- gen_device_reference.py : ensure_device_pages() + ensure_category_indexes()
  créent les .md manquants dans le format exact de process() → idempotent
- render_matrix() : inclut tous les canaux (nightly sans JSON = ligne stub)
- generate_summary() : intègre check mode + inclut toutes les entrées nav
- process()/repl() : gère __index_<cat>__ et nightly sans JSON → stub
- load_plugins/load_meta : logging explicite pour JSON vides ou non parsables
- Supprimer stubs manuels hvac/{daikinairco,sgready,simpleheatpump,index}.md
  et onduleurs/{fronius,index}.md → remplacés par fichiers générés
- 9 appareils dans la matrice et dans le SUMMARY.md, mkdocs build --strict OK

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 13:05:23 +02:00
5ca9b91b17 ci: install rsync dans le conteneur avant déploiement
All checks were successful
Build & Deploy docs / build-deploy (push) Successful in 1m20s
2026-06-03 07:06:32 +02:00
acc33d399f add 6 pages stub hvac/index hvac/daikinairco hvac/sgready hvac/simpleheatpump onduleurs/index onduleurs/fronius -> test runner gitea
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 1m14s
2026-06-03 06:56:26 +02:00
171076db28 ci: corrige nom repo nymea-plugins-genericthings
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 14m29s
2026-06-03 06:17:30 +02:00
e6884e6488 ci: install python3-pip dans le conteneur node
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 1m27s
2026-06-02 14:44:55 +02:00
9ff2f07e4b ci: remove smoke test workflow
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 7s
2026-06-02 14:38:11 +02:00
42407c2b98 ci: restore build & deploy workflow
Some checks failed
smoke / hello (push) Successful in 5s
Build & Deploy docs / build-deploy (push) Failing after 11s
2026-06-02 14:33:08 +02:00
b955aca55e runner on VM etm-srv-runner
All checks were successful
smoke / hello (push) Successful in 1m22s
2026-06-02 12:25:55 +02:00
925e78a8c2 ci: supprime defaults working-dir, cd explicite dans chaque step
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 0s
2026-06-02 11:13:45 +02:00
3f83cc49de ci: debug checkout — workdir fixe + echos
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 6s
2026-06-02 10:55:09 +02:00
c81cdd3e41 ci: remplace actions/checkout+setup-python par git/pip natifs (évite téléchargements GitHub)
Some checks failed
Build & Deploy docs / build-deploy (push) Failing after 10m4s
2026-06-02 10:26:57 +02:00
9eee067829 feat: docs-as-code — générateur, literate-nav, badges, CI Gitea Actions
- PORTING_STATUS.yaml : source de vérité canal APT + placement nav
- scripts/gen_device_reference.py : génération matrice + fiches + SUMMARY.md
  depuis integrationplugin*.json + meta.json ; nightly sans JSON = invisible
- mkdocs.yml : plugin literate-nav, nav 6 sections, Appareils via SUMMARY.md
- .gitea/workflows/docs.yml : CI complet — fetch JSON (branche auto-détectée),
  génération, build --strict, check idempotence, rsync deploy
- Badges HTML (stable/testing/nightly + consumer/community + ok/part/road)
- Fiches appareils : Eastron, ABB B2x, ABB Terra, Keba, Waveshare
- requirements.txt : mkdocs-material, mkdocs-literate-nav, PyYAML

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 08:53:54 +02:00
Patrick Schurig
394d8bc54a docs: <ce qui a changé> 2026-05-28 17:26:17 +02:00