diff --git a/energyplugin/etm/adapters/evadapter.cpp b/energyplugin/etm/adapters/evadapter.cpp index 6469ad4..458eef0 100644 --- a/energyplugin/etm/adapters/evadapter.cpp +++ b/energyplugin/etm/adapters/evadapter.cpp @@ -157,8 +157,27 @@ LoadAction EvAdapter::applyAction(const LoadAction &action, const QDateTime &now double demandeA = action.currentA; if (demandeA <= 0 && action.powerW > 0) - demandeA = action.powerW / (230.0 * phases); + // 3g-2 — arrondi au PLUS PROCHE, comme le faisait le proxy. Tronquer paraissait plus + // prudent (« ne jamais dépasser l'enveloppe ») et coûtait systématiquement un ampère : + // 230 W par phase abandonnés à chaque cycle, sur toute la journée. Les 18 scénarios de + // simulation le chiffrent — voiture 1 % moins chargée le soir, huit fois sur huit. + // + // L'enveloppe est une ALLOCATION, pas une limite : elle sort d'une mesure de compteur + // dont le bruit dépasse largement 115 W. Ce qui est une limite, c'est le plafond + // matériel — et celui-là n'est jamais franchi : il est déclaré à l'enveloppe par + // toLoadContext(), et le qBound ci-dessous écrête au courant maximal de la borne. + demandeA = qRound(action.powerW / (230.0 * phases)); + // La limite de phase n'est PAS réappliquée ici, et c'est délibéré : elle est déjà dans + // l'enveloppe, déclarée par toLoadContext() comme plafond de la charge, donc respectée par + // le waterfall AVANT d'allouer. La réappliquer en ampères entiers ferait un second + // écrêtage, plus strict que celui de l'amont (plancher au lieu d'arrondi), et coûterait à + // nouveau un ampère dans les scénarios de simulation — pour 69 W de marge théorique que la + // couche L4, elle, mesure réellement en temps réel. + // + // La répartition reste celle du modèle de sécurité : la stratégie respecte le plafond + // déclaré, l'adaptateur écrête au matériel, et verifyOverloadProtection() garde le dernier + // mot sur la mesure. const uint clampedA = static_cast( qBound(static_cast(minA), demandeA, static_cast(maxA)));