23 Commits

Author SHA1 Message Date
Patrick Schurig
81621b2bcc docs: emballement du banc — artefact, pas défaut ; ECS-303 non affaibli
Correction de mon explication du volet 2. Le chauffe-eau n'était pas à 3500 W par
reliquat mais par EMBALLEMENT, et le mécanisme change la conclusion.

Deux conditions se composent sur .75 : les Things sont des relais GPIO, dont la
ThingClass n'expose pas currentPower — le recrédit anti-clignotement crédite donc
le nominal commandé ; et le rootmeter est la vue SunSpec du simulateur, aveugle
aux résistances câblées sur ces broches — la conso ECS ne fait jamais baisser
l'export mesuré. budget_charge = surplus + palier double-compte, le palier monte
d'un cran par cycle tant que le surplus dépasse 500 W, jusqu'au plafond. C'est ce
qui explique les quatorze plateaux sans commutation, pas un point de départ
malheureux.

GARDE-FOU ajouté sous « Correction B » dans AGENTS.md et dans le relevé : c'est un
ARTEFACT DE BANC, pas un défaut du moteur. Sur une installation réelle l'ECS est
derrière le compteur réseau, sa consommation fait réellement chuter l'export, et
le recrédit compense exactement ce qu'elle vient de retirer. Le supprimer casserait
l'anti-oscillation qu'il protège (ECS-404) sans rien régler. Sans cette note,
quelqu'un « corrigerait » la correction B sur la foi de cette mesure.

ECS-303 n'est donc PAS affaibli : ma remarque valait pour ce banc, où aucune montée
pas à pas n'est possible. Avec de la physique réelle, la rampe matinale traverse la
bande 1500-2000 W lentement et la frontière est franchie normalement. Le volet 2
n'est pas à refaire depuis le palier 0 sur le simulateur — il est à faire après le
câblage, sur la vraie installation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 09:59:28 +02:00
Patrick Schurig
9e37fdcbbb docs(agents): invariants BUILD — corriger la référence qt5 → qt6, d'après le build réel
Documente ce qui a effectivement tourné, pas ce qui était supposé. Build
1.15.2+etm3 du 2026-08-08, cross arm64, réussi.

- L'exclusion DH_OPTIONS=-N nymea-energy-tests était citée pour debian-qt5/rules
  alors que c'est qt6 qui construit (debian -> debian-qt6, dh --buildsystem=qmake6).
  Vérifié avant le build : l'exclusion EST présente dans debian-qt6/rules:6, donc
  seule la citation était périmée. Aucun paquet nymea-energy-tests produit.

- Les dépendances étaient annoncées « toutes en 1.15.0 » avec Qt5
  (libqt5websockets5-dev, qtbase5-dev, qttools5-dev-tools). Le build réel utilise
  nymea 1.15.2+202606191336~trixie1 et Qt 6.8.2 — chaîne Qt6 de bout en bout,
  cohérente avec la box (aucun libqt5 installé sur .75, ldd du .so ne renvoie que
  du Qt6).

- Ajouté : debian-qt6/changelog est un lien symbolique VERSIONNÉ vers
  ../debian-qt5/changelog, comme copyright et nymea-energy-tests.install.in. Il
  n'y a qu'un changelog réel. Sans cette note, lire les deux fichiers donne
  l'illusion d'une divergence — c'est l'erreur que j'ai commise et rapportée.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 14:57:27 +02:00
Patrick Schurig
e70a60c180 docs(etm): contrats Doxygen — types de config/contexte et adaptateurs stables
Couverture des fichiers non visés par la restructuration à venir : l'extraction
du noyau de calcul (étape 2) et celle de m_relayMapping (étape 3) ne les
touchent pas. relayrouter.h et energyarbitrator.h sont volontairement DIFFÉRÉS —
documenter ce qui va changer produirait du bruit d'historique.

Mesure sur la config du Doxyfile : 113 → 31 avertissements.
  loadconfig.h 41→0 · surpluscontext.h 30→0 · sgreadyadapter.h 4→1 (le \return
  restant relève du lot suivant) · etmvariableloadadapter.h 2→0 · evadapter.h 1→0

