diff --git a/energyplugin/etm/energyarbitrator.cpp b/energyplugin/etm/energyarbitrator.cpp index fd0bd99..76288a1 100644 --- a/energyplugin/etm/energyarbitrator.cpp +++ b/energyplugin/etm/energyarbitrator.cpp @@ -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."; + } } }