From 8a4e73adce6a21f805352aa44540c996268a642e Mon Sep 17 00:00:00 2001 From: Patrick Schurig Date: Mon, 10 Aug 2026 06:32:32 +0200 Subject: [PATCH] =?UTF-8?q?fix(rpc):=20va-et-vient=20Get=20=E2=86=92=20Set?= =?UTF-8?q?=20cass=C3=A9=20par=20l'union=20LM-300?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GetLoadConfig sérialise via pack(), donc via le méta-objet : toutes les propriétés déclarées sortent, y compris un « sgReady » VIDE sur une charge qui n'est pas SG-Ready. Le schéma SetLoadConfig exigeait « states » dès que la clé était présente, et nymea valide les paramètres AVANT le handler : lire puis réécrire une configuration relay-router était donc impossible — c'est-à-dire le geste ordinaire de l'app. C'est le mur que spec_loadmodel.md §3 annonçait à la frontière RPC, touché par un côté qu'il n'avait pas prévu : les clés INTERNES d'une charge utile optionnelle doivent être optionnelles elles aussi, sans quoi elles contraignent les charges des AUTRES mécanismes. L'exigence réelle (states non vide, état 2 présent) reste tenue par isValid(). Constaté au banc à la première tentative réelle de SetLoadConfig. Aucun test ne rejouait le va-et-vient de l'app ; testLoadConfigRpc §3bis le fait maintenant, et il a été vérifié échouant sans le correctif. Co-Authored-By: Claude Opus 5 (1M context) --- energyplugin/nymeaenergyjsonhandler.cpp | 8 +++++++- tests/auto/simulation/simulation.cpp | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/energyplugin/nymeaenergyjsonhandler.cpp b/energyplugin/nymeaenergyjsonhandler.cpp index 9421e14..4e38786 100644 --- a/energyplugin/nymeaenergyjsonhandler.cpp +++ b/energyplugin/nymeaenergyjsonhandler.cpp @@ -187,7 +187,13 @@ NymeaEnergyJsonHandler::NymeaEnergyJsonHandler(SpotMarketManager *spotMarketMana sgStateItem.insert("relays", QVariantList() << enumValueName(String)); sgStateItem.insert("estimatedPowerW", enumValueName(Double)); QVariantMap sgItem; - sgItem.insert("states", QVariantList() << sgStateItem); + // « states » est OPTIONNEL ici, et c'est le mur documenté en LM-302 : GET sérialise la + // charge via le méta-objet, donc TOUTES les propriétés déclarées — y compris un sgReady + // VIDE pour un relay-router. Exiger « states » à l'intérieur casserait le va-et-vient + // Get → Set de l'app sur toute charge non SG-Ready. Défaut constaté au banc le + // 2026-08-10, sur la première tentative réelle de SetLoadConfig. + // L'exigence réelle (states non vide, état 2 présent) est tenue par LoadConfig::isValid(). + sgItem.insert("o:states", QVariantList() << sgStateItem); sgItem.insert("o:minStateHoldS", enumValueName(Uint)); loadItem.insert("o:sgReady", sgItem); // sg-ready (LM-300) loadItem.insert("o:minOnS", enumValueName(Uint)); diff --git a/tests/auto/simulation/simulation.cpp b/tests/auto/simulation/simulation.cpp index 8c32140..26b73d4 100644 --- a/tests/auto/simulation/simulation.cpp +++ b/tests/auto/simulation/simulation.cpp @@ -486,6 +486,17 @@ void Simulation::testLoadConfigRpc() QCOMPARE(relays.last().toMap().value("powerW").toInt(), 1500); QCOMPARE(relayGot.value("minOnS").toInt(), 60); + // 3bis. VA-ET-VIENT : réinjecter tel quel ce que GET vient de rendre. C'est le geste réel + // de l'app — lire, modifier un champ, réécrire — et il échouait : GET sérialise via le + // méta-objet, donc TOUTES les propriétés déclarées, y compris un « sgReady » VIDE sur une + // charge qui n'est pas SG-Ready. Le schéma SET exigeait « states » dès que la clé était + // présente, et nymea rejetait AVANT le handler. Constaté au banc le 2026-08-10, sur la + // première tentative réelle de SetLoadConfig — aucun test ne faisait ce va-et-vient. + resp = injectAndWait("NymeaEnergy.SetLoadConfig", {{"loadConfigs", got}}); + QCOMPARE(resp.toMap().value("params").toMap().value("energyError").toString(), QString("EnergyErrorNoError")); + resp = injectAndWait("NymeaEnergy.GetLoadConfig"); + QCOMPARE(resp.toMap().value("params").toMap().value("loadConfigs").toList().size(), 3); + // 4. Fichier persisté. QVERIFY(QFileInfo::exists(cfgPath));