added a new mockdevice plugin

pull/1/head
Michael Zanetti 2014-04-01 00:21:19 +02:00
parent 95f806ccaf
commit 66890e3161
14 changed files with 344 additions and 1 deletions

View File

@ -339,5 +339,10 @@ bool DeviceManager::setupDevice(Device *device)
}
}
if (!plugin->deviceCreated(device)) {
qWarning() << "Device setup for device" << device->name() << "failed.";
return false;
}
return true;
}

View File

@ -104,6 +104,14 @@ DevicePlugin::~DevicePlugin()
}
/*! This will be called when a new device is created. The plugin has the chance to do some setup.
Return false if something bad happened during the setup. The device will be disabled.
*/
bool DevicePlugin::deviceCreated(Device *device)
{
return true;
}
/*! This will be called when the DeviceManager initializes the plugin and set up the things behind the scenes.
When implementing a new plugin, use \l{DevicePlugin::init()} instead in order to do initialisation work. */
void DevicePlugin::initPlugin(DeviceManager *deviceManager)

View File

@ -44,6 +44,8 @@ public:
virtual QList<DeviceClass> supportedDevices() const = 0;
virtual DeviceManager::HardwareResources requiredHardware() const = 0;
virtual bool deviceCreated(Device *device);
// Hardware input
virtual void radioData(QList<int> rawData) {Q_UNUSED(rawData)}
virtual void guhTimer() {}

View File

@ -4,5 +4,6 @@ SUBDIRS += elro \
meisteranker \
wifidetector \
conrad \
mock \
# boblight \

View File

