fix(arbitre): un filtre par interface qui ne trouve rien doit le DIRE
Un filterByInterface qui rend une liste vide est toujours ambigu entre « il n'y a pas de batterie » et « il y en a une, mal déclarée ». Le second désactive une règle de sécurité sans produire ni erreur ni panne — même mode de défaillance qu'un seuil de réserve mal réglé : rien ne se signale. Constaté sur le banc : le Thing « SunSpec Storage » déclare battery mais pas energystorage. La réserve ne s'est donc JAMAIS appliquée — ni dans le waterfall que je viens d'écrire, ni dans le proxy amont qui utilisait le même filtre depuis toujours, ni dans le bilan de puissance de l'experience-plugin qui filtre pareil. GetPowerBalance rend currentPowerStorage: 0 pendant que la batterie affiche 50 % et « Holding » : elle n'est pas à zéro, elle est invisible. L'arbitre émet maintenant un avertissement quand des appareils portent 'battery' sans 'energystorage'. Il ne corrige rien — la déclaration appartient au plugin — mais il rend la cause lisible au lieu de la laisser deviner. Brief émis vers etm-powersync-plugins-modbus : ce n'est pas une ligne de JSON, l'interface exige currentPower et capacity que la classe ne fournit pas, et un currentPower de batterie à zéro serait pire que son absence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XPUo3RMr8SzK6qbFtfBm8H
This commit is contained in:
parent
9157ebdfe7
commit
5685ee8596
@ -437,6 +437,28 @@ SurplusContext EnergyArbitrator::buildContext(const QDateTime &now) const
|
||||
ctx.battery.present = true;
|
||||
ctx.battery.socPercent = niveauTotal / n;
|
||||
ctx.battery.powerW = puissanceTotale; // > 0 charge, < 0 décharge
|
||||
} else {
|
||||
// Un filtre par interface qui ne trouve rien est TOUJOURS ambigu : « il n'y a pas
|
||||
// de batterie » et « il y en a une, mal déclarée » se ressemblent, et la seconde
|
||||
// désactive une règle de sécurité EN SILENCE. C'est le même mode de défaillance
|
||||
// qu'un seuil de réserve mal réglé : rien ne se signale.
|
||||
//
|
||||
// Constaté sur le banc le 2026-08-26 : le Thing « SunSpec Storage » déclare
|
||||
// `battery` mais pas `energystorage`, donc la réserve ne s'est jamais appliquée —
|
||||
// ni ici, ni dans le proxy amont qui utilisait le même filtre, ni dans le bilan de
|
||||
// puissance de l'experience-plugin qui filtre pareil.
|
||||
const Things candidates = m_tm->configuredThings().filterByInterface("battery");
|
||||
if (!candidates.isEmpty()) {
|
||||
QStringList noms;
|
||||
for (Thing *t : candidates)
|
||||
noms << t->name();
|
||||
qCWarning(dcNymeaEnergy())
|
||||
<< "[Arbitre] Réserve de stockage INACTIVE :" << candidates.count()
|
||||
<< "appareil(s) portant l'interface 'battery' mais PAS 'energystorage' —"
|
||||
<< noms.join(", ") << ". Le waterfall ne peut pas les prendre en compte, et"
|
||||
<< "le bilan de puissance de nymea non plus. À corriger dans le plugin qui"
|
||||
<< "déclare la classe, pas ici.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user