diff --git a/backend/backend.pro b/backend/backend.pro index 1914d77e..c911e7b2 100644 --- a/backend/backend.pro +++ b/backend/backend.pro @@ -1,17 +1,48 @@ -QT += qml quick websockets +include(../guh-control.pri) + +QT += qml quick websockets quickcontrols2 TARGET = guh-control -CONFIG += c++11 +RESOURCES += ../ui/qml.qrc ../data.qrc -SOURCES += main.cpp +INCLUDEPATH += $$top_srcdir/libguh-common +LIBS += -L$$top_builddir/libguh-common/ -lguh-common -RESOURCES += ui/qml.qrc +QML_FILES += $$files(*.qml,true) \ + $$files(*.js,true) -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = ui/ +OTHER_FILES += $${QML_FILES} -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target +HEADERS += \ + engine.h \ + guhinterface.h \ + devicemanager.h \ + websocketinterface.h \ + jsonrpc/jsontypes.h \ + jsonrpc/jsonrpcclient.h \ + jsonrpc/devicehandler.h \ + jsonrpc/jsonhandler.h \ + jsonrpc/actionhandler.h \ + jsonrpc/eventhandler.h \ + jsonrpc/logginghandler.h \ + jsonrpc/networkmanagerhandler.h \ + jsonrpc/configurationhandler.h + +SOURCES += main.cpp \ + engine.cpp \ + guhinterface.cpp \ + devicemanager.cpp \ + websocketinterface.cpp \ + jsonrpc/jsontypes.cpp \ + jsonrpc/jsonrpcclient.cpp \ + jsonrpc/devicehandler.cpp \ + jsonrpc/jsonhandler.cpp \ + jsonrpc/actionhandler.cpp \ + jsonrpc/eventhandler.cpp \ + jsonrpc/logginghandler.cpp \ + jsonrpc/networkmanagerhandler.cpp \ + jsonrpc/configurationhandler.cpp + +target.path = /usr/bin +INSTALLS += target diff --git a/backend/bluetoothinterface.cpp b/backend/bluetoothinterface.cpp new file mode 100644 index 00000000..cebcc98d --- /dev/null +++ b/backend/bluetoothinterface.cpp @@ -0,0 +1,93 @@ +#include "bluetoothinterface.h" + +#include +#include + +BluetoothInterface::BluetoothInterface(QObject *parent) : + GuhInterface(parent), + m_socket(0), + m_discovery(new BluetoothDiscovery(this)) +{ + connect(m_discovery, &BluetoothDiscovery::serviceFound, this, &BluetoothInterface::onServiceFound); +} + +void BluetoothInterface::sendData(const QByteArray &data) +{ + if (m_socket) + m_socket->write(data + '\n'); +} + +void BluetoothInterface::sendRequest(const QVariantMap &request) +{ + sendData(QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact)); +} + +BluetoothDiscovery *BluetoothInterface::discovery() +{ + return m_discovery; +} + +void BluetoothInterface::enable() +{ + if (m_socket) + return; + + m_socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); + + connect(m_socket, &QBluetoothSocket::readyRead, this, &BluetoothInterface::onDataReady); + connect(m_socket, &QBluetoothSocket::connected, this, &BluetoothInterface::onConnected); + connect(m_socket, &QBluetoothSocket::disconnected, this, &BluetoothInterface::onDisconnected); +} + +void BluetoothInterface::disable() +{ + delete m_socket; + m_socket = 0; +} + +void BluetoothInterface::onServiceFound(const QBluetoothServiceInfo &service) +{ + m_service = service; + enable(); + + if (m_socket->isOpen()) + return; + + qDebug() << "Connecting to service" << m_service.serviceName(); + m_socket->connectToService(m_service); +} + +void BluetoothInterface::onConnected() +{ + qDebug() << "Bluetooth Interface: connected" << m_socket->peerName() << m_socket->peerAddress(); + setConnected(true); +} + +void BluetoothInterface::onDisconnected() +{ + qDebug() << "Bluetooth Interface: disconnected"; + setConnected(false); +} + +void BluetoothInterface::onDataReady() +{ + if (!m_socket) + return; + + QByteArray message; + while (m_socket->canReadLine()) { + QByteArray dataLine = m_socket->readLine(); + message.append(dataLine); + if (dataLine.endsWith('\n')) { + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(message, &error); + if (error.error != QJsonParseError::NoError) { + qWarning() << "Could not parse json data from guh" << message << error.errorString(); + return; + } + + emit dataReady(jsonDoc.toVariant().toMap()); + message.clear(); + } + } +} diff --git a/backend/bluetoothinterface.h b/backend/bluetoothinterface.h new file mode 100644 index 00000000..c2abd3c1 --- /dev/null +++ b/backend/bluetoothinterface.h @@ -0,0 +1,44 @@ +#ifndef BLUETOOTHINTERFACE_H +#define BLUETOOTHINTERFACE_H + +#include +#include + +#include "guhinterface.h" +#include "discovery/bluetoothdiscovery.h" + +class BluetoothInterface : public GuhInterface +{ + Q_OBJECT + Q_PROPERTY(BluetoothDiscovery *discovery READ discovery CONSTANT) + +public: + explicit BluetoothInterface(QObject *parent = 0); + + void sendData(const QByteArray &data) override; + void sendRequest(const QVariantMap &request) override; + + BluetoothDiscovery *discovery(); + +private: + QBluetoothSocket *m_socket; + QBluetoothServiceInfo m_service; + + BluetoothDiscovery *m_discovery; + +signals: + +public slots: + Q_INVOKABLE void enable() override; + Q_INVOKABLE void disable() override; + +private slots: + void onServiceFound(const QBluetoothServiceInfo &service); + void onConnected(); + void onDisconnected(); + + void onDataReady(); + +}; + +#endif // BLUETOOTHINTERFACE_H diff --git a/backend/connectionmanager.cpp b/backend/connectionmanager.cpp new file mode 100644 index 00000000..8c7b1f0a --- /dev/null +++ b/backend/connectionmanager.cpp @@ -0,0 +1,129 @@ +#include "connectionmanager.h" + +#include +#include + +ConnectionManager::ConnectionManager(QObject *parent) : + QObject(parent), + m_discovery(new UpnpDiscovery(this)), + m_interface(0), + m_websocketInterface(new WebsocketInterface(this)), + m_bluetoothInterface(new BluetoothInterface(this)) +{ + +} + +GuhInterface *ConnectionManager::interface() +{ + return m_interface; +} + +UpnpDiscovery *ConnectionManager::upnpDiscovery() +{ + return m_discovery; +} + +WebsocketInterface *ConnectionManager::websocketInterface() +{ + return m_websocketInterface; +} + +BluetoothInterface *ConnectionManager::bluetoothInterface() +{ + return m_bluetoothInterface; +} + +QString ConnectionManager::currentInterfaceName() const +{ + return m_currentInterfaceName; +} + +QString ConnectionManager::currentStatusMessage() const +{ + return m_currentStatusMessage; +} + +void ConnectionManager::setInterface(GuhInterface *interface) +{ + if (m_interface) { + disconnect(m_interface, &GuhInterface::connectedChanged, this, &ConnectionManager::onConnectedChanged); + disconnect(m_interface, &GuhInterface::dataReady, this, &ConnectionManager::dataReady); + } + + m_interface = interface; + + connect(m_interface, &GuhInterface::connectedChanged, this, &ConnectionManager::onConnectedChanged); + connect(m_interface, &GuhInterface::dataReady, this, &ConnectionManager::dataReady); + emit interfaceChanged(); +} + +void ConnectionManager::setCurrentInterfaceName(const QString &name) +{ + m_currentInterfaceName = name; + emit currentInterfaceNameChanged(); +} + +void ConnectionManager::setCurrentStatusMessage(const QString &message) +{ + m_currentStatusMessage = message; + emit currentStatusMessageChanged(); +} + +void ConnectionManager::onConnectedChanged() +{ + if (m_interface->connected()) + emit connected(); + else + emit disconnect(); + + emit connectedChanged(); +} + +void ConnectionManager::onConnectingState() +{ + QSettings settings; + qDebug() << "Loading last connection" << settings.fileName(); + settings.beginGroup("Connections"); + QString url = settings.value("webSocketUrl").toString(); + settings.endGroup(); + + if (url.isEmpty()) { + qDebug() << "No stored websocket url"; + m_websocketInterface->connectionFailed(); + } + + m_websocketInterface->setUrl(url); + m_websocketInterface->enable(); +} + +void ConnectionManager::onUpnpDiscoveringState() +{ + upnpDiscovery()->discover(); +} + +void ConnectionManager::start(const ConnectionType &connectionType) +{ + switch (connectionType) { + case ConnectionTypeAuto: + setInterface(m_websocketInterface); + break; + case ConnectionTypeWebSocket: + setInterface(m_websocketInterface); + m_discovery->discover(); + break; + case ConnectionTypeCloud: + + break; + case ConnectionTypeBluetooth: + setInterface(m_bluetoothInterface); + break; + default: + setInterface(m_bluetoothInterface); + break; + } +} + +void ConnectionManager::stop() +{ + m_interface->disable(); +} diff --git a/backend/connectionmanager.h b/backend/connectionmanager.h new file mode 100644 index 00000000..f032c954 --- /dev/null +++ b/backend/connectionmanager.h @@ -0,0 +1,82 @@ +#ifndef CONNECTIONMANAGER_H +#define CONNECTIONMANAGER_H + +#include +#include + +#include "guhinterface.h" +#include "websocketinterface.h" +#include "bluetoothinterface.h" +#include "cloudconnection/cloudconnection.h" +#include "discovery/upnpdiscovery.h" + +class ConnectionManager : public QObject +{ + Q_OBJECT + Q_ENUMS(ConnectionType) + Q_PROPERTY(UpnpDiscovery *upnpDiscovery READ upnpDiscovery CONSTANT) + Q_PROPERTY(GuhInterface *interface READ interface NOTIFY interfaceChanged) + Q_PROPERTY(WebsocketInterface *websocketInterface READ websocketInterface CONSTANT) + Q_PROPERTY(BluetoothInterface *bluetoothInterface READ bluetoothInterface CONSTANT) + Q_PROPERTY(QString currentInterfaceName READ currentInterfaceName WRITE setCurrentInterfaceName NOTIFY currentInterfaceNameChanged) + Q_PROPERTY(QString currentStatusMessage READ currentStatusMessage WRITE setCurrentStatusMessage NOTIFY currentStatusMessageChanged) + +public: + enum ConnectionType { + ConnectionTypeAuto, + ConnectionTypeWebSocket, + ConnectionTypeCloud, + ConnectionTypeBluetooth + }; + + explicit ConnectionManager(QObject *parent = 0); + + GuhInterface *interface(); + UpnpDiscovery *upnpDiscovery(); + + WebsocketInterface *websocketInterface(); + BluetoothInterface *bluetoothInterface(); + + QString currentInterfaceName() const; + QString currentStatusMessage() const; + +private: + UpnpDiscovery *m_discovery; + GuhInterface *m_interface; + WebsocketInterface *m_websocketInterface; + BluetoothInterface *m_bluetoothInterface; + + QString m_currentInterfaceName; + QString m_currentStatusMessage; + + void setInterface(GuhInterface *interface); + void setCurrentInterfaceName(const QString &name); + void setCurrentStatusMessage(const QString &message); + +private slots: + void onConnectedChanged(); + + // State slots + void onConnectingState(); + void onUpnpDiscoveringState(); + +signals: + void connectedChanged(); + + void dataReady(const QVariantMap &data); + + void connected(); + void disconnected(); + + void interfaceChanged(); + void websocketInterfaceChanged(); + void currentInterfaceNameChanged(); + void currentStatusMessageChanged(); + +public slots: + void start(const ConnectionType &connectionType = ConnectionTypeAuto); + void stop(); + +}; + +#endif // CONNECTIONMANAGER_H diff --git a/backend/devicemanager.cpp b/backend/devicemanager.cpp new file mode 100644 index 00000000..0b865fd6 --- /dev/null +++ b/backend/devicemanager.cpp @@ -0,0 +1,81 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "devicemanager.h" +#include "engine.h" + +DeviceManager::DeviceManager(QObject *parent) : + QObject(parent), + m_vendors(new Vendors(this)), + m_vendorsProxy(new VendorsProxy(this)), + m_plugins(new Plugins(this)), + m_pluginsProxy(new PluginsProxy(this)), + m_devices(new Devices(this)), + m_devicesProxy(new DevicesProxy(this)), + m_deviceClasses(new DeviceClasses(this)), + m_deviceClassesProxy(new DeviceClassesProxy(this)) +{ + m_vendorsProxy->setVendors(m_vendors); + m_pluginsProxy->setPlugins(m_plugins); + m_devicesProxy->setDevices(m_devices); + m_deviceClassesProxy->setDeviceClasses(m_deviceClasses); +} + +Vendors *DeviceManager::vendors() const +{ + return m_vendors; +} + +VendorsProxy *DeviceManager::vendorsProxy() const +{ + return m_vendorsProxy; +} + +Plugins *DeviceManager::plugins() const +{ + return m_plugins; +} + +PluginsProxy *DeviceManager::pluginsProxy() const +{ + return m_pluginsProxy; +} + +Devices *DeviceManager::devices() const +{ + return m_devices; +} + +DevicesProxy *DeviceManager::devicesProxy() const +{ + return m_devicesProxy; +} + +DeviceClasses *DeviceManager::deviceClasses() const +{ + return m_deviceClasses; +} + +DeviceClassesProxy *DeviceManager::deviceClassesProxy() const +{ + return m_deviceClassesProxy; +} + + diff --git a/backend/devicemanager.h b/backend/devicemanager.h new file mode 100644 index 00000000..f012dedb --- /dev/null +++ b/backend/devicemanager.h @@ -0,0 +1,71 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DEVICEMANAGER_H +#define DEVICEMANAGER_H + +#include + +#include "types/vendors.h" +#include "types/vendorsproxy.h" +#include "types/devices.h" +#include "types/devicesproxy.h" +#include "types/deviceclasses.h" +#include "types/deviceclassesproxy.h" +#include "types/plugins.h" +#include "types/pluginsproxy.h" + +class DeviceManager : public QObject +{ + Q_OBJECT + Q_PROPERTY(Vendors *vendors READ vendors CONSTANT) + Q_PROPERTY(VendorsProxy *vendorsProxy READ vendorsProxy CONSTANT) + Q_PROPERTY(Plugins *plugins READ plugins CONSTANT) + Q_PROPERTY(PluginsProxy *pluginsProxy READ pluginsProxy CONSTANT) + Q_PROPERTY(Devices *devices READ devices CONSTANT) + Q_PROPERTY(DevicesProxy *devicesProxy READ devicesProxy CONSTANT) + Q_PROPERTY(DeviceClasses *deviceClasses READ deviceClasses CONSTANT) + Q_PROPERTY(DeviceClassesProxy *deviceClassesProxy READ deviceClassesProxy CONSTANT) + +public: + explicit DeviceManager(QObject *parent = 0); + + Vendors *vendors() const; + VendorsProxy *vendorsProxy() const; + Plugins *plugins() const; + PluginsProxy *pluginsProxy() const; + Devices *devices() const; + DevicesProxy *devicesProxy() const; + DeviceClasses *deviceClasses() const; + DeviceClassesProxy *deviceClassesProxy() const; + +private: + Vendors *m_vendors; + VendorsProxy *m_vendorsProxy; + Plugins *m_plugins; + PluginsProxy *m_pluginsProxy; + Devices *m_devices; + DevicesProxy *m_devicesProxy; + DeviceClasses *m_deviceClasses; + DeviceClassesProxy *m_deviceClassesProxy; + +}; + +#endif // DEVICEMANAGER_H diff --git a/backend/engine.cpp b/backend/engine.cpp new file mode 100644 index 00000000..cc5e0d05 --- /dev/null +++ b/backend/engine.cpp @@ -0,0 +1,100 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "engine.h" + +Engine* Engine::s_instance = 0; + +Engine *Engine::instance() +{ + if (!s_instance) + s_instance = new Engine(); + + return s_instance; +} + +QObject *Engine::qmlInstance(QQmlEngine *qmlEngine, QJSEngine *jsEngine) +{ + Q_UNUSED(qmlEngine) + Q_UNUSED(jsEngine) + + return Engine::instance(); +} + +bool Engine::connected() const +{ + return m_connected; +} + +DeviceManager *Engine::deviceManager() +{ + return m_deviceManager; +} + +JsonRpcClient *Engine::jsonRpcClient() +{ + return m_jsonRpcClient; +} + +WebsocketInterface *Engine::interface() +{ + return m_interface; +} + +void Engine::connectGuh() +{ + m_interface->setUrl("ws://loop.local:4444"); + m_interface->enable(); +} + +Engine::Engine(QObject *parent) : + QObject(parent), + m_connected(false), + m_deviceManager(new DeviceManager(this)), + m_jsonRpcClient(new JsonRpcClient(this)), + m_interface(new WebsocketInterface(this)) +{ + connect(m_interface, &WebsocketInterface::connectedChanged, this, &Engine::onConnectedChanged); + connect(m_interface, &WebsocketInterface::dataReady, m_jsonRpcClient, &JsonRpcClient::dataReceived); + +} + +void Engine::setConnected(const bool &connected) +{ + if (m_connected != connected) { + m_connected = connected; + emit connectedChanged(m_connected); + } +} + +void Engine::onConnectedChanged(const bool &connected) +{ + setConnected(connected); + + // delete all data + if (!connected) { + deviceManager()->devices()->clearModel(); + deviceManager()->deviceClasses()->clearModel(); + deviceManager()->vendors()->clearModel(); + deviceManager()->plugins()->clearModel(); + } else { + Engine::instance()->jsonRpcClient()->getVendors(); + } +} diff --git a/backend/engine.h b/backend/engine.h new file mode 100644 index 00000000..9b266790 --- /dev/null +++ b/backend/engine.h @@ -0,0 +1,74 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef ENGINE_H +#define ENGINE_H + +#include +#include +#include + +#include "devicemanager.h" +#include "websocketinterface.h" +#include "jsonrpc/jsonrpcclient.h" + +class Engine : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) + Q_PROPERTY(DeviceManager *deviceManager READ deviceManager CONSTANT) + Q_PROPERTY(JsonRpcClient *jsonRpcClient READ jsonRpcClient CONSTANT) + Q_PROPERTY(WebsocketInterface *interface READ interface CONSTANT) + +public: + static Engine *instance(); + static QObject *qmlInstance(QQmlEngine *qmlEngine, QJSEngine *jsEngine); + + bool connected() const; + + DeviceManager *deviceManager(); + JsonRpcClient *jsonRpcClient(); + WebsocketInterface *interface(); + + Q_INVOKABLE void connectGuh(); + +private: + explicit Engine(QObject *parent = 0); + static Engine *s_instance; + + bool m_connected; + + DeviceManager *m_deviceManager; + JsonRpcClient *m_jsonRpcClient; + WebsocketInterface *m_interface; + + void setConnected(const bool &connected); + +signals: + void connectedChanged(const bool &connected); + +private slots: + void onConnectedChanged(const bool &connected); + +public slots: + +}; + +#endif // ENGINE_H diff --git a/backend/guhinterface.cpp b/backend/guhinterface.cpp new file mode 100644 index 00000000..e49c92ae --- /dev/null +++ b/backend/guhinterface.cpp @@ -0,0 +1,41 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "guhinterface.h" + +GuhInterface::GuhInterface(QObject *parent) : + QObject(parent), + m_connected(false) +{ + +} + +bool GuhInterface::connected() +{ + return m_connected; +} + +void GuhInterface::setConnected(const bool &connected) +{ + if (m_connected != connected) { + m_connected = connected; + emit connectedChanged(connected); + } +} diff --git a/backend/guhinterface.h b/backend/guhinterface.h new file mode 100644 index 00000000..f7616708 --- /dev/null +++ b/backend/guhinterface.h @@ -0,0 +1,53 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef GUHINTERFACE_H +#define GUHINTERFACE_H + +#include + +class GuhInterface : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged) + +public: + explicit GuhInterface(QObject *parent = 0); + + bool connected(); + + virtual void sendData(const QByteArray &data) = 0; + virtual void sendRequest(const QVariantMap &request) = 0; + +protected: + bool m_connected; + void setConnected(const bool &connected); + +signals: + void dataReady(const QVariantMap &data); + void connectedChanged(const bool &connected); + +public slots: + virtual void enable() { } + virtual void disable() { } + +}; + +#endif // GUHINTERFACE_H diff --git a/backend/jsonrpc/actionhandler.cpp b/backend/jsonrpc/actionhandler.cpp new file mode 100644 index 00000000..a5615e82 --- /dev/null +++ b/backend/jsonrpc/actionhandler.cpp @@ -0,0 +1,40 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "actionhandler.h" + +#include + +ActionHandler::ActionHandler(QObject *parent) : + JsonHandler(parent) +{ +} + +QString ActionHandler::nameSpace() const +{ + return "Actions"; +} + +void ActionHandler::processExecuteAction(const QVariantMap ¶ms) +{ + // response handled in the ui + Q_UNUSED(params); +} + diff --git a/backend/jsonrpc/actionhandler.h b/backend/jsonrpc/actionhandler.h new file mode 100644 index 00000000..755113c0 --- /dev/null +++ b/backend/jsonrpc/actionhandler.h @@ -0,0 +1,40 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef ACTIONHANDLER_H +#define ACTIONHANDLER_H + +#include + +#include "jsonhandler.h" + +class ActionHandler : public JsonHandler +{ + Q_OBJECT +public: + explicit ActionHandler(QObject *parent = 0); + + QString nameSpace() const; + + Q_INVOKABLE void processExecuteAction(const QVariantMap ¶ms); + +}; + +#endif // ACTIONHANDLER_H diff --git a/backend/jsonrpc/configurationhandler.cpp b/backend/jsonrpc/configurationhandler.cpp new file mode 100644 index 00000000..3c95b2c4 --- /dev/null +++ b/backend/jsonrpc/configurationhandler.cpp @@ -0,0 +1,12 @@ +#include "configurationhandler.h" + +ConfigurationHandler::ConfigurationHandler(QObject *parent) : + JsonHandler(parent) +{ + +} + +QString ConfigurationHandler::nameSpace() const +{ + return "Configuration"; +} diff --git a/backend/jsonrpc/configurationhandler.h b/backend/jsonrpc/configurationhandler.h new file mode 100644 index 00000000..2b6f2a11 --- /dev/null +++ b/backend/jsonrpc/configurationhandler.h @@ -0,0 +1,21 @@ +#ifndef CONFIGURATIONHANDLER_H +#define CONFIGURATIONHANDLER_H + +#include + +#include "jsonhandler.h" + +class ConfigurationHandler : public JsonHandler +{ + Q_OBJECT +public: + explicit ConfigurationHandler(QObject *parent = 0); + + QString nameSpace() const; + +signals: + +public slots: +}; + +#endif // CONFIGURATIONHANDLER_H diff --git a/backend/jsonrpc/devicehandler.cpp b/backend/jsonrpc/devicehandler.cpp new file mode 100644 index 00000000..a07eaa7a --- /dev/null +++ b/backend/jsonrpc/devicehandler.cpp @@ -0,0 +1,166 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "devicehandler.h" +#include "jsontypes.h" +#include "engine.h" +#include "types/states.h" +#include "types/deviceclass.h" + +DeviceHandler::DeviceHandler(QObject *parent) : + JsonHandler(parent) +{ + +} + +QString DeviceHandler::nameSpace() const +{ + return QString("Devices"); +} + +void DeviceHandler::processGetSupportedVendors(const QVariantMap ¶ms) +{ + if (params.value("params").toMap().keys().contains("vendors")) { + QVariantList vendorList = params.value("params").toMap().value("vendors").toList(); + foreach (QVariant vendorVariant, vendorList) { + Vendor *vendor = JsonTypes::unpackVendor(vendorVariant.toMap(), Engine::instance()->deviceManager()->vendors()); + Engine::instance()->deviceManager()->vendors()->addVendor(vendor); + } + } + Engine::instance()->jsonRpcClient()->getDeviceClasses(); +} + +void DeviceHandler::processGetPlugins(const QVariantMap ¶ms) +{ + if (params.value("params").toMap().keys().contains("plugins")) { + QVariantList pluginList = params.value("params").toMap().value("plugins").toList(); + foreach (QVariant pluginVariant, pluginList) { + Plugin *plugin = JsonTypes::unpackPlugin(pluginVariant.toMap(), Engine::instance()->deviceManager()->plugins()); + Engine::instance()->deviceManager()->plugins()->addPlugin(plugin); + } + } + Engine::instance()->jsonRpcClient()->getDevices(); + +} + +void DeviceHandler::processGetSupportedDevices(const QVariantMap ¶ms) +{ + if (params.value("params").toMap().keys().contains("deviceClasses")) { + QVariantList deviceClassList = params.value("params").toMap().value("deviceClasses").toList(); + foreach (QVariant deviceClassVariant, deviceClassList) { + DeviceClass *deviceClass = JsonTypes::unpackDeviceClass(deviceClassVariant.toMap(), Engine::instance()->deviceManager()->deviceClasses()); + Engine::instance()->deviceManager()->deviceClasses()->addDeviceClass(deviceClass); + } + } + Engine::instance()->jsonRpcClient()->getPlugins(); +} + +void DeviceHandler::processGetConfiguredDevices(const QVariantMap ¶ms) +{ + if (params.value("params").toMap().keys().contains("devices")) { + QVariantList deviceList = params.value("params").toMap().value("devices").toList(); + foreach (QVariant deviceVariant, deviceList) { + Device *device = JsonTypes::unpackDevice(deviceVariant.toMap(), Engine::instance()->deviceManager()->devices()); + Engine::instance()->deviceManager()->devices()->addDevice(device); + + //qDebug() << QJsonDocument::fromVariant(deviceVariant).toJson(); + + // set initial state values + QVariantList stateVariantList = deviceVariant.toMap().value("states").toList(); + foreach (const QVariant &stateMap, stateVariantList) { + QUuid stateTypeId = stateMap.toMap().value("stateTypeId").toUuid(); + QVariant value = stateMap.toMap().value("value"); + + foreach (Device *d, Engine::instance()->deviceManager()->devices()->devices()) { + if (d->hasState(stateTypeId)) { + d->setStateValue(stateTypeId, value); + } + } + } + } + } +} + +void DeviceHandler::processRemoveConfiguredDevice(const QVariantMap ¶ms) +{ + // response handled in the ui + Q_UNUSED(params); +} + +void DeviceHandler::processAddConfiguredDevice(const QVariantMap ¶ms) +{ + // response handled in the ui + Q_UNUSED(params); +} + +void DeviceHandler::processGetDiscoveredDevices(const QVariantMap ¶ms) +{ + // response handled in the ui + Q_UNUSED(params); +} + +void DeviceHandler::processPairDevice(const QVariantMap ¶ms) +{ + // response handled in the ui + Q_UNUSED(params); +} + +void DeviceHandler::processConfirmPairing(const QVariantMap ¶ms) +{ + // response handled in the ui + Q_UNUSED(params); +} + +void DeviceHandler::processDeviceRemoved(const QVariantMap ¶ms) +{ + QUuid deviceId = params.value("params").toMap().value("deviceId").toUuid(); + qDebug() << "JsonRpc: Notification: Device removed" << deviceId.toString(); + Device *device = Engine::instance()->deviceManager()->devices()->getDevice(deviceId); + Engine::instance()->deviceManager()->devices()->removeDevice(device); + device->deleteLater(); +} + +void DeviceHandler::processDeviceAdded(const QVariantMap ¶ms) +{ + if (params.value("params").toMap().keys().contains("device")) { + QVariantMap deviceVariant = params.value("params").toMap().value("device").toMap(); + Device *device = JsonTypes::unpackDevice(deviceVariant, Engine::instance()->deviceManager()->devices()); + qDebug() << "JsonRpc: Notification: Device added" << device->id().toString(); + Engine::instance()->deviceManager()->devices()->addDevice(device); + } +} + +void DeviceHandler::processStateChanged(const QVariantMap ¶ms) +{ + QVariantMap notification = params.value("params").toMap(); + QUuid deviceId = notification.value("deviceId").toUuid(); + + Device *device = Engine::instance()->deviceManager()->devices()->getDevice(deviceId); + + if (!device) { + qWarning() << "JsonRpc: ERROR: could not find device for state changed notification"; + return; + } + + QUuid stateTypeId = notification.value("stateTypeId").toUuid(); + QVariant value = notification.value("value"); + + device->setStateValue(stateTypeId, value); +} diff --git a/backend/jsonrpc/devicehandler.h b/backend/jsonrpc/devicehandler.h new file mode 100644 index 00000000..4e823296 --- /dev/null +++ b/backend/jsonrpc/devicehandler.h @@ -0,0 +1,56 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DEVICEHANDLER_H +#define DEVICEHANDLER_H + +#include + +#include "jsonhandler.h" + +class DeviceHandler : public JsonHandler +{ + Q_OBJECT +public: + explicit DeviceHandler(QObject *parent = 0); + + QString nameSpace() const; + + // Get methods internal + Q_INVOKABLE void processGetSupportedVendors(const QVariantMap ¶ms); + Q_INVOKABLE void processGetPlugins(const QVariantMap ¶ms); + Q_INVOKABLE void processGetSupportedDevices(const QVariantMap ¶ms); + Q_INVOKABLE void processGetConfiguredDevices(const QVariantMap ¶ms); + + // Methods ui + Q_INVOKABLE void processRemoveConfiguredDevice(const QVariantMap ¶ms); + Q_INVOKABLE void processAddConfiguredDevice(const QVariantMap ¶ms); + Q_INVOKABLE void processGetDiscoveredDevices(const QVariantMap ¶ms); + Q_INVOKABLE void processPairDevice(const QVariantMap ¶ms); + Q_INVOKABLE void processConfirmPairing(const QVariantMap ¶ms); + + // Notifications + Q_INVOKABLE void processDeviceRemoved(const QVariantMap ¶ms); + Q_INVOKABLE void processDeviceAdded(const QVariantMap ¶ms); + Q_INVOKABLE void processStateChanged(const QVariantMap ¶ms); + +}; + +#endif // DEVICEHANDLER_H diff --git a/backend/jsonrpc/eventhandler.cpp b/backend/jsonrpc/eventhandler.cpp new file mode 100644 index 00000000..b3e6b101 --- /dev/null +++ b/backend/jsonrpc/eventhandler.cpp @@ -0,0 +1,38 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "eventhandler.h" + +EventHandler::EventHandler(QObject *parent) : + JsonHandler(parent) +{ + +} + +QString EventHandler::nameSpace() const +{ + return "Events"; +} + +void EventHandler::processEventTriggered(const QVariantMap ¶ms) +{ + Q_UNUSED(params); +} + diff --git a/backend/jsonrpc/eventhandler.h b/backend/jsonrpc/eventhandler.h new file mode 100644 index 00000000..f3c2c49c --- /dev/null +++ b/backend/jsonrpc/eventhandler.h @@ -0,0 +1,40 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef EVENTHANDLER_H +#define EVENTHANDLER_H + +#include + +#include "jsonhandler.h" + +class EventHandler : public JsonHandler +{ + Q_OBJECT +public: + explicit EventHandler(QObject *parent = 0); + + QString nameSpace() const; + + Q_INVOKABLE void processEventTriggered(const QVariantMap ¶ms); + +}; + +#endif // EVENTHANDLER_H diff --git a/backend/jsonrpc/jsonhandler.cpp b/backend/jsonrpc/jsonhandler.cpp new file mode 100644 index 00000000..98094494 --- /dev/null +++ b/backend/jsonrpc/jsonhandler.cpp @@ -0,0 +1,26 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "jsonhandler.h" + +JsonHandler::JsonHandler(QObject *parent) : + QObject(parent) +{ +} diff --git a/backend/jsonrpc/jsonhandler.h b/backend/jsonrpc/jsonhandler.h new file mode 100644 index 00000000..00503637 --- /dev/null +++ b/backend/jsonrpc/jsonhandler.h @@ -0,0 +1,35 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef JSONHANDLER_H +#define JSONHANDLER_H + +#include +#include + +class JsonHandler : public QObject +{ + Q_OBJECT +public: + JsonHandler(QObject *parent = 0); + virtual QString nameSpace() const = 0; +}; + +#endif // JSONHANDLER_H diff --git a/backend/jsonrpc/jsonrpcclient.cpp b/backend/jsonrpc/jsonrpcclient.cpp new file mode 100644 index 00000000..83c248bf --- /dev/null +++ b/backend/jsonrpc/jsonrpcclient.cpp @@ -0,0 +1,249 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "jsonrpcclient.h" +#include "engine.h" +#include "types/param.h" +#include "types/params.h" + +#include +#include +#include + +JsonRpcClient::JsonRpcClient(QObject *parent) : + QObject(parent), + m_id(0) +{ + m_deviceHandler = new DeviceHandler(this); + m_actionHandler = new ActionHandler(this); + m_eventHandler = new EventHandler(this); + m_loggingHandler = new LoggingHandler(this); + m_networkManagerHandler = new NetworkManagerHandler(this); + + m_handlers.insert(m_deviceHandler->nameSpace(), m_deviceHandler); + m_handlers.insert(m_actionHandler->nameSpace(), m_actionHandler); + m_handlers.insert(m_eventHandler->nameSpace(), m_eventHandler); + m_handlers.insert(m_loggingHandler->nameSpace(), m_loggingHandler); + m_handlers.insert(m_networkManagerHandler->nameSpace(), m_networkManagerHandler); +} + +void JsonRpcClient::getVendors() +{ + qDebug() << "JsonRpc: get vendors"; + JsonRpcReply *reply = createReply("Devices", "GetSupportedVendors"); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); +} + +void JsonRpcClient::getPlugins() +{ + qDebug() << "JsonRpc: get plugins"; + JsonRpcReply *reply = createReply("Devices", "GetPlugins"); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); +} + +void JsonRpcClient::getDevices() +{ + qDebug() << "JsonRpc: get devices"; + JsonRpcReply *reply = createReply("Devices", "GetConfiguredDevices"); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); +} + +void JsonRpcClient::getDeviceClasses() +{ + qDebug() << "JsonRpc: get device classes"; + JsonRpcReply *reply = createReply("Devices", "GetSupportedDevices"); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); +} + +int JsonRpcClient::addDevice(const QUuid &deviceClassId, const QVariantList &deviceParams) +{ + qDebug() << "JsonRpc: add device " << deviceClassId.toString(); + QVariantMap params; + params.insert("deviceClassId", deviceClassId.toString()); + params.insert("deviceParams", deviceParams); + JsonRpcReply *reply = createReply("Devices", "AddConfiguredDevice", params); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); + return reply->commandId(); +} + +int JsonRpcClient::addDiscoveredDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId) +{ + qDebug() << "JsonRpc: add discovered device " << deviceClassId.toString(); + QVariantMap params; + params.insert("deviceClassId", deviceClassId.toString()); + params.insert("deviceDescriptorId", deviceDescriptorId.toString()); + JsonRpcReply *reply = createReply("Devices", "AddConfiguredDevice", params); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); + return reply->commandId(); +} + +int JsonRpcClient::pairDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId) +{ + qDebug() << "JsonRpc: pair device " << deviceClassId.toString(); + QVariantMap params; + params.insert("name", "name"); + params.insert("deviceClassId", deviceClassId.toString()); + params.insert("deviceDescriptorId", deviceDescriptorId.toString()); + JsonRpcReply *reply = createReply("Devices", "PairDevice", params); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); + return reply->commandId(); +} + +int JsonRpcClient::confirmPairing(const QUuid &pairingTransactionId, const QString &secret) +{ + qDebug() << "JsonRpc: confirm pairing" << pairingTransactionId.toString(); + QVariantMap params; + params.insert("pairingTransactionId", pairingTransactionId.toString()); + params.insert("secret", secret); + JsonRpcReply *reply = createReply("Devices", "ConfirmPairing", params); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); + return reply->commandId(); +} + +int JsonRpcClient::removeDevice(const QUuid &deviceId) +{ + qDebug() << "JsonRpc: delete device" << deviceId.toString(); + QVariantMap params; + params.insert("deviceId", deviceId.toString()); + JsonRpcReply *reply = createReply("Devices", "RemoveConfiguredDevice", params); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); + return reply->commandId(); +} + +int JsonRpcClient::discoverDevices(const QUuid &deviceClassId, const QVariantList &discoveryParams) +{ + qDebug() << "JsonRpc: discover devices " << deviceClassId.toString(); + QVariantMap params; + params.insert("deviceClassId", deviceClassId.toString()); + if (!discoveryParams.isEmpty()) { + params.insert("discoveryParams", discoveryParams); + } + + JsonRpcReply *reply = createReply("Devices", "GetDiscoveredDevices", params); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); + return reply->commandId(); +} + +int JsonRpcClient::executeAction(const QUuid &deviceId, const QUuid &actionTypeId, const QVariantList ¶ms) +{ + qDebug() << "JsonRpc: execute action " << deviceId.toString() << actionTypeId.toString() << params; + QVariantMap p; + p.insert("deviceId", deviceId.toString()); + p.insert("actionTypeId", actionTypeId.toString()); + if (!params.isEmpty()) { + p.insert("params", params); + } + + JsonRpcReply *reply = createReply("Actions", "ExecuteAction", p); + m_replies.insert(reply->commandId(), reply); + Engine::instance()->interface()->sendRequest(reply->requestMap()); + return reply->commandId(); +} + +JsonRpcReply *JsonRpcClient::createReply(QString nameSpace, QString method, QVariantMap params) +{ + m_id++; + return new JsonRpcReply(m_id, nameSpace, method, params, this); +} + +void JsonRpcClient::dataReceived(const QVariantMap &data) +{ + int commandId = data.value("id").toInt(); + JsonRpcReply *reply = m_replies.take(commandId); + + // check if this is a reply to a request + if (reply) { + qDebug() << "JsonRpc: got response for" << QString("%1.%2").arg(reply->nameSpace(), reply->method()); + JsonHandler *handler = m_handlers.value(reply->nameSpace()); + + if (!QMetaObject::invokeMethod(handler, QString("process" + reply->method()).toLatin1().data(), Q_ARG(QVariantMap, data))) + qWarning() << "JsonRpc: method not implemented:" << reply->method(); + + emit responseReceived(reply->commandId(), data.value("params").toMap()); + return; + } + + // check if this is a notification + if (data.contains("notification")) { + QStringList notification = data.value("notification").toString().split("."); + QString nameSpace = notification.first(); + QString method = notification.last(); + JsonHandler *handler = m_handlers.value(nameSpace); + + if (!handler) { + qWarning() << "JsonRpc: handler not implemented:" << nameSpace; + return; + } + + if (!QMetaObject::invokeMethod(handler, QString("process" + method).toLatin1().data(), Q_ARG(QVariantMap, data))) + qWarning() << "method not implemented"; + + } +} + +JsonRpcReply::JsonRpcReply(int commandId, QString nameSpace, QString method, QVariantMap params, QObject *parent): + QObject(parent), + m_commandId(commandId), + m_nameSpace(nameSpace), + m_method(method), + m_params(params) +{ +} + +int JsonRpcReply::commandId() const +{ + return m_commandId; +} + +QString JsonRpcReply::nameSpace() const +{ + return m_nameSpace; +} + +QString JsonRpcReply::method() const +{ + return m_method; +} + +QVariantMap JsonRpcReply::params() const +{ + return m_params; +} + +QVariantMap JsonRpcReply::requestMap() +{ + QVariantMap request; + request.insert("id", m_commandId); + request.insert("method", m_nameSpace + "." + m_method); + if (!m_params.isEmpty()) + request.insert("params", m_params); + + return request; +} diff --git a/backend/jsonrpc/jsonrpcclient.h b/backend/jsonrpc/jsonrpcclient.h new file mode 100644 index 00000000..6c35416c --- /dev/null +++ b/backend/jsonrpc/jsonrpcclient.h @@ -0,0 +1,101 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef JSONRPCCLIENT_H +#define JSONRPCCLIENT_H + +#include +#include + +#include "devicehandler.h" +#include "actionhandler.h" +#include "eventhandler.h" +#include "logginghandler.h" +#include "networkmanagerhandler.h" + +class JsonRpcReply; +class JsonHandler; +class Param; +class Params; + +class JsonRpcClient : public QObject +{ + Q_OBJECT +public: + explicit JsonRpcClient(QObject *parent = 0); + + // internal + void getVendors(); + void getPlugins(); + void getDevices(); + void getDeviceClasses(); + + // ui methods + Q_INVOKABLE int addDevice(const QUuid &deviceClassId, const QVariantList &deviceParams); + Q_INVOKABLE int addDiscoveredDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId); + Q_INVOKABLE int pairDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId); + Q_INVOKABLE int confirmPairing(const QUuid &pairingTransactionId, const QString &secret = QString()); + Q_INVOKABLE int removeDevice(const QUuid &deviceId); + Q_INVOKABLE int discoverDevices(const QUuid &deviceClassId, const QVariantList &discoveryParams = QVariantList()); + Q_INVOKABLE int executeAction(const QUuid &deviceId, const QUuid &actionTypeId, const QVariantList ¶ms = QVariantList()); + +private: + int m_id; + QHash m_handlers; + QHash m_replies; + + DeviceHandler *m_deviceHandler; + ActionHandler *m_actionHandler; + EventHandler *m_eventHandler; + LoggingHandler *m_loggingHandler; + NetworkManagerHandler *m_networkManagerHandler; + + JsonRpcReply *createReply(QString nameSpace, QString method, QVariantMap params = QVariantMap()); + +signals: + void responseReceived(const int &commandId, const QVariantMap &response); + +public slots: + void dataReceived(const QVariantMap &data); + +}; + + +class JsonRpcReply : public QObject +{ + Q_OBJECT +public: + explicit JsonRpcReply(int commandId, QString nameSpace, QString method, QVariantMap params = QVariantMap(), QObject *parent = 0); + + int commandId() const; + QString nameSpace() const; + QString method() const; + QVariantMap params() const; + QVariantMap requestMap(); + +private: + int m_commandId; + QString m_nameSpace; + QString m_method; + QVariantMap m_params; +}; + + +#endif // JSONRPCCLIENT_H diff --git a/backend/jsonrpc/jsontypes.cpp b/backend/jsonrpc/jsontypes.cpp new file mode 100644 index 00000000..0839d23c --- /dev/null +++ b/backend/jsonrpc/jsontypes.cpp @@ -0,0 +1,315 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "jsontypes.h" +#include "engine.h" +#include "types/vendors.h" +#include "types/deviceclasses.h" +#include "types/params.h" +#include "types/paramtypes.h" + +#include + +JsonTypes::JsonTypes(QObject *parent) : + QObject(parent) +{ +} + +Vendor *JsonTypes::unpackVendor(const QVariantMap &vendorMap, QObject *parent) +{ + return new Vendor(vendorMap.value("id").toUuid(), vendorMap.value("name").toString(), parent); +} + +Plugin *JsonTypes::unpackPlugin(const QVariantMap &pluginMap, QObject *parent) +{ + Plugin *plugin = new Plugin(parent); + plugin->setName(pluginMap.value("name").toString()); + plugin->setPluginId(pluginMap.value("id").toUuid()); + ParamTypes *paramTypes = new ParamTypes(plugin); + foreach (QVariant paramType, pluginMap.value("paramTypes").toList()) { + paramTypes->addParamType(JsonTypes::unpackParamType(paramType.toMap(), paramTypes)); + } + plugin->setParamTypes(paramTypes); + return plugin; +} + +DeviceClass *JsonTypes::unpackDeviceClass(const QVariantMap &deviceClassMap, QObject *parent) +{ + DeviceClass *deviceClass = new DeviceClass(parent); + deviceClass->setName(deviceClassMap.value("name").toString()); + deviceClass->setId(deviceClassMap.value("id").toUuid()); + deviceClass->setVendorId(deviceClassMap.value("vendorId").toUuid()); + QVariantList createMethodsList = deviceClassMap.value("createMethods").toList(); + QStringList createMethods; + foreach (QVariant method, createMethodsList) { + createMethods.append(method.toString()); + } + deviceClass->setCreateMethods(createMethods); + deviceClass->setSetupMethod(stringToSetupMethod(deviceClassMap.value("setupMethod").toString())); + + // ParamTypes + ParamTypes *paramTypes = new ParamTypes(deviceClass); + foreach (QVariant paramType, deviceClassMap.value("paramTypes").toList()) { + paramTypes->addParamType(JsonTypes::unpackParamType(paramType.toMap(), paramTypes)); + } + deviceClass->setParamTypes(paramTypes); + + // discovery ParamTypes + ParamTypes *discoveryParamTypes = new ParamTypes(deviceClass); + foreach (QVariant paramType, deviceClassMap.value("discoveryParamTypes").toList()) { + discoveryParamTypes->addParamType(JsonTypes::unpackParamType(paramType.toMap(), discoveryParamTypes)); + } + deviceClass->setDiscoveryParamTypes(discoveryParamTypes); + + // StateTypes + StateTypes *stateTypes = new StateTypes(deviceClass); + foreach (QVariant stateType, deviceClassMap.value("stateTypes").toList()) { + stateTypes->addStateType(JsonTypes::unpackStateType(stateType.toMap(), stateTypes)); + } + deviceClass->setStateTypes(stateTypes); + + // EventTypes + EventTypes *eventTypes = new EventTypes(deviceClass); + foreach (QVariant eventType, deviceClassMap.value("eventTypes").toList()) { + eventTypes->addEventType(JsonTypes::unpackEventType(eventType.toMap(), eventTypes)); + } + deviceClass->setEventTypes(eventTypes); + + // ActionTypes + ActionTypes *actionTypes = new ActionTypes(deviceClass); + foreach (QVariant actionType, deviceClassMap.value("actionTypes").toList()) { + actionTypes->addActionType(JsonTypes::unpackActionType(actionType.toMap(), actionTypes)); + } + deviceClass->setActionTypes(actionTypes); + + return deviceClass; +} + +Param *JsonTypes::unpackParam(const QVariantMap ¶mMap, QObject *parent) +{ + return new Param(paramMap.value("name").toString(), paramMap.value("value"), parent); +} + +ParamType *JsonTypes::unpackParamType(const QVariantMap ¶mTypeMap, QObject *parent) +{ + ParamType *paramType = new ParamType(parent); + paramType->setName(paramTypeMap.value("name").toString()); + paramType->setType(paramTypeMap.value("type").toString()); + paramType->setIndex(paramTypeMap.value("index").toInt()); + paramType->setDefaultValue(paramTypeMap.value("defaultValue")); + paramType->setMinValue(paramTypeMap.value("minValue")); + paramType->setMaxValue(paramTypeMap.value("maxValue")); + paramType->setAllowedValues(paramTypeMap.value("allowedValues").toList()); + paramType->setInputType(stringToInputType(paramTypeMap.value("inputType").toString())); + paramType->setReadOnly(paramTypeMap.value("readOnly").toBool()); + QPair unit = stringToUnit(paramTypeMap.value("unit").toString()); + paramType->setUnit(unit.first); + paramType->setUnitString(unit.second); + return paramType; +} + +StateType *JsonTypes::unpackStateType(const QVariantMap &stateTypeMap, QObject *parent) +{ + StateType *stateType = new StateType(parent); + stateType->setId(stateTypeMap.value("id").toUuid()); + stateType->setName(stateTypeMap.value("name").toString()); + stateType->setIndex(stateTypeMap.value("index").toInt()); + stateType->setDefaultValue(stateTypeMap.value("defaultValue")); + stateType->setType(stateTypeMap.value("type").toString()); + QPair unit = stringToUnit(stateTypeMap.value("unit").toString()); + stateType->setUnit(unit.first); + stateType->setUnitString(unit.second); + return stateType; +} + +EventType *JsonTypes::unpackEventType(const QVariantMap &eventTypeMap, QObject *parent) +{ + EventType *eventType = new EventType(parent); + eventType->setId(eventTypeMap.value("id").toUuid()); + eventType->setName(eventTypeMap.value("name").toString()); + eventType->setIndex(eventTypeMap.value("index").toInt()); + ParamTypes *paramTypes = new ParamTypes(eventType); + foreach (QVariant paramType, eventTypeMap.value("paramTypes").toList()) { + paramTypes->addParamType(JsonTypes::unpackParamType(paramType.toMap(), paramTypes)); + } + eventType->setParamTypes(paramTypes); + return eventType; +} + +ActionType *JsonTypes::unpackActionType(const QVariantMap &actionTypeMap, QObject *parent) +{ + ActionType *actionType = new ActionType(parent); + actionType->setId(actionTypeMap.value("id").toUuid()); + actionType->setName(actionTypeMap.value("name").toString()); + actionType->setIndex(actionTypeMap.value("index").toInt()); + ParamTypes *paramTypes = new ParamTypes(actionType); + foreach (QVariant paramType, actionTypeMap.value("paramTypes").toList()) { + paramTypes->addParamType(JsonTypes::unpackParamType(paramType.toMap(), paramTypes)); + } + actionType->setParamTypes(paramTypes); + return actionType; +} + +Device *JsonTypes::unpackDevice(const QVariantMap &deviceMap, QObject *parent) +{ + Device *device = new Device(parent); + device->setDeviceName(deviceMap.value("name").toString()); + device->setId(deviceMap.value("id").toUuid()); + device->setDeviceClassId(deviceMap.value("deviceClassId").toUuid()); + device->setSetupComplete(deviceMap.value("setupComplete").toBool()); + + Params *params = new Params(device); + foreach (QVariant param, deviceMap.value("params").toList()) { + params->addParam(JsonTypes::unpackParam(param.toMap(), params)); + } + device->setParams(params); + + DeviceClass *deviceClass = Engine::instance()->deviceManager()->deviceClasses()->getDeviceClass(device->deviceClassId()); + States *states = new States(device); + foreach (StateType *stateType, deviceClass->stateTypes()->stateTypes()) { + State *state = new State(device->id(), stateType->id(), stateType->defaultValue(), states); + states->addState(state); + } + device->setStates(states); + + return device; +} + +DeviceClass::SetupMethod JsonTypes::stringToSetupMethod(const QString &setupMethodString) +{ + if (setupMethodString == "SetupMethodJustAdd") { + return DeviceClass::SetupMethodJustAdd; + } else if (setupMethodString == "SetupMethodDisplayPin") { + return DeviceClass::SetupMethodDisplayPin; + } else if (setupMethodString == "SetupMethodEnterPin") { + return DeviceClass::SetupMethodEnterPin; + } else if (setupMethodString == "SetupMethodPushButton") { + return DeviceClass::SetupMethodPushButton; + } + return DeviceClass::SetupMethodJustAdd; +} + +QPair JsonTypes::stringToUnit(const QString &unitString) +{ + if (unitString == "UnitNone") { + return QPair(Types::UnitNone, "-"); + } else if (unitString == "UnitSeconds") { + return QPair(Types::UnitSeconds, "s"); + } else if (unitString == "UnitMinutes") { + return QPair(Types::UnitMinutes, "m"); + } else if (unitString == "UnitHours") { + return QPair(Types::UnitHours, "h"); + } else if (unitString == "UnitUnixTime") { + return QPair(Types::UnitUnixTime, ""); + } else if (unitString == "UnitMeterPerSecond") { + return QPair(Types::UnitMeterPerSecond, "m/s"); + } else if (unitString == "UnitKiloMeterPerHour") { + return QPair(Types::UnitKiloMeterPerHour, "km/h"); + } else if (unitString == "UnitDegree") { + return QPair(Types::UnitDegree, "°"); + } else if (unitString == "UnitRadiant") { + return QPair(Types::UnitRadiant, "rad"); + } else if (unitString == "UnitDegreeCelsius") { + return QPair(Types::UnitDegreeCelsius, "°C"); + } else if (unitString == "UnitDegreeKelvin") { + return QPair(Types::UnitDegreeKelvin, "°K"); + } else if (unitString == "UnitMired") { + return QPair(Types::UnitMired, "mir"); + } else if (unitString == "UnitMilliBar") { + return QPair(Types::UnitMilliBar, "mbar"); + } else if (unitString == "UnitBar") { + return QPair(Types::UnitBar, "bar"); + } else if (unitString == "UnitPascal") { + return QPair(Types::UnitPascal, "Pa"); + } else if (unitString == "UnitHectoPascal") { + return QPair(Types::UnitHectoPascal, "hPa"); + } else if (unitString == "UnitAtmosphere") { + return QPair(Types::UnitAtmosphere, "atm"); + } else if (unitString == "UnitLumen") { + return QPair(Types::UnitLumen, "lm"); + } else if (unitString == "UnitLux") { + return QPair(Types::UnitLux, "lx"); + } else if (unitString == "UnitCandela") { + return QPair(Types::UnitCandela, "cd"); + } else if (unitString == "UnitMilliMeter") { + return QPair(Types::UnitMilliMeter, "mm"); + } else if (unitString == "UnitCentiMeter") { + return QPair(Types::UnitCentiMeter, "cm"); + } else if (unitString == "UnitMeter") { + return QPair(Types::UnitMeter, "m"); + } else if (unitString == "UnitKiloMeter") { + return QPair(Types::UnitKiloMeter, "km"); + } else if (unitString == "UnitGram") { + return QPair(Types::UnitGram, "g"); + } else if (unitString == "UnitKiloGram") { + return QPair(Types::UnitKiloGram, "kg"); + } else if (unitString == "UnitDezibel") { + return QPair(Types::UnitDezibel, "db"); + } else if (unitString == "UnitKiloByte") { + return QPair(Types::UnitKiloByte, "kB"); + } else if (unitString == "UnitMegaByte") { + return QPair(Types::UnitMegaByte, "MB"); + } else if (unitString == "UnitGigaByte") { + return QPair(Types::UnitGigaByte, "GB"); + } else if (unitString == "UnitTeraByte") { + return QPair(Types::UnitTeraByte, "TB"); + } else if (unitString == "UnitMilliWatt") { + return QPair(Types::UnitMilliWatt, "mW"); + } else if (unitString == "UnitWatt") { + return QPair(Types::UnitWatt, "W"); + } else if (unitString == "UnitKiloWatt") { + return QPair(Types::UnitKiloWatt, "kW"); + } else if (unitString == "UnitKiloWattHour") { + return QPair(Types::UnitKiloWattHour, "kWh"); + } else if (unitString == "UnitPercentage") { + return QPair(Types::UnitPercentage, "%"); + } else if (unitString == "UnitEuro") { + return QPair(Types::UnitEuro, "€"); + } else if (unitString == "UnitDollar") { + return QPair(Types::UnitDollar, "$"); + } + return QPair(Types::UnitNone, ""); +} + +Types::InputType JsonTypes::stringToInputType(const QString &inputTypeString) +{ + if (inputTypeString == "InputTypeNone") { + return Types::InputTypeNone; + } else if (inputTypeString == "InputTypeTextLine") { + return Types::InputTypeTextLine; + } else if (inputTypeString == "InputTypeTextArea") { + return Types::InputTypeTextArea; + } else if (inputTypeString == "InputTypePassword") { + return Types::InputTypePassword; + } else if (inputTypeString == "InputTypeSearch") { + return Types::InputTypeSearch; + } else if (inputTypeString == "InputTypeMail") { + return Types::InputTypeMail; + } else if (inputTypeString == "InputTypeIPv4Address") { + return Types::InputTypeIPv4Address; + } else if (inputTypeString == "InputTypeIPv6Address") { + return Types::InputTypeIPv6Address; + } else if (inputTypeString == "InputTypeUrl") { + return Types::InputTypeUrl; + } else if (inputTypeString == "InputTypeMacAddress") { + return Types::InputTypeMacAddress; + } + return Types::InputTypeNone; +} diff --git a/backend/jsonrpc/jsontypes.h b/backend/jsonrpc/jsontypes.h new file mode 100644 index 00000000..cb63216d --- /dev/null +++ b/backend/jsonrpc/jsontypes.h @@ -0,0 +1,64 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef JSONTYPES_H +#define JSONTYPES_H + +#include +#include +#include +#include + +#include "types/types.h" +#include "types/device.h" +#include "types/plugin.h" +#include "types/deviceclass.h" +#include "types/paramtype.h" +#include "types/statetype.h" +#include "types/state.h" +#include "types/eventtype.h" +#include "types/actiontype.h" + +class Vendor; + +class JsonTypes : public QObject +{ + Q_OBJECT +public: + explicit JsonTypes(QObject *parent = 0); + + static Vendor *unpackVendor(const QVariantMap &vendorMap, QObject *parent); + static Plugin *unpackPlugin(const QVariantMap &pluginMap, QObject *parent); + static DeviceClass *unpackDeviceClass(const QVariantMap &deviceClassMap, QObject *parent); + static Param *unpackParam(const QVariantMap ¶mMap, QObject *parent); + static ParamType *unpackParamType(const QVariantMap ¶mTypeMap, QObject *parent); + static StateType *unpackStateType(const QVariantMap &stateTypeMap, QObject *parent); + static EventType *unpackEventType(const QVariantMap &eventTypeMap, QObject *parent); + static ActionType *unpackActionType(const QVariantMap &actionTypeMap, QObject *parent); + static Device *unpackDevice(const QVariantMap &deviceMap, QObject *parent); + +private: + static DeviceClass::SetupMethod stringToSetupMethod(const QString &setupMethodString); + static QPair stringToUnit(const QString &unitString); + static Types::InputType stringToInputType(const QString &inputTypeString); + +}; + +#endif // JSONTYPES_H diff --git a/backend/jsonrpc/logginghandler.cpp b/backend/jsonrpc/logginghandler.cpp new file mode 100644 index 00000000..484b6e13 --- /dev/null +++ b/backend/jsonrpc/logginghandler.cpp @@ -0,0 +1,43 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "logginghandler.h" + +LoggingHandler::LoggingHandler(QObject *parent) : + JsonHandler(parent) +{ + +} + +QString LoggingHandler::nameSpace() const +{ + return "Logging"; +} + +void LoggingHandler::processLogEntryAdded(const QVariantMap ¶ms) +{ + Q_UNUSED(params); +} + +void LoggingHandler::processLogDatabaseUpdated(const QVariantMap ¶ms) +{ + Q_UNUSED(params); +} + diff --git a/backend/jsonrpc/logginghandler.h b/backend/jsonrpc/logginghandler.h new file mode 100644 index 00000000..77f3e6aa --- /dev/null +++ b/backend/jsonrpc/logginghandler.h @@ -0,0 +1,41 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef LOGGINGHANDLER_H +#define LOGGINGHANDLER_H + +#include + +#include "jsonhandler.h" + +class LoggingHandler : public JsonHandler +{ + Q_OBJECT +public: + explicit LoggingHandler(QObject *parent = 0); + + QString nameSpace() const; + + Q_INVOKABLE void processLogEntryAdded(const QVariantMap ¶ms); + Q_INVOKABLE void processLogDatabaseUpdated(const QVariantMap ¶ms); + +}; + +#endif // LOGGINGHANDLER_H diff --git a/backend/jsonrpc/networkmanagerhandler.cpp b/backend/jsonrpc/networkmanagerhandler.cpp new file mode 100644 index 00000000..bf4d29a3 --- /dev/null +++ b/backend/jsonrpc/networkmanagerhandler.cpp @@ -0,0 +1,19 @@ +#include "networkmanagerhandler.h" + +#include + +NetworkManagerHandler::NetworkManagerHandler(QObject *parent) : + JsonHandler(parent) +{ + +} + +QString NetworkManagerHandler::nameSpace() const +{ + return "NetworkManager"; +} + +void NetworkManagerHandler::processWirelessNetworkDeviceChanged(const QVariantMap ¶ms) +{ + Q_UNUSED(params); +} diff --git a/backend/jsonrpc/networkmanagerhandler.h b/backend/jsonrpc/networkmanagerhandler.h new file mode 100644 index 00000000..637c7154 --- /dev/null +++ b/backend/jsonrpc/networkmanagerhandler.h @@ -0,0 +1,23 @@ +#ifndef NETWORKMANAGERHANDLER_H +#define NETWORKMANAGERHANDLER_H + +#include + +#include "jsonhandler.h" + +class NetworkManagerHandler : public JsonHandler +{ + Q_OBJECT +public: + explicit NetworkManagerHandler(QObject *parent = 0); + + QString nameSpace() const; + + Q_INVOKABLE void processWirelessNetworkDeviceChanged(const QVariantMap ¶ms); + +signals: + +public slots: +}; + +#endif // NETWORKMANAGERHANDLER_H diff --git a/backend/main.cpp b/backend/main.cpp index 34614e74..8083439c 100644 --- a/backend/main.cpp +++ b/backend/main.cpp @@ -1,13 +1,81 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include +#include +#include #include +#include + +#include "engine.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication app(argc, argv); + QGuiApplication application(argc, argv); + + // backend + qmlRegisterSingletonType("Guh", 1, 0, "Engine", Engine::qmlInstance); + + qmlRegisterUncreatableType("Guh", 1, 0, "DeviceManager", "Can't create this in QML. Get it from the Core."); + qmlRegisterUncreatableType("Guh", 1, 0, "JsonRpcClient", "Can't create this in QML. Get it from the Core."); + qmlRegisterUncreatableType("Guh", 1, 0, "GuhInterface", "Can't create this in QML. Get it from the Core."); + qmlRegisterUncreatableType("Guh", 1, 0, "WebsocketInterface", "Can't create this in QML. Get it from the Core."); + + // libguh-common + qmlRegisterUncreatableType("Guh", 1, 0, "Types", "Can't create this in QML. Get it from the Core."); + + qmlRegisterUncreatableType("Guh", 1, 0, "ParamType", "Can't create this in QML. Get it from the ParamTypes."); + qmlRegisterUncreatableType("Guh", 1, 0, "ParamTypes", "Can't create this in QML. Get it from the DeviceClass."); + qmlRegisterUncreatableType("Guh", 1, 0, "EventType", "Can't create this in QML. Get it from the EventTypes."); + qmlRegisterUncreatableType("Guh", 1, 0, "EventTypes", "Can't create this in QML. Get it from the DeviceClass."); + qmlRegisterUncreatableType("Guh", 1, 0, "StateType", "Can't create this in QML. Get it from the StateTypes."); + qmlRegisterUncreatableType("Guh", 1, 0, "StateTypes", "Can't create this in QML. Get it from the DeviceClass."); + qmlRegisterUncreatableType("Guh", 1, 0, "ActionType", "Can't create this in QML. Get it from the ActionTypes."); + qmlRegisterUncreatableType("Guh", 1, 0, "ActionTypes", "Can't create this in QML. Get it from the DeviceClass."); + + qmlRegisterUncreatableType("Guh", 1, 0, "State", "Can't create this in QML. Get it from the States."); + qmlRegisterUncreatableType("Guh", 1, 0, "States", "Can't create this in QML. Get it from the Device."); + qmlRegisterUncreatableType("Guh", 1, 0, "StatesProxy", "Can't create this in QML. Get it from the Device."); + + qmlRegisterUncreatableType("Guh", 1, 0, "Vendor", "Can't create this in QML. Get it from the Vendors."); + qmlRegisterUncreatableType("Guh", 1, 0, "Vendors", "Can't create this in QML. Get it from the DeviceManager."); + qmlRegisterUncreatableType("Guh", 1, 0, "VendorsProxy", "Can't create this in QML. Get it from the DeviceManager."); + + qmlRegisterUncreatableType("Guh", 1, 0, "Device", "Can't create this in QML. Get it from the Devices."); + qmlRegisterUncreatableType("Guh", 1, 0, "Devices", "Can't create this in QML. Get it from the DeviceManager."); + qmlRegisterUncreatableType("Guh", 1, 0, "DevicesProxy", "Can't create this in QML. Get it from the DeviceManager."); + + qmlRegisterUncreatableType("Guh", 1, 0, "DeviceClass", "Can't create this in QML. Get it from the DeviceClasses."); + qmlRegisterUncreatableType("Guh", 1, 0, "DeviceClasses", "Can't create this in QML. Get it from the DeviceManager."); + qmlRegisterUncreatableType("Guh", 1, 0, "DeviceClassesProxy", "Can't create this in QML. Get it from the DeviceManager."); + + qmlRegisterUncreatableType("Guh", 1, 0, "Plugin", "Can't create this in QML. Get it from the Plugins."); + qmlRegisterUncreatableType("Guh", 1, 0, "Plugins", "Can't create this in QML. Get it from the DeviceManager."); + qmlRegisterUncreatableType("Guh", 1, 0, "PluginsProxy", "Can't create this in QML. Get it from the DeviceManager."); QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml"))); - return app.exec(); + + Engine::instance(); + + return application.exec(); } diff --git a/backend/ui/main.qml b/backend/ui/main.qml deleted file mode 100644 index 4d12a6a3..00000000 --- a/backend/ui/main.qml +++ /dev/null @@ -1,52 +0,0 @@ -import QtQuick 2.7 -import QtQuick.Controls 2.0 -import QtQuick.Layouts 1.0 - -ApplicationWindow { - visible: true - width: 640 - height: 480 - title: qsTr("guh control") - - SwipeView { - id: swipeView - anchors.fill: parent - currentIndex: tabBar.currentIndex - - Page { - id: devicePage - Label { - text: qsTr("Devices list") - anchors.centerIn: parent - } - } - - Page { - Label { - text: qsTr("Rules") - anchors.centerIn: parent - } - } - - Page { - Label { - text: qsTr("Settings") - anchors.centerIn: parent - } - } - } - - footer: TabBar { - id: tabBar - currentIndex: swipeView.currentIndex - TabButton { - text: qsTr("Devices") - } - TabButton { - text: qsTr("Rules") - } - TabButton { - text: qsTr("Settings") - } - } -} diff --git a/backend/websocketinterface.cpp b/backend/websocketinterface.cpp new file mode 100644 index 00000000..a3a96c58 --- /dev/null +++ b/backend/websocketinterface.cpp @@ -0,0 +1,114 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "websocketinterface.h" +#include "engine.h" + +#include +#include +#include +#include + +WebsocketInterface::WebsocketInterface(QObject *parent) : + GuhInterface(parent) +{ + m_socket = new QWebSocket(QGuiApplication::applicationName(), QWebSocketProtocol::Version13, this); + + connect(m_socket, SIGNAL(connected()), this, SLOT(onConnected())); + connect(m_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected())); + connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError))); + connect(m_socket, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString))); +} + +void WebsocketInterface::sendData(const QByteArray &data) +{ + m_socket->sendTextMessage(QString::fromUtf8(data)); +} + +void WebsocketInterface::sendRequest(const QVariantMap &request) +{ + sendData(QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact)); +} + +void WebsocketInterface::setUrl(const QString &url) +{ + m_urlString = url; + emit urlChanged(); +} + +QString WebsocketInterface::url() const +{ + return m_urlString; +} + +void WebsocketInterface::enable() +{ + if (connected()) + disable(); + + qDebug() << "Connecting to" << QUrl(m_urlString).toString(); + m_socket->open(QUrl(m_urlString)); + emit connecting(); +} + +void WebsocketInterface::disable() +{ + m_socket->close(); +} + +void WebsocketInterface::onConnected() +{ + qDebug() << "Connected to" << m_urlString; + + QSettings settings; + qDebug() << "Save last connection" << settings.fileName(); + settings.beginGroup("Connections"); + settings.setValue("webSocketUrl", m_urlString); + settings.endGroup(); + + setConnected(true); + + //Engine::instance()->connections()->addConnection("guhIO", m_socket->peerAddress().toString(), m_urlString); +} + +void WebsocketInterface::onDisconnected() +{ + qDebug() << "Disconnected from" << m_urlString << ": reason:" << m_socket->closeReason(); + setConnected(false); +} + +void WebsocketInterface::onTextMessageReceived(const QString &data) +{ + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data.toUtf8(), &error); + if (error.error != QJsonParseError::NoError) { + qWarning() << "Could not parse json data from guh" << data << error.errorString(); + return; + } + + emit dataReady(jsonDoc.toVariant().toMap()); +} + +void WebsocketInterface::onError(QAbstractSocket::SocketError error) +{ + qWarning() << "Websocket error:" << error << m_socket->errorString(); + emit websocketError(m_socket->errorString()); + emit connectionFailed(); +} diff --git a/backend/websocketinterface.h b/backend/websocketinterface.h new file mode 100644 index 00000000..64481e20 --- /dev/null +++ b/backend/websocketinterface.h @@ -0,0 +1,65 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control. * + * * + * guh-control 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 3 of the License. * + * * + * guh-control 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-control. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef WEBSOCKETINTERFACE_H +#define WEBSOCKETINTERFACE_H + +#include +#include + +#include "guhinterface.h" + +class WebsocketInterface : public GuhInterface +{ + Q_OBJECT + Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) + +public: + explicit WebsocketInterface(QObject *parent = 0); + + void sendData(const QByteArray &data) override; + void sendRequest(const QVariantMap &request) override; + + void setUrl(const QString &url); + QString url() const; + +private: + QWebSocket *m_socket; + QString m_urlString; + +signals: + void urlChanged(); + void disconnected(); + void connecting(); + void connectionFailed(); + void websocketError(const QString &errorString); + +public slots: + Q_INVOKABLE void enable() override; + Q_INVOKABLE void disable() override; + +private slots: + void onConnected(); + void onDisconnected(); + void onTextMessageReceived(const QString &data); + void onError(QAbstractSocket::SocketError error); +}; + +#endif // WEBSOCKETINTERFACE_H diff --git a/backend/ui/qml.qrc b/data.qrc similarity index 52% rename from backend/ui/qml.qrc rename to data.qrc index 5f6483ac..5a15240e 100644 --- a/backend/ui/qml.qrc +++ b/data.qrc @@ -1,5 +1,5 @@ - main.qml + data/icons/busy-indicator.svg diff --git a/data/icons/busy-indicator.svg b/data/icons/busy-indicator.svg new file mode 100644 index 00000000..b0b8d6af --- /dev/null +++ b/data/icons/busy-indicator.svg @@ -0,0 +1,195 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/guh-control.pri b/guh-control.pri new file mode 100644 index 00000000..f0080518 --- /dev/null +++ b/guh-control.pri @@ -0,0 +1,4 @@ +CONFIG += c++11 + +top_srcdir=$$PWD +top_builddir=$$shadowed($$PWD) diff --git a/guh-control.pro b/guh-control.pro index 228a7fa3..575aa648 100644 --- a/guh-control.pro +++ b/guh-control.pro @@ -1,3 +1,5 @@ +include(guh-control.pri) + TEMPLATE=subdirs SUBDIRS += backend libguh-common diff --git a/libguh-common/libguh-common.pro b/libguh-common/libguh-common.pro index fb105dee..3170db5e 100644 --- a/libguh-common/libguh-common.pro +++ b/libguh-common/libguh-common.pro @@ -1,3 +1,5 @@ +include(../guh-control.pri) + TARGET = guh-common TEMPLATE = lib @@ -59,7 +61,6 @@ SOURCES += types/vendor.cpp \ types/plugins.cpp \ types/pluginsproxy.cpp \ - # install header file with relative subdirectory for(header, HEADERS) { path = /usr/include/guh-common/$${dirname(header)} diff --git a/libguh-common/types/actiontype.cpp b/libguh-common/types/actiontype.cpp index 794d0eb7..9268045d 100644 --- a/libguh-common/types/actiontype.cpp +++ b/libguh-common/types/actiontype.cpp @@ -47,6 +47,16 @@ void ActionType::setName(const QString &name) m_name = name; } +int ActionType::index() const +{ + return m_index; +} + +void ActionType::setIndex(const int &index) +{ + m_index = index; +} + ParamTypes *ActionType::paramTypes() const { return m_paramTypes; diff --git a/libguh-common/types/actiontype.h b/libguh-common/types/actiontype.h index af362142..771af508 100644 --- a/libguh-common/types/actiontype.h +++ b/libguh-common/types/actiontype.h @@ -33,6 +33,7 @@ class ActionType : public QObject Q_OBJECT Q_PROPERTY(QUuid id READ id CONSTANT) Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(int index READ index CONSTANT) Q_PROPERTY(ParamTypes *paramTypes READ paramTypes NOTIFY paramTypesChanged) public: @@ -44,12 +45,16 @@ public: QString name() const; void setName(const QString &name); + int index() const; + void setIndex(const int &index); + ParamTypes *paramTypes() const; void setParamTypes(ParamTypes *paramTypes); private: QUuid m_id; QString m_name; + int m_index; ParamTypes *m_paramTypes; signals: diff --git a/libguh-common/types/eventtype.cpp b/libguh-common/types/eventtype.cpp index 7140476e..7ec61e22 100644 --- a/libguh-common/types/eventtype.cpp +++ b/libguh-common/types/eventtype.cpp @@ -47,6 +47,16 @@ void EventType::setName(const QString &name) m_name = name; } +int EventType::index() const +{ + return m_index; +} + +void EventType::setIndex(const int &index) +{ + m_index = index; +} + ParamTypes *EventType::paramTypes() const { return m_paramTypes; diff --git a/libguh-common/types/eventtype.h b/libguh-common/types/eventtype.h index dabbc499..ebc1a1ff 100644 --- a/libguh-common/types/eventtype.h +++ b/libguh-common/types/eventtype.h @@ -33,6 +33,7 @@ class EventType : public QObject Q_OBJECT Q_PROPERTY(QUuid id READ id CONSTANT) Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(int index READ index CONSTANT) Q_PROPERTY(ParamTypes paramTypes READ paramTypes CONSTANT) public: @@ -44,12 +45,16 @@ public: QString name() const; void setName(const QString &name); + int index() const; + void setIndex(const int &index); + ParamTypes *paramTypes() const; void setParamTypes(ParamTypes *paramTypes); private: QUuid m_id; QString m_name; + int m_index; ParamTypes *m_paramTypes; }; diff --git a/libguh-common/types/paramtype.cpp b/libguh-common/types/paramtype.cpp index 9fa13f77..ba89de9e 100644 --- a/libguh-common/types/paramtype.cpp +++ b/libguh-common/types/paramtype.cpp @@ -57,6 +57,16 @@ void ParamType::setType(const QString &type) m_type = type; } +int ParamType::index() const +{ + return m_index; +} + +void ParamType::setIndex(const int &index) +{ + m_index = index; +} + QVariant ParamType::defaultValue() const { return m_defaultValue; diff --git a/libguh-common/types/paramtype.h b/libguh-common/types/paramtype.h index 92ee8031..fd0586d6 100644 --- a/libguh-common/types/paramtype.h +++ b/libguh-common/types/paramtype.h @@ -34,6 +34,7 @@ class ParamType : public QObject Q_OBJECT Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString type READ type CONSTANT) + Q_PROPERTY(int index READ index CONSTANT) Q_PROPERTY(QVariant defaultValue READ defaultValue CONSTANT) Q_PROPERTY(QVariant minValue READ minValue CONSTANT) Q_PROPERTY(QVariant maxValue READ maxValue CONSTANT) @@ -52,6 +53,9 @@ public: QString type() const; void setType(const QString &type); + int index() const; + void setIndex(const int &index); + QVariant defaultValue() const; void setDefaultValue(const QVariant &defaultValue); @@ -79,6 +83,7 @@ public: private: QString m_name; QString m_type; + int m_index; QVariant m_defaultValue; QVariant m_minValue; QVariant m_maxValue; diff --git a/libguh-common/types/statetype.cpp b/libguh-common/types/statetype.cpp index c4a8bc59..e3b38047 100644 --- a/libguh-common/types/statetype.cpp +++ b/libguh-common/types/statetype.cpp @@ -57,6 +57,16 @@ void StateType::setType(const QString &type) m_type = type; } +int StateType::index() const +{ + return m_index; +} + +void StateType::setIndex(const int &index) +{ + m_index = index; +} + QVariant StateType::defaultValue() const { return m_defaultValue; diff --git a/libguh-common/types/statetype.h b/libguh-common/types/statetype.h index da42079e..3958fd05 100644 --- a/libguh-common/types/statetype.h +++ b/libguh-common/types/statetype.h @@ -35,6 +35,7 @@ class StateType : public QObject Q_PROPERTY(QUuid id READ id CONSTANT) Q_PROPERTY(QString name READ name CONSTANT) Q_PROPERTY(QString type READ type CONSTANT) + Q_PROPERTY(int index READ index CONSTANT) Q_PROPERTY(QVariant defaultValue READ defaultValue CONSTANT) Q_PROPERTY(Types::Unit unit READ unit CONSTANT) Q_PROPERTY(QString unitString READ unitString CONSTANT) @@ -51,6 +52,9 @@ public: QString type() const; void setType(const QString &type); + int index() const; + void setIndex(const int &index); + QVariant defaultValue() const; void setDefaultValue(const QVariant &defaultValue); @@ -64,6 +68,7 @@ private: QUuid m_id; QString m_name; QString m_type; + int m_index; QVariant m_defaultValue; Types::Unit m_unit; QString m_unitString; diff --git a/ui/ConnectionPage.qml b/ui/ConnectionPage.qml new file mode 100644 index 00000000..6ff92b61 --- /dev/null +++ b/ui/ConnectionPage.qml @@ -0,0 +1,47 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.1 +import Guh 1.0 + +Page { + id: root + + Connections { + target: Engine + onConnectedChanged: { + if (connected) { + mainStack.push(Qt.resolvedUrl("MainPage.qml")) + } + } + } + + Button { + text: qsTr("Connect") + anchors.centerIn: parent + onClicked: { + Engine.connectGuh() + } + } +} diff --git a/ui/DevicePage.qml b/ui/DevicePage.qml new file mode 100644 index 00000000..9450f6ad --- /dev/null +++ b/ui/DevicePage.qml @@ -0,0 +1,104 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.1 + +import Guh 1.0 + +Page { + id: root + + property var device: null + property var deviceClass: Engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId) + + Rectangle { + id: header + color: "lightgray" + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: 40 + + Button { + id: backButton + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + width: parent.height + height: parent.height + text: "🡰" + onClicked: mainStack.pop() + } + + Label { + anchors.centerIn: parent + text: device.name + } + } + + Flickable { + id: flickable + anchors.fill: parent + anchors.topMargin: header.height + anchors.leftMargin: 5 + anchors.rightMargin: 5 + contentHeight: stateColumn.height + contentWidth: parent.width + + clip: true + + Column { + id: stateColumn + anchors.fill: parent + spacing: 5 + + Repeater { + anchors.fill: parent + model: deviceClass.stateTypes + delegate: Item { + width: parent.width / 2 + height: 20 + + Rectangle { anchors.fill: parent; color: "green"; opacity: 0.5 } + + Label { + id: stateLable + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 5 + text: name + } + + Label { + id: valueLable + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 5 + text: device.states.getState(id).value + " " + deviceClass.stateTypes.getStateType(id).unitString + } + } + } + } + + } +} diff --git a/ui/DevicesPage.qml b/ui/DevicesPage.qml new file mode 100644 index 00000000..9866b0b3 --- /dev/null +++ b/ui/DevicesPage.qml @@ -0,0 +1,73 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.1 + +import Guh 1.0 + +Page { + id: root + + GridView { + id: gridView + anchors.fill: parent + + anchors.margins: 10 + + property real cellSize: width / 5 + + + cellWidth: cellSize + cellHeight: cellSize + + model: Engine.deviceManager.devicesProxy + + clip: true + + delegate: Item { + height: gridView.cellSize + width: gridView.cellSize + + Button { + anchors.fill: parent + anchors.margins: 5 + text: model.name + + onClicked: mainStack.push(Qt.resolvedUrl("DevicePage.qml"), { device: Engine.deviceManager.devices.getDevice(model.id)}) + } + +// Rectangle { +// anchors.fill: parent +// anchors.margins: 4 +// color: "lightgray" + +// radius: width / 8 + +// border.width: 1 +// border.color: "darkgray" +// } + + } + } +} diff --git a/ui/MainPage.qml b/ui/MainPage.qml new file mode 100644 index 00000000..4f72d0d1 --- /dev/null +++ b/ui/MainPage.qml @@ -0,0 +1,72 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.1 + +Page { + id: root + + TabBar { + id: tabBar + currentIndex: swipeView.currentIndex + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + + TabButton { + text: qsTr("Devices") + } + + TabButton { + text: qsTr("Rules") + } + + TabButton { + text: qsTr("Settings") + } + } + + SwipeView { + id: swipeView + anchors.fill: parent + anchors.topMargin: tabBar.height + currentIndex: tabBar.currentIndex + + DevicesPage { id: devicePage } + + Page { + Label { + text: qsTr("Rules") + anchors.centerIn: parent + } + } + + Page { + Label { + text: qsTr("Settings") + anchors.centerIn: parent + } + } + } +} diff --git a/ui/main.qml b/ui/main.qml new file mode 100644 index 00000000..109851aa --- /dev/null +++ b/ui/main.qml @@ -0,0 +1,126 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stuerz * + * * + * This file is part of guh-control * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.1 + +import Guh 1.0 + +ApplicationWindow { + visible: true + width: 640 + height: 480 + title: qsTr("guh control") + + Connections { + target: Engine + onConnectedChanged: { + if (!connected) { + mainStack.clear() + mainStack.push(Qt.resolvedUrl("ConnectionPage.qml")) + } + } + } + + StackView { + id: mainStack + initialItem: ConnectionPage { } + anchors.fill: parent + } + + footer: Item { + id: footerItem + height: 20 + + Rectangle { anchors.fill: parent; color: "darkgray"} + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.leftMargin: 5 + anchors.rightMargin: 5 + spacing: 5 + + Item { + id: busyIndicator + Layout.preferredHeight: parent.height + Layout.preferredWidth: parent.height + Layout.alignment: Qt.AlignVCenter + + RotationAnimation { + target: busyIndicatorImage + duration: 2000 + from: 360 + to: 0 + running: true + loops: RotationAnimation.Infinite + } + + Image { + id: busyIndicatorImage + anchors.fill: parent + anchors.margins: 2 + source: "qrc:/data/icons/busy-indicator.svg" + } + } + + Label { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + anchors.verticalCenter: parent.verticalCenter + text: "guh-control" + color: "white" + } + + + Item { + id: connectionStatusItem + Layout.preferredHeight: parent.height + Layout.preferredWidth: parent.height + Layout.alignment: Qt.AlignVCenter + + Rectangle { + anchors.fill: parent + anchors.margins: parent.height / 10 + radius: height / 2 + color: Engine.connected ? "green" : "red" + + Behavior on color { + ColorAnimation { + duration: 300 + easing.type: Easing.InCubic + } + } + } + + MouseArea { + anchors.fill: parent + onClicked: Engine.interface.disable() + } + } + } + } +} diff --git a/ui/qml.qrc b/ui/qml.qrc new file mode 100644 index 00000000..b3749dfb --- /dev/null +++ b/ui/qml.qrc @@ -0,0 +1,9 @@ + + + main.qml + MainPage.qml + ConnectionPage.qml + DevicesPage.qml + DevicePage.qml + +