diff --git a/plugins/deviceplugins/wifidetector/devicepluginwifidetector.cpp b/plugins/deviceplugins/wifidetector/devicepluginwifidetector.cpp index d7f15139..83a10635 100644 --- a/plugins/deviceplugins/wifidetector/devicepluginwifidetector.cpp +++ b/plugins/deviceplugins/wifidetector/devicepluginwifidetector.cpp @@ -27,7 +27,6 @@ QUuid pluginUuid = QUuid("8e0f791e-b273-4267-8605-b7c2f55a68ab"); QUuid detectorId = QUuid("bd216356-f1ec-4324-9785-6982d2174e17"); QUuid inRangeStateTypeId = QUuid("cb43e1b5-4f61-4538-bfa2-c33055c542cf"); -QUuid inRangeEventTypeId = QUuid("7cae711a-a0af-41b4-b3bf-38d3e23b41ba"); DevicePluginWifiDetector::DevicePluginWifiDetector() { @@ -58,20 +57,6 @@ QList DevicePluginWifiDetector::supportedDevices() const deviceClassWifiDetector.setStates(detectorStates); - QList 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); return ret; @@ -132,13 +117,6 @@ void DevicePluginWifiDetector::processFinished(int exitCode, QProcess::ExitStatu bool wasFound = foundDevices.contains(device->params().value("mac").toString().toLower()); if (wasInRange != 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); } } } diff --git a/server/guhcore.cpp b/server/guhcore.cpp index 3edc328d..5b21ff9e 100644 --- a/server/guhcore.cpp +++ b/server/guhcore.cpp @@ -80,8 +80,6 @@ GuhCore::GuhCore(QObject *parent) : m_jsonServer = new JsonRPCServer(this); 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 @@ -92,8 +90,3 @@ void GuhCore::gotEvent(const Event &event) m_deviceManager->executeAction(action); } } - -void GuhCore::deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value) -{ - m_jsonServer->emitStateChangeNotification(device, stateTypeId, value); -} diff --git a/server/guhcore.h b/server/guhcore.h index 669e5702..8edf2d9c 100644 --- a/server/guhcore.h +++ b/server/guhcore.h @@ -48,7 +48,6 @@ private: private slots: void gotEvent(const Event &event); - void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value); }; diff --git a/server/jsonrpc/devicehandler.cpp b/server/jsonrpc/devicehandler.cpp index 091fa9f4..b55a147e 100644 --- a/server/jsonrpc/devicehandler.cpp +++ b/server/jsonrpc/devicehandler.cpp @@ -17,12 +17,14 @@ ***************************************************************************/ #include "devicehandler.h" - +#include "device.h" #include "deviceclass.h" #include "guhcore.h" #include "devicemanager.h" #include "deviceplugin.h" +#include + DeviceHandler::DeviceHandler(QObject *parent) : JsonHandler(parent) { @@ -91,6 +93,15 @@ DeviceHandler::DeviceHandler(QObject *parent) : actions.append(JsonTypes::actionTypeRef()); returns.insert("actionTypes", actions); 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 @@ -200,3 +211,19 @@ QVariantMap DeviceHandler::GetActionTypes(const QVariantMap ¶ms) const returns.insert("actionTypes", actionList); 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); +} diff --git a/server/jsonrpc/devicehandler.h b/server/jsonrpc/devicehandler.h index a8fee9a1..db7c096a 100644 --- a/server/jsonrpc/devicehandler.h +++ b/server/jsonrpc/devicehandler.h @@ -43,6 +43,11 @@ public: Q_INVOKABLE QVariantMap GetActionTypes(const QVariantMap ¶ms) const; +signals: + void StateChanged(const QVariantMap ¶ms); + +private slots: + void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value); }; #endif // DEVICEHANDLER_H diff --git a/server/jsonrpc/jsonhandler.cpp b/server/jsonrpc/jsonhandler.cpp index 52459c9f..53790abe 100644 --- a/server/jsonrpc/jsonhandler.cpp +++ b/server/jsonrpc/jsonhandler.cpp @@ -26,20 +26,42 @@ JsonHandler::JsonHandler(QObject *parent) : { } -QVariantMap JsonHandler::introspect() +QVariantMap JsonHandler::introspect(QMetaMethod::MethodType type) { QVariantMap data; for (int i = 0; i < metaObject()->methodCount(); ++i) { QMetaMethod method = metaObject()->method(i); - if (method.methodType() == QMetaMethod::Method) { - QVariantMap methodData; + qDebug() << "checking method" << method.methodType() << method.methodSignature() << method.name(); + + 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())) { continue; } + QVariantMap methodData; methodData.insert("description", m_descriptions.value(method.name())); methodData.insert("params", m_params.value(method.name())); methodData.insert("returns", m_returns.value(method.name())); 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; diff --git a/server/jsonrpc/jsonhandler.h b/server/jsonrpc/jsonhandler.h index 310f3ae6..a449cd3b 100644 --- a/server/jsonrpc/jsonhandler.h +++ b/server/jsonrpc/jsonhandler.h @@ -23,6 +23,7 @@ #include #include +#include class JsonHandler : public QObject { @@ -32,7 +33,7 @@ public: virtual QString name() const = 0; - QVariantMap introspect(); + QVariantMap introspect(QMetaMethod::MethodType); bool hasMethod(const QString &methodName); QPair validateParams(const QString &methodName, const QVariantMap ¶ms); diff --git a/server/jsonrpc/jsonrpcserver.cpp b/server/jsonrpc/jsonrpcserver.cpp index 740a12fe..97ee8754 100644 --- a/server/jsonrpc/jsonrpcserver.cpp +++ b/server/jsonrpc/jsonrpcserver.cpp @@ -44,10 +44,11 @@ JsonRPCServer::JsonRPCServer(QObject *parent): JsonHandler(parent), #ifdef TESTING_ENABLED - m_tcpServer(new MockTcpServer(this)) + m_tcpServer(new MockTcpServer(this)), #else - m_tcpServer(new TcpServer(this)) + m_tcpServer(new TcpServer(this)), #endif + m_notificationId(0) { // First, define our own JSONRPC methods QVariantMap returns; @@ -79,27 +80,7 @@ JsonRPCServer::JsonRPCServer(QObject *parent): connect(m_tcpServer, SIGNAL(dataAvailable(const QUuid &, QByteArray)), this, SLOT(processData(const QUuid &, QByteArray))); m_tcpServer->startServer(); - registerHandler(this); - 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()); + QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection); } QString JsonRPCServer::name() const @@ -115,10 +96,16 @@ QVariantMap JsonRPCServer::Introspect(const QVariantMap ¶ms) const data.insert("types", JsonTypes::allTypes()); QVariantMap methods; foreach (JsonHandler *handler, m_handlers) { -// qDebug() << "got handler" << handler->name() << handler->introspect(); - methods.unite(handler->introspect()); + methods.unite(handler->introspect(QMetaMethod::Method)); } data.insert("methods", methods); + + QVariantMap signalsMap; + foreach (JsonHandler *handler, m_handlers) { + signalsMap.unite(handler->introspect(QMetaMethod::Signal)); + } + data.insert("signals", signalsMap); + return data; } @@ -142,6 +129,14 @@ QVariantMap JsonRPCServer::SetNotificationStatus(const QVariantMap ¶ms) 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) { QJsonParseError error; @@ -200,9 +195,29 @@ void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &jsonDat sendResponse(clientId, commandId, returns); } +void JsonRPCServer::sendNotification(const QVariantMap ¶ms) +{ + JsonHandler *handler = qobject_cast(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) { 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) diff --git a/server/jsonrpc/jsonrpcserver.h b/server/jsonrpc/jsonrpcserver.h index af2b6206..9a4697ab 100644 --- a/server/jsonrpc/jsonrpcserver.h +++ b/server/jsonrpc/jsonrpcserver.h @@ -41,8 +41,6 @@ class JsonRPCServer: public JsonHandler public: JsonRPCServer(QObject *parent = 0); - void emitStateChangeNotification(Device *device, const QUuid &stateTypeId, const QVariant &value); - // JsonHandler API implementation QString name() const; Q_INVOKABLE QVariantMap Introspect(const QVariantMap ¶ms) const; @@ -53,11 +51,15 @@ signals: void commandReceived(const QString &targetNamespace, const QString &command, const QVariantMap ¶ms); private slots: + void setup(); + void clientConnected(const QUuid &clientId); void clientDisconnected(const QUuid &clientId); void processData(const QUuid &clientId, const QByteArray &jsonData); + void sendNotification(const QVariantMap ¶ms); + private: void registerHandler(JsonHandler *handler); @@ -74,6 +76,8 @@ private: // clientId, notificationsEnabled QHash m_clients; + + int m_notificationId; }; #endif