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);