mirror of https://github.com/nymea/nymea.git
added a new mockdevice plugin
parent
95f806ccaf
commit
66890e3161
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,6 @@ SUBDIRS += elro \
|
|||
meisteranker \
|
||||
wifidetector \
|
||||
conrad \
|
||||
mock \
|
||||
|
||||
# boblight \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
include(../../plugins.pri)
|
||||
|
||||
QT+= network
|
||||
|
||||
TARGET = $$qtLibraryTarget(guh_devicepluginmock)
|
||||
|
||||
SOURCES += \
|
||||
devicepluginmock.cpp \
|
||||
httpdaemon.cpp
|
||||
|
||||
HEADERS += \
|
||||
devicepluginmock.h \
|
||||
httpdaemon.h
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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[])
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue