mirror of https://github.com/nymea/nymea.git
137 lines
4.0 KiB
C++
137 lines
4.0 KiB
C++
#include "jsonrpcserver.h"
|
|
#include "jsontypes.h"
|
|
|
|
#ifdef TESTING_ENABLED
|
|
#include "mocktcpserver.h"
|
|
#else
|
|
#include "tcpserver.h"
|
|
#endif
|
|
#include "jsonhandler.h"
|
|
|
|
#include "hivecore.h"
|
|
#include "devicemanager.h"
|
|
#include "deviceplugin.h"
|
|
#include "deviceclass.h"
|
|
#include "device.h"
|
|
#include "rule.h"
|
|
#include "ruleengine.h"
|
|
|
|
#include "devicehandler.h"
|
|
#include "actionhandler.h"
|
|
#include "ruleshandler.h"
|
|
|
|
#include <QJsonDocument>
|
|
#include <QStringList>
|
|
|
|
JsonRPCServer::JsonRPCServer(QObject *parent):
|
|
QObject(parent),
|
|
#ifdef TESTING_ENABLED
|
|
m_tcpServer(new MockTcpServer(this))
|
|
#else
|
|
m_tcpServer(new TcpServer(this))
|
|
#endif
|
|
{
|
|
connect(m_tcpServer, SIGNAL(jsonDataAvailable(int,QByteArray)), this, SLOT(processData(int,QByteArray)));
|
|
m_tcpServer->startServer();
|
|
|
|
|
|
registerHandler(new DeviceHandler(this));
|
|
registerHandler(new ActionHandler(this));
|
|
registerHandler(new RulesHandler(this));
|
|
}
|
|
|
|
void JsonRPCServer::processData(int clientId, const QByteArray &jsonData)
|
|
{
|
|
QJsonParseError error;
|
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error);
|
|
|
|
if(error.error != QJsonParseError::NoError) {
|
|
qDebug() << "failed to parse data" << jsonData << ":" << error.errorString();
|
|
}
|
|
qDebug() << "-------------------------\n" << jsonDoc.toJson();
|
|
|
|
QVariantMap message = jsonDoc.toVariant().toMap();
|
|
|
|
bool success;
|
|
int commandId = message.value("id").toInt(&success);
|
|
if (!success) {
|
|
qWarning() << "Error parsing command. Missing \"id\":" << jsonData;
|
|
return;
|
|
}
|
|
|
|
QStringList commandList = message.value("method").toString().split('.');
|
|
if (commandList.count() != 2) {
|
|
qWarning() << "Error parsing method.\nGot:" << message.value("method").toString() << "\nExpected: \"Namespace.method\"";
|
|
return;
|
|
}
|
|
|
|
QString targetNamespace = commandList.first();
|
|
QString method = commandList.last();
|
|
QVariantMap params = message.value("params").toMap();
|
|
|
|
qDebug() << "got:" << targetNamespace << method << params;
|
|
emit commandReceived(targetNamespace, method, params);
|
|
|
|
if (targetNamespace == "JSONRPC") {
|
|
if (method == "Introspect") {
|
|
QVariantMap data;
|
|
data.insert("types", JsonTypes::allTypes());
|
|
QVariantMap methods;
|
|
foreach (JsonHandler *handler, m_handlers) {
|
|
// qDebug() << "got handler" << handler->name() << handler->introspect();
|
|
methods.unite(handler->introspect());
|
|
}
|
|
data.insert("methods", methods);
|
|
sendResponse(clientId, commandId, data);
|
|
return;
|
|
}
|
|
}
|
|
|
|
JsonHandler *handler = m_handlers.value(targetNamespace);
|
|
if (!handler) {
|
|
sendErrorResponse(clientId, commandId, "No such namespace");
|
|
return;
|
|
}
|
|
if (!handler->hasMethod(method)) {
|
|
sendErrorResponse(clientId, commandId, "No such method");
|
|
return;
|
|
}
|
|
if (!handler->validateParams(method, params)) {
|
|
sendErrorResponse(clientId, commandId, "Invalid params");
|
|
return;
|
|
}
|
|
QVariantMap returns;
|
|
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(QVariantMap, returns), Q_ARG(QVariantMap, params));
|
|
Q_ASSERT(handler->validateReturns(method, returns));
|
|
sendResponse(clientId, commandId, returns);
|
|
}
|
|
|
|
void JsonRPCServer::registerHandler(JsonHandler *handler)
|
|
{
|
|
m_handlers.insert(handler->name(), handler);
|
|
}
|
|
|
|
void JsonRPCServer::sendResponse(int clientId, int commandId, const QVariantMap ¶ms)
|
|
{
|
|
QVariantMap rsp;
|
|
rsp.insert("id", commandId);
|
|
rsp.insert("status", "success");
|
|
rsp.insert("params", params);
|
|
|
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
|
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
|
}
|
|
|
|
void JsonRPCServer::sendErrorResponse(int clientId, int commandId, const QString &error)
|
|
{
|
|
QVariantMap rsp;
|
|
rsp.insert("id", commandId);
|
|
rsp.insert("status", "error");
|
|
rsp.insert("error", error);
|
|
|
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
|
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
|
}
|
|
|
|
|