added JSONRPC.Version and JSONRPC.SetNotificationStatus
This commit is contained in:
parent
2492b0fdda
commit
61a7a68ee0
@ -24,23 +24,86 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
JsonRPCServer::JsonRPCServer(QObject *parent):
|
JsonRPCServer::JsonRPCServer(QObject *parent):
|
||||||
QObject(parent),
|
JsonHandler(parent),
|
||||||
#ifdef TESTING_ENABLED
|
#ifdef TESTING_ENABLED
|
||||||
m_tcpServer(new MockTcpServer(this))
|
m_tcpServer(new MockTcpServer(this))
|
||||||
#else
|
#else
|
||||||
m_tcpServer(new TcpServer(this))
|
m_tcpServer(new TcpServer(this))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
connect(m_tcpServer, SIGNAL(jsonDataAvailable(int,QByteArray)), this, SLOT(processData(int,QByteArray)));
|
// First, define our own JSONRPC methods
|
||||||
|
QVariantMap returns;
|
||||||
|
QVariantMap params;
|
||||||
|
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
setDescription("Introspect", "Introspect this API.");
|
||||||
|
setParams("Introspect", params);
|
||||||
|
returns.insert("methods", "object");
|
||||||
|
returns.insert("types", "object");
|
||||||
|
setReturns("Introspect", returns);
|
||||||
|
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
setDescription("Version", "Version of this Guh/JSONRPC interface.");
|
||||||
|
setParams("Version", params);
|
||||||
|
returns.insert("version", "string");
|
||||||
|
setReturns("Version", returns);
|
||||||
|
|
||||||
|
params.clear(); returns.clear();
|
||||||
|
setDescription("SetNotificationStatus", "Enable/Disable notifications for this connections.");
|
||||||
|
setParams("SetNotificationStatus", params);
|
||||||
|
returns.insert("status", "string");
|
||||||
|
// returns.insert("enabled", "bool");
|
||||||
|
setReturns("SetNotificationStatus", returns);
|
||||||
|
|
||||||
|
// Now set up the logic
|
||||||
|
connect(m_tcpServer, SIGNAL(clientConnected(const QUuid &)), this, SLOT(clientConnected(const QUuid &)));
|
||||||
|
connect(m_tcpServer, SIGNAL(clientDisconnected(const QUuid &)), this, SLOT(clientDisconnected(const QUuid &)));
|
||||||
|
connect(m_tcpServer, SIGNAL(dataAvailable(const QUuid &, QByteArray)), this, SLOT(processData(const QUuid &, QByteArray)));
|
||||||
m_tcpServer->startServer();
|
m_tcpServer->startServer();
|
||||||
|
|
||||||
|
registerHandler(this);
|
||||||
registerHandler(new DeviceHandler(this));
|
registerHandler(new DeviceHandler(this));
|
||||||
registerHandler(new ActionHandler(this));
|
registerHandler(new ActionHandler(this));
|
||||||
registerHandler(new RulesHandler(this));
|
registerHandler(new RulesHandler(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonRPCServer::processData(int clientId, const QByteArray &jsonData)
|
QString JsonRPCServer::name() const
|
||||||
|
{
|
||||||
|
return QStringLiteral("JSONRPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonRPCServer::Introspect(const QVariantMap ¶ms) const
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonRPCServer::Version(const QVariantMap ¶ms) const
|
||||||
|
{
|
||||||
|
QVariantMap data;
|
||||||
|
data.insert("version", "0.0.0");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap JsonRPCServer::SetNotificationStatus(const QVariantMap ¶ms)
|
||||||
|
{
|
||||||
|
QUuid clientId = this->property("clientId").toUuid();
|
||||||
|
// qDebug() << "got client socket" << clientId;
|
||||||
|
m_clients[clientId] = params.value("enabled").toBool();
|
||||||
|
QVariantMap returns;
|
||||||
|
returns.insert("status", "success");
|
||||||
|
returns.insert("enabled", m_clients[clientId]);
|
||||||
|
return returns;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &jsonData)
|
||||||
{
|
{
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error);
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &error);
|
||||||
@ -48,7 +111,7 @@ void JsonRPCServer::processData(int clientId, const QByteArray &jsonData)
|
|||||||
if(error.error != QJsonParseError::NoError) {
|
if(error.error != QJsonParseError::NoError) {
|
||||||
qDebug() << "failed to parse data" << jsonData << ":" << error.errorString();
|
qDebug() << "failed to parse data" << jsonData << ":" << error.errorString();
|
||||||
}
|
}
|
||||||
qDebug() << "-------------------------\n" << jsonDoc.toJson();
|
// qDebug() << "-------------------------\n" << jsonDoc.toJson();
|
||||||
|
|
||||||
QVariantMap message = jsonDoc.toVariant().toMap();
|
QVariantMap message = jsonDoc.toVariant().toMap();
|
||||||
|
|
||||||
@ -72,21 +135,6 @@ void JsonRPCServer::processData(int clientId, const QByteArray &jsonData)
|
|||||||
qDebug() << "got:" << targetNamespace << method << params;
|
qDebug() << "got:" << targetNamespace << method << params;
|
||||||
emit commandReceived(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);
|
JsonHandler *handler = m_handlers.value(targetNamespace);
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
sendErrorResponse(clientId, commandId, "No such namespace");
|
sendErrorResponse(clientId, commandId, "No such namespace");
|
||||||
@ -100,9 +148,13 @@ void JsonRPCServer::processData(int clientId, const QByteArray &jsonData)
|
|||||||
sendErrorResponse(clientId, commandId, "Invalid params");
|
sendErrorResponse(clientId, commandId, "Invalid params");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hack: attach clientId to handler to be able to handle the JSONRPC methods. Do not use this outside of jsonrpcserver
|
||||||
|
handler->setProperty("clientId", clientId);
|
||||||
|
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(QVariantMap, returns), Q_ARG(QVariantMap, params));
|
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(QVariantMap, returns), Q_ARG(QVariantMap, params));
|
||||||
Q_ASSERT(handler->validateReturns(method, returns));
|
Q_ASSERT((targetNamespace == "JSONRPC" && method == "Introspect") || handler->validateReturns(method, returns));
|
||||||
sendResponse(clientId, commandId, returns);
|
sendResponse(clientId, commandId, returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +163,18 @@ void JsonRPCServer::registerHandler(JsonHandler *handler)
|
|||||||
m_handlers.insert(handler->name(), handler);
|
m_handlers.insert(handler->name(), handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonRPCServer::sendResponse(int clientId, int commandId, const QVariantMap ¶ms)
|
void JsonRPCServer::clientConnected(const QUuid &clientId)
|
||||||
|
{
|
||||||
|
// Notifications disabled by default
|
||||||
|
m_clients.insert(clientId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonRPCServer::clientDisconnected(const QUuid &clientId)
|
||||||
|
{
|
||||||
|
m_clients.remove(clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonRPCServer::sendResponse(const QUuid &clientId, int commandId, const QVariantMap ¶ms)
|
||||||
{
|
{
|
||||||
QVariantMap rsp;
|
QVariantMap rsp;
|
||||||
rsp.insert("id", commandId);
|
rsp.insert("id", commandId);
|
||||||
@ -119,10 +182,10 @@ void JsonRPCServer::sendResponse(int clientId, int commandId, const QVariantMap
|
|||||||
rsp.insert("params", params);
|
rsp.insert("params", params);
|
||||||
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
||||||
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
m_tcpServer->sendData(clientId, jsonDoc.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonRPCServer::sendErrorResponse(int clientId, int commandId, const QString &error)
|
void JsonRPCServer::sendErrorResponse(const QUuid &clientId, int commandId, const QString &error)
|
||||||
{
|
{
|
||||||
QVariantMap rsp;
|
QVariantMap rsp;
|
||||||
rsp.insert("id", commandId);
|
rsp.insert("id", commandId);
|
||||||
@ -130,7 +193,7 @@ void JsonRPCServer::sendErrorResponse(int clientId, int commandId, const QString
|
|||||||
rsp.insert("error", error);
|
rsp.insert("error", error);
|
||||||
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
QJsonDocument jsonDoc = QJsonDocument::fromVariant(rsp);
|
||||||
m_tcpServer->sendResponse(clientId, jsonDoc.toJson());
|
m_tcpServer->sendData(clientId, jsonDoc.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "deviceclass.h"
|
#include "deviceclass.h"
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "jsonhandler.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
@ -15,25 +16,33 @@ class MockTcpServer;
|
|||||||
class TcpServer;
|
class TcpServer;
|
||||||
#endif
|
#endif
|
||||||
class Device;
|
class Device;
|
||||||
class JsonHandler;
|
|
||||||
|
|
||||||
class JsonRPCServer: public QObject
|
class JsonRPCServer: public JsonHandler
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
JsonRPCServer(QObject *parent = 0);
|
JsonRPCServer(QObject *parent = 0);
|
||||||
|
|
||||||
|
// JsonHandler API implementation
|
||||||
|
QString name() const;
|
||||||
|
Q_INVOKABLE QVariantMap Introspect(const QVariantMap ¶ms) const;
|
||||||
|
Q_INVOKABLE QVariantMap Version(const QVariantMap ¶ms) const;
|
||||||
|
Q_INVOKABLE QVariantMap SetNotificationStatus(const QVariantMap ¶ms);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void commandReceived(const QString &targetNamespace, const QString &command, const QVariantMap ¶ms);
|
void commandReceived(const QString &targetNamespace, const QString &command, const QVariantMap ¶ms);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void processData(int clientId, const QByteArray &jsonData);
|
void clientConnected(const QUuid &clientId);
|
||||||
|
void clientDisconnected(const QUuid &clientId);
|
||||||
|
|
||||||
|
void processData(const QUuid &clientId, const QByteArray &jsonData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void registerHandler(JsonHandler *handler);
|
void registerHandler(JsonHandler *handler);
|
||||||
|
|
||||||
void sendResponse(int clientId, int commandId, const QVariantMap ¶ms = QVariantMap());
|
void sendResponse(const QUuid &clientId, int commandId, const QVariantMap ¶ms = QVariantMap());
|
||||||
void sendErrorResponse(int clientId, int commandId, const QString &error);
|
void sendErrorResponse(const QUuid &clientId, int commandId, const QString &error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef TESTING_ENABLED
|
#ifdef TESTING_ENABLED
|
||||||
@ -42,6 +51,9 @@ private:
|
|||||||
TcpServer *m_tcpServer;
|
TcpServer *m_tcpServer;
|
||||||
#endif
|
#endif
|
||||||
QHash<QString, JsonHandler*> m_handlers;
|
QHash<QString, JsonHandler*> m_handlers;
|
||||||
|
|
||||||
|
// clientId, notificationsEnabled
|
||||||
|
QHash<QUuid, bool> m_clients;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -95,7 +95,6 @@ void JsonTypes::init()
|
|||||||
s_rule.insert("actions", QVariantList() << actionRef());
|
s_rule.insert("actions", QVariantList() << actionRef());
|
||||||
s_rule.insert("states", QVariantList() << stateRef());
|
s_rule.insert("states", QVariantList() << stateRef());
|
||||||
|
|
||||||
|
|
||||||
s_initialized = true;
|
s_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,6 @@ public:
|
|||||||
|
|
||||||
DECLARE_TYPE(basicTypes, "BasicType")
|
DECLARE_TYPE(basicTypes, "BasicType")
|
||||||
DECLARE_TYPE(ruleTypes, "RuleType")
|
DECLARE_TYPE(ruleTypes, "RuleType")
|
||||||
|
|
||||||
DECLARE_OBJECT(paramType, "ParamType")
|
DECLARE_OBJECT(paramType, "ParamType")
|
||||||
DECLARE_OBJECT(param, "Param")
|
DECLARE_OBJECT(param, "Param")
|
||||||
DECLARE_OBJECT(stateType, "StateType")
|
DECLARE_OBJECT(stateType, "StateType")
|
||||||
|
|||||||
@ -17,7 +17,14 @@ TcpServer::TcpServer(QObject *parent) :
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpServer::sendResponse(int clientId, const QByteArray &data)
|
void TcpServer::sendData(const QList<QUuid> &clients, const QByteArray &data)
|
||||||
|
{
|
||||||
|
foreach (const QUuid &client, clients) {
|
||||||
|
sendData(client, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpServer::sendData(const QUuid &clientId, const QByteArray &data)
|
||||||
{
|
{
|
||||||
QTcpSocket *client = m_clientList.value(clientId);
|
QTcpSocket *client = m_clientList.value(clientId);
|
||||||
if (client) {
|
if (client) {
|
||||||
@ -32,14 +39,15 @@ void TcpServer::newClientConnected()
|
|||||||
QTcpSocket *newConnection = server->nextPendingConnection();
|
QTcpSocket *newConnection = server->nextPendingConnection();
|
||||||
qDebug() << "new client connected:" << newConnection->peerAddress().toString();
|
qDebug() << "new client connected:" << newConnection->peerAddress().toString();
|
||||||
|
|
||||||
|
QUuid clientId = QUuid::createUuid();
|
||||||
|
|
||||||
// append the new client to the client list
|
// append the new client to the client list
|
||||||
m_clientList.insert(m_clientList.count(), newConnection);
|
m_clientList.insert(clientId, newConnection);
|
||||||
|
|
||||||
connect(newConnection, SIGNAL(readyRead()),this,SLOT(readPackage()));
|
connect(newConnection, SIGNAL(readyRead()),this,SLOT(readPackage()));
|
||||||
connect(newConnection,SIGNAL(disconnected()),this,SLOT(clientDisconnected()));
|
connect(newConnection,SIGNAL(disconnected()),this,SLOT(slotClientDisconnected()));
|
||||||
|
|
||||||
// TODO: properly handle this with jsonrpcserver
|
emit clientConnected(clientId);
|
||||||
newConnection->write("{\n \"id\":0,\n \"status\": \"connected\",\n \"server\":\"Hive JSONRPC Interface\",\n \"version\":\"0.0.0\"\n}\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -53,16 +61,18 @@ void TcpServer::readPackage()
|
|||||||
qDebug() << "line in:" << dataLine;
|
qDebug() << "line in:" << dataLine;
|
||||||
message.append(dataLine);
|
message.append(dataLine);
|
||||||
if(dataLine.endsWith('\n')){
|
if(dataLine.endsWith('\n')){
|
||||||
emit jsonDataAvailable(m_clientList.key(client), message);
|
emit dataAvailable(m_clientList.key(client), message);
|
||||||
message.clear();
|
message.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpServer::clientDisconnected()
|
void TcpServer::slotClientDisconnected()
|
||||||
{
|
{
|
||||||
QTcpSocket *client = qobject_cast<QTcpSocket*>(sender());
|
QTcpSocket *client = qobject_cast<QTcpSocket*>(sender());
|
||||||
qDebug() << "client disconnected:" << client->peerAddress().toString();
|
qDebug() << "client disconnected:" << client->peerAddress().toString();
|
||||||
|
QUuid clientId = m_clientList.key(client);
|
||||||
|
m_clientList.take(clientId)->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TcpServer::startServer()
|
bool TcpServer::startServer()
|
||||||
@ -73,7 +83,7 @@ bool TcpServer::startServer()
|
|||||||
if(server->listen(address, 1234)) {
|
if(server->listen(address, 1234)) {
|
||||||
qDebug() << "server listening on" << address.toString();
|
qDebug() << "server listening on" << address.toString();
|
||||||
connect(server, SIGNAL(newConnection()), SLOT(newClientConnected()));
|
connect(server, SIGNAL(newConnection()), SLOT(newClientConnected()));
|
||||||
m_serverList.insert(m_serverList.count(), server);
|
m_serverList.insert(QUuid::createUuid(), server);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "ERROR: can not listening to" << address.toString();
|
qDebug() << "ERROR: can not listening to" << address.toString();
|
||||||
delete server;
|
delete server;
|
||||||
@ -99,11 +109,4 @@ bool TcpServer::stopServer()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpServer::sendToAll(QByteArray data)
|
|
||||||
{
|
|
||||||
foreach(QTcpSocket *client,m_clientList){
|
|
||||||
client->write(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <QNetworkInterface>
|
#include <QNetworkInterface>
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
class TcpServer : public QObject
|
class TcpServer : public QObject
|
||||||
{
|
{
|
||||||
@ -12,24 +13,26 @@ class TcpServer : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit TcpServer(QObject *parent = 0);
|
explicit TcpServer(QObject *parent = 0);
|
||||||
|
|
||||||
void sendResponse(int clientId, const QByteArray &data);
|
void sendData(const QUuid &clientId, const QByteArray &data);
|
||||||
|
void sendData(const QList<QUuid> &clients, const QByteArray &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<int, QTcpServer*> m_serverList;
|
QHash<QUuid, QTcpServer*> m_serverList;
|
||||||
QHash<int, QTcpSocket*> m_clientList;
|
QHash<QUuid, QTcpSocket*> m_clientList;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void jsonDataAvailable(int clientId, const QByteArray &data);
|
void clientConnected(const QUuid &clientId);
|
||||||
|
void clientDisconnected(const QUuid &clientId);
|
||||||
|
void dataAvailable(const QUuid &clientId, const QByteArray &data);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void newClientConnected();
|
void newClientConnected();
|
||||||
void readPackage();
|
void readPackage();
|
||||||
void clientDisconnected();
|
void slotClientDisconnected();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool startServer();
|
bool startServer();
|
||||||
bool stopServer();
|
bool stopServer();
|
||||||
void sendToAll(QByteArray data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TCPSERVER_H
|
#endif // TCPSERVER_H
|
||||||
|
|||||||
@ -13,7 +13,7 @@ MockTcpServer::~MockTcpServer()
|
|||||||
s_allServers.removeAll(this);
|
s_allServers.removeAll(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockTcpServer::sendResponse(int clientId, const QByteArray &data)
|
void MockTcpServer::sendData(const QUuid &clientId, const QByteArray &data)
|
||||||
{
|
{
|
||||||
emit outgoingData(clientId, data);
|
emit outgoingData(clientId, data);
|
||||||
}
|
}
|
||||||
@ -23,9 +23,9 @@ QList<MockTcpServer *> MockTcpServer::servers()
|
|||||||
return s_allServers;
|
return s_allServers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockTcpServer::injectData(int clientId, const QByteArray &data)
|
void MockTcpServer::injectData(const QUuid &clientId, const QByteArray &data)
|
||||||
{
|
{
|
||||||
emit jsonDataAvailable(clientId, data);
|
emit dataAvailable(clientId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MockTcpServer::startServer()
|
bool MockTcpServer::startServer()
|
||||||
|
|||||||
@ -12,17 +12,17 @@ public:
|
|||||||
explicit MockTcpServer(QObject *parent = 0);
|
explicit MockTcpServer(QObject *parent = 0);
|
||||||
~MockTcpServer();
|
~MockTcpServer();
|
||||||
|
|
||||||
void sendResponse(int clientId, const QByteArray &data);
|
void sendData(const QUuid &clientId, const QByteArray &data);
|
||||||
|
|
||||||
/************** Used for testing **************************/
|
/************** Used for testing **************************/
|
||||||
static QList<MockTcpServer*> servers();
|
static QList<MockTcpServer*> servers();
|
||||||
void injectData(int clientId, const QByteArray &data);
|
void injectData(const QUuid &clientId, const QByteArray &data);
|
||||||
signals:
|
signals:
|
||||||
void outgoingData(int clientId, const QByteArray &data);
|
void outgoingData(const QUuid &clientId, const QByteArray &data);
|
||||||
/************** Used for testing **************************/
|
/************** Used for testing **************************/
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void jsonDataAvailable(int clientId, const QByteArray &data);
|
void dataAvailable(const QUuid &clientId, const QByteArray &data);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool startServer();
|
bool startServer();
|
||||||
|
|||||||
@ -13,12 +13,22 @@ class TestJSONRPC: public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private slots:
|
private slots:
|
||||||
void initTestcase();
|
void initTestcase();
|
||||||
|
|
||||||
void introspect();
|
void introspect();
|
||||||
|
|
||||||
void getSupportedDevices();
|
void getSupportedDevices();
|
||||||
|
|
||||||
|
void enableDisableNotifications_data();
|
||||||
|
void enableDisableNotifications();
|
||||||
|
|
||||||
|
void version();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVariant injectAndWait(const QByteArray data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MockTcpServer *m_mockTcpServer;
|
MockTcpServer *m_mockTcpServer;
|
||||||
int m_clientId;
|
QUuid m_clientId;
|
||||||
};
|
};
|
||||||
|
|
||||||
void TestJSONRPC::initTestcase()
|
void TestJSONRPC::initTestcase()
|
||||||
@ -36,12 +46,29 @@ void TestJSONRPC::initTestcase()
|
|||||||
// If Hive should create more than one TcpServer at some point, this needs to be updated.
|
// If Hive should create more than one TcpServer at some point, this needs to be updated.
|
||||||
QCOMPARE(MockTcpServer::servers().count(), 1);
|
QCOMPARE(MockTcpServer::servers().count(), 1);
|
||||||
m_mockTcpServer = MockTcpServer::servers().first();
|
m_mockTcpServer = MockTcpServer::servers().first();
|
||||||
m_clientId = 0;
|
m_clientId = QUuid::createUuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TestJSONRPC::injectAndWait(const QByteArray data)
|
||||||
|
{
|
||||||
|
QSignalSpy spy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
|
||||||
|
|
||||||
|
m_mockTcpServer->injectData(m_clientId, data);
|
||||||
|
|
||||||
|
if (spy.count() == 0) {
|
||||||
|
spy.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the response it a valid JSON string
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(spy.takeFirst().last().toByteArray(), &error);
|
||||||
|
|
||||||
|
return jsonDoc.toVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestJSONRPC::introspect()
|
void TestJSONRPC::introspect()
|
||||||
{
|
{
|
||||||
QSignalSpy spy(m_mockTcpServer, SIGNAL(outgoingData(int,QByteArray)));
|
QSignalSpy spy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
|
||||||
QVERIFY(spy.isValid());
|
QVERIFY(spy.isValid());
|
||||||
|
|
||||||
m_mockTcpServer->injectData(m_clientId, "{\"id\":42, \"method\":\"JSONRPC.Introspect\"}");
|
m_mockTcpServer->injectData(m_clientId, "{\"id\":42, \"method\":\"JSONRPC.Introspect\"}");
|
||||||
@ -54,7 +81,7 @@ void TestJSONRPC::introspect()
|
|||||||
QVERIFY(spy.count() == 1);
|
QVERIFY(spy.count() == 1);
|
||||||
|
|
||||||
// Make sure the introspect response goes to the correct clientId
|
// Make sure the introspect response goes to the correct clientId
|
||||||
QCOMPARE(spy.first().first().toInt(), m_clientId);
|
QCOMPARE(spy.first().first().toString(), m_clientId.toString());
|
||||||
|
|
||||||
// Make sure the response it a valid JSON string
|
// Make sure the response it a valid JSON string
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
@ -67,22 +94,7 @@ void TestJSONRPC::introspect()
|
|||||||
|
|
||||||
void TestJSONRPC::getSupportedDevices()
|
void TestJSONRPC::getSupportedDevices()
|
||||||
{
|
{
|
||||||
QSignalSpy spy(m_mockTcpServer, SIGNAL(outgoingData(int,QByteArray)));
|
QVariant supportedDevices = injectAndWait("{\"id\":1, \"method\":\"Devices.GetSupportedDevices\"}");
|
||||||
|
|
||||||
m_mockTcpServer->injectData(m_clientId, "{\"id\":1, \"method\":\"Devices.GetSupportedDevices\"}");
|
|
||||||
|
|
||||||
if (spy.count() == 0) {
|
|
||||||
spy.wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the response it a valid JSON string
|
|
||||||
QJsonParseError error;
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(spy.first().last().toByteArray(), &error);
|
|
||||||
QCOMPARE(error.error, QJsonParseError::NoError);
|
|
||||||
|
|
||||||
QVariant supportedDevices = jsonDoc.toVariant();
|
|
||||||
|
|
||||||
qDebug() << spy.first().last();
|
|
||||||
|
|
||||||
// Make sure there is exactly 1 supported device class with the name Mock Wifi Device
|
// Make sure there is exactly 1 supported device class with the name Mock Wifi Device
|
||||||
QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), 1);
|
QCOMPARE(supportedDevices.toMap().value("params").toMap().value("deviceClasses").toList().count(), 1);
|
||||||
@ -90,5 +102,31 @@ void TestJSONRPC::getSupportedDevices()
|
|||||||
QCOMPARE(deviceName, QString("Mock WiFi Device"));
|
QCOMPARE(deviceName, QString("Mock WiFi Device"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestJSONRPC::enableDisableNotifications_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("enabled");
|
||||||
|
|
||||||
|
QTest::newRow("enabled") << "true";
|
||||||
|
QTest::newRow("disabled") << "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestJSONRPC::enableDisableNotifications()
|
||||||
|
{
|
||||||
|
QFETCH(QString, enabled);
|
||||||
|
|
||||||
|
QVariant response = injectAndWait(QString("{\"id\":1, \"method\":\"JSONRPC.SetNotificationStatus\", \"params\":{\"enabled\": " + enabled + " }}").toLatin1());
|
||||||
|
|
||||||
|
QCOMPARE(response.toMap().value("params").toMap().value("status").toString(), QString("success"));
|
||||||
|
QCOMPARE(response.toMap().value("params").toMap().value("enabled").toString(), enabled);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestJSONRPC::version()
|
||||||
|
{
|
||||||
|
QVariant response = injectAndWait("{\"id\":1, \"method\":\"JSONRPC.Version\"}");
|
||||||
|
|
||||||
|
QCOMPARE(response.toMap().value("params").toMap().value("version").toString(), QString("0.0.0"));
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestJSONRPC)
|
QTEST_MAIN(TestJSONRPC)
|
||||||
#include "testjsonrpc.moc"
|
#include "testjsonrpc.moc"
|
||||||
|
|||||||
@ -3,5 +3,5 @@
|
|||||||
if [ -z $2 ]; then
|
if [ -z $2 ]; then
|
||||||
echo "usage: $0 host deviceClassId"
|
echo "usage: $0 host deviceClassId"
|
||||||
else
|
else
|
||||||
(echo '{"id":1, "method":"Devices.GetTriggerTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 1234
|
(echo '{"id":1, "method":"Devices.GetEventTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 1234
|
||||||
fi
|
fi
|
||||||
|
|||||||
7
tests/scripts/getversion.sh
Executable file
7
tests/scripts/getversion.sh
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -z $1 ]; then
|
||||||
|
echo "usage: $0 host"
|
||||||
|
else
|
||||||
|
(echo '{"id":1, "method": "JSONRPC.Version"}'; sleep 1) | nc $1 1234
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user