More work on the experience mode framework

This commit is contained in:
Michael Zanetti 2019-10-23 16:23:28 +02:00
parent f8d23db584
commit e2cf9cb5c3
22 changed files with 152 additions and 96 deletions

View File

@ -1,7 +1,7 @@
#include "experiencemanager.h" #include "experiencemanager.h"
#include "experiences/experienceplugin.h" #include "experiences/experienceplugin.h"
#include "jsonrpc/jsonrpcserver.h" #include "jsonrpc/jsonrpcserverimplementation.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include <QCoreApplication> #include <QCoreApplication>
@ -11,7 +11,8 @@
namespace nymeaserver { 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) m_jsonRpcServer(jsonRpcServer)
{ {
staticMetaObject.invokeMethod(this, "loadPlugins", Qt::QueuedConnection); staticMetaObject.invokeMethod(this, "loadPlugins", Qt::QueuedConnection);
@ -70,13 +71,10 @@ void ExperienceManager::loadExperiencePlugin(const QString &file)
return; return;
} }
qCDebug(dcExperiences()) << "Loaded experience plugin:" << loader.fileName(); qCDebug(dcExperiences()) << "Loaded experience plugin:" << loader.fileName();
plugin->setParent(this);
m_plugins.append(plugin); m_plugins.append(plugin);
plugin->setParent(this);
plugin->initPlugin(m_deviceManager, m_jsonRpcServer);
foreach (JsonHandler *handler, plugin->jsonHandlers()) {
m_jsonRpcServer->registerHandler(handler);
}
} }
} }

View File

