From e2cf9cb5c3321cf59dd01e1658d589e2d6052afd Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 23 Oct 2019 16:23:28 +0200 Subject: [PATCH] More work on the experience mode framework --- .../experiences/experiencemanager.cpp | 12 +- libnymea-core/experiences/experiencemanager.h | 6 +- ...er.cpp => jsonrpcserverimplementation.cpp} | 105 +++++++++--------- ...server.h => jsonrpcserverimplementation.h} | 14 ++- libnymea-core/libnymea-core.pro | 12 +- libnymea-core/nymeacore.cpp | 6 +- libnymea-core/nymeacore.h | 4 +- libnymea-core/servermanager.cpp | 6 +- libnymea-core/servermanager.h | 6 +- libnymea/experiences/experienceplugin.cpp | 26 ++++- libnymea/experiences/experienceplugin.h | 18 ++- libnymea/jsonrpc/jsonrpcserver.cpp | 5 + libnymea/jsonrpc/jsonrpcserver.h | 16 +++ libnymea/libnymea.pro | 12 ++ .../time/calendaritem.cpp | 0 .../time/calendaritem.h | 0 .../time/repeatingoption.cpp | 0 .../time/repeatingoption.h | 0 .../time/timedescriptor.cpp | 0 .../time/timedescriptor.h | 0 .../time/timeeventitem.cpp | 0 .../time/timeeventitem.h | 0 22 files changed, 152 insertions(+), 96 deletions(-) rename libnymea-core/jsonrpc/{jsonrpcserver.cpp => jsonrpcserverimplementation.cpp} (91%) rename libnymea-core/jsonrpc/{jsonrpcserver.h => jsonrpcserverimplementation.h} (92%) create mode 100644 libnymea/jsonrpc/jsonrpcserver.cpp create mode 100644 libnymea/jsonrpc/jsonrpcserver.h rename {libnymea-core => libnymea}/time/calendaritem.cpp (100%) rename {libnymea-core => libnymea}/time/calendaritem.h (100%) rename {libnymea-core => libnymea}/time/repeatingoption.cpp (100%) rename {libnymea-core => libnymea}/time/repeatingoption.h (100%) rename {libnymea-core => libnymea}/time/timedescriptor.cpp (100%) rename {libnymea-core => libnymea}/time/timedescriptor.h (100%) rename {libnymea-core => libnymea}/time/timeeventitem.cpp (100%) rename {libnymea-core => libnymea}/time/timeeventitem.h (100%) diff --git a/libnymea-core/experiences/experiencemanager.cpp b/libnymea-core/experiences/experiencemanager.cpp index 4b11eabc..e0582898 100644 --- a/libnymea-core/experiences/experiencemanager.cpp +++ b/libnymea-core/experiences/experiencemanager.cpp @@ -1,7 +1,7 @@ #include "experiencemanager.h" #include "experiences/experienceplugin.h" -#include "jsonrpc/jsonrpcserver.h" +#include "jsonrpc/jsonrpcserverimplementation.h" #include "loggingcategories.h" #include @@ -11,7 +11,8 @@ namespace nymeaserver { -ExperienceManager::ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent), +ExperienceManager::ExperienceManager(DeviceManager *deviceManager, JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent), + m_deviceManager(deviceManager), m_jsonRpcServer(jsonRpcServer) { staticMetaObject.invokeMethod(this, "loadPlugins", Qt::QueuedConnection); @@ -70,13 +71,10 @@ void ExperienceManager::loadExperiencePlugin(const QString &file) return; } qCDebug(dcExperiences()) << "Loaded experience plugin:" << loader.fileName(); - plugin->setParent(this); - m_plugins.append(plugin); + plugin->setParent(this); + plugin->initPlugin(m_deviceManager, m_jsonRpcServer); - foreach (JsonHandler *handler, plugin->jsonHandlers()) { - m_jsonRpcServer->registerHandler(handler); - } } } diff --git a/libnymea-core/experiences/experiencemanager.h b/libnymea-core/experiences/experiencemanager.h index cfb0a3aa..1231d456 100644 --- a/libnymea-core/experiences/experiencemanager.h +++ b/libnymea-core/experiences/experiencemanager.h @@ -4,16 +4,17 @@ #include class ExperiencePlugin; +class JsonRPCServer; +class DeviceManager; namespace nymeaserver { -class JsonRPCServer; class ExperienceManager : public QObject { Q_OBJECT public: - explicit ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent = nullptr); + explicit ExperienceManager(DeviceManager *deviceManager, JsonRPCServer *jsonRpcServer, QObject *parent = nullptr); signals: @@ -26,6 +27,7 @@ private: QStringList pluginSearchDirs() const; private: + DeviceManager *m_deviceManager = nullptr; JsonRPCServer *m_jsonRpcServer = nullptr; void loadExperiencePlugin(const QString &file); diff --git a/libnymea-core/jsonrpc/jsonrpcserver.cpp b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp similarity index 91% rename from libnymea-core/jsonrpc/jsonrpcserver.cpp rename to libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp index 6ad3d6f8..1f6c8bb4 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp @@ -36,7 +36,7 @@ */ -#include "jsonrpcserver.h" +#include "jsonrpcserverimplementation.h" #include "jsonrpc/jsonhandler.h" #include "jsonvalidator.h" #include "nymeacore.h" @@ -67,7 +67,7 @@ namespace nymeaserver { /*! Constructs a \l{JsonRPCServer} with the given \a sslConfiguration and \a parent. */ -JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject *parent): +JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration &sslConfiguration, QObject *parent): JsonHandler(parent), m_notificationId(0) { @@ -235,16 +235,16 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection); - connect(NymeaCore::instance()->userManager(), &UserManager::pushButtonAuthFinished, this, &JsonRPCServer::onPushButtonAuthFinished); + connect(NymeaCore::instance()->userManager(), &UserManager::pushButtonAuthFinished, this, &JsonRPCServerImplementation::onPushButtonAuthFinished); } /*! Returns the \e namespace of \l{JsonHandler}. */ -QString JsonRPCServer::name() const +QString JsonRPCServerImplementation::name() const { return QStringLiteral("JSONRPC"); } -JsonReply *JsonRPCServer::Hello(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::Hello(const QVariantMap ¶ms) { TransportInterface *interface = reinterpret_cast(property("transportInterface").toLongLong()); @@ -264,13 +264,13 @@ JsonReply *JsonRPCServer::Hello(const QVariantMap ¶ms) return createReply(createWelcomeMessage(interface, clientId)); } -JsonReply* JsonRPCServer::Introspect(const QVariantMap ¶ms) const +JsonReply* JsonRPCServerImplementation::Introspect(const QVariantMap ¶ms) const { Q_UNUSED(params) return createReply(m_api); } -JsonReply* JsonRPCServer::Version(const QVariantMap ¶ms) const +JsonReply* JsonRPCServerImplementation::Version(const QVariantMap ¶ms) const { Q_UNUSED(params) @@ -280,7 +280,7 @@ JsonReply* JsonRPCServer::Version(const QVariantMap ¶ms) const return createReply(data); } -JsonReply* JsonRPCServer::SetNotificationStatus(const QVariantMap ¶ms) +JsonReply* JsonRPCServerImplementation::SetNotificationStatus(const QVariantMap ¶ms) { QUuid clientId = this->property("clientId").toUuid(); Q_ASSERT_X(m_clientTransports.contains(clientId), "JsonRPCServer", "Invalid client ID."); @@ -307,7 +307,7 @@ JsonReply* JsonRPCServer::SetNotificationStatus(const QVariantMap ¶ms) return createReply(returns); } -JsonReply *JsonRPCServer::CreateUser(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::CreateUser(const QVariantMap ¶ms) { QString username = params.value("username").toString(); QString password = params.value("password").toString(); @@ -319,7 +319,7 @@ JsonReply *JsonRPCServer::CreateUser(const QVariantMap ¶ms) return createReply(returns); } -JsonReply *JsonRPCServer::Authenticate(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::Authenticate(const QVariantMap ¶ms) { QString username = params.value("username").toString(); QString password = params.value("password").toString(); @@ -334,7 +334,7 @@ JsonReply *JsonRPCServer::Authenticate(const QVariantMap ¶ms) return createReply(ret); } -JsonReply *JsonRPCServer::RequestPushButtonAuth(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::RequestPushButtonAuth(const QVariantMap ¶ms) { QString deviceName = params.value("deviceName").toString(); QUuid clientId = this->property("clientId").toUuid(); @@ -349,7 +349,7 @@ JsonReply *JsonRPCServer::RequestPushButtonAuth(const QVariantMap ¶ms) return createReply(data); } -JsonReply *JsonRPCServer::Tokens(const QVariantMap ¶ms) const +JsonReply *JsonRPCServerImplementation::Tokens(const QVariantMap ¶ms) const { Q_UNUSED(params) QByteArray token = property("token").toByteArray(); @@ -369,7 +369,7 @@ JsonReply *JsonRPCServer::Tokens(const QVariantMap ¶ms) const return createReply(retMap); } -JsonReply *JsonRPCServer::RemoveToken(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::RemoveToken(const QVariantMap ¶ms) { QUuid tokenId = params.value("tokenId").toUuid(); UserManager::UserError error = NymeaCore::instance()->userManager()->removeToken(tokenId); @@ -378,7 +378,7 @@ JsonReply *JsonRPCServer::RemoveToken(const QVariantMap ¶ms) return createReply(ret); } -JsonReply *JsonRPCServer::SetupCloudConnection(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::SetupCloudConnection(const QVariantMap ¶ms) { if (NymeaCore::instance()->cloudManager()->connectionState() != CloudManager::CloudConnectionStateUnconfigured) { qCDebug(dcCloud) << "Cloud already configured. Not changing configuration as it won't work anyways. If you want to reconfigure this instance to a different cloud, change the system UUID and wipe the cloud settings from the config."; @@ -397,7 +397,7 @@ JsonReply *JsonRPCServer::SetupCloudConnection(const QVariantMap ¶ms) return createReply(ret); } -JsonReply *JsonRPCServer::SetupRemoteAccess(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::SetupRemoteAccess(const QVariantMap ¶ms) { QString idToken = params.value("idToken").toString(); QString userId = params.value("userId").toString(); @@ -410,7 +410,7 @@ JsonReply *JsonRPCServer::SetupRemoteAccess(const QVariantMap ¶ms) return reply; } -JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::IsCloudConnected(const QVariantMap ¶ms) { Q_UNUSED(params) bool connected = NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected; @@ -421,7 +421,7 @@ JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap ¶ms) } /*! A client may use this as a ping/pong mechanism to check server connectivity. */ -JsonReply *JsonRPCServer::KeepAlive(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::KeepAlive(const QVariantMap ¶ms) { QString sessionId = params.value("sessionId").toString(); qCDebug(dcJsonRpc()) << "KeepAlive received" << sessionId; @@ -432,36 +432,36 @@ JsonReply *JsonRPCServer::KeepAlive(const QVariantMap ¶ms) } /*! Returns the list of registered \l{JsonHandler}{JsonHandlers} and their name.*/ -QHash JsonRPCServer::handlers() const +QHash JsonRPCServerImplementation::handlers() const { return m_handlers; } /*! Register a new \l{TransportInterface} to the JSON server. If the given interface is already registered, just the authenticationRequired flag will be updated. */ -void JsonRPCServer::registerTransportInterface(TransportInterface *interface, bool authenticationRequired) +void JsonRPCServerImplementation::registerTransportInterface(TransportInterface *interface, bool authenticationRequired) { if (!m_interfaces.contains(interface)) { - connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected); - connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected); - connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData); + connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServerImplementation::clientConnected); + connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServerImplementation::clientDisconnected); + connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServerImplementation::processData); m_interfaces.insert(interface, authenticationRequired); } else { m_interfaces[interface] = authenticationRequired; } } -void JsonRPCServer::unregisterTransportInterface(TransportInterface *interface) +void JsonRPCServerImplementation::unregisterTransportInterface(TransportInterface *interface) { - disconnect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected); - disconnect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected); - disconnect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData); + disconnect(interface, &TransportInterface::clientConnected, this, &JsonRPCServerImplementation::clientConnected); + disconnect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServerImplementation::clientDisconnected); + disconnect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServerImplementation::processData); m_interfaces.take(interface); } /*! Send a JSON success response to the client with the given \a clientId, * \a commandId and \a params to the inerted \l{TransportInterface}. */ -void JsonRPCServer::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms) +void JsonRPCServerImplementation::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms) { QVariantMap response; response.insert("id", commandId); @@ -476,7 +476,7 @@ void JsonRPCServer::sendResponse(TransportInterface *interface, const QUuid &cli /*! Send a JSON error response to the client with the given \a clientId, * \a commandId and \a error to the inerted \l{TransportInterface}. */ -void JsonRPCServer::sendErrorResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) +void JsonRPCServerImplementation::sendErrorResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) { QVariantMap errorResponse; errorResponse.insert("id", commandId); @@ -488,7 +488,7 @@ void JsonRPCServer::sendErrorResponse(TransportInterface *interface, const QUuid interface->sendData(clientId, data); } -void JsonRPCServer::sendUnauthorizedResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) +void JsonRPCServerImplementation::sendUnauthorizedResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) { QVariantMap errorResponse; errorResponse.insert("id", commandId); @@ -500,7 +500,7 @@ void JsonRPCServer::sendUnauthorizedResponse(TransportInterface *interface, cons interface->sendData(clientId, data); } -QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const +QVariantMap JsonRPCServerImplementation::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const { QVariantMap handshake; handshake.insert("server", "nymea"); @@ -517,7 +517,7 @@ QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, c return handshake; } -void JsonRPCServer::setup() +void JsonRPCServerImplementation::setup() { registerHandler(this); registerHandler(new DeviceHandler(this)); @@ -531,11 +531,11 @@ void JsonRPCServer::setup() registerHandler(new TagsHandler(this)); registerHandler(new SystemHandler(NymeaCore::instance()->platform(), this)); - connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServer::pairingFinished); - connect(NymeaCore::instance()->cloudManager(), &CloudManager::connectionStateChanged, this, &JsonRPCServer::onCloudConnectionStateChanged); + connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServerImplementation::pairingFinished); + connect(NymeaCore::instance()->cloudManager(), &CloudManager::connectionStateChanged, this, &JsonRPCServerImplementation::onCloudConnectionStateChanged); } -void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &data) +void JsonRPCServerImplementation::processData(const QUuid &clientId, const QByteArray &data) { qCDebug(dcJsonRpcTraffic()) << "Incoming data:" << data; @@ -562,7 +562,7 @@ void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &data) } } -void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data) +void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data) { QJsonParseError error; QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); @@ -670,7 +670,7 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid m_asyncReplies.insert(reply, interface); reply->setClientId(clientId); reply->setCommandId(commandId); - connect(reply, &JsonReply::finished, this, &JsonRPCServer::asyncReplyFinished); + connect(reply, &JsonReply::finished, this, &JsonRPCServerImplementation::asyncReplyFinished); reply->startWait(); } else { JsonValidator validator; @@ -682,7 +682,7 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid } } -QVariantMap JsonRPCServer::packTokenInfo(const TokenInfo &tokenInfo) +QVariantMap JsonRPCServerImplementation::packTokenInfo(const TokenInfo &tokenInfo) { QVariantMap ret; ret.insert("id", tokenInfo.id().toString()); @@ -692,7 +692,7 @@ QVariantMap JsonRPCServer::packTokenInfo(const TokenInfo &tokenInfo) return ret; } -void JsonRPCServer::sendNotification(const QVariantMap ¶ms) +void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms) { JsonHandler *handler = qobject_cast(sender()); QMetaMethod method = handler->metaObject()->method(senderSignalIndex()); @@ -717,7 +717,7 @@ void JsonRPCServer::sendNotification(const QVariantMap ¶ms) } } -void JsonRPCServer::asyncReplyFinished() +void JsonRPCServerImplementation::asyncReplyFinished() { JsonReply *reply = qobject_cast(sender()); TransportInterface *interface = m_asyncReplies.take(reply); @@ -740,7 +740,7 @@ void JsonRPCServer::asyncReplyFinished() reply->deleteLater(); } -void JsonRPCServer::pairingFinished(QString cognitoUserId, int status, const QString &message) +void JsonRPCServerImplementation::pairingFinished(QString cognitoUserId, int status, const QString &message) { JsonReply *reply = m_pairingRequests.take(cognitoUserId); if (!reply) { @@ -753,7 +753,7 @@ void JsonRPCServer::pairingFinished(QString cognitoUserId, int status, const QSt reply->finished(); } -void JsonRPCServer::onCloudConnectionStateChanged() +void JsonRPCServerImplementation::onCloudConnectionStateChanged() { QVariantMap params; params.insert("connected", NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected); @@ -761,7 +761,7 @@ void JsonRPCServer::onCloudConnectionStateChanged() emit CloudConnectedChanged(params); } -void JsonRPCServer::onPushButtonAuthFinished(int transactionId, bool success, const QByteArray &token) +void JsonRPCServerImplementation::onPushButtonAuthFinished(int transactionId, bool success, const QByteArray &token) { QUuid clientId = m_pushButtonTransactions.take(transactionId); if (clientId.isNull()) { @@ -790,7 +790,7 @@ void JsonRPCServer::onPushButtonAuthFinished(int transactionId, bool success, co transport->sendData(clientId, QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact)); } -void JsonRPCServer::registerHandler(JsonHandler *handler) +bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler) { // Sanity checks on API: // * Make sure all $ref: entries are valid. A Handler can reference Types from previously loaded handlers or own ones. @@ -804,7 +804,7 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QVariantList list = handler->jsonEnums().value(enumName).toList(); if (types.contains(enumName)) { qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name(); - return; + return false; } types.insert(enumName, list); } @@ -817,12 +817,12 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) // Check for name clashes if (types.contains(objectName)) { qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name(); - return; + return false; } // Check for invalid $ref: entries if (!JsonValidator::checkRefs(object, typesIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name(); - return; + return false; } } types = typesIncludingThis; @@ -833,15 +833,15 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QVariantMap method = handler->jsonMethods().value(methodName).toMap(); if (handler->metaObject()->indexOfMethod(methodName.toUtf8() + "(QVariantMap)") < 0) { qCWarning(dcJsonRpc()).nospace().noquote() << "Invalid method \"" << methodName << "\". Method \"JsonReply* " + methodName + "(QVariantMap)\" does not exist. Not registering handler " << handler->name(); - return; + return false; } if (!JsonValidator::checkRefs(method.value("params").toMap(), types)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of method " << methodName << ". Not registering handler " << handler->name(); - return; + return false; } if (!JsonValidator::checkRefs(method.value("returns").toMap(), types)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in return value of method " << methodName << ". Not registering handler " << handler->name(); - return; + return false; } newMethods.insert(handler->name() + '.' + methodName, method); } @@ -853,7 +853,7 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap(); if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name(); - return; + return false; } newNotifications.insert(handler->name() + '.' + notificationName, notification); } @@ -872,9 +872,10 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QObject::connect(handler, method, this, metaObject()->method(metaObject()->indexOfSlot("sendNotification(QVariantMap)"))); } } + return true; } -void JsonRPCServer::clientConnected(const QUuid &clientId) +void JsonRPCServerImplementation::clientConnected(const QUuid &clientId) { qCDebug(dcJsonRpc()) << "Client connected with uuid" << clientId.toString(); TransportInterface *interface = qobject_cast(sender()); @@ -895,7 +896,7 @@ void JsonRPCServer::clientConnected(const QUuid &clientId) timer->start(10000); } -void JsonRPCServer::clientDisconnected(const QUuid &clientId) +void JsonRPCServerImplementation::clientDisconnected(const QUuid &clientId) { qCDebug(dcJsonRpc()) << "Client disconnected:" << clientId; m_clientTransports.remove(clientId); diff --git a/libnymea-core/jsonrpc/jsonrpcserver.h b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h similarity index 92% rename from libnymea-core/jsonrpc/jsonrpcserver.h rename to libnymea-core/jsonrpc/jsonrpcserverimplementation.h index d3709afa..4f5741bc 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.h +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h @@ -19,9 +19,10 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifndef JSONRPCSERVER_H -#define JSONRPCSERVER_H +#ifndef JSONRPCSERVERIMPLEMENTATION_H +#define JSONRPCSERVERIMPLEMENTATION_H +#include "jsonrpc/jsonrpcserver.h" #include "jsonrpc/jsonhandler.h" #include "transportinterface.h" #include "usermanager/usermanager.h" @@ -39,11 +40,11 @@ class Device; namespace nymeaserver { -class JsonRPCServer: public JsonHandler +class JsonRPCServerImplementation: public JsonHandler, public JsonRPCServer { Q_OBJECT public: - JsonRPCServer(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = nullptr); + JsonRPCServerImplementation(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = nullptr); // JsonHandler API implementation QString name() const; @@ -71,7 +72,7 @@ public: void registerTransportInterface(TransportInterface *interface, bool authenticationRequired); void unregisterTransportInterface(TransportInterface *interface); - void registerHandler(JsonHandler *handler); + bool registerHandler(JsonHandler *handler) override; private: QHash handlers() const; @@ -124,4 +125,5 @@ private: } -#endif // JSONRPCSERVER_H +#endif // JSONRPCSERVERIMPLEMENTATION_H + diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro index f99e9dcf..5e5fbf32 100644 --- a/libnymea-core/libnymea-core.pro +++ b/libnymea-core/libnymea-core.pro @@ -19,6 +19,7 @@ HEADERS += nymeacore.h \ devices/devicemanagerimplementation.h \ devices/translator.h \ experiences/experiencemanager.h \ + jsonrpc/jsonrpcserverimplementation.h \ ruleengine/ruleengine.h \ ruleengine/rule.h \ ruleengine/stateevaluator.h \ @@ -35,7 +36,6 @@ HEADERS += nymeacore.h \ servers/bluetoothserver.h \ servers/websocketserver.h \ servers/mqttbroker.h \ - jsonrpc/jsonrpcserver.h \ jsonrpc/jsonvalidator.h \ jsonrpc/devicehandler.h \ jsonrpc/ruleshandler.h \ @@ -50,10 +50,6 @@ HEADERS += nymeacore.h \ logging/logfilter.h \ logging/logentry.h \ logging/logvaluetool.h \ - time/timedescriptor.h \ - time/calendaritem.h \ - time/repeatingoption.h \ - time/timeeventitem.h \ time/timemanager.h \ networkmanager/dbus-interfaces.h \ networkmanager/networkmanager.h \ @@ -97,6 +93,7 @@ SOURCES += nymeacore.cpp \ devices/devicemanagerimplementation.cpp \ devices/translator.cpp \ experiences/experiencemanager.cpp \ + jsonrpc/jsonrpcserverimplementation.cpp \ ruleengine/ruleengine.cpp \ ruleengine/rule.cpp \ ruleengine/stateevaluator.cpp \ @@ -113,7 +110,6 @@ SOURCES += nymeacore.cpp \ servers/websocketserver.cpp \ servers/bluetoothserver.cpp \ servers/mqttbroker.cpp \ - jsonrpc/jsonrpcserver.cpp \ jsonrpc/jsonvalidator.cpp \ jsonrpc/devicehandler.cpp \ jsonrpc/ruleshandler.cpp \ @@ -127,10 +123,6 @@ SOURCES += nymeacore.cpp \ logging/logfilter.cpp \ logging/logentry.cpp \ logging/logvaluetool.cpp \ - time/timedescriptor.cpp \ - time/calendaritem.cpp \ - time/repeatingoption.cpp \ - time/timeeventitem.cpp \ time/timemanager.cpp \ networkmanager/networkmanager.cpp \ networkmanager/networkdevice.cpp \ diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index 97b3ac00..eb382c48 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -91,7 +91,7 @@ #include "nymeacore.h" #include "loggingcategories.h" #include "platform/platform.h" -#include "jsonrpc/jsonrpcserver.h" +#include "jsonrpc/jsonrpcserverimplementation.h" #include "ruleengine/ruleengine.h" #include "networkmanager/networkmanager.h" #include "nymeasettings.h" @@ -173,7 +173,7 @@ void NymeaCore::init() { m_cloudManager = new CloudManager(m_configuration, m_networkManager, this); qCDebug(dcApplication()) << "Loading experiences"; - new ExperienceManager(m_serverManager->jsonServer(), this); + new ExperienceManager(m_deviceManager, m_serverManager->jsonServer(), this); CloudNotifications *cloudNotifications = m_cloudManager->createNotificationsPlugin(); @@ -854,7 +854,7 @@ LogEngine* NymeaCore::logEngine() const } /*! Returns the pointer to the \l{JsonRPCServer} of this instance. */ -JsonRPCServer *NymeaCore::jsonRPCServer() const +JsonRPCServerImplementation *NymeaCore::jsonRPCServer() const { return m_serverManager->jsonServer(); } diff --git a/libnymea-core/nymeacore.h b/libnymea-core/nymeacore.h index a49c5576..06c7c2f0 100644 --- a/libnymea-core/nymeacore.h +++ b/libnymea-core/nymeacore.h @@ -46,7 +46,7 @@ class Device; namespace nymeaserver { -class JsonRPCServer; +class JsonRPCServerImplementation; class LogEngine; class NetworkManager; class NymeaConfiguration; @@ -81,7 +81,7 @@ public: NymeaConfiguration *configuration() const; LogEngine* logEngine() const; - JsonRPCServer *jsonRPCServer() const; + JsonRPCServerImplementation *jsonRPCServer() const; DeviceManager *deviceManager() const; RuleEngine *ruleEngine() const; TimeManager *timeManager() const; diff --git a/libnymea-core/servermanager.cpp b/libnymea-core/servermanager.cpp index ceb023d8..c2406080 100644 --- a/libnymea-core/servermanager.cpp +++ b/libnymea-core/servermanager.cpp @@ -40,7 +40,7 @@ #include "platform/platform.h" #include "platform/platformzeroconfcontroller.h" -#include "jsonrpc/jsonrpcserver.h" +#include "jsonrpc/jsonrpcserverimplementation.h" #include "servers/mocktcpserver.h" #include "servers/tcpserver.h" #include "servers/websocketserver.h" @@ -99,7 +99,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati } // Interfaces - m_jsonServer = new JsonRPCServer(m_sslConfiguration, this); + m_jsonServer = new JsonRPCServerImplementation(m_sslConfiguration, this); // Transports MockTcpServer *tcpServer = new MockTcpServer(this); @@ -158,7 +158,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati } /*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */ -JsonRPCServer *ServerManager::jsonServer() const +JsonRPCServerImplementation *ServerManager::jsonServer() const { return m_jsonServer; } diff --git a/libnymea-core/servermanager.h b/libnymea-core/servermanager.h index 78a4cc26..17831f96 100644 --- a/libnymea-core/servermanager.h +++ b/libnymea-core/servermanager.h @@ -34,7 +34,7 @@ namespace nymeaserver { class Platform; class NymeaConfiguration; -class JsonRPCServer; +class JsonRPCServerImplementation; class TcpServer; class WebSocketServer; class WebServer; @@ -50,7 +50,7 @@ public: explicit ServerManager(Platform *platform, NymeaConfiguration *configuration, QObject *parent = nullptr); // Interfaces - JsonRPCServer *jsonServer() const; + JsonRPCServerImplementation *jsonServer() const; BluetoothServer* bluetoothServer() const; @@ -78,7 +78,7 @@ private: Platform *m_platform = nullptr; // Interfaces - JsonRPCServer *m_jsonServer; + JsonRPCServerImplementation *m_jsonServer; BluetoothServer *m_bluetoothServer; QHash m_tcpServers; diff --git a/libnymea/experiences/experienceplugin.cpp b/libnymea/experiences/experienceplugin.cpp index c589c12b..098a7824 100644 --- a/libnymea/experiences/experienceplugin.cpp +++ b/libnymea/experiences/experienceplugin.cpp @@ -5,12 +5,30 @@ ExperiencePlugin::ExperiencePlugin(QObject *parent) : QObject(parent) } -QList ExperiencePlugin::jsonHandlers() const +/*! This method will be called when the plugin has been completely loaded and experience + logic may start operating. A plugin can reimplment this to do initialisation code. */ +void ExperiencePlugin::init() { - return m_jsonHandlers; + } -void ExperiencePlugin::registerJsonHandler(JsonHandler *handler) +/*! Returns a pointer to the DeviceManager. The pointer won't be valid unless init() has been called. */ +DeviceManager *ExperiencePlugin::deviceManager() { - m_jsonHandlers.append(handler); + return m_deviceManager; +} + +/*! Returns a pointer to the JsonRPCServer. The pointer won't be valid unless init() has been called. */ +JsonRPCServer *ExperiencePlugin::jsonRpcServer() +{ + return m_jsonRpcServer; +} + + +void ExperiencePlugin::initPlugin(DeviceManager *deviceManager, JsonRPCServer *jsonRPCServer) +{ + m_deviceManager = deviceManager; + m_jsonRpcServer = jsonRPCServer; + + init(); } diff --git a/libnymea/experiences/experienceplugin.h b/libnymea/experiences/experienceplugin.h index 845f34cd..1dd7c401 100644 --- a/libnymea/experiences/experienceplugin.h +++ b/libnymea/experiences/experienceplugin.h @@ -3,21 +3,31 @@ #include -class JsonHandler; +class DeviceManager; +class JsonRPCServer; +namespace nymeaserver { +class ExperienceManager; +} class ExperiencePlugin : public QObject { Q_OBJECT public: explicit ExperiencePlugin(QObject *parent = nullptr); - QList jsonHandlers() const; + virtual void init() = 0; protected: - void registerJsonHandler(JsonHandler *handler); + DeviceManager* deviceManager(); + JsonRPCServer* jsonRpcServer(); private: - QList m_jsonHandlers; + friend class nymeaserver::ExperienceManager; + void initPlugin(DeviceManager *deviceManager, JsonRPCServer *jsonRPCServer); + + DeviceManager *m_deviceManager = nullptr; + JsonRPCServer *m_jsonRpcServer = nullptr; + }; Q_DECLARE_INTERFACE(ExperiencePlugin, "io.nymea.ExperiencePlugin") diff --git a/libnymea/jsonrpc/jsonrpcserver.cpp b/libnymea/jsonrpc/jsonrpcserver.cpp new file mode 100644 index 00000000..3bcc03f2 --- /dev/null +++ b/libnymea/jsonrpc/jsonrpcserver.cpp @@ -0,0 +1,5 @@ +#include "jsonrpcserver.h" + +/*! \fn void JsonRPCServer::registerJsonHandler(JsonHandler *handler) + Register a JSON RPC handler on the JSON RPC server. +*/ diff --git a/libnymea/jsonrpc/jsonrpcserver.h b/libnymea/jsonrpc/jsonrpcserver.h new file mode 100644 index 00000000..b83c3a47 --- /dev/null +++ b/libnymea/jsonrpc/jsonrpcserver.h @@ -0,0 +1,16 @@ +#ifndef JSONRPCSERVER_H +#define JSONRPCSERVER_H + +class JsonHandler; + +class JsonRPCServer +{ +public: + explicit JsonRPCServer() = default; + virtual ~JsonRPCServer() = default; + + virtual bool registerHandler(JsonHandler *handler) = 0; + +}; + +#endif // JSONRPCSERVER_H diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index a3d6c0dd..b00b7833 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -27,6 +27,7 @@ HEADERS += \ jsonrpc/jsonhandler.h \ jsonrpc/jsonreply.h \ experiences/experienceplugin.h \ + jsonrpc/jsonrpcserver.h \ libnymea.h \ platform/package.h \ platform/repository.h \ @@ -76,6 +77,10 @@ HEADERS += \ types/paramdescriptor.h \ types/statedescriptor.h \ types/interface.h \ + time/timedescriptor.h \ + time/calendaritem.h \ + time/repeatingoption.h \ + time/timeeventitem.h \ hardwareresource.h \ plugintimer.h \ hardwaremanager.h \ @@ -85,6 +90,7 @@ HEADERS += \ platform/platformsystemcontroller.h \ platform/platformupdatecontroller.h \ platform/platformzeroconfcontroller.h \ + experiences/experienceplugin.h \ SOURCES += \ devices/browseractioninfo.cpp \ @@ -104,6 +110,7 @@ SOURCES += \ jsonrpc/jsonhandler.cpp \ jsonrpc/jsonreply.cpp \ experiences/experienceplugin.cpp \ + jsonrpc/jsonrpcserver.cpp \ loggingcategories.cpp \ nymeasettings.cpp \ platform/package.cpp \ @@ -151,6 +158,10 @@ SOURCES += \ types/paramdescriptor.cpp \ types/statedescriptor.cpp \ types/interface.cpp \ + time/timedescriptor.cpp \ + time/calendaritem.cpp \ + time/repeatingoption.cpp \ + time/timeeventitem.cpp \ hardwareresource.cpp \ plugintimer.cpp \ hardwaremanager.cpp \ @@ -160,6 +171,7 @@ SOURCES += \ platform/platformsystemcontroller.cpp \ platform/platformupdatecontroller.cpp \ platform/platformzeroconfcontroller.cpp \ + experiences/experienceplugin.cpp \ RESOURCES += \ diff --git a/libnymea-core/time/calendaritem.cpp b/libnymea/time/calendaritem.cpp similarity index 100% rename from libnymea-core/time/calendaritem.cpp rename to libnymea/time/calendaritem.cpp diff --git a/libnymea-core/time/calendaritem.h b/libnymea/time/calendaritem.h similarity index 100% rename from libnymea-core/time/calendaritem.h rename to libnymea/time/calendaritem.h diff --git a/libnymea-core/time/repeatingoption.cpp b/libnymea/time/repeatingoption.cpp similarity index 100% rename from libnymea-core/time/repeatingoption.cpp rename to libnymea/time/repeatingoption.cpp diff --git a/libnymea-core/time/repeatingoption.h b/libnymea/time/repeatingoption.h similarity index 100% rename from libnymea-core/time/repeatingoption.h rename to libnymea/time/repeatingoption.h diff --git a/libnymea-core/time/timedescriptor.cpp b/libnymea/time/timedescriptor.cpp similarity index 100% rename from libnymea-core/time/timedescriptor.cpp rename to libnymea/time/timedescriptor.cpp diff --git a/libnymea-core/time/timedescriptor.h b/libnymea/time/timedescriptor.h similarity index 100% rename from libnymea-core/time/timedescriptor.h rename to libnymea/time/timedescriptor.h diff --git a/libnymea-core/time/timeeventitem.cpp b/libnymea/time/timeeventitem.cpp similarity index 100% rename from libnymea-core/time/timeeventitem.cpp rename to libnymea/time/timeeventitem.cpp diff --git a/libnymea-core/time/timeeventitem.h b/libnymea/time/timeeventitem.h similarity index 100% rename from libnymea-core/time/timeeventitem.h rename to libnymea/time/timeeventitem.h