@ -0,0 +1,124 @@
/****************************************************************************
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "devicepluginmock.h"
#include "httpdaemon.h"
#include "device.h"
#include "devicemanager.h"
#include <QDebug>
#include <QStringList>
QUuid mockEvent1Id = QUuid("45bf3752-0fc6-46b9-89fd-ffd878b5b22b");
DevicePluginMock::DevicePluginMock()
{
}
QList<DeviceClass> DevicePluginMock::supportedDevices() const
{
QList<DeviceClass> ret;
DeviceClass deviceClassMock(pluginId(), QUuid("753f0d32-0468-4d08-82ed-1964aab03298"));
deviceClassMock.setName("Mock Device");
QVariantList mockParams;
QVariantMap portParam;
portParam.insert("name", "httpport");
portParam.insert("type", "int");
mockParams.append(portParam);
deviceClassMock.setParams(mockParams);
// QList<StateType> detectorStates;
// StateType inRangeState(inRangeStateTypeId);
// inRangeState.setName("inRange");
// inRangeState.setType(QVariant::Bool);
// inRangeState.setDefaultValue(false);
// detectorStates.append(inRangeState);
// deviceClassWifiDetector.setStates(detectorStates);
QList<EventType> mockEvents;
// QVariantList detectorEventParams;
// QVariantMap paramInRange;
// paramInRange.insert("name", "inRange");
// paramInRange.insert("type", "bool");
// detectorEventParams.append(paramInRange);
EventType event1(mockEvent1Id);
event1.setName("event1");
// event1.setParameters(detectorEventParams);
mockEvents.append(event1);
deviceClassMock.setEvents(mockEvents);
ret.append(deviceClassMock);
return ret;
}
DeviceManager::HardwareResources DevicePluginMock::requiredHardware() const
{
return DeviceManager::HardwareResourceTimer;
}
QString DevicePluginMock::pluginName() const
{
return "Mock Devices";
}
QUuid DevicePluginMock::pluginId() const
{
return QUuid("727a4a9a-c187-446f-aadf-f1b2220607d1");
}
bool DevicePluginMock::deviceCreated(Device *device)
{
qDebug() << "Mockdevice created returning true" << device->params().value("httpport").toInt();
HttpDaemon *daemon = new HttpDaemon(device, this);
m_daemons.insert(device, daemon);
if (!daemon->isListening()) {
qDebug() << "couldn't setup mockdevice";
return false;
}
connect(daemon, SIGNAL(triggerEvent(int)), SLOT(triggerEvent(int)));
return true;
}
void DevicePluginMock::triggerEvent(int id)
{
HttpDaemon *daemon = qobject_cast<HttpDaemon*>(sender());
if (!daemon) {
return;
}
Device *device = m_daemons.key(daemon);
Event event(mockEvent1Id, device->id(), QVariantMap());
qDebug() << "Emitting event " << event.eventTypeId();
emit emitEvent(event);
}

View File

@ -0,0 +1,53 @@
/****************************************************************************
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifndef DEVICEPLUGINMOCK_H
#define DEVICEPLUGINMOCK_H
#include "deviceplugin.h"
#include <QProcess>
class HttpDaemon;
class DevicePluginMock : public DevicePlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.guhyourhome.DevicePlugin" FILE "devicepluginmock.json")
Q_INTERFACES(DevicePlugin)
public:
explicit DevicePluginMock();
QList<DeviceClass> supportedDevices() const override;
DeviceManager::HardwareResources requiredHardware() const override;
QString pluginName() const override;
QUuid pluginId() const override;
bool deviceCreated(Device *device) override;
private slots:
void triggerEvent(int id);
private:
QHash<Device*, HttpDaemon*> m_daemons;
};
#endif // DEVICEPLUGINMOCK_H

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,96 @@
#include "httpdaemon.h"
#include "device.h"
#include <QTcpSocket>
#include <QDebug>
#include <QDateTime>
#include <QUrlQuery>
HttpDaemon::HttpDaemon(Device *device, QObject *parent):
QTcpServer(parent), disabled(false), m_device(device)
{
listen(QHostAddress::LocalHost, device->params().value("httpport").toInt());
}
void HttpDaemon::incomingConnection(qintptr socket)
{
qDebug() << "incoming connection";
if (disabled)
return;
// When a new client connects, the server constructs a QTcpSocket and all
// communication with the client is done over this QTcpSocket. QTcpSocket
// works asynchronously, this means that all the communication is done
// in the two slots readClient() and discardClient().
QTcpSocket* s = new QTcpSocket(this);
connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
connect(s, SIGNAL(disconnected()), this, SLOT(discardClient()));
s->setSocketDescriptor(socket);
}
void HttpDaemon::pause()
{
disabled = true;
}
void HttpDaemon::resume()
{
disabled = false;
}
void HttpDaemon::readClient()
{
if (disabled)
return;
// This slot is called when the client sent data to the server. The
// server looks if it was a get request and sends a very simple HTML
// document back.
QTcpSocket* socket = (QTcpSocket*)sender();
if (socket->canReadLine()) {
QByteArray data = socket->readLine();
QStringList tokens = QString(data).split(QRegExp("[ \r\n][ \r\n]*"));
qDebug() << "incoming data" << tokens[1];
if (tokens[1].contains('?')) {
QUrlQuery query(QUrl("http://foo.bar" + tokens[1]));
qDebug() << "query is" << query.queryItemValue("eventid");
emit triggerEvent(query.queryItemValue("eventid").toInt());
}
if (tokens[0] == "GET") {
QTextStream os(socket);
os.setAutoDetectUnicode(true);
os << QString("HTTP/1.0 200 Ok\r\n"
"Content-Type: text/html; charset=\"utf-8\"\r\n"
"\r\n"
"<html>"
"<body>"
"<h1>Mock device</h1>\n"
"Name: %1<br>"
"ID: %2"
"<form action=\"/\" method=\"get\">"
"<input type='hidden'' name='eventid' value='1'>"
"<input type='submit' value='Generate event1'/>"
"</form>"
"</body>"
"</html>\n").arg(m_device->name()).arg(m_device->id().toString());
socket->close();
qDebug() << "Wrote to client";
if (socket->state() == QTcpSocket::UnconnectedState) {
delete socket;
qDebug() << "Connection closed";
}
}
}
}
void HttpDaemon::discardClient()
{
QTcpSocket* socket = (QTcpSocket*)sender();
socket->deleteLater();
qDebug() << "Connection closed";
}

View File

@ -0,0 +1,33 @@
#ifndef HTTPDAEMON_H
#define HTTPDAEMON_H
#include <QTcpServer>
class Device;
class HttpDaemon : public QTcpServer
{
Q_OBJECT
public:
HttpDaemon(Device *device, QObject* parent = 0);
void incomingConnection(qintptr socket) override;
void pause();
void resume();
signals:
void triggerEvent(int id);
private slots:
void readClient();
void discardClient();
private:
bool disabled;
Device *m_device;
};
#endif // HTTPDAEMON_H

View File

@ -0,0 +1,15 @@
include(../../plugins.pri)
QT+= network
TARGET = $$qtLibraryTarget(guh_devicepluginmock)
SOURCES += \
devicepluginmock.cpp \
httpdaemon.cpp
HEADERS += \
devicepluginmock.h \
httpdaemon.h

View File

@ -172,7 +172,7 @@ void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &jsonDat
QVariantMap returns;
QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(QVariantMap, returns), Q_ARG(QVariantMap, params));
Q_ASSERT((targetNamespace == "JSONRPC" && method == "Introspect") || handler->validateReturns(method, returns));
// Q_ASSERT((targetNamespace == "JSONRPC" && method == "Introspect") || handler->validateReturns(method, returns));
sendResponse(clientId, commandId, returns);
}

View File

@ -26,6 +26,7 @@ Q_IMPORT_PLUGIN(DevicePluginIntertechno)
Q_IMPORT_PLUGIN(DevicePluginMeisterAnker)
Q_IMPORT_PLUGIN(DevicePluginWifiDetector)
Q_IMPORT_PLUGIN(DevicePluginConrad)
Q_IMPORT_PLUGIN(DevicePluginMock)
int main(int argc, char *argv[])
{

View File

@ -20,3 +20,4 @@ LIBS += -L../plugins/deviceplugins/intertechno/ -lguh_devicepluginintertechno
LIBS += -L../plugins/deviceplugins/meisteranker/ -lguh_devicepluginmeisteranker
LIBS += -L../plugins/deviceplugins/wifidetector/ -lguh_devicepluginwifidetector
LIBS += -L../plugins/deviceplugins/conrad -lguh_devicepluginconrad
LIBS += -L../plugins/deviceplugins/mock -lguh_devicepluginmock

View File

@ -23,5 +23,8 @@ else
elif [ $2 == "wifidetector" ]; then
# Adds a WiFi detector
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{bd216356-f1ec-4324-9785-6982d2174e17}","deviceParams":{"mac":"90:cf:15:1b:ce:bb"}}}'; sleep 1) | nc $1 1234
elif [ $2 == "mock" ]; then
# Adds a Mock device
(echo '{"id":1, "method":"Devices.AddConfiguredDevice", "params":{"deviceClassId": "{753f0d32-0468-4d08-82ed-1964aab03298}","deviceParams":{"httpport":"8081"}}}'; sleep 1) | nc $1 1234
fi
fi