diff --git a/energyplugin/etm/etm.pri b/energyplugin/etm/etm.pri
index 7809f0b..845f353 100644
--- a/energyplugin/etm/etm.pri
+++ b/energyplugin/etm/etm.pri
@@ -53,6 +53,9 @@ SOURCES += \
$$PWD/energyarbitrator.cpp \
$$PWD/spotmarketbuild.cpp \
+# Le contrat OpenRPC du protocole optimiseur (docs/), embarqué : NymeaEnergy.GetOptimizerProtocol.
+RESOURCES += $$PWD/scheduler/etm-powersync-optimizer-protocol.qrc
+
# Version du moteur annoncée au handshake de l'optimiseur (OPTIMIZER_PROTOCOL §3, `engine`) : lue
# dans le changelog Debian, seule source de la version livrée — une constante dans le code
# dériverait au premier `+etmN`.
diff --git a/energyplugin/etm/scheduler/etm-powersync-optimizer-protocol.qrc b/energyplugin/etm/scheduler/etm-powersync-optimizer-protocol.qrc
new file mode 100644
index 0000000..bdf4b10
--- /dev/null
+++ b/energyplugin/etm/scheduler/etm-powersync-optimizer-protocol.qrc
@@ -0,0 +1,8 @@
+
+
+
+
+ ../../../docs/etm-powersync-optimizer-protocol.openrpc.json
+
+
diff --git a/energyplugin/etm/scheduler/optimizerprotocol.cpp b/energyplugin/etm/scheduler/optimizerprotocol.cpp
index 994d192..c78a770 100644
--- a/energyplugin/etm/scheduler/optimizerprotocol.cpp
+++ b/energyplugin/etm/scheduler/optimizerprotocol.cpp
@@ -3,8 +3,14 @@
#include "optimizerprotocol.h"
#include "../types/ecotarget.h"
+#include
+#include
+#include
+#include
#include
+Q_DECLARE_LOGGING_CATEGORY(dcNymeaEnergy)
+
namespace OptimizerProtocol {
namespace {
@@ -277,6 +283,27 @@ QVariantMap forecastDepuisInstantane(const QVariantMap &instantane)
return out;
}
+QByteArray schemaDocumentBytes()
+{
+ QFile f(QString::fromLatin1(SchemaResource));
+ if (!f.open(QIODevice::ReadOnly))
+ return QByteArray();
+ return f.readAll();
+}
+
+QVariantMap schemaDocument()
+{
+ QJsonParseError erreur;
+ const QJsonDocument doc = QJsonDocument::fromJson(schemaDocumentBytes(), &erreur);
+ if (erreur.error != QJsonParseError::NoError || !doc.isObject()) {
+ qCWarning(dcNymeaEnergy()).noquote()
+ << "[Optimiseur] contrat OpenRPC embarqué ILLISIBLE (" + erreur.errorString()
+ + ") — GetOptimizerProtocol rend un schéma vide";
+ return QVariantMap();
+ }
+ return doc.object().toVariantMap();
+}
+
QVariantMap getPlanParams(const SurplusContext &ctx, const ContexteFil &fil)
{
QVariantMap out;
diff --git a/energyplugin/etm/scheduler/optimizerprotocol.h b/energyplugin/etm/scheduler/optimizerprotocol.h
index be62c01..4c43dc2 100644
--- a/energyplugin/etm/scheduler/optimizerprotocol.h
+++ b/energyplugin/etm/scheduler/optimizerprotocol.h
@@ -30,6 +30,23 @@ namespace OptimizerProtocol {
//! Version du protocole parlée par ce sérialiseur (§3, §9).
constexpr const char *ProtocolVersion = "1.1";
+//! Ressource Qt du contrat OpenRPC embarqué (\c docs/etm-powersync-optimizer-protocol.openrpc.json).
+constexpr const char *SchemaResource = ":/etm-powersync/optimizer-protocol.openrpc.json";
+
+/*!
+ * \brief Le contrat OpenRPC du protocole, tel qu'EMBARQUÉ dans ce binaire.
+ * \return Les octets de la ressource \c SchemaResource — ceux de \c docs/ au moment du build ;
+ * vide si la ressource manque (build cassé). Jamais lu sur disque à l'exécution.
+ */
+QByteArray schemaDocumentBytes();
+
+/*!
+ * \brief Le contrat OpenRPC analysé, pour \c NymeaEnergy.GetOptimizerProtocol.
+ * \return L'objet JSON du document ; vide si la ressource manque ou ne s'analyse pas (dit au
+ * journal, en avertissement, à chaque appel — un contrat qui ne se sert pas ne doit pas se taire).
+ */
+QVariantMap schemaDocument();
+
//! Mesure d'une charge, telle que la résout l'arbitre (\c EnergyArbitrator::mesurerCharge).
struct MesureFil {
QString source = QStringLiteral("none"); //!< \c meter | \c device | \c none
diff --git a/energyplugin/nymeaenergyjsonhandler.cpp b/energyplugin/nymeaenergyjsonhandler.cpp
index 151947d..f03a5c0 100644
--- a/energyplugin/nymeaenergyjsonhandler.cpp
+++ b/energyplugin/nymeaenergyjsonhandler.cpp
@@ -36,6 +36,7 @@
#include "etm/spotmarketbuild.h"
#include "etm/types/loadconfig.h"
#include "etm/config/loadconfigstore.h"
+#include "etm/scheduler/optimizerprotocol.h" // contrat OpenRPC embarqué : GetOptimizerProtocol
#include
@@ -651,6 +652,21 @@ NymeaEnergyJsonHandler::NymeaEnergyJsonHandler(SpotMarketManager *spotMarketMana
returns.insert("o:fallbackCode", enumValueName(String));
registerMethod("GetPlan", description, params, returns, Types::PermissionScopeControlThings);
+ // [ETM] Le contrat OpenRPC du protocole optimiseur, EMBARQUÉ (ressource Qt) : celui du moteur qui
+ // tourne, jamais un fichier relu sur disque. Lecture, aucun secret — même permission que les
+ // autres Get* de l'optimiseur. Statique pour un binaire donné : pas de *Changed (invariant 11
+ // vise un état runtime ; celui-ci ne change qu'avec le paquet).
+ params.clear(); returns.clear();
+ description = "The OpenRPC 1.3 document of the engine <-> optimizer protocol spoken by THIS "
+ "engine (docs/etm-powersync-optimizer-protocol.openrpc.json, embedded at build "
+ "time). protocolVersion: the version sent at handshake. schema: the document "
+ "(methods Handshake, GetPlan, UpdateLearned; components.schemas; x-etm-* "
+ "extensions for transport, fallback machine and semantic rules). No secret. "
+ "Static for a given binary: no notification.";
+ returns.insert("protocolVersion", enumValueName(String));
+ returns.insert("schema", enumValueName(Object));
+ registerMethod("GetOptimizerProtocol", description, params, returns, Types::PermissionScopeControlThings);
+
// Notifications
params.clear();
@@ -1701,6 +1717,13 @@ JsonReply *NymeaEnergyJsonHandler::GetPlan(const QVariantMap ¶ms)
return createReply({{"inForce", false}});
}
+JsonReply *NymeaEnergyJsonHandler::GetOptimizerProtocol(const QVariantMap ¶ms)
+{
+ Q_UNUSED(params)
+ return createReply({{"protocolVersion", QString::fromLatin1(OptimizerProtocol::ProtocolVersion)},
+ {"schema", OptimizerProtocol::schemaDocument()}});
+}
+
JsonReply *NymeaEnergyJsonHandler::SetLoadDerogation(const QVariantMap ¶ms)
{
#ifdef ETM_ARBITRATOR
diff --git a/energyplugin/nymeaenergyjsonhandler.h b/energyplugin/nymeaenergyjsonhandler.h
index a9c085b..bd43783 100644
--- a/energyplugin/nymeaenergyjsonhandler.h
+++ b/energyplugin/nymeaenergyjsonhandler.h
@@ -162,6 +162,9 @@ public:
//! \brief [ETM] Le plan en vigueur au dernier cycle (exigence app 2). \param params Aucun.
//! \return \c EnergyArbitrator::publishedPlan() ; \c {inForce: false} sans plan en vigueur.
Q_INVOKABLE JsonReply *GetPlan(const QVariantMap ¶ms);
+ //! \brief [ETM] Le contrat OpenRPC du protocole optimiseur, embarqué (lot contrat OpenRPC).
+ //! \param params Aucun. \return \c protocolVersion et \c schema (\c OptimizerProtocol::schemaDocument()).
+ Q_INVOKABLE JsonReply *GetOptimizerProtocol(const QVariantMap ¶ms);
signals:
void PhasePowerLimitChanged(const QVariantMap ¶ms);