states implemented

This commit is contained in:
Michael Zanetti 2014-04-04 01:34:13 +02:00
parent 8301500200
commit 5a6d7bf2ba
9 changed files with 106 additions and 62 deletions

View File

@ -27,7 +27,6 @@
QUuid pluginUuid = QUuid("8e0f791e-b273-4267-8605-b7c2f55a68ab"); QUuid pluginUuid = QUuid("8e0f791e-b273-4267-8605-b7c2f55a68ab");
QUuid detectorId = QUuid("bd216356-f1ec-4324-9785-6982d2174e17"); QUuid detectorId = QUuid("bd216356-f1ec-4324-9785-6982d2174e17");
QUuid inRangeStateTypeId = QUuid("cb43e1b5-4f61-4538-bfa2-c33055c542cf"); QUuid inRangeStateTypeId = QUuid("cb43e1b5-4f61-4538-bfa2-c33055c542cf");
QUuid inRangeEventTypeId = QUuid("7cae711a-a0af-41b4-b3bf-38d3e23b41ba");
DevicePluginWifiDetector::DevicePluginWifiDetector() DevicePluginWifiDetector::DevicePluginWifiDetector()
{ {
@ -58,20 +57,6 @@ QList<DeviceClass> DevicePluginWifiDetector::supportedDevices() const
deviceClassWifiDetector.setStates(detectorStates); deviceClassWifiDetector.setStates(detectorStates);
QList<EventType> detectorEvents;
QVariantList detectorEventParams;
QVariantMap paramInRange;
paramInRange.insert("name", "inRange");
paramInRange.insert("type", "bool");
detectorEventParams.append(paramInRange);
EventType inRangeEvent(inRangeEventTypeId);
inRangeEvent.setName("inRange");
inRangeEvent.setParameters(detectorEventParams);
detectorEvents.append(inRangeEvent);
deviceClassWifiDetector.setEvents(detectorEvents);
ret.append(deviceClassWifiDetector); ret.append(deviceClassWifiDetector);
return ret; return ret;
@ -132,13 +117,6 @@ void DevicePluginWifiDetector::processFinished(int exitCode, QProcess::ExitStatu
bool wasFound = foundDevices.contains(device->params().value("mac").toString().toLower()); bool wasFound = foundDevices.contains(device->params().value("mac").toString().toLower());
if (wasInRange != wasFound) { if (wasInRange != wasFound) {
device->setStateValue(inRangeStateTypeId, wasFound); device->setStateValue(inRangeStateTypeId, wasFound);
QVariantMap params;
params.insert("inRange", wasFound);
Event event(inRangeEventTypeId, device->id(), params);
qDebug() << "Device" << device->name() << QStringLiteral("is now ") + (wasFound ? "in" : "out of") + " range";
emit emitEvent(event);
} }
} }
} }

View File

@ -80,8 +80,6 @@ GuhCore::GuhCore(QObject *parent) :
m_jsonServer = new JsonRPCServer(this); m_jsonServer = new JsonRPCServer(this);
connect(m_deviceManager, &DeviceManager::emitEvent, this, &GuhCore::gotEvent); connect(m_deviceManager, &DeviceManager::emitEvent, this, &GuhCore::gotEvent);
connect(m_deviceManager, &DeviceManager::deviceStateChanged, this, &GuhCore::deviceStateChanged);
} }
/*! Connected to the DeviceManager's emitEvent signal. Events received in /*! Connected to the DeviceManager's emitEvent signal. Events received in
@ -92,8 +90,3 @@ void GuhCore::gotEvent(const Event &event)
m_deviceManager->executeAction(action); m_deviceManager->executeAction(action);
} }
} }
void GuhCore::deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value)
{
m_jsonServer->emitStateChangeNotification(device, stateTypeId, value);
}

View File

@ -48,7 +48,6 @@ private:
private slots: private slots:
void gotEvent(const Event &event); void gotEvent(const Event &event);
void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value);
}; };

View File

@ -17,12 +17,14 @@
***************************************************************************/ ***************************************************************************/
#include "devicehandler.h" #include "devicehandler.h"
#include "device.h"
#include "deviceclass.h" #include "deviceclass.h"
#include "guhcore.h" #include "guhcore.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "deviceplugin.h" #include "deviceplugin.h"
#include <QDebug>
DeviceHandler::DeviceHandler(QObject *parent) : DeviceHandler::DeviceHandler(QObject *parent) :
JsonHandler(parent) JsonHandler(parent)
{ {
@ -91,6 +93,15 @@ DeviceHandler::DeviceHandler(QObject *parent) :
actions.append(JsonTypes::actionTypeRef()); actions.append(JsonTypes::actionTypeRef());
returns.insert("actionTypes", actions); returns.insert("actionTypes", actions);
setReturns("GetActionTypes", returns); setReturns("GetActionTypes", returns);
params.clear(); returns.clear();
setDescription("StateChanged", "Emitted whenever a State of a device changes.");
params.insert("deviceId", "uuid");
params.insert("stateTypeId", "uuid");
params.insert("variant", "value");
setParams("StateChanged", params);
connect(GuhCore::instance()->deviceManager(), &DeviceManager::deviceStateChanged, this, &DeviceHandler::deviceStateChanged);
} }
QString DeviceHandler::name() const QString DeviceHandler::name() const
@ -200,3 +211,19 @@ QVariantMap DeviceHandler::GetActionTypes(const QVariantMap &params) const
returns.insert("actionTypes", actionList); returns.insert("actionTypes", actionList);
return returns; return returns;
} }
void DeviceHandler::deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value)
{
qDebug() << "************************************";
QVariantMap notification;
notification.insert("notification", "Device.StateChanged");
QVariantMap params;
params.insert("deviceId", device->id());
params.insert("stateTypeId", stateTypeId);
params.insert("value", value);
notification.insert("params", params);
emit StateChanged(notification);
}