Ce sont des contrats, pas des étiquettes : enabled dit qu'une charge déclarée
mais exclue n'est JAMAIS pilotée ; priority qu'il s'agit d'un rang ascendant et
non d'un poids ; timestamp qu'il est la source unique du temps, dont dérivent
verrous et fenêtres ; setPowerLevels qu'il trie et déduplique ; fromMap qu'il
retourne une config NON validée ; internalRootMeter() qu'il peut être nul.

Ajouts « // [ETM] » hors etm/ (smartchargingmanager.h) : ils échappent au
périmètre du Doxyfile, la frontière étant un répertoire. Un inventaire explicite
est posé au marqueur [ETM] BEGIN, distinguant les trois cas — degradedMode() et
les trois accesseurs internal* sont des ajouts ETM et sont documentés ; les huit
changements de visibilité seule gardent la documentation de l'amont. La
définition de fait d'AGENTS.md renvoie à cet inventaire et l'étend explicitement
aux ajouts hors etm/.

Build amd64 0 erreur. Simulation : 7/7.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 11:47:05 +02:00
Patrick Schurig
f6a4be5560 docs(agents): consolidation des zones périmées (12 zones, aucun code)
Purge des affirmations devenues fausses depuis la rév. 3. Chaque correction est
vérifiée contre le code ; rien n'est repris du texte existant par défaut.

Zones : ÉTAT (tableau + Détail 3c) · « ce que le moteur sait faire » · DÉFÉRÉ
(2 entrées) · PLAN 3C · ARCHITECTURE CIBLE · WORKFLOW phase 3 · 3b révisé ·
Verrous minOn/minOff (2 endroits) · MODÈLE DE SÉCURITÉ (L2) · ROADMAP ·
RÉFÉRENCES.

Principales remises au fait :
  - EcsRelayAdapter et le kind Stage, supprimés en 5100674, disparaissent du
    schéma « non négociable » au profit de RelayRouter + EtmVariableLoadAdapter ;
    SocketScheduler et BatteryAdapter, qui n'existent pas, sont marqués [3d]/[3f].
  - EvAdapter::applyAction() n'est pas « inactif » : il est implémenté
    (evadapter.cpp:62-94) mais jamais appelé (energyarbitrator.cpp:288).
    3g est un travail de câblage, pas d'écriture.
  - minStage/maxStage ont été retirés du contexte ; minState/maxState et
    minStateHold subsistent et sont conservés tels quels.
  - La configuration des charges est persistée et rechargée à chaud depuis
    7184fe4 — le point (b) de la ROADMAP est fait côté moteur, seule l'UI
    Flutter reste ouverte.
  - Le watchdog L2 est en place, plus « à coder en 3c ».
  - PLAN 3C n'est plus reproduit (pseudocode nommant une classe supprimée et un
    identifiant « relay-stages » jamais livré) ; les corrections A et B, toujours
    en vigueur, sont conservées avec leurs références actuelles.
  - PRÉCONDITION ajoutée au basculement de SgReadyAdapter sur la config :
    retirer d'abord Q_ASSERT(m_stateRelays.contains(2)) au profit d'un refus
    explicite — l'assertion garde l'état 2, repli sûr du mode dégradé L2, et
    disparaît en release.