@ -4,16 +4,17 @@
#include <QObject> #include <QObject>
class ExperiencePlugin; class ExperiencePlugin;
class JsonRPCServer;
class DeviceManager;
namespace nymeaserver { namespace nymeaserver {
class JsonRPCServer;
class ExperienceManager : public QObject class ExperienceManager : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent = nullptr); explicit ExperienceManager(DeviceManager *deviceManager, JsonRPCServer *jsonRpcServer, QObject *parent = nullptr);
signals: signals:
@ -26,6 +27,7 @@ private:
QStringList pluginSearchDirs() const; QStringList pluginSearchDirs() const;
private: private:
DeviceManager *m_deviceManager = nullptr;
JsonRPCServer *m_jsonRpcServer = nullptr; JsonRPCServer *m_jsonRpcServer = nullptr;
void loadExperiencePlugin(const QString &file); void loadExperiencePlugin(const QString &file);

View File

@ -36,7 +36,7 @@
*/ */
#include "jsonrpcserver.h" #include "jsonrpcserverimplementation.h"
#include "jsonrpc/jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "jsonvalidator.h" #include "jsonvalidator.h"
#include "nymeacore.h" #include "nymeacore.h"
@ -67,7 +67,7 @@
namespace nymeaserver { namespace nymeaserver {
/*! Constructs a \l{JsonRPCServer} with the given \a sslConfiguration and \a parent. */ /*! 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), JsonHandler(parent),
m_notificationId(0) m_notificationId(0)
{ {
@ -235,16 +235,16 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection); 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}. */ /*! Returns the \e namespace of \l{JsonHandler}. */
QString JsonRPCServer::name() const QString JsonRPCServerImplementation::name() const
{ {
return QStringLiteral("JSONRPC"); return QStringLiteral("JSONRPC");
} }
JsonReply *JsonRPCServer::Hello(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::Hello(const QVariantMap &params)
{ {
TransportInterface *interface = reinterpret_cast<TransportInterface*>(property("transportInterface").toLongLong()); TransportInterface *interface = reinterpret_cast<TransportInterface*>(property("transportInterface").toLongLong());
@ -264,13 +264,13 @@ JsonReply *JsonRPCServer::Hello(const QVariantMap &params)
return createReply(createWelcomeMessage(interface, clientId)); return createReply(createWelcomeMessage(interface, clientId));
} }
JsonReply* JsonRPCServer::Introspect(const QVariantMap &params) const JsonReply* JsonRPCServerImplementation::Introspect(const QVariantMap &params) const
{ {
Q_UNUSED(params) Q_UNUSED(params)
return createReply(m_api); return createReply(m_api);
} }
JsonReply* JsonRPCServer::Version(const QVariantMap &params) const JsonReply* JsonRPCServerImplementation::Version(const QVariantMap &params) const
{ {
Q_UNUSED(params) Q_UNUSED(params)
@ -280,7 +280,7 @@ JsonReply* JsonRPCServer::Version(const QVariantMap &params) const
return createReply(data); return createReply(data);
} }
JsonReply* JsonRPCServer::SetNotificationStatus(const QVariantMap &params) JsonReply* JsonRPCServerImplementation::SetNotificationStatus(const QVariantMap &params)
{ {
QUuid clientId = this->property("clientId").toUuid(); QUuid clientId = this->property("clientId").toUuid();
Q_ASSERT_X(m_clientTransports.contains(clientId), "JsonRPCServer", "Invalid client ID."); Q_ASSERT_X(m_clientTransports.contains(clientId), "JsonRPCServer", "Invalid client ID.");
@ -307,7 +307,7 @@ JsonReply* JsonRPCServer::SetNotificationStatus(const QVariantMap &params)
return createReply(returns); return createReply(returns);
} }
JsonReply *JsonRPCServer::CreateUser(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::CreateUser(const QVariantMap &params)
{ {
QString username = params.value("username").toString(); QString username = params.value("username").toString();
QString password = params.value("password").toString(); QString password = params.value("password").toString();
@ -319,7 +319,7 @@ JsonReply *JsonRPCServer::CreateUser(const QVariantMap &params)
return createReply(returns); return createReply(returns);
} }
JsonReply *JsonRPCServer::Authenticate(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::Authenticate(const QVariantMap &params)
{ {
QString username = params.value("username").toString(); QString username = params.value("username").toString();
QString password = params.value("password").toString(); QString password = params.value("password").toString();
@ -334,7 +334,7 @@ JsonReply *JsonRPCServer::Authenticate(const QVariantMap &params)
return createReply(ret); return createReply(ret);
} }
JsonReply *JsonRPCServer::RequestPushButtonAuth(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::RequestPushButtonAuth(const QVariantMap &params)
{ {
QString deviceName = params.value("deviceName").toString(); QString deviceName = params.value("deviceName").toString();
QUuid clientId = this->property("clientId").toUuid(); QUuid clientId = this->property("clientId").toUuid();
@ -349,7 +349,7 @@ JsonReply *JsonRPCServer::RequestPushButtonAuth(const QVariantMap &params)
return createReply(data); return createReply(data);
} }
JsonReply *JsonRPCServer::Tokens(const QVariantMap &params) const JsonReply *JsonRPCServerImplementation::Tokens(const QVariantMap &params) const
{ {
Q_UNUSED(params) Q_UNUSED(params)
QByteArray token = property("token").toByteArray(); QByteArray token = property("token").toByteArray();
@ -369,7 +369,7 @@ JsonReply *JsonRPCServer::Tokens(const QVariantMap &params) const
return createReply(retMap); return createReply(retMap);
} }
JsonReply *JsonRPCServer::RemoveToken(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::RemoveToken(const QVariantMap &params)
{ {
QUuid tokenId = params.value("tokenId").toUuid(); QUuid tokenId = params.value("tokenId").toUuid();
UserManager::UserError error = NymeaCore::instance()->userManager()->removeToken(tokenId); UserManager::UserError error = NymeaCore::instance()->userManager()->removeToken(tokenId);
@ -378,7 +378,7 @@ JsonReply *JsonRPCServer::RemoveToken(const QVariantMap &params)
return createReply(ret); return createReply(ret);
} }
JsonReply *JsonRPCServer::SetupCloudConnection(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::SetupCloudConnection(const QVariantMap &params)
{ {
if (NymeaCore::instance()->cloudManager()->connectionState() != CloudManager::CloudConnectionStateUnconfigured) { 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."; 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 &params)
return createReply(ret); return createReply(ret);
} }
JsonReply *JsonRPCServer::SetupRemoteAccess(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::SetupRemoteAccess(const QVariantMap &params)
{ {
QString idToken = params.value("idToken").toString(); QString idToken = params.value("idToken").toString();
QString userId = params.value("userId").toString(); QString userId = params.value("userId").toString();
@ -410,7 +410,7 @@ JsonReply *JsonRPCServer::SetupRemoteAccess(const QVariantMap &params)
return reply; return reply;
} }
JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::IsCloudConnected(const QVariantMap &params)
{ {
Q_UNUSED(params) Q_UNUSED(params)
bool connected = NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected; bool connected = NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected;
@ -421,7 +421,7 @@ JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap &params)
} }
/*! A client may use this as a ping/pong mechanism to check server connectivity. */ /*! A client may use this as a ping/pong mechanism to check server connectivity. */
JsonReply *JsonRPCServer::KeepAlive(const QVariantMap &params) JsonReply *JsonRPCServerImplementation::KeepAlive(const QVariantMap &params)
{ {
QString sessionId = params.value("sessionId").toString(); QString sessionId = params.value("sessionId").toString();
qCDebug(dcJsonRpc()) << "KeepAlive received" << sessionId; qCDebug(dcJsonRpc()) << "KeepAlive received" << sessionId;
@ -432,36 +432,36 @@ JsonReply *JsonRPCServer::KeepAlive(const QVariantMap &params)
} }
/*! Returns the list of registered \l{JsonHandler}{JsonHandlers} and their name.*/ /*! Returns the list of registered \l{JsonHandler}{JsonHandlers} and their name.*/
QHash<QString, JsonHandler *> JsonRPCServer::handlers() const QHash<QString, JsonHandler *> JsonRPCServerImplementation::handlers() const
{ {
return m_handlers; 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. */ /*! 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)) { if (!m_interfaces.contains(interface)) {
connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected); connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServerImplementation::clientConnected);
connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected); connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServerImplementation::clientDisconnected);
connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData); connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServerImplementation::processData);
m_interfaces.insert(interface, authenticationRequired); m_interfaces.insert(interface, authenticationRequired);
} else { } else {
m_interfaces[interface] = authenticationRequired; m_interfaces[interface] = authenticationRequired;
} }
} }
void JsonRPCServer::unregisterTransportInterface(TransportInterface *interface) void JsonRPCServerImplementation::unregisterTransportInterface(TransportInterface *interface)
{ {
disconnect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected); disconnect(interface, &TransportInterface::clientConnected, this, &JsonRPCServerImplementation::clientConnected);
disconnect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected); disconnect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServerImplementation::clientDisconnected);
disconnect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData); disconnect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServerImplementation::processData);
m_interfaces.take(interface); m_interfaces.take(interface);
} }
/*! Send a JSON success response to the client with the given \a clientId, /*! Send a JSON success response to the client with the given \a clientId,
* \a commandId and \a params to the inerted \l{TransportInterface}. * \a commandId and \a params to the inerted \l{TransportInterface}.
*/ */
void JsonRPCServer::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap &params) void JsonRPCServerImplementation::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap &params)
{ {
QVariantMap response; QVariantMap response;
response.insert("id", commandId); 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, /*! Send a JSON error response to the client with the given \a clientId,
* \a commandId and \a error to the inerted \l{TransportInterface}. * \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; QVariantMap errorResponse;
errorResponse.insert("id", commandId); errorResponse.insert("id", commandId);
@ -488,7 +488,7 @@ void JsonRPCServer::sendErrorResponse(TransportInterface *interface, const QUuid
interface->sendData(clientId, data); 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; QVariantMap errorResponse;
errorResponse.insert("id", commandId); errorResponse.insert("id", commandId);
@ -500,7 +500,7 @@ void JsonRPCServer::sendUnauthorizedResponse(TransportInterface *interface, cons
interface->sendData(clientId, data); interface->sendData(clientId, data);
} }
QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const QVariantMap JsonRPCServerImplementation::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const
{ {
QVariantMap handshake; QVariantMap handshake;
handshake.insert("server", "nymea"); handshake.insert("server", "nymea");
@ -517,7 +517,7 @@ QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, c
return handshake; return handshake;
} }
void JsonRPCServer::setup() void JsonRPCServerImplementation::setup()
{ {
registerHandler(this); registerHandler(this);
registerHandler(new DeviceHandler(this)); registerHandler(new DeviceHandler(this));
@ -531,11 +531,11 @@ void JsonRPCServer::setup()
registerHandler(new TagsHandler(this)); registerHandler(new TagsHandler(this));
registerHandler(new SystemHandler(NymeaCore::instance()->platform(), this)); registerHandler(new SystemHandler(NymeaCore::instance()->platform(), this));
connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServer::pairingFinished); connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServerImplementation::pairingFinished);
connect(NymeaCore::instance()->cloudManager(), &CloudManager::connectionStateChanged, this, &JsonRPCServer::onCloudConnectionStateChanged); 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; 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; QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
@ -670,7 +670,7 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid
m_asyncReplies.insert(reply, interface); m_asyncReplies.insert(reply, interface);
reply->setClientId(clientId); reply->setClientId(clientId);
reply->setCommandId(commandId); reply->setCommandId(commandId);
connect(reply, &JsonReply::finished, this, &JsonRPCServer::asyncReplyFinished); connect(reply, &JsonReply::finished, this, &JsonRPCServerImplementation::asyncReplyFinished);
reply->startWait(); reply->startWait();
} else { } else {
JsonValidator validator; 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; QVariantMap ret;
ret.insert("id", tokenInfo.id().toString()); ret.insert("id", tokenInfo.id().toString());
@ -692,7 +692,7 @@ QVariantMap JsonRPCServer::packTokenInfo(const TokenInfo &tokenInfo)
return ret; return ret;
} }
void JsonRPCServer::sendNotification(const QVariantMap &params) void JsonRPCServerImplementation::sendNotification(const QVariantMap &params)
{ {
JsonHandler *handler = qobject_cast<JsonHandler *>(sender()); JsonHandler *handler = qobject_cast<JsonHandler *>(sender());
QMetaMethod method = handler->metaObject()->method(senderSignalIndex()); QMetaMethod method = handler->metaObject()->method(senderSignalIndex());
@ -717,7 +717,7 @@ void JsonRPCServer::sendNotification(const QVariantMap &params)
} }
} }
void JsonRPCServer::asyncReplyFinished() void JsonRPCServerImplementation::asyncReplyFinished()
{ {
JsonReply *reply = qobject_cast<JsonReply *>(sender()); JsonReply *reply = qobject_cast<JsonReply *>(sender());
TransportInterface *interface = m_asyncReplies.take(reply); TransportInterface *interface = m_asyncReplies.take(reply);
@ -740,7 +740,7 @@ void JsonRPCServer::asyncReplyFinished()
reply->deleteLater(); 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); JsonReply *reply = m_pairingRequests.take(cognitoUserId);
if (!reply) { if (!reply) {
@ -753,7 +753,7 @@ void JsonRPCServer::pairingFinished(QString cognitoUserId, int status, const QSt
reply->finished(); reply->finished();
} }
void JsonRPCServer::onCloudConnectionStateChanged() void JsonRPCServerImplementation::onCloudConnectionStateChanged()
{ {
QVariantMap params; QVariantMap params;
params.insert("connected", NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected); params.insert("connected", NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected);
@ -761,7 +761,7 @@ void JsonRPCServer::onCloudConnectionStateChanged()
emit CloudConnectedChanged(params); 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); QUuid clientId = m_pushButtonTransactions.take(transactionId);
if (clientId.isNull()) { if (clientId.isNull()) {
@ -790,7 +790,7 @@ void JsonRPCServer::onPushButtonAuthFinished(int transactionId, bool success, co
transport->sendData(clientId, QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact)); transport->sendData(clientId, QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact));
} }
void JsonRPCServer::registerHandler(JsonHandler *handler) bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler)
{ {
// Sanity checks on API: // Sanity checks on API:
// * Make sure all $ref: entries are valid. A Handler can reference Types from previously loaded handlers or own ones. // * 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(); QVariantList list = handler->jsonEnums().value(enumName).toList();
if (types.contains(enumName)) { if (types.contains(enumName)) {
qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name(); qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name();
return; return false;
} }
types.insert(enumName, list); types.insert(enumName, list);
} }
@ -817,12 +817,12 @@ void JsonRPCServer::registerHandler(JsonHandler *handler)
// Check for name clashes // Check for name clashes
if (types.contains(objectName)) { if (types.contains(objectName)) {
qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name(); qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name();
return; return false;
} }
// Check for invalid $ref: entries // Check for invalid $ref: entries
if (!JsonValidator::checkRefs(object, typesIncludingThis)) { if (!JsonValidator::checkRefs(object, typesIncludingThis)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name(); qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name();
return; return false;
} }
} }
types = typesIncludingThis; types = typesIncludingThis;
@ -833,15 +833,15 @@ void JsonRPCServer::registerHandler(JsonHandler *handler)
QVariantMap method = handler->jsonMethods().value(methodName).toMap(); QVariantMap method = handler->jsonMethods().value(methodName).toMap();
if (handler->metaObject()->indexOfMethod(methodName.toUtf8() + "(QVariantMap)") < 0) { 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(); 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)) { if (!JsonValidator::checkRefs(method.value("params").toMap(), types)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of method " << methodName << ". Not registering handler " << handler->name(); 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)) { if (!JsonValidator::checkRefs(method.value("returns").toMap(), types)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in return value of method " << methodName << ". Not registering handler " << handler->name(); 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); newMethods.insert(handler->name() + '.' + methodName, method);
} }
@ -853,7 +853,7 @@ void JsonRPCServer::registerHandler(JsonHandler *handler)
QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap(); QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap();
if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) { if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) {
qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name(); qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name();
return; return false;
} }
newNotifications.insert(handler->name() + '.' + notificationName, notification); 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)"))); 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(); qCDebug(dcJsonRpc()) << "Client connected with uuid" << clientId.toString();
TransportInterface *interface = qobject_cast<TransportInterface *>(sender()); TransportInterface *interface = qobject_cast<TransportInterface *>(sender());
@ -895,7 +896,7 @@ void JsonRPCServer::clientConnected(const QUuid &clientId)
timer->start(10000); timer->start(10000);
} }
void JsonRPCServer::clientDisconnected(const QUuid &clientId) void JsonRPCServerImplementation::clientDisconnected(const QUuid &clientId)
{ {
qCDebug(dcJsonRpc()) << "Client disconnected:" << clientId; qCDebug(dcJsonRpc()) << "Client disconnected:" << clientId;
m_clientTransports.remove(clientId); m_clientTransports.remove(clientId);

View File

@ -19,9 +19,10 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef JSONRPCSERVER_H #ifndef JSONRPCSERVERIMPLEMENTATION_H
#define JSONRPCSERVER_H #define JSONRPCSERVERIMPLEMENTATION_H
#include "jsonrpc/jsonrpcserver.h"
#include "jsonrpc/jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "transportinterface.h" #include "transportinterface.h"
#include "usermanager/usermanager.h" #include "usermanager/usermanager.h"
@ -39,11 +40,11 @@ class Device;
namespace nymeaserver { namespace nymeaserver {
class JsonRPCServer: public JsonHandler class JsonRPCServerImplementation: public JsonHandler, public JsonRPCServer
{ {
Q_OBJECT Q_OBJECT
public: public:
JsonRPCServer(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = nullptr); JsonRPCServerImplementation(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = nullptr);
// JsonHandler API implementation // JsonHandler API implementation
QString name() const; QString name() const;
@ -71,7 +72,7 @@ public:
void registerTransportInterface(TransportInterface *interface, bool authenticationRequired); void registerTransportInterface(TransportInterface *interface, bool authenticationRequired);
void unregisterTransportInterface(TransportInterface *interface); void unregisterTransportInterface(TransportInterface *interface);
void registerHandler(JsonHandler *handler); bool registerHandler(JsonHandler *handler) override;
private: private:
QHash<QString, JsonHandler *> handlers() const; QHash<QString, JsonHandler *> handlers() const;
@ -124,4 +125,5 @@ private:
} }
#endif // JSONRPCSERVER_H #endif // JSONRPCSERVERIMPLEMENTATION_H

View File

@ -19,6 +19,7 @@ HEADERS += nymeacore.h \
devices/devicemanagerimplementation.h \ devices/devicemanagerimplementation.h \
devices/translator.h \ devices/translator.h \
experiences/experiencemanager.h \ experiences/experiencemanager.h \
jsonrpc/jsonrpcserverimplementation.h \
ruleengine/ruleengine.h \ ruleengine/ruleengine.h \
ruleengine/rule.h \ ruleengine/rule.h \
ruleengine/stateevaluator.h \ ruleengine/stateevaluator.h \
@ -35,7 +36,6 @@ HEADERS += nymeacore.h \
servers/bluetoothserver.h \ servers/bluetoothserver.h \
servers/websocketserver.h \ servers/websocketserver.h \
servers/mqttbroker.h \ servers/mqttbroker.h \
jsonrpc/jsonrpcserver.h \
jsonrpc/jsonvalidator.h \ jsonrpc/jsonvalidator.h \
jsonrpc/devicehandler.h \ jsonrpc/devicehandler.h \
jsonrpc/ruleshandler.h \ jsonrpc/ruleshandler.h \
@ -50,10 +50,6 @@ HEADERS += nymeacore.h \
logging/logfilter.h \ logging/logfilter.h \
logging/logentry.h \ logging/logentry.h \
logging/logvaluetool.h \ logging/logvaluetool.h \
time/timedescriptor.h \
time/calendaritem.h \
time/repeatingoption.h \
time/timeeventitem.h \
time/timemanager.h \ time/timemanager.h \
networkmanager/dbus-interfaces.h \ networkmanager/dbus-interfaces.h \
networkmanager/networkmanager.h \ networkmanager/networkmanager.h \
@ -97,6 +93,7 @@ SOURCES += nymeacore.cpp \
devices/devicemanagerimplementation.cpp \ devices/devicemanagerimplementation.cpp \
devices/translator.cpp \ devices/translator.cpp \
experiences/experiencemanager.cpp \ experiences/experiencemanager.cpp \
jsonrpc/jsonrpcserverimplementation.cpp \
ruleengine/ruleengine.cpp \ ruleengine/ruleengine.cpp \
ruleengine/rule.cpp \ ruleengine/rule.cpp \
ruleengine/stateevaluator.cpp \ ruleengine/stateevaluator.cpp \
@ -113,7 +110,6 @@ SOURCES += nymeacore.cpp \
servers/websocketserver.cpp \ servers/websocketserver.cpp \
servers/bluetoothserver.cpp \ servers/bluetoothserver.cpp \
servers/mqttbroker.cpp \ servers/mqttbroker.cpp \
jsonrpc/jsonrpcserver.cpp \
jsonrpc/jsonvalidator.cpp \ jsonrpc/jsonvalidator.cpp \
jsonrpc/devicehandler.cpp \ jsonrpc/devicehandler.cpp \
jsonrpc/ruleshandler.cpp \ jsonrpc/ruleshandler.cpp \
@ -127,10 +123,6 @@ SOURCES += nymeacore.cpp \
logging/logfilter.cpp \ logging/logfilter.cpp \
logging/logentry.cpp \ logging/logentry.cpp \
logging/logvaluetool.cpp \ logging/logvaluetool.cpp \
time/timedescriptor.cpp \
time/calendaritem.cpp \
time/repeatingoption.cpp \
time/timeeventitem.cpp \
time/timemanager.cpp \ time/timemanager.cpp \
networkmanager/networkmanager.cpp \ networkmanager/networkmanager.cpp \
networkmanager/networkdevice.cpp \ networkmanager/networkdevice.cpp \

View File

@ -91,7 +91,7 @@
#include "nymeacore.h" #include "nymeacore.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "platform/platform.h" #include "platform/platform.h"
#include "jsonrpc/jsonrpcserver.h" #include "jsonrpc/jsonrpcserverimplementation.h"
#include "ruleengine/ruleengine.h" #include "ruleengine/ruleengine.h"
#include "networkmanager/networkmanager.h" #include "networkmanager/networkmanager.h"
#include "nymeasettings.h" #include "nymeasettings.h"
@ -173,7 +173,7 @@ void NymeaCore::init() {
m_cloudManager = new CloudManager(m_configuration, m_networkManager, this); m_cloudManager = new CloudManager(m_configuration, m_networkManager, this);
qCDebug(dcApplication()) << "Loading experiences"; qCDebug(dcApplication()) << "Loading experiences";
new ExperienceManager(m_serverManager->jsonServer(), this); new ExperienceManager(m_deviceManager, m_serverManager->jsonServer(), this);
CloudNotifications *cloudNotifications = m_cloudManager->createNotificationsPlugin(); CloudNotifications *cloudNotifications = m_cloudManager->createNotificationsPlugin();
@ -854,7 +854,7 @@ LogEngine* NymeaCore::logEngine() const
} }
/*! Returns the pointer to the \l{JsonRPCServer} of this instance. */ /*! Returns the pointer to the \l{JsonRPCServer} of this instance. */
JsonRPCServer *NymeaCore::jsonRPCServer() const JsonRPCServerImplementation *NymeaCore::jsonRPCServer() const
{ {
return m_serverManager->jsonServer(); return m_serverManager->jsonServer();
} }

View File

@ -46,7 +46,7 @@ class Device;
namespace nymeaserver { namespace nymeaserver {
class JsonRPCServer; class JsonRPCServerImplementation;
class LogEngine; class LogEngine;
class NetworkManager; class NetworkManager;
class NymeaConfiguration; class NymeaConfiguration;
@ -81,7 +81,7 @@ public:
NymeaConfiguration *configuration() const; NymeaConfiguration *configuration() const;
LogEngine* logEngine() const; LogEngine* logEngine() const;
JsonRPCServer *jsonRPCServer() const; JsonRPCServerImplementation *jsonRPCServer() const;
DeviceManager *deviceManager() const; DeviceManager *deviceManager() const;
RuleEngine *ruleEngine() const; RuleEngine *ruleEngine() const;
TimeManager *timeManager() const; TimeManager *timeManager() const;

View File

@ -40,7 +40,7 @@
#include "platform/platform.h" #include "platform/platform.h"
#include "platform/platformzeroconfcontroller.h" #include "platform/platformzeroconfcontroller.h"
#include "jsonrpc/jsonrpcserver.h" #include "jsonrpc/jsonrpcserverimplementation.h"
#include "servers/mocktcpserver.h" #include "servers/mocktcpserver.h"
#include "servers/tcpserver.h" #include "servers/tcpserver.h"
#include "servers/websocketserver.h" #include "servers/websocketserver.h"
@ -99,7 +99,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati
} }
// Interfaces // Interfaces
m_jsonServer = new JsonRPCServer(m_sslConfiguration, this); m_jsonServer = new JsonRPCServerImplementation(m_sslConfiguration, this);
// Transports // Transports
MockTcpServer *tcpServer = new MockTcpServer(this); 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}. */ /*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */
JsonRPCServer *ServerManager::jsonServer() const JsonRPCServerImplementation *ServerManager::jsonServer() const
{ {
return m_jsonServer; return m_jsonServer;
} }

View File

@ -34,7 +34,7 @@ namespace nymeaserver {
class Platform; class Platform;
class NymeaConfiguration; class NymeaConfiguration;
class JsonRPCServer; class JsonRPCServerImplementation;
class TcpServer; class TcpServer;
class WebSocketServer; class WebSocketServer;
class WebServer; class WebServer;
@ -50,7 +50,7 @@ public:
explicit ServerManager(Platform *platform, NymeaConfiguration *configuration, QObject *parent = nullptr); explicit ServerManager(Platform *platform, NymeaConfiguration *configuration, QObject *parent = nullptr);
// Interfaces // Interfaces
JsonRPCServer *jsonServer() const; JsonRPCServerImplementation *jsonServer() const;
BluetoothServer* bluetoothServer() const; BluetoothServer* bluetoothServer() const;
@ -78,7 +78,7 @@ private:
Platform *m_platform = nullptr; Platform *m_platform = nullptr;
// Interfaces // Interfaces
JsonRPCServer *m_jsonServer; JsonRPCServerImplementation *m_jsonServer;
BluetoothServer *m_bluetoothServer; BluetoothServer *m_bluetoothServer;
QHash<QString, TcpServer*> m_tcpServers; QHash<QString, TcpServer*> m_tcpServers;

View File

@ -5,12 +5,30 @@ ExperiencePlugin::ExperiencePlugin(QObject *parent) : QObject(parent)
} }
QList<JsonHandler *> 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();
} }

View File

@ -3,21 +3,31 @@
#include <QObject> #include <QObject>
class JsonHandler; class DeviceManager;
class JsonRPCServer;
namespace nymeaserver {
class ExperienceManager;
}
class ExperiencePlugin : public QObject class ExperiencePlugin : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ExperiencePlugin(QObject *parent = nullptr); explicit ExperiencePlugin(QObject *parent = nullptr);
QList<JsonHandler*> jsonHandlers() const; virtual void init() = 0;
protected: protected:
void registerJsonHandler(JsonHandler *handler); DeviceManager* deviceManager();
JsonRPCServer* jsonRpcServer();
private: private:
QList<JsonHandler*> 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") Q_DECLARE_INTERFACE(ExperiencePlugin, "io.nymea.ExperiencePlugin")

View File

@ -0,0 +1,5 @@
#include "jsonrpcserver.h"
/*! \fn void JsonRPCServer::registerJsonHandler(JsonHandler *handler)
Register a JSON RPC handler on the JSON RPC server.
*/

View File

@ -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

View File

@ -27,6 +27,7 @@ HEADERS += \
jsonrpc/jsonhandler.h \ jsonrpc/jsonhandler.h \
jsonrpc/jsonreply.h \ jsonrpc/jsonreply.h \
experiences/experienceplugin.h \ experiences/experienceplugin.h \
jsonrpc/jsonrpcserver.h \
libnymea.h \ libnymea.h \
platform/package.h \ platform/package.h \
platform/repository.h \ platform/repository.h \
@ -76,6 +77,10 @@ HEADERS += \
types/paramdescriptor.h \ types/paramdescriptor.h \
types/statedescriptor.h \ types/statedescriptor.h \
types/interface.h \ types/interface.h \
time/timedescriptor.h \
time/calendaritem.h \
time/repeatingoption.h \
time/timeeventitem.h \
hardwareresource.h \ hardwareresource.h \
plugintimer.h \ plugintimer.h \
hardwaremanager.h \ hardwaremanager.h \
@ -85,6 +90,7 @@ HEADERS += \
platform/platformsystemcontroller.h \ platform/platformsystemcontroller.h \
platform/platformupdatecontroller.h \ platform/platformupdatecontroller.h \
platform/platformzeroconfcontroller.h \ platform/platformzeroconfcontroller.h \
experiences/experienceplugin.h \
SOURCES += \ SOURCES += \
devices/browseractioninfo.cpp \ devices/browseractioninfo.cpp \
@ -104,6 +110,7 @@ SOURCES += \
jsonrpc/jsonhandler.cpp \ jsonrpc/jsonhandler.cpp \
jsonrpc/jsonreply.cpp \ jsonrpc/jsonreply.cpp \
experiences/experienceplugin.cpp \ experiences/experienceplugin.cpp \
jsonrpc/jsonrpcserver.cpp \
loggingcategories.cpp \ loggingcategories.cpp \
nymeasettings.cpp \ nymeasettings.cpp \
platform/package.cpp \ platform/package.cpp \
@ -151,6 +158,10 @@ SOURCES += \
types/paramdescriptor.cpp \ types/paramdescriptor.cpp \
types/statedescriptor.cpp \ types/statedescriptor.cpp \
types/interface.cpp \ types/interface.cpp \
time/timedescriptor.cpp \
time/calendaritem.cpp \
time/repeatingoption.cpp \
time/timeeventitem.cpp \
hardwareresource.cpp \ hardwareresource.cpp \
plugintimer.cpp \ plugintimer.cpp \
hardwaremanager.cpp \ hardwaremanager.cpp \
@ -160,6 +171,7 @@ SOURCES += \
platform/platformsystemcontroller.cpp \ platform/platformsystemcontroller.cpp \
platform/platformupdatecontroller.cpp \ platform/platformupdatecontroller.cpp \
platform/platformzeroconfcontroller.cpp \ platform/platformzeroconfcontroller.cpp \
experiences/experienceplugin.cpp \
RESOURCES += \ RESOURCES += \