diff --git a/libguh/bluetooth/bluetoothdiscoveryreply.cpp b/libguh/bluetooth/bluetoothdiscoveryreply.cpp new file mode 100644 index 00000000..11335d36 --- /dev/null +++ b/libguh/bluetooth/bluetoothdiscoveryreply.cpp @@ -0,0 +1,65 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stürz * + * * + * This file is part of guh. * + * * + * 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "bluetoothdiscoveryreply.h" + +#include + +bool BluetoothDiscoveryReply::isFinished() const +{ + return m_finished; +} + +BluetoothDiscoveryReply::BluetoothDiscoveryReplyError BluetoothDiscoveryReply::error() const +{ + return m_error; +} + +QList BluetoothDiscoveryReply::discoveredDevices() const +{ + return m_discoveredDevices; +} + +BluetoothDiscoveryReply::BluetoothDiscoveryReply(QObject *parent) : QObject(parent) +{ + +} + +void BluetoothDiscoveryReply::setError(const BluetoothDiscoveryReply::BluetoothDiscoveryReplyError &error) +{ + m_error = error; + if (m_error != BluetoothDiscoveryReplyErrorNoError) { + emit errorOccured(m_error); + } +} + +void BluetoothDiscoveryReply::setDiscoveredDevices(const QList &discoveredDevices) +{ + m_discoveredDevices = discoveredDevices; +} + +void BluetoothDiscoveryReply::setFinished() +{ + m_finished = true; + // Note: this makes sure the finished signal will be processed in the next event loop + QTimer::singleShot(0, this, &BluetoothDiscoveryReply::finished); +} diff --git a/libguh/bluetooth/bluetoothdiscoveryreply.h b/libguh/bluetooth/bluetoothdiscoveryreply.h new file mode 100644 index 00000000..7ed0620d --- /dev/null +++ b/libguh/bluetooth/bluetoothdiscoveryreply.h @@ -0,0 +1,65 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stürz * + * * + * This file is part of guh. * + * * + * 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BLUETOOTHDISCOVERYREPLY_H +#define BLUETOOTHDISCOVERYREPLY_H + +#include +#include + +class BluetoothDiscoveryReply : public QObject +{ + Q_OBJECT + + friend class BluetoothLowEnergyManager; + +public: + enum BluetoothDiscoveryReplyError { + BluetoothDiscoveryReplyErrorNoError, + BluetoothDiscoveryReplyErrorNotAvailable, + BluetoothDiscoveryReplyErrorNotEnabled, + BluetoothDiscoveryReplyErrorBusy + }; + Q_ENUM(BluetoothDiscoveryReplyError) + + bool isFinished() const; + BluetoothDiscoveryReplyError error() const; + QList discoveredDevices() const; + +private: + explicit BluetoothDiscoveryReply(QObject *parent = nullptr); + + bool m_finished = false; + BluetoothDiscoveryReplyError m_error = BluetoothDiscoveryReplyErrorNoError; + QList m_discoveredDevices; + + void setError(const BluetoothDiscoveryReplyError &error); + void setDiscoveredDevices(const QList &discoveredDevices); + void setFinished(); + +signals: + void finished(); + void errorOccured(const BluetoothDiscoveryReplyError &error); + +}; + +#endif // BLUETOOTHDISCOVERYREPLY_H diff --git a/libguh/bluetooth/bluetoothlowenergymanager.cpp b/libguh/bluetooth/bluetoothlowenergymanager.cpp index 49c7ef82..93d6ea4b 100644 --- a/libguh/bluetooth/bluetoothlowenergymanager.cpp +++ b/libguh/bluetooth/bluetoothlowenergymanager.cpp @@ -23,33 +23,45 @@ #include "bluetoothlowenergymanager.h" #include "loggingcategories.h" -bool BluetoothLowEnergyManager::discoverDevices(QPointer caller, const QString &callbackMethod) +BluetoothDiscoveryReply *BluetoothLowEnergyManager::discoverDevices(const int &interval) { + // Create the reply for this discovery request + QPointer reply = new BluetoothDiscoveryReply(this); if (!available()) { qCWarning(dcHardware()) << name() << "is not avilable."; - return false; + reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNotAvailable); + reply->setFinished(); + return reply.data(); } if (!enabled()) { qCWarning(dcHardware()) << name() << "is not enabled."; - return false; + reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNotEnabled); + reply->setFinished(); + return reply.data(); } - if (m_timer->isActive()) { - qCWarning(dcHardware()) << name() << "discovery already running."; - return false; + if (!m_currentReply.isNull()) { + qCWarning(dcHardware()) << name() << "resource busy. There is already a discovery running."; + reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorBusy); + reply->setFinished(); + return reply.data(); } + qCDebug(dcHardware) << name() << "start discovering"; + m_currentReply = reply; m_discoveredDevices.clear(); - m_currentReply.caller = caller; - m_currentReply.callbackMethod = callbackMethod; // Start discovery on all adapters qCDebug(dcHardware()) << name() << "Start bluetooth discovery"; foreach (QBluetoothDeviceDiscoveryAgent *discoveryAgent, m_bluetoothDiscoveryAgents) { discoveryAgent->start(); } - return true; + + // TODO: limit interval to prevent resource blocking from a plugin + m_timer->start(interval); + + return reply.data(); } BluetoothLowEnergyManager::BluetoothLowEnergyManager(QObject *parent) : @@ -80,7 +92,6 @@ BluetoothLowEnergyManager::BluetoothLowEnergyManager(QObject *parent) : // Discovery timer m_timer = new QTimer(this); m_timer->setSingleShot(true); - m_timer->setInterval(5000); connect(m_timer, &QTimer::timeout, this, &BluetoothLowEnergyManager::discoveryTimeout); @@ -90,21 +101,25 @@ BluetoothLowEnergyManager::BluetoothLowEnergyManager(QObject *parent) : void BluetoothLowEnergyManager::discoveryTimeout() { - // Start discovery on all adapters + // Stop discovery on all adapters qCDebug(dcHardware()) << name() << "Stop bluetooth discovery"; foreach (QBluetoothDeviceDiscoveryAgent *discoveryAgent, m_bluetoothDiscoveryAgents) { discoveryAgent->stop(); } - qCDebug(dcHardware()) << name() << "Discovery finished. Found"<< m_discoveredDevices.count() << "Bluetooth devices."; + qCDebug(dcHardware()) << name() << "Discovery finished. Found" << m_discoveredDevices.count() << "bluetooth devices."; - if (m_currentReply.caller.isNull()) { - qCWarning(dcHardware()) << name() << "The reciver of the discovery request does not exist any more."; - } else { - // Invoke the method containing the discovered devicelist - // FIXME: check the callback method paramters during compililation - QMetaObject::invokeMethod(m_currentReply.caller.data(), m_currentReply.callbackMethod.toLatin1().data(), Q_ARG(QList, m_discoveredDevices)); + if (m_currentReply.isNull()) { + qCWarning(dcHardware()) << name() << "Reply does not exist any more. Please don't delete the reply before it has finished."; + m_currentReply.clear(); + return; } + + m_currentReply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNoError); + m_currentReply->setDiscoveredDevices(m_discoveredDevices); + m_currentReply->setFinished(); + + m_currentReply.clear(); } void BluetoothLowEnergyManager::onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo) diff --git a/libguh/bluetooth/bluetoothlowenergymanager.h b/libguh/bluetooth/bluetoothlowenergymanager.h index b667ce0b..bb3f0868 100644 --- a/libguh/bluetooth/bluetoothlowenergymanager.h +++ b/libguh/bluetooth/bluetoothlowenergymanager.h @@ -31,12 +31,7 @@ #include #include "hardwareresource.h" - -struct BluetoothDiscoveryReply -{ - QPointer caller; - QString callbackMethod; -}; +#include "bluetoothdiscoveryreply.h" class BluetoothLowEnergyManager : public HardwareResource { @@ -45,7 +40,7 @@ class BluetoothLowEnergyManager : public HardwareResource friend class HardwareManager; public: - bool discoverDevices(QPointer caller = QPointer(), const QString &callbackMethod = QString()); + BluetoothDiscoveryReply *discoverDevices(const int &interval = 5000); private: explicit BluetoothLowEnergyManager(QObject *parent = nullptr); @@ -54,7 +49,7 @@ private: QList m_bluetoothDiscoveryAgents; QList m_discoveredDevices; - BluetoothDiscoveryReply m_currentReply; + QPointer m_currentReply; signals: diff --git a/libguh/devicemanager.cpp b/libguh/devicemanager.cpp index 03dbb8bb..68102cfe 100644 --- a/libguh/devicemanager.cpp +++ b/libguh/devicemanager.cpp @@ -973,7 +973,7 @@ DeviceManager::DeviceError DeviceManager::executeAction(const Action &action) /*! Centralized time tick for the GuhTimer resource. Ticks every second. */ void DeviceManager::timeTick() { - + m_hardwareManager->timeTick(); } void DeviceManager::loadPlugins() diff --git a/libguh/hardwaremanager.cpp b/libguh/hardwaremanager.cpp index 284eb0fc..39f74c36 100644 --- a/libguh/hardwaremanager.cpp +++ b/libguh/hardwaremanager.cpp @@ -25,6 +25,7 @@ #include "plugintimer.h" #include "loggingcategories.h" #include "hardware/radio433/radio433.h" +#include "bluetooth/bluetoothlowenergymanager.h" #include "network/networkaccessmanager.h" #include "network/upnp/upnpdiscovery.h" #include "network/upnp/upnpdevicedescriptor.h" @@ -33,8 +34,9 @@ HardwareManager::HardwareManager(QObject *parent) : QObject(parent) { // Init hardware resources - m_pluginTimer = new PluginTimer(10000, this); - m_hardwareResources.append(m_pluginTimer); + m_pluginTimerManager = new PluginTimerManager(this); + m_pluginTimerManager->enable(); + m_hardwareResources.append(m_pluginTimerManager); m_radio433 = new Radio433(this); m_hardwareResources.append(m_radio433); @@ -60,12 +62,11 @@ HardwareManager::HardwareManager(QObject *parent) : QObject(parent) m_hardwareResources.append(m_avahiBrowser); m_avahiBrowser->enable(); -// // Bluetooth LE -// m_bluetoothScanner = new BluetoothScanner(this); -// if (!m_bluetoothScanner->isAvailable()) { -// delete m_bluetoothScanner; -// m_bluetoothScanner = nullptr; -// } + // Bluetooth LE + m_bluetoothLowEnergyManager = new BluetoothLowEnergyManager(this); + m_hardwareResources.append(m_bluetoothLowEnergyManager); + if (m_networkManager->available()) + m_networkManager->enable(); qCDebug(dcHardware()) << "Hardware manager initialized successfully"; } @@ -75,9 +76,9 @@ Radio433 *HardwareManager::radio433() return m_radio433; } -PluginTimer *HardwareManager::pluginTimer() +PluginTimerManager *HardwareManager::pluginTimerManager() { - return m_pluginTimer; + return m_pluginTimerManager; } NetworkAccessManager *HardwareManager::networkManager() @@ -95,9 +96,9 @@ QtAvahiServiceBrowser *HardwareManager::avahiBrowser() return m_avahiBrowser; } -BluetoothScanner *HardwareManager::bluetoothScanner() +BluetoothLowEnergyManager *HardwareManager::bluetoothLowEnergyManager() { - return m_bluetoothScanner; + return m_bluetoothLowEnergyManager; } bool HardwareManager::isAvailable(const HardwareResource::Type &hardwareResourceType) const @@ -140,3 +141,8 @@ bool HardwareManager::disableHardwareReource(const HardwareResource::Type &hardw return false; } +void HardwareManager::timeTick() +{ + m_pluginTimerManager->timeTick(); +} + diff --git a/libguh/hardwaremanager.h b/libguh/hardwaremanager.h index 789d09e6..02d28b9b 100644 --- a/libguh/hardwaremanager.h +++ b/libguh/hardwaremanager.h @@ -28,8 +28,8 @@ #include "hardwareresource.h" -class PluginTimer; -class BluetoothScanner; +class PluginTimerManager; +class BluetoothLowEnergyManager; class Radio433; class NetworkAccessManager; class UpnpDiscovery; @@ -46,11 +46,11 @@ public: explicit HardwareManager(QObject *parent = nullptr); Radio433 *radio433(); - PluginTimer *pluginTimer(); + PluginTimerManager *pluginTimerManager(); NetworkAccessManager *networkManager(); UpnpDiscovery *upnpDiscovery(); QtAvahiServiceBrowser *avahiBrowser(); - BluetoothScanner *bluetoothScanner(); + BluetoothLowEnergyManager *bluetoothLowEnergyManager(); bool isAvailable(const HardwareResource::Type &hardwareResourceType) const; bool isEnabled(const HardwareResource::Type &hardwareResourceType) const; @@ -62,15 +62,17 @@ private: // Hardware Resources Radio433 *m_radio433 = nullptr; - PluginTimer *m_pluginTimer = nullptr; + PluginTimerManager *m_pluginTimerManager = nullptr; NetworkAccessManager *m_networkManager = nullptr; UpnpDiscovery *m_upnpDiscovery = nullptr; QtAvahiServiceBrowser *m_avahiBrowser = nullptr; - BluetoothScanner *m_bluetoothScanner = nullptr; + BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr; bool enableHardwareReource(const HardwareResource::Type &hardwareResourceType); bool disableHardwareReource(const HardwareResource::Type &hardwareResourceType); + void timeTick(); + signals: void hardwareResourceAvailableChanged(const HardwareResource::Type &hardwareResourceType, const bool &available); void hardwareResourceEnabledChanged(const HardwareResource::Type &hardwareResourceType, const bool &enabled); diff --git a/libguh/libguh.pro b/libguh/libguh.pro index 689f9c4c..27f4faa1 100644 --- a/libguh/libguh.pro +++ b/libguh/libguh.pro @@ -70,7 +70,9 @@ HEADERS += devicemanager.h \ hardwareresource.h \ plugintimer.h \ hardwaremanager.h \ - bluetooth/bluetoothlowenergymanager.h + bluetooth/bluetoothlowenergymanager.h \ + network/upnp/upnpdiscoveryreply.h \ + bluetooth/bluetoothdiscoveryreply.h SOURCES += devicemanager.cpp \ loggingcategories.cpp \ @@ -126,7 +128,9 @@ SOURCES += devicemanager.cpp \ hardwareresource.cpp \ plugintimer.cpp \ hardwaremanager.cpp \ - bluetooth/bluetoothlowenergymanager.cpp + bluetooth/bluetoothlowenergymanager.cpp \ + network/upnp/upnpdiscoveryreply.cpp \ + bluetooth/bluetoothdiscoveryreply.cpp # install plugininfo python script for libguh-dev generateplugininfo.files = $$top_srcdir/plugins/guh-generateplugininfo diff --git a/libguh/network/avahi/qtavahiservicebrowser.cpp b/libguh/network/avahi/qtavahiservicebrowser.cpp index 75c66b4a..b2929467 100644 --- a/libguh/network/avahi/qtavahiservicebrowser.cpp +++ b/libguh/network/avahi/qtavahiservicebrowser.cpp @@ -73,8 +73,6 @@ QtAvahiServiceBrowser::~QtAvahiServiceBrowser() delete d_ptr; } - - /*! Returns the current \l{AvahiServiceEntry} list of this \l{QtAvahiServiceBrowser}. */ QList QtAvahiServiceBrowser::serviceEntries() const { diff --git a/libguh/network/networkaccessmanager.cpp b/libguh/network/networkaccessmanager.cpp index e1306f0c..b101f665 100644 --- a/libguh/network/networkaccessmanager.cpp +++ b/libguh/network/networkaccessmanager.cpp @@ -82,12 +82,12 @@ QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QIODevi QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data) { - return m_manager->post(request, data); + return m_manager->put(request, data); } QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart) { - return m_manager->post(request, multiPart); + return m_manager->put(request, multiPart); } QNetworkReply *NetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data) diff --git a/libguh/network/upnp/upnpdiscovery.cpp b/libguh/network/upnp/upnpdiscovery.cpp index 6ca9f4cd..391f73be 100644 --- a/libguh/network/upnp/upnpdiscovery.cpp +++ b/libguh/network/upnp/upnpdiscovery.cpp @@ -80,40 +80,35 @@ UpnpDiscovery::~UpnpDiscovery() m_socket->close(); } -/*! Returns false, if the \l{UpnpDiscovery} resource is not available. Returns true, if a device with - * the given \a searchTarget, \a userAgent and \a pluginId can be discovered.*/ -bool UpnpDiscovery::discoverDevices(QPointer caller, const QString &callbackMethod, const QString &searchTarget, const QString &userAgent) +UpnpDiscoveryReply *UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &userAgent, const int &timeout) { + // Create the reply for this discovery request + QPointer reply = new UpnpDiscoveryReply(searchTarget, userAgent, this); + if (!available()) { - qCWarning(dcHardware()) << name() << "not available."; - return false; + qCWarning(dcHardware()) << name() << "is not avilable."; + reply->setError(UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNotAvailable); + reply->setFinished(); + return reply.data(); } if (!enabled()) { - qCWarning(dcHardware()) << name() << "disabled."; - return false; - } - - if (!m_socket) - return false; - - if(m_socket->state() != QUdpSocket::BoundState){ - qCWarning(dcHardware) << "UPnP not bound to port 1900"; - return false; + qCWarning(dcHardware()) << name() << "is not enabled."; + reply->setError(UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNotEnabled); + reply->setFinished(); + return reply.data(); } qCDebug(dcHardware) << name() << "discover" << searchTarget << userAgent; - - // Create a new request - UpnpDiscoveryRequest *request = new UpnpDiscoveryRequest(this, caller, callbackMethod, searchTarget, userAgent); + // Looks good so far, lets start a request + UpnpDiscoveryRequest *request = new UpnpDiscoveryRequest(this, reply); connect(request, &UpnpDiscoveryRequest::discoveryTimeout, this, &UpnpDiscovery::discoverTimeout); - request->discover(); + request->discover(timeout); m_discoverRequests.append(request); - return true; + return reply.data(); } - void UpnpDiscovery::requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor) { QNetworkReply *replay = m_networkAccessManager->get(networkRequest); @@ -420,13 +415,14 @@ void UpnpDiscovery::sendAliveMessage() void UpnpDiscovery::discoverTimeout() { UpnpDiscoveryRequest *discoveryRequest = static_cast(sender()); + QPointer reply = discoveryRequest->reply(); - if (discoveryRequest->caller().isNull()) { - qCWarning(dcHardware()) << name() << "The reciver of the discovery request does not exist any more."; - } else { - // Invoke the method containing the discovered devicelist - // FIXME: check the callback method paramters during compililation - QMetaObject::invokeMethod(discoveryRequest->caller().data(), discoveryRequest->callbackMethod().toLatin1().data(), Q_ARG(QList, discoveryRequest->deviceList())); + if (reply.isNull()) { + qCWarning(dcHardware()) << name() << "Reply does not exist any more. Please don't delete the reply before it has finished."; + } else { + reply->setDeviceDescriptors(discoveryRequest->deviceList()); + reply->setError(UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNoError); + reply->setFinished(); } m_discoverRequests.removeOne(discoveryRequest); diff --git a/libguh/network/upnp/upnpdiscovery.h b/libguh/network/upnp/upnpdiscovery.h index 591d57ee..58c34c56 100644 --- a/libguh/network/upnp/upnpdiscovery.h +++ b/libguh/network/upnp/upnpdiscovery.h @@ -34,6 +34,7 @@ #include "libguh.h" #include "devicemanager.h" #include "hardwareresource.h" +#include "upnpdiscoveryreply.h" #include "upnpdiscoveryrequest.h" #include "upnpdevicedescriptor.h" @@ -49,7 +50,7 @@ class LIBGUH_EXPORT UpnpDiscovery : public HardwareResource friend class HardwareManager; public: - bool discoverDevices(QPointer caller = QPointer(), const QString &callbackMethod = QString(), const QString &searchTarget = "ssdp:all", const QString &userAgent = QString()); + UpnpDiscoveryReply *discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = QString(), const int &timeout = 5000); void sendToMulticast(const QByteArray &data); private: @@ -65,7 +66,7 @@ private: QNetworkAccessManager *m_networkAccessManager = nullptr; QList m_discoverRequests; - QHash m_informationRequestList; + QHash m_informationRequestList; void requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor); void respondToSearchRequest(QHostAddress host, int port); diff --git a/libguh/network/upnp/upnpdiscoveryreply.cpp b/libguh/network/upnp/upnpdiscoveryreply.cpp new file mode 100644 index 00000000..fc657b8b --- /dev/null +++ b/libguh/network/upnp/upnpdiscoveryreply.cpp @@ -0,0 +1,78 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stürz * + * * + * This file is part of guh. * + * * + * 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "upnpdiscoveryreply.h" + +#include + +QString UpnpDiscoveryReply::searchTarget() const +{ + return m_searchTarget; +} + +QString UpnpDiscoveryReply::userAgent() const +{ + return m_userAgent; +} + +UpnpDiscoveryReply::UpnpDiscoveryReplyError UpnpDiscoveryReply::error() const +{ + return m_error; +} + +bool UpnpDiscoveryReply::isFinished() const +{ + return m_finished; +} + +QList UpnpDiscoveryReply::deviceDescriptors() const +{ + return m_deviceDescriptors; +} + +UpnpDiscoveryReply::UpnpDiscoveryReply(const QString &searchTarget, const QString &userAgent, QObject *parent) : + QObject(parent), + m_searchTarget(searchTarget), + m_userAgent(userAgent) +{ + +} + +void UpnpDiscoveryReply::setDeviceDescriptors(const QList &deviceDescriptors) +{ + m_deviceDescriptors = deviceDescriptors; +} + +void UpnpDiscoveryReply::setError(const UpnpDiscoveryReply::UpnpDiscoveryReplyError &error) +{ + m_error = error; + if (m_error != UpnpDiscoveryReplyErrorNoError) { + emit errorOccured(m_error); + } +} + +void UpnpDiscoveryReply::setFinished() +{ + m_finished = true; + // Note: this makes sure the finished signal will be processed in the next event loop + QTimer::singleShot(0, this, &UpnpDiscoveryReply::finished); +} diff --git a/libguh/network/upnp/upnpdiscoveryreply.h b/libguh/network/upnp/upnpdiscoveryreply.h new file mode 100644 index 00000000..0547f2aa --- /dev/null +++ b/libguh/network/upnp/upnpdiscoveryreply.h @@ -0,0 +1,74 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2017 Simon Stürz * + * * + * This file is part of guh. * + * * + * 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef UPNPDISCOVERYREPLY_H +#define UPNPDISCOVERYREPLY_H + +#include + +#include "upnpdevicedescriptor.h" + +class UpnpDiscoveryReply : public QObject +{ + Q_OBJECT + + friend class UpnpDiscovery; + +public: + enum UpnpDiscoveryReplyError { + UpnpDiscoveryReplyErrorNoError, + UpnpDiscoveryReplyErrorNotAvailable, + UpnpDiscoveryReplyErrorNotEnabled, + UpnpDiscoveryReplyErrorResourceBusy + }; + Q_ENUM(UpnpDiscoveryReplyError) + + QString searchTarget() const; + QString userAgent() const; + + UpnpDiscoveryReplyError error() const; + bool isFinished() const; + + QList deviceDescriptors() const; + +private: + explicit UpnpDiscoveryReply(const QString &searchTarget, const QString &userAgent, QObject *parent = nullptr); + + QString m_searchTarget; + QString m_userAgent; + + QList m_deviceDescriptors; + UpnpDiscoveryReplyError m_error = UpnpDiscoveryReplyErrorNoError; + bool m_finished = false; + + // Methods for UpnpDiscovery + void setDeviceDescriptors(const QList &deviceDescriptors); + void setError(const UpnpDiscoveryReplyError &error); + void setFinished(); + +signals: + void finished(); + void errorOccured(const UpnpDiscoveryReplyError &error); + +}; + +#endif // UPNPDISCOVERYREPLY_H diff --git a/libguh/network/upnp/upnpdiscoveryrequest.cpp b/libguh/network/upnp/upnpdiscoveryrequest.cpp index b271cee7..fa97eb40 100644 --- a/libguh/network/upnp/upnpdiscoveryrequest.cpp +++ b/libguh/network/upnp/upnpdiscoveryrequest.cpp @@ -23,35 +23,31 @@ #include "upnpdiscoveryrequest.h" #include "loggingcategories.h" -UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer caller, const QString &callbackMethod, QString searchTarget, QString userAgent): +UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer reply): QObject(upnpDiscovery), m_upnpDiscovery(upnpDiscovery), - m_caller(caller), - m_callbackMethod(callbackMethod), - m_searchTarget(searchTarget), - m_userAgent(userAgent) + m_reply(reply) { m_timer = new QTimer(this); m_timer->setSingleShot(true); connect(m_timer, &QTimer::timeout, this, &UpnpDiscoveryRequest::discoveryTimeout); } -void UpnpDiscoveryRequest::discover() +void UpnpDiscoveryRequest::discover(const int &timeout) { QByteArray ssdpSearchMessage = QByteArray("M-SEARCH * HTTP/1.1\r\n" "HOST:239.255.255.250:1900\r\n" "MAN:\"ssdp:discover\"\r\n" "MX:4\r\n" - "ST: " + m_searchTarget.toUtf8() + "\r\n" - "USR-AGENT: " + m_userAgent.toUtf8() + "\r\n\r\n"); + "ST: " + reply()->searchTarget().toUtf8() + "\r\n" + "USR-AGENT: " + reply()->userAgent().toUtf8() + "\r\n\r\n"); m_upnpDiscovery->sendToMulticast(ssdpSearchMessage); // TODO: call in 500ms steps qCDebug(dcHardware) << "--> UPnP discovery called."; - - m_timer->start(5000); + m_timer->start(timeout); } void UpnpDiscoveryRequest::addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor) @@ -73,7 +69,7 @@ QNetworkRequest UpnpDiscoveryRequest::createNetworkRequest(UpnpDeviceDescriptor QNetworkRequest deviceRequest; deviceRequest.setUrl(deviveDescriptor.location()); deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("text/xml")); - deviceRequest.setHeader(QNetworkRequest::UserAgentHeader,QVariant(m_userAgent)); + deviceRequest.setHeader(QNetworkRequest::UserAgentHeader,QVariant(reply()->userAgent())); return deviceRequest; } @@ -83,22 +79,7 @@ QList UpnpDiscoveryRequest::deviceList() const return m_deviceList; } -QPointer UpnpDiscoveryRequest::caller() const +QPointer UpnpDiscoveryRequest::reply() { - return m_caller; -} - -QString UpnpDiscoveryRequest::callbackMethod() const -{ - return m_callbackMethod; -} - -QString UpnpDiscoveryRequest::searchTarget() const -{ - return m_searchTarget; -} - -QString UpnpDiscoveryRequest::userAgent() const -{ - return m_userAgent; + return m_reply; } diff --git a/libguh/network/upnp/upnpdiscoveryrequest.h b/libguh/network/upnp/upnpdiscoveryrequest.h index 6da909c8..85045408 100644 --- a/libguh/network/upnp/upnpdiscoveryrequest.h +++ b/libguh/network/upnp/upnpdiscoveryrequest.h @@ -28,6 +28,7 @@ #include #include "upnpdiscovery.h" +#include "upnpdiscoveryreply.h" #include "upnpdevicedescriptor.h" #include "libguh.h" #include "typeutils.h" @@ -38,26 +39,20 @@ class LIBGUH_EXPORT UpnpDiscoveryRequest : public QObject { Q_OBJECT public: - explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer caller, const QString &callbackMethod, QString searchTarget, QString userAgent); + explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer reply); - void discover(); + void discover(const int &timeout); void addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor); QNetworkRequest createNetworkRequest(UpnpDeviceDescriptor deviveDescriptor); QList deviceList() const; - QPointer caller() const; - QString callbackMethod() const; - QString searchTarget() const; - QString userAgent() const; + QPointer reply(); private: UpnpDiscovery *m_upnpDiscovery; - QTimer *m_timer; - QPointer m_caller; - QString m_callbackMethod; - QString m_searchTarget; - QString m_userAgent; + QPointer m_reply; + QTimer *m_timer = nullptr; QList m_deviceList; signals: diff --git a/libguh/plugintimer.cpp b/libguh/plugintimer.cpp index 7ea6aa95..ac483bbf 100644 --- a/libguh/plugintimer.cpp +++ b/libguh/plugintimer.cpp @@ -23,37 +23,154 @@ #include "plugintimer.h" #include "loggingcategories.h" -PluginTimer::PluginTimer(int intervall, QObject *parent) : - HardwareResource(HardwareResource::TypeTimer, "Plugin timer", parent), - m_intervall(intervall) +int PluginTimer::interval() const { - // FIXME: the timer should be able to emit timerEvents with different resolutions - m_timer = new QTimer(this); - m_timer->setSingleShot(false); - m_timer->setInterval(m_intervall); + return m_interval; +} - connect(m_timer, &QTimer::timeout, this, &PluginTimer::timerEvent); +void PluginTimer::pause() +{ + m_paused = true; +} + +void PluginTimer::resume() +{ + m_paused = false; +} + +int PluginTimer::currentTick() const +{ + return m_currentTick; +} + +bool PluginTimer::running() const +{ + return m_running; +} + +PluginTimer::PluginTimer(int intervall, QObject *parent) : + QObject(parent), + m_interval(intervall) +{ + +} + +void PluginTimer::setRunning(const bool &running) +{ + if (m_running != running) { + m_running = running; + emit runningChanged(m_running); + } +} + +void PluginTimer::setPaused(const bool &paused) +{ + if (m_paused != paused) { + m_paused = paused; + emit pausedChanged(m_paused); + } +} + +void PluginTimer::setCurrentTick(const int &tick) +{ + if (m_currentTick != tick) { + m_currentTick = tick; + emit currentTickChanged(m_currentTick); + } +} + +void PluginTimer::tick() +{ + if (m_paused) + return; + + if (!m_running) + return; + + setCurrentTick(m_currentTick += 1); + + if (m_currentTick >= m_interval) { + emit timeout(); + reset(); + } +} + +void PluginTimer::reset() +{ + setCurrentTick(0); +} + +void PluginTimer::start() +{ + setPaused(false); + setRunning(true); +} + +void PluginTimer::stop() +{ + setPaused(false); + setRunning(false); +} + + +PluginTimer *PluginTimerManager::registerTimer(int seconds) +{ + QPointer pluginTimer = new PluginTimer(seconds, this); + m_timers.append(pluginTimer); + return pluginTimer.data(); +} + +void PluginTimerManager::unregisterTimer(PluginTimer *timer) +{ + QPointer timerPointer(timer); + if (timerPointer.isNull()) { + qCWarning(dcHardware()) << name() << "Cannot unregister timer. Looks like the timer is already unregistered."; + return; + } + + foreach (QPointer tPointer, m_timers) { + if (timerPointer.data() == tPointer.data()) { + m_timers.removeAll(tPointer); + tPointer->deleteLater(); + } + } +} + +PluginTimerManager::PluginTimerManager(QObject *parent) : + HardwareResource(HardwareResource::TypeTimer, "Plugin timer manager", parent) +{ setAvailable(true); - qCDebug(dcHardware()) << "-->" << name() << "created successfully."; } -bool PluginTimer::enable() +void PluginTimerManager::timeTick() +{ + // If timer resource is not enabled do nothing + if (!enabled()) { + return; + } + + foreach (PluginTimer *timer, m_timers) { + timer->tick(); + } +} + +bool PluginTimerManager::enable() { if (!available()) return false; - m_timer->start(); setEnabled(true); return true; } -bool PluginTimer::disable() +bool PluginTimerManager::disable() { if (!available()) return false; - m_timer->stop(); setEnabled(false); return true; } + + diff --git a/libguh/plugintimer.h b/libguh/plugintimer.h index f5eb582c..b010b09d 100644 --- a/libguh/plugintimer.h +++ b/libguh/plugintimer.h @@ -23,24 +23,69 @@ #ifndef PLUGINTIMER_H #define PLUGINTIMER_H -#include #include +#include +#include #include "hardwareresource.h" -class PluginTimer : public HardwareResource +class PluginTimer : public QObject { Q_OBJECT -public: - explicit PluginTimer(int intervall, QObject *parent = nullptr); -private: - QTimer *m_timer = nullptr; - int m_intervall = 10000; + friend class PluginTimerManager; + +public: + int interval() const; + + void pause(); + void resume(); + int currentTick() const; + + bool running() const; signals: - // TODO: emit different resolutions - void timerEvent(); + void timeout(); + void currentTickChanged(const int ¤tTick); + void runningChanged(const bool &running); + void pausedChanged(const bool &paused); + +private: + explicit PluginTimer(int intervall, QObject *parent = nullptr); + int m_interval; + int m_currentTick = 0; + + bool m_paused = false; + bool m_running = true; + + void setRunning(const bool &running); + void setPaused(const bool &paused); + void setCurrentTick(const int &tick); + + void tick(); + +public slots: + void reset(); + void start(); + void stop(); +}; + + +class PluginTimerManager : public HardwareResource +{ + Q_OBJECT + + friend class HardwareManager; + +public: + PluginTimer *registerTimer(int seconds = 60); + void unregisterTimer(PluginTimer *timer = nullptr); + +private: + explicit PluginTimerManager(QObject *parent = nullptr); + QList > m_timers; + + void timeTick(); public slots: bool enable();