Aucune règle absolue 1 à 10 modifiée (vérifié identique à HEAD).
INVARIANTS BUILD / PACKAGING intact. Aucun code touché.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 10:51:10 +02:00
Patrick Schurig
65f281cd5a docs: AGENTS.md — acte bascule Voie B (Provides/Conflicts/Replaces) + version générique
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:25:28 +02:00
Patrick Schurig
3afef0436d [packaging] renommage powersync-* + version 1.15.0+etm1 + invariants AGENTS
- debian/control : Source+Package → powersync-energy-plugin-nymea ;
  Provides/Conflicts/Replaces: nymea-energy-plugin-nymea (remplace l'amont) ;
  description + homepage ETM.
- debian/changelog : nouvelle entrée tête powersync-energy-plugin-nymea
  (1.15.0+etm1) trixie — plus de 1.13.0/jammy comme version courante.
- debian/nymea-energy-plugin-nymea.install.in → powersync-energy-plugin-nymea.install.in
  (déjà commité via git mv).
- AGENTS.md : section "INVARIANTS BUILD / PACKAGING" (nom powersync-*,
  version +etmN, cross arm64, tests hors deb, vérification post-build).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 14:50:40 +02:00
Patrick Schurig
6670bed6cc [3e+doc] clôture 3e + TEST_TERRAIN.md + point d'étape
docs/TEST_TERRAIN.md : procédure Palier 1 (14 tests T1-T14) pour le banc nymea-dev arm64
— §0 pré-vol (forçables [À LIRE SUR LA BOX]), §1 déploiement (cross-arm64→scp→dpkg,
logging NymeaEnergy.debug, déclaration adaptateurs codée dans energypluginnymea.cpp),
§2-3 ECS 1/3 relais (dont transition non-cascadée 1500→2000), §4 SG-Ready (montée/
atomicité/hystérésis), §5 watchdog L2, §6 interaction priorités, §7 EV optionnel.

AGENTS.md ÉTAT : 3e clôturée (testEcsRelayTopologies dfdd988), audit Doxygen (5→0),
TEST_TERRAIN créé ; déféré = passe README+contrats (force/minStage-maxStage/min-maxState/
degradedMode pas encore dans le protocole publié), Waveshare, V2C, 3f, 3g, config priorités,
arm64 CI, Doxyfile+CI. Prochaine action : test terrain vendredi puis passe contrats.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 00:31:47 +02:00
Patrick Schurig
e641f289db [3e-étape] ÉTAT : 3e FAITE (suite 19/19) + récap capacités moteur + liste différé
Point d'étape : EV proxy + ECS + SG-Ready sur budget unifié trié par priorité,
protection compresseur, watchdog L2/mode dégradé. Différé : Waveshare (session
dédiée Modbus), 3d/3f/3g, config priorités API+UI, arm64 CI, test terrain vendredi.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 23:46:27 +02:00
Patrick Schurig
093fa09b5e [3e-3] mapping sémantique SG-Ready + waterfall unifié ECS/SG-Ready
getPlan : cascade unique sur charges non-EV (relay-stages + sg-ready) triées par
priorité — budget de surplus partagé. buildSgReadyStateAction : mapping qualitatif
(4 forcé hyst. 1,2/1,0 ; 3 reco ≥P3 ; 2 normal mains off ; 1 jamais via surplus),
recrédit sur puissance allouée déclarée, clamp lock-aware minState/maxState.

AGENTS.md : ROADMAP config priorités utilisateur (acquis tri unifié ; manque 3g VE
+ couche config JSON-RPC/UI Flutter pour drag-and-drop à chaud). Build 0/0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 23:19:54 +02:00
Patrick Schurig
cbee13e455 [3c-clôture] ÉTAT : 3c FAITE (suite 18/18 + charging 46/46), arm64 cross délégué CI
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 22:27:30 +02:00
Patrick Schurig
3a8eb5da86 [3c-docs] défauts minOn/minOff par type + séparation budget/verrou (protection compresseur)
Décision Patrick : délestage strict au budget, MAIS minOn/minOff (protection
compresseur, anti court-cycling) bornent le palier via l'adaptateur, pas le budget.
Paramètres par charge (config installateur, jamais hardcodé) + défauts indicatifs
par type (résistif / thermodynamique-PAC / SG-Ready). Note seam de temps unifié.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 21:26:38 +02:00
Patrick Schurig
f71e0405b4 [3c-6] degradedMode() + notification ChargingSchedulesChanged + invariant zéro-cloud
virtual degradedMode() dans SmartChargingManager (base false, [ETM] additif),
override EnergyArbitrator. Champ o:degradedMode (additif) dans la notification
NymeaEnergy.ChargingSchedulesChanged, émise aussi aux transitions du mode dégradé
(planif suspendue → push du flag via emit chargingSchedulesChanged()).
INTERFACE.md : champ degradedMode documenté.

SAFETY.md : notification réconciliée (ChargingSchedulesChanged, pas EnergyManagerChanged)
+ limite "valeur figée non détectée". Correction ZÉRO CLOUD : suppression de la section
"Alertes externes" / mécanisme n8n, remplacée par une signalisation 100% locale
(notification nymea in-app + buzzer/relais via règle nymea, aucun canal réseau sortant).
Invariant 10 "ZÉRO cloud" gravé dans AGENTS.md.

Build 0 erreur / 0 warning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 17:04:09 +02:00
Patrick Schurig
312a2484ae [3c-5] watchdog L2 : QTimer fraîcheur compteur + mode dégradé conservateur
QTimer 30s indépendant des signaux ; m_lastMeterUpdate picoté sur powerBalanceChanged.
Silence >90s → mode dégradé (appliqué à la TRANSITION uniquement) :
  - ECS palier 0 force=true ;
  - EV : clamp courant minimum SEULEMENT si déjà en charge (pas d'activation forcée ;
    "jamais 0 A si branché" relève du failsafe L1, pas du repli logiciel).
update() suspend la planification + le dispatch tant que m_degradedMode (sécurité L4
en position 3 reste active) → pas de rallumage sur le cache d'un compteur mort, pas
d'oscillation. Reprise au retour du compteur.

SAFETY.md §L2 : nuance maintenu/démarré + suspension planification. AGENTS.md morceau 7 :
exiger ECS reste à 0 sur plusieurs cycles. SG-Ready/Batterie déférés 3e/3f ;
flag degradedMode exposé en 3c-6. Build 0 erreur / 0 warning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:43:28 +02:00
Patrick Schurig
6298d5d42f [3c-3] waterfall ECS dans RuleBasedScheduler::getPlan() + tri priorité ASC
Corrections A (déduction EV unique) et B (anti-clignotement) intégrées.
Tri priorité ascendant (rang 1 = premier servi, OPTIMIZER_PROTOCOL §5/annexe C) —
corrige l'inversion du PLAN 3C et 3 doc-comments (plan.h, loaddescriptor.h,
ecsrelayadapter.h). Build 0 erreur / 0 warning.