View File

@ -43,6 +43,11 @@ public:
Q_INVOKABLE QVariantMap GetActionTypes(const QVariantMap &params) const; Q_INVOKABLE QVariantMap GetActionTypes(const QVariantMap &params) const;
signals:
void StateChanged(const QVariantMap &params);
private slots:
void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value);
}; };
#endif // DEVICEHANDLER_H #endif // DEVICEHANDLER_H

View File

@ -26,20 +26,42 @@ JsonHandler::JsonHandler(QObject *parent) :
{ {
} }
QVariantMap JsonHandler::introspect() QVariantMap JsonHandler::introspect(QMetaMethod::MethodType type)
{ {
QVariantMap data; QVariantMap data;
for (int i = 0; i < metaObject()->methodCount(); ++i) { for (int i = 0; i < metaObject()->methodCount(); ++i) {
QMetaMethod method = metaObject()->method(i); QMetaMethod method = metaObject()->method(i);
if (method.methodType() == QMetaMethod::Method) { qDebug() << "checking method" << method.methodType() << method.methodSignature() << method.name();
QVariantMap methodData;
if (method.methodType() != type) {
continue;
}
switch (method.methodType()) {
case QMetaMethod::Method: {
if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name()) || !m_returns.contains(method.name())) { if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name()) || !m_returns.contains(method.name())) {
continue; continue;
} }
QVariantMap methodData;
methodData.insert("description", m_descriptions.value(method.name())); methodData.insert("description", m_descriptions.value(method.name()));
methodData.insert("params", m_params.value(method.name())); methodData.insert("params", m_params.value(method.name()));
methodData.insert("returns", m_returns.value(method.name())); methodData.insert("returns", m_returns.value(method.name()));
data.insert(name() + "." + method.name(), methodData); data.insert(name() + "." + method.name(), methodData);
break;
}
case QMetaMethod::Signal: {
if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name())) {
continue;
}
if (QString(method.name()).contains(QRegExp("^[A-Z]"))) {
qDebug() << "got signal" << method.name();
QVariantMap methodData;
methodData.insert("description", m_descriptions.value(method.name()));
methodData.insert("params", m_params.value(method.name()));
data.insert(name() + "." + method.name(), methodData);
}
break;
}
} }
} }
return data; return data;

View File