telemetry() ECS : currentPowerW MESURÉE si au moins un relais expose "currentPower"
(thermostat coupé → 0, pas de fantôme), DÉCLARÉE en repli seulement sans comptage.
Dette evadapter.cpp priority=100 (ancienne convention) inscrite en 3g.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 16:20:08 +02:00
Patrick Schurig
7709057335 [wip] 3c morceaux 0-2 compilés + plan 3c validé dans AGENTS.md
Morceaux 0-2 implémentés et compilés (0 erreur / 0 warning) :
- M0 : LoadAction.force=false (bypass verrous anti-rebond sécurité)
- M1 : EcsRelayAdapter (.h+.cpp) — N paliers powerswitch, anti-rebond, etm.pri
- M2 : buildContext() — SurplusMeter brut, loads EV+ECS, registerEcsAdapter()

AGENTS.md : section PLAN 3C ajoutée avec corrections A+B intégrées.
Corrections A (déduction EV unique dans scheduler) et B (recrédit conso
propre anti-clignotement) documentées avant implémentation morceau 3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 13:34:42 +02:00
Patrick Schurig
19951a1e3e [3c-prep] AGENTS.md : ajout watchdog L2 + testMeterSilentFallback à la DoD 3c
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:36:12 +02:00
Patrick Schurig
5bb6da0e9f [3b-iv] ETM_ARBITRATOR actif — iso-fonctionnalité prouvée (simulation + tests charging, diff décisions zéro écart)
- energyplugin/energyplugin.pri : décommente DEFINES += ETM_ARBITRATOR (flip actif)
- energyplugin/etm/energyarbitrator.cpp : ajoute qCDebug "Updating smart charging" en tête
  de update() — comparabilité des logs avec l'amont garantie
- AGENTS.md : 3b →  FAITE, chiffres de preuve, prochaine action 3c

Preuve iso-fonctionnalité :
- Simulation : 226 lignes décisions (Theoretically/Surplus/Current load) — diff = 0
- Tests charging : 57 lignes décisions — diff = 0 ; 46/46 PASS ref ET ETM
- [Arbitre] présents avec raisons françaises (idle, surplus PV, aWATTar, deadline)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:29:34 +02:00
Patrick Schurig
c3fedfe36b [3b] décision B + modèle sécurité (AGENTS + SAFETY.md) + Doxygen proxy/inactif
- AGENTS.md : nouvelle entrée "3b révisé — délégation EV à l'amont" (beta hybride
  assumée, ETM réel en 3c, transplantation EV en 3g) ; modèle sécurité L0-L4
  avec double déclenchement verifyOverloadProtection documenté (signal ligne 127 +
  appel cyclique ligne 313 SCM.cpp).
- docs/SAFETY.md : document normatif 5 couches + signalisation locale optionnelle ;
  Variante B confirmée pour le repli L2 (EV au minimum + notification nymea +
  risque 1,4 kW accepté) ; table défaillances/couches corrigée (L1 ne couvre pas
  compteur hors ligne).
- energyarbitrator.cpp update() : commentaire explicitant la correspondance exacte
  avec l'ordre SCM (1-4 parent, ETM entre 4 et 7, planSpot+planSurplus via getPlan).
- rulebasedscheduler.h : Doxygen getPlan() marqué "PROXY AMONT POUR L'EV (beta)".
- evadapter.h : Doxygen applyAction() marqué "Inactif jusqu'à 3g".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 07:41:12 +02:00
Patrick Schurig
7d3fc6e5ea add adresse IP dans AGENTS.md 2026-06-08 07:23:55 +02:00
Patrick Schurig
08039a3542 [wip] état session — phases 0-3b, prochaine action 3b-iv, topologie remotes 2026-06-07 23:34:18 +02:00
Patrick Schurig
5f49e4ca3c [3b-wip] EnergyArbitrator + RuleBasedScheduler + EvAdapter (dispatch amont, ETM_ARBITRATOR désactivé)
- EnergyArbitrator : public SmartChargingManager — raison documentée dans AGENTS.md §DÉCISIONS DE DESIGN
- SmartChargingManager : protected slots + virtual update() + 3 accesseurs inline [ETM]
- RuleBasedScheduler::getPlan() wraps planSurplusCharging/planSpotMarketCharging, annote chaque action d'un reason français
- EvAdapter : ILoadAdapter concret pour evcharger — applyAction() implémenté, NON appelé en 3b (dispatch via adjustEvChargers() amont, iso-fonctionnel)
- ETM_ARBITRATOR : commenté dans .pro — ne s'active qu'après preuve iso-fonctionnelle (3b-iv)
- Doxygen \brief + invariants + contrats sur toutes les classes/méthodes publiques etm/ (DoD §5)
- plan.h : timeSlots (pas slots, mot-clé Qt) ; commentaire JSON sérialisation "slots" OPTIMIZER_PROTOCOL §6
- .clangd : flags de repli Qt/nymea pour clangd via symlink ~/Schreibtisch/
- compile_commands.json gitignore (chemins absolus locaux)
- Build : 0 erreurs, 0 warnings — libnymea_energypluginnymea.so 914 KB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 23:16:49 +02:00
Patrick Schurig
9017a880ac [brief] AGENTS.md = version définitive (architecture+workflow), statut phases 0-3a, décision TARGET drop-in actée 2026-06-07 22:06:50 +02:00
Patrick Schurig
074fa71308 [brief] AGENTS.md définitif (arbitre+LoadAdapters), CLAUDE.md pointeur, protocole versionné 2026-06-07 21:32:12 +02:00