@ -23,6 +23,7 @@
#include <QObject> #include <QObject>
#include <QVariantMap> #include <QVariantMap>
#include <QMetaMethod>
class JsonHandler : public QObject class JsonHandler : public QObject
{ {
@ -32,7 +33,7 @@ public:
virtual QString name() const = 0; virtual QString name() const = 0;
QVariantMap introspect(); QVariantMap introspect(QMetaMethod::MethodType);
bool hasMethod(const QString &methodName); bool hasMethod(const QString &methodName);
QPair<bool, QString> validateParams(const QString &methodName, const QVariantMap &params); QPair<bool, QString> validateParams(const QString &methodName, const QVariantMap &params);

View File

@ -44,10 +44,11 @@
JsonRPCServer::JsonRPCServer(QObject *parent): JsonRPCServer::JsonRPCServer(QObject *parent):
JsonHandler(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
m_notificationId(0)
{ {
// First, define our own JSONRPC methods // First, define our own JSONRPC methods
QVariantMap returns; QVariantMap returns;
@ -79,27 +80,7 @@ JsonRPCServer::JsonRPCServer(QObject *parent):
connect(m_tcpServer, SIGNAL(dataAvailable(const QUuid &, QByteArray)), this, SLOT(processData(const QUuid &, QByteArray))); connect(m_tcpServer, SIGNAL(dataAvailable(const QUuid &, QByteArray)), this, SLOT(processData(const QUuid &, QByteArray)));
m_tcpServer->startServer(); m_tcpServer->startServer();
registerHandler(this); QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection);
registerHandler(new DeviceHandler(this));
registerHandler(new ActionHandler(this));
registerHandler(new RulesHandler(this));
}
void JsonRPCServer::emitStateChangeNotification(Device *device, const QUuid &stateTypeId, const QVariant &value)
{
QVariantMap notification;
notification.insert("notification", "Device.StateChanged");
QVariantMap params;
params.insert("deviceId", device->id());
params.insert("stateTypeId", stateTypeId);
params.insert("value", value);
notification.insert("params", params);
QJsonDocument jsonDoc = QJsonDocument::fromVariant(notification);
m_tcpServer->sendData(m_clients.keys(true), jsonDoc.toJson());
} }
QString JsonRPCServer::name() const QString JsonRPCServer::name() const
@ -115,10 +96,16 @@ QVariantMap JsonRPCServer::Introspect(const QVariantMap &params) const
data.insert("types", JsonTypes::allTypes()); data.insert("types", JsonTypes::allTypes());
QVariantMap methods; QVariantMap methods;
foreach (JsonHandler *handler, m_handlers) { foreach (JsonHandler *handler, m_handlers) {
// qDebug() << "got handler" << handler->name() << handler->introspect(); methods.unite(handler->introspect(QMetaMethod::Method));
methods.unite(handler->introspect());
} }
data.insert("methods", methods); data.insert("methods", methods);
QVariantMap signalsMap;
foreach (JsonHandler *handler, m_handlers) {
signalsMap.unite(handler->introspect(QMetaMethod::Signal));
}
data.insert("signals", signalsMap);
return data; return data;
} }
@ -142,6 +129,14 @@ QVariantMap JsonRPCServer::SetNotificationStatus(const QVariantMap &params)
return returns; return returns;
} }
void JsonRPCServer::setup()
{
registerHandler(this);
registerHandler(new DeviceHandler(this));
registerHandler(new ActionHandler(this));
registerHandler(new RulesHandler(this));
}
void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &jsonData) void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &jsonData)
{ {
QJsonParseError error; QJsonParseError error;
@ -200,9 +195,29 @@ void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &jsonDat
sendResponse(clientId, commandId, returns); sendResponse(clientId, commandId, returns);
} }
void JsonRPCServer::sendNotification(const QVariantMap &params)
{
JsonHandler *handler = qobject_cast<JsonHandler*>(sender());
QMetaMethod method = handler->metaObject()->method(senderSignalIndex());
QVariantMap notification;
notification.insert("id", m_notificationId++);
notification.insert("notification", handler->name() + "." + method.name());
notification.insert("params", params);
QJsonDocument jsonDoc = QJsonDocument::fromVariant(notification);
m_tcpServer->sendData(m_clients.keys(true), jsonDoc.toJson());
}
void JsonRPCServer::registerHandler(JsonHandler *handler) void JsonRPCServer::registerHandler(JsonHandler *handler)
{ {
m_handlers.insert(handler->name(), handler); m_handlers.insert(handler->name(), handler);
for (int i = 0; i < handler->metaObject()->methodCount(); ++i) {
QMetaMethod method = handler->metaObject()->method(i);
if (method.methodType() == QMetaMethod::Signal && QString(method.name()).contains(QRegExp("^[A-Z]"))) {
QObject::connect(handler, method, this, metaObject()->method(metaObject()->indexOfSlot("sendNotification(QVariantMap)")));
}
}
} }
void JsonRPCServer::clientConnected(const QUuid &clientId) void JsonRPCServer::clientConnected(const QUuid &clientId)

View File

@ -41,8 +41,6 @@ class JsonRPCServer: public JsonHandler
public: public:
JsonRPCServer(QObject *parent = 0); JsonRPCServer(QObject *parent = 0);
void emitStateChangeNotification(Device *device, const QUuid &stateTypeId, const QVariant &value);
// JsonHandler API implementation // JsonHandler API implementation
QString name() const; QString name() const;
Q_INVOKABLE QVariantMap Introspect(const QVariantMap &params) const; Q_INVOKABLE QVariantMap Introspect(const QVariantMap &params) const;
@ -53,11 +51,15 @@ signals:
void commandReceived(const QString &targetNamespace, const QString &command, const QVariantMap &params); void commandReceived(const QString &targetNamespace, const QString &command, const QVariantMap &params);
private slots: private slots:
void setup();
void clientConnected(const QUuid &clientId); void clientConnected(const QUuid &clientId);
void clientDisconnected(const QUuid &clientId); void clientDisconnected(const QUuid &clientId);
void processData(const QUuid &clientId, const QByteArray &jsonData); void processData(const QUuid &clientId, const QByteArray &jsonData);
void sendNotification(const QVariantMap &params);
private: private:
void registerHandler(JsonHandler *handler); void registerHandler(JsonHandler *handler);
@ -74,6 +76,8 @@ private:
// clientId, notificationsEnabled // clientId, notificationsEnabled
QHash<QUuid, bool> m_clients; QHash<QUuid, bool> m_clients;
int m_notificationId;
}; };
#endif #endif