Continue migrating hardware resources

This commit is contained in:
Simon Stürz 2017-11-13 15:46:32 +01:00 committed by Michael Zanetti
parent ac436b0751
commit 66b537cadc
15 changed files with 289 additions and 303 deletions

View File

@ -185,6 +185,8 @@
#include "guhsettings.h" #include "guhsettings.h"
#include "unistd.h" #include "unistd.h"
#include "plugintimer.h"
#include <QPluginLoader> #include <QPluginLoader>
#include <QStaticPlugin> #include <QStaticPlugin>
#include <QtPlugin> #include <QtPlugin>
@ -205,10 +207,9 @@ DeviceManager::DeviceManager(const QLocale &locale, QObject *parent) :
m_hardwareManager = new HardwareManager(this); m_hardwareManager = new HardwareManager(this);
connect(m_hardwareManager->pluginTimer(), &PluginTimer::timerEvent, this, &DeviceManager::timerEvent); connect(m_hardwareManager->pluginTimer(), &PluginTimer::timerEvent, this, &DeviceManager::timerEvent);
connect(m_hardwareManager->networkManager(), &NetworkAccessManager::replyReady, this, &DeviceManager::replyReady); // connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished);
connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished); // connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::upnpNotify, this, &DeviceManager::upnpNotifyReceived);
connect(m_hardwareManager->upnpDiscovery(), &UpnpDiscovery::upnpNotify, this, &DeviceManager::upnpNotifyReceived); // connect(m_hardwareManager->bluetoothScanner(), &BluetoothScanner::bluetoothDiscoveryFinished, this, &DeviceManager::bluetoothDiscoveryFinished);
connect(m_hardwareManager->bluetoothScanner(), &BluetoothScanner::bluetoothDiscoveryFinished, this, &DeviceManager::bluetoothDiscoveryFinished);
// Give hardware a chance to start up before loading plugins etc. // Give hardware a chance to start up before loading plugins etc.
QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "loadPlugins", Qt::QueuedConnection);
@ -1424,63 +1425,63 @@ void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const
emit eventTriggered(event); emit eventTriggered(event);
} }
void DeviceManager::radio433SignalReceived(QList<int> rawData) //void DeviceManager::radio433SignalReceived(QList<int> rawData)
{ //{
QList<DevicePlugin*> targetPlugins; // QList<DevicePlugin*> targetPlugins;
foreach (Device *device, m_configuredDevices) { // foreach (Device *device, m_configuredDevices) {
DeviceClass deviceClass = m_supportedDevices.value(device->deviceClassId()); // DeviceClass deviceClass = m_supportedDevices.value(device->deviceClassId());
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId()); // DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) { // if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) {
targetPlugins.append(plugin); // targetPlugins.append(plugin);
} // }
} // }
foreach (DevicePlugin *plugin, m_discoveringPlugins) { // foreach (DevicePlugin *plugin, m_discoveringPlugins) {
if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) { // if (plugin->requiredHardware().testFlag(HardwareResource::TypeRadio433) && !targetPlugins.contains(plugin)) {
targetPlugins.append(plugin); // targetPlugins.append(plugin);
} // }
} // }
foreach (DevicePlugin *plugin, targetPlugins) { // foreach (DevicePlugin *plugin, targetPlugins) {
plugin->radioData(rawData); // plugin->radioData(rawData);
} // }
} //}
void DeviceManager::replyReady(const PluginId &pluginId, QNetworkReply *reply) //void DeviceManager::replyReady(const PluginId &pluginId, QNetworkReply *reply)
{ //{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) { // foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeNetworkManager) && devicePlugin->pluginId() == pluginId) { // if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeNetworkManager) && devicePlugin->pluginId() == pluginId) {
devicePlugin->networkManagerReplyReady(reply); // devicePlugin->networkManagerReplyReady(reply);
} // }
} // }
} //}
void DeviceManager::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId) //void DeviceManager::upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId)
{ //{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) { // foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery) && devicePlugin->pluginId() == pluginId) { // if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery) && devicePlugin->pluginId() == pluginId) {
devicePlugin->upnpDiscoveryFinished(deviceDescriptorList); // devicePlugin->upnpDiscoveryFinished(deviceDescriptorList);
} // }
} // }
} //}
void DeviceManager::upnpNotifyReceived(const QByteArray &notifyData) //void DeviceManager::upnpNotifyReceived(const QByteArray &notifyData)
{ //{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) { // foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery)) { // if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeUpnpDisovery)) {
devicePlugin->upnpNotifyReceived(notifyData); // devicePlugin->upnpNotifyReceived(notifyData);
} // }
} // }
} //}
void DeviceManager::bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos) //void DeviceManager::bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos)
{ //{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) { // foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeBluetoothLE) && devicePlugin->pluginId() == pluginId) { // if (devicePlugin->requiredHardware().testFlag(HardwareResource::TypeBluetoothLE) && devicePlugin->pluginId() == pluginId) {
devicePlugin->bluetoothDiscoveryFinished(deviceInfos); // devicePlugin->bluetoothDiscoveryFinished(deviceInfos);
} // }
} // }
} //}
void DeviceManager::timerEvent() void DeviceManager::timerEvent()
{ {

View File

@ -165,13 +165,14 @@ private slots:
// Only connect this to Devices. It will query the sender() // Only connect this to Devices. It will query the sender()
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value); void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
void radio433SignalReceived(QList<int> rawData); // void radio433SignalReceived(QList<int> rawData);
void replyReady(const PluginId &pluginId, QNetworkReply *reply);
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId); // void replyReady(const PluginId &pluginId, QNetworkReply *reply);
void upnpNotifyReceived(const QByteArray &notifyData);
void bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos); // void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId);
// void upnpNotifyReceived(const QByteArray &notifyData);
// void bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos);
void timerEvent(); void timerEvent();
@ -196,15 +197,6 @@ private:
QList<DevicePlugin *> m_pluginTimerUsers; QList<DevicePlugin *> m_pluginTimerUsers;
HardwareManager *m_hardwareManager; HardwareManager *m_hardwareManager;
// // Hardware Resources
// Radio433 *m_radio433;
// PluginTimer *m_pluginTimer;
// NetworkAccessManager *m_networkManager;
// UpnpDiscovery *m_upnpDiscovery;
// QtAvahiServiceBrowser *m_avahiBrowser;
// BluetoothScanner *m_bluetoothScanner;
QHash<QUuid, DevicePairingInfo> m_pairingsJustAdd; QHash<QUuid, DevicePairingInfo> m_pairingsJustAdd;
QHash<QUuid, DevicePairingInfo> m_pairingsDiscovery; QHash<QUuid, DevicePairingInfo> m_pairingsDiscovery;

View File

@ -56,24 +56,14 @@
/*! Construct the hardware resource Radio433 with the given \a parent. Each possible 433 MHz hardware will be initialized here. */ /*! Construct the hardware resource Radio433 with the given \a parent. Each possible 433 MHz hardware will be initialized here. */
Radio433::Radio433(QObject *parent) : Radio433::Radio433(QObject *parent) :
HardwareResource(HardwareResource::TypeRadio433, parent) HardwareResource(HardwareResource::TypeRadio433, "Radio 433 MHz", parent)
{ {
GuhSettings settings(GuhSettings::SettingsRoleGlobal);
qCDebug(dcHardware) << "Loading GPIO settings from:" << settings.fileName();
settings.beginGroup("RF433");
int transmitterGpioNumber = settings.value("rf433tx",22).toInt();
settings.endGroup();
m_transmitter = new Radio433Trasmitter(this, transmitterGpioNumber);
m_brennenstuhlTransmitter = new Radio433BrennenstuhlGateway(this); m_brennenstuhlTransmitter = new Radio433BrennenstuhlGateway(this);
connect(m_brennenstuhlTransmitter, &Radio433BrennenstuhlGateway::availableChanged, this, &Radio433::brennenstuhlAvailableChanged); connect(m_brennenstuhlTransmitter, &Radio433BrennenstuhlGateway::availableChanged, this, &Radio433::brennenstuhlAvailableChanged);
}
/*! Destroys the hardware resource Radio433 object. */ setAvailable(false);
Radio433::~Radio433()
{ qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
m_transmitter->quit();
} }
/*! Enables GPIO transmitter and receiver and the Brennenstuhl Lan Gateway. /*! Enables GPIO transmitter and receiver and the Brennenstuhl Lan Gateway.
@ -81,22 +71,7 @@ Radio433::~Radio433()
bool Radio433::enable() bool Radio433::enable()
{ {
m_brennenstuhlTransmitter->enable(); m_brennenstuhlTransmitter->enable();
// check if GPIOs are available
if (Gpio::isAvailable()) {
bool transmitterAvailable = m_transmitter->startTransmitter();
if (!transmitterAvailable) {
//qCWarning(dcHardware) << "ERROR: radio 433 MHz transmitter not available on GPIO's";
}
if (!transmitterAvailable) {
qCWarning(dcHardware) << "--> Radio 433 MHz GPIO's not available.";
return false;
}
}
setEnabled(true); setEnabled(true);
qCDebug(dcDeviceManager()) << "--> Radio 433 MHz GPIO's enabled.";
return true; return true;
} }
@ -111,26 +86,26 @@ bool Radio433::disable()
void Radio433::brennenstuhlAvailableChanged(const bool &available) void Radio433::brennenstuhlAvailableChanged(const bool &available)
{ {
if (available) { if (available) {
qCDebug(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway available."; qCDebug(dcHardware()) << name() << "Brennenstuhl LAN Gateway available.";
setAvailable(true); setAvailable(true);
} else { } else {
qCWarning(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway NOT available."; qCWarning(dcHardware()) << name() << "Brennenstuhl LAN Gateway not available.";
setAvailable(false);
} }
} }
/*! Returns true, if the \a rawData with a certain \a delay (pulse length) could be sent \a repetitions times. */ /*! Returns true, if the \a rawData with a certain \a delay (pulse length) could be sent \a repetitions times. */
bool Radio433::sendData(int delay, QList<int> rawData, int repetitions) bool Radio433::sendData(int delay, QList<int> rawData, int repetitions)
{ {
bool sendGpio = false; if (!available()) {
bool sendBrennenstuhl = false; qCWarning(dcHardware()) << name() << "Brennenstuhl gateway not available";
return false;
if (m_brennenstuhlTransmitter->available()) {
sendBrennenstuhl = m_brennenstuhlTransmitter->sendData(delay, rawData, repetitions);
} }
if (m_transmitter->available()) { if (!enabled()) {
m_transmitter->sendData(delay, rawData, repetitions); qCWarning(dcHardware()) << name() << "Hardware reouce disabled.";
sendGpio = true; return false;
} }
return (sendGpio || sendBrennenstuhl);
return m_brennenstuhlTransmitter->sendData(delay, rawData, repetitions);
} }

View File

@ -25,8 +25,6 @@
#include <QObject> #include <QObject>
#include "radio433transmitter.h"
#include "libguh.h" #include "libguh.h"
#include "hardwareresource.h" #include "hardwareresource.h"
#include "radio433brennenstuhlgateway.h" #include "radio433brennenstuhlgateway.h"
@ -34,13 +32,11 @@
class LIBGUH_EXPORT Radio433 : public HardwareResource class LIBGUH_EXPORT Radio433 : public HardwareResource
{ {
Q_OBJECT Q_OBJECT
public:
explicit Radio433(QObject *parent = 0);
~Radio433();
friend class HardwareManager;
private: private:
Radio433Trasmitter *m_transmitter; explicit Radio433(QObject *parent = 0);
Radio433BrennenstuhlGateway *m_brennenstuhlTransmitter; Radio433BrennenstuhlGateway *m_brennenstuhlTransmitter;
private slots: private slots:

View File

@ -1,20 +1,34 @@
#include "hardwaremanager.h" #include "hardwaremanager.h"
#include "plugintimer.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"
#include "network/upnp/upnpdevicedescriptor.h"
#include "network/avahi/qtavahiservicebrowser.h"
HardwareManager::HardwareManager(QObject *parent) : QObject(parent) HardwareManager::HardwareManager(QObject *parent) : QObject(parent)
{ {
// Init hardware resources // Init hardware resources
m_pluginTimer = new PluginTimer(10000, this); m_pluginTimer = new PluginTimer(10000, this);
m_hardwareResources.append(m_pluginTimer); m_hardwareResources.append(m_pluginTimer);
m_radio433 = new Radio433(this); m_radio433 = new Radio433(this);
m_hardwareResources.append(m_radio433);
m_radio433->enable(); m_radio433->enable();
// Create network access manager for all resources, centralized
m_networkAccessManager = new QNetworkAccessManager(this);
// Note: configuration and proxy settings could be implemented here
// Network manager // Network manager
m_networkManager = new NetworkAccessManager(this); m_networkManager = new NetworkAccessManager(m_networkAccessManager, this);
m_hardwareResources.append(m_networkManager);
m_networkManager->enable();
// UPnP discovery // UPnP discovery
m_upnpDiscovery = new UpnpDiscovery(this); m_upnpDiscovery = new UpnpDiscovery(m_networkAccessManager, this);
// Avahi Browser // Avahi Browser
m_avahiBrowser = new QtAvahiServiceBrowser(this); m_avahiBrowser = new QtAvahiServiceBrowser(this);

View File

@ -2,17 +2,17 @@
#define HARDWAREMANAGER_H #define HARDWAREMANAGER_H
#include <QObject> #include <QObject>
#include <QNetworkAccessManager>
#include "plugintimer.h" #include "hardwareresource.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"
#include "network/upnp/upnpdevicedescriptor.h"
#include "network/avahi/qtavahiservicebrowser.h"
class PluginTimer; class PluginTimer;
class BluetoothScanner;
class Radio433;
class NetworkAccessManager;
class UpnpDiscovery; class UpnpDiscovery;
class UpnpDeviceDescriptor;
class QtAvahiServiceBrowser;
class HardwareManager : public QObject class HardwareManager : public QObject
{ {
@ -33,6 +33,8 @@ public:
private: private:
QList<HardwareResource *> m_hardwareResources; QList<HardwareResource *> m_hardwareResources;
QNetworkAccessManager *m_networkAccessManager;
// Hardware Resources // Hardware Resources
Radio433 *m_radio433 = nullptr; Radio433 *m_radio433 = nullptr;
PluginTimer *m_pluginTimer = nullptr; PluginTimer *m_pluginTimer = nullptr;

View File

@ -24,13 +24,19 @@
#include "guhsettings.h" #include "guhsettings.h"
#include "hardwaremanager.h" #include "hardwaremanager.h"
HardwareResource::HardwareResource(const Type &hardwareReourceType, QObject *parent) : HardwareResource::HardwareResource(const Type &hardwareReourceType, const QString &name, QObject *parent) :
QObject(parent), QObject(parent),
m_hardwareReourceType(hardwareReourceType) m_hardwareReourceType(hardwareReourceType),
m_name(name)
{ {
// TODO: load if hardware resource is enabled or not // TODO: load if hardware resource is enabled or not
} }
QString HardwareResource::name() const
{
return m_name;
}
bool HardwareResource::available() const bool HardwareResource::available() const
{ {
return m_available; return m_available;

View File

@ -40,17 +40,21 @@ public:
Q_ENUM(Type) Q_ENUM(Type)
Q_DECLARE_FLAGS(Types, Type) Q_DECLARE_FLAGS(Types, Type)
explicit HardwareResource(const HardwareResource::Type &hardwareReourceType, QObject *parent = nullptr); explicit HardwareResource(const HardwareResource::Type &hardwareReourceType, const QString &name, QObject *parent = nullptr);
HardwareResource::Type hardwareReourceType() const;
QString name() const;
bool available() const; bool available() const;
bool enabled() const; bool enabled() const;
HardwareResource::Type hardwareReourceType() const;
private: private:
HardwareResource::Type m_hardwareReourceType;
QString m_name;
bool m_available = false; bool m_available = false;
bool m_enabled = true; bool m_enabled = true;
HardwareResource::Type m_hardwareReourceType;
protected: protected:
void setEnabled(const bool &enabled); void setEnabled(const bool &enabled);

View File

@ -29,77 +29,82 @@
The network manager class is a reimplementation of the \l{http://doc-snapshot.qt-project.org/qt5-5.4/qnetworkaccessmanager.html}{QNetworkAccessManager} The network manager class is a reimplementation of the \l{http://doc-snapshot.qt-project.org/qt5-5.4/qnetworkaccessmanager.html}{QNetworkAccessManager}
and allows plugins to send network requests and receive replies. and allows plugins to send network requests and receive replies.
*/
/*! */
* \fn NetworkAccessManager::replyReady(const PluginId &pluginId, QNetworkReply *reply)
* This signal will be emitted whenever a pending network \a reply for the plugin with the given \a pluginId is finished.
*
* \sa DevicePlugin::networkManagerReplyReady()
*/
#include "networkaccessmanager.h" #include "networkaccessmanager.h"
#include "loggingcategories.h" #include "loggingcategories.h"
/*! Construct the hardware resource NetworkAccessManager with the given \a parent. */ /*! Construct the hardware resource NetworkAccessManager with the given \a parent. */
NetworkAccessManager::NetworkAccessManager(QObject *parent) : NetworkAccessManager::NetworkAccessManager(QNetworkAccessManager *networkManager, QObject *parent) :
QObject(parent) HardwareResource(HardwareResource::TypeNetworkManager, "Network access manager" , parent),
m_manager(networkManager)
{ {
m_manager = new QNetworkAccessManager(this); setAvailable(true);
connect(m_manager, &QNetworkAccessManager::finished, this, &NetworkAccessManager::replyFinished);
qCDebug(dcDeviceManager) << "--> Network manager created successfully."; qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
} }
/*! Posts a request to obtain the contents of the target \a request from the plugin with the given \a pluginId QNetworkReply *NetworkAccessManager::get(const QNetworkRequest &request)
* and returns a new QNetworkReply object opened for reading which emits the replyReady() signal whenever new
* data arrives.
* The contents as well as associated headers will be downloaded.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa DevicePlugin::networkManagerGet()
*/
QNetworkReply *NetworkAccessManager::get(const PluginId &pluginId, const QNetworkRequest &request)
{ {
QNetworkReply *reply = m_manager->get(request); return m_manager->get(request);
m_replies.insert(reply, pluginId);
return reply;
} }
/*! Sends an HTTP POST request to the destination specified by \a request from the plugin with the given QNetworkReply *NetworkAccessManager::deleteResource(const QNetworkRequest &request)
* \a pluginId and returns a new QNetworkReply object opened for reading that will contain the reply sent
* by the server. The contents of the \a data will be uploaded to the server.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa DevicePlugin::networkManagerPost()
*/
QNetworkReply *NetworkAccessManager::post(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data)
{ {
QNetworkReply *reply = m_manager->post(request, data); return m_manager->deleteResource(request);
m_replies.insert(reply, pluginId);
return reply;
} }
/*! Uploads the contents of \a data to the destination \a request from the plugin with the given QNetworkReply *NetworkAccessManager::head(const QNetworkRequest &request)
* \a pluginId and returnes a new QNetworkReply object that will be open for reply.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa DevicePlugin::networkManagerPut()
*/
QNetworkReply *NetworkAccessManager::put(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data)
{ {
QNetworkReply *reply = m_manager->put(request, data); return m_manager->head(request);
m_replies.insert(reply, pluginId);
return reply;
} }
void NetworkAccessManager::replyFinished(QNetworkReply *reply) QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
{ {
// NOTE: Each plugin has to delete his own replys with deleteLater()!! return m_manager->post(request, data);
// NOTE: also the reply->error() has to be handled in each plugin!! }
PluginId pluginId = m_replies.take(reply);
emit replyReady(pluginId, reply); QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
{
return m_manager->post(request, data);
}
QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
{
return m_manager->post(request, multiPart);
}
QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
{
return m_manager->put(request, data);
}
QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
{
return m_manager->post(request, data);
}
QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
{
return m_manager->post(request, multiPart);
}
QNetworkReply *NetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
{
return m_manager->sendCustomRequest(request, verb, data);
}
bool NetworkAccessManager::enable()
{
m_manager->setNetworkAccessible(QNetworkAccessManager::Accessible);
setEnabled(true);
return true;
}
bool NetworkAccessManager::disable()
{
m_manager->setNetworkAccessible(QNetworkAccessManager::NotAccessible);
setEnabled(false);
return true;
} }

View File

@ -25,6 +25,7 @@
#include "libguh.h" #include "libguh.h"
#include "typeutils.h" #include "typeutils.h"
#include "hardwareresource.h"
#include <QObject> #include <QObject>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
@ -33,25 +34,36 @@
#include <QDebug> #include <QDebug>
#include <QUrl> #include <QUrl>
class LIBGUH_EXPORT NetworkAccessManager : public QObject class LIBGUH_EXPORT NetworkAccessManager : public HardwareResource
{ {
Q_OBJECT Q_OBJECT
public:
explicit NetworkAccessManager(QObject *parent = 0);
QNetworkReply *get(const PluginId &pluginId, const QNetworkRequest &request); friend class HardwareManager;
QNetworkReply *post(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *put(const PluginId &pluginId, const QNetworkRequest &request, const QByteArray &data); public:
// Note: only these methods are allowed from a plugin perspective
QNetworkReply *get(const QNetworkRequest &request);
QNetworkReply *deleteResource(const QNetworkRequest &request);
QNetworkReply *head(const QNetworkRequest &request);
QNetworkReply *post(const QNetworkRequest &request, QIODevice *data);
QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *post(const QNetworkRequest &request, QHttpMultiPart *multiPart);
QNetworkReply *put(const QNetworkRequest &request, QIODevice *data);
QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *put(const QNetworkRequest &request, QHttpMultiPart *multiPart);
QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data = nullptr);
private: private:
// Note: only the HardwareManager is allowed to create this resource
NetworkAccessManager(QNetworkAccessManager *networkManager, QObject *parent = 0);
QNetworkAccessManager *m_manager; QNetworkAccessManager *m_manager;
QHash<QNetworkReply *, PluginId> m_replies;
signals: public slots:
void replyReady(const PluginId &pluginId, QNetworkReply *reply); bool enable();
bool disable();
private slots:
void replyFinished(QNetworkReply *reply);
}; };

View File

@ -57,44 +57,17 @@
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
/*! Construct the hardware resource UpnpDiscovery with the given \a parent. */ /*! Construct the hardware resource UpnpDiscovery with the given \a parent. */
UpnpDiscovery::UpnpDiscovery(QObject *parent) : UpnpDiscovery::UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent) :
QUdpSocket(parent) HardwareResource(HardwareResource::TypeUpnpDisovery, "UPnP discovery", parent),
m_networkAccessManager(networkAccessManager)
{ {
// bind udp socket and join multicast group
m_port = 1900;
m_host = QHostAddress("239.255.255.250");
setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1));
setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1));
if(!bind(QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress)){
qCWarning(dcHardware) << "UPnP discovery could not bind to port" << m_port;
return;
}
if(!joinMulticastGroup(m_host)){
qCWarning(dcHardware) << "UPnP discovery could not join multicast group" << m_host;
return;
}
// network access manager for requesting device information
m_networkAccessManager = new QNetworkAccessManager(this);
connect(m_networkAccessManager, &QNetworkAccessManager::finished, this, &UpnpDiscovery::replyFinished);
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
connect(this, &UpnpDiscovery::readyRead, this, &UpnpDiscovery::readData);
m_notificationTimer = new QTimer(this); m_notificationTimer = new QTimer(this);
m_notificationTimer->setInterval(30000); m_notificationTimer->setInterval(30000);
m_notificationTimer->setSingleShot(false); m_notificationTimer->setSingleShot(false);
connect(m_notificationTimer, &QTimer::timeout, this, &UpnpDiscovery::notificationTimeout); connect(m_notificationTimer, &QTimer::timeout, this, &UpnpDiscovery::notificationTimeout);
m_notificationTimer->start(); setAvailable(true);
qCDebug(dcDeviceManager) << "-->" << name() << "created successfully.";
qCDebug(dcDeviceManager) << "--> UPnP discovery created successfully.";
sendAliveMessage();
sendAliveMessage();
} }
/*! Destruct this \l{UpnpDiscovery} object. */ /*! Destruct this \l{UpnpDiscovery} object. */
@ -102,20 +75,20 @@ UpnpDiscovery::~UpnpDiscovery()
{ {
qCDebug(dcApplication) << "Shutting down \"UPnP Server\""; qCDebug(dcApplication) << "Shutting down \"UPnP Server\"";
sendByeByeMessage(); sendByeByeMessage();
waitForBytesWritten(); m_socket->waitForBytesWritten();
close(); m_socket->close();
} }
/*! Returns false, if the \l{UpnpDiscovery} resource is not available. Returns true, if a device with /*! 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.*/ * the given \a searchTarget, \a userAgent and \a pluginId can be discovered.*/
bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &userAgent, const PluginId &pluginId) bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &userAgent, const PluginId &pluginId)
{ {
if(state() != BoundState){ if(m_socket->state() != QUdpSocket::BoundState){
qCWarning(dcHardware) << "UPnP not bound to port 1900"; qCWarning(dcHardware) << "UPnP not bound to port 1900";
return false; return false;
} }
qCDebug(dcHardware) << "UPnP: discover" << searchTarget << userAgent; qCDebug(dcHardware) << name() << "discover" << searchTarget << userAgent;
// create a new request // create a new request
UpnpDiscoveryRequest *request = new UpnpDiscoveryRequest(this, pluginId, searchTarget, userAgent); UpnpDiscoveryRequest *request = new UpnpDiscoveryRequest(this, pluginId, searchTarget, userAgent);
@ -129,8 +102,7 @@ bool UpnpDiscovery::discoverDevices(const QString &searchTarget, const QString &
void UpnpDiscovery::requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor) void UpnpDiscovery::requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor)
{ {
QNetworkReply *replay; QNetworkReply *replay = m_networkAccessManager->get(networkRequest);
replay = m_networkAccessManager->get(networkRequest);
m_informationRequestList.insert(replay, upnpDeviceDescriptor); m_informationRequestList.insert(replay, upnpDeviceDescriptor);
} }
@ -187,7 +159,7 @@ void UpnpDiscovery::respondToSearchRequest(QHostAddress host, int port)
"\r\n"); "\r\n");
//qCDebug(dcHardware) << QString("Sending response to %1:%2\n").arg(host.toString()).arg(port); //qCDebug(dcHardware) << QString("Sending response to %1:%2\n").arg(host.toString()).arg(port);
writeDatagram(rootdeviceResponseMessage, host, port); m_socket->writeDatagram(rootdeviceResponseMessage, host, port);
} }
} }
} }
@ -197,12 +169,12 @@ void UpnpDiscovery::respondToSearchRequest(QHostAddress host, int port)
/*! This method will be called to send the SSDP message \a data to the UPnP multicast.*/ /*! This method will be called to send the SSDP message \a data to the UPnP multicast.*/
void UpnpDiscovery::sendToMulticast(const QByteArray &data) void UpnpDiscovery::sendToMulticast(const QByteArray &data)
{ {
writeDatagram(data, m_host, m_port); m_socket->writeDatagram(data, m_host, m_port);
} }
void UpnpDiscovery::error(QAbstractSocket::SocketError error) void UpnpDiscovery::error(QAbstractSocket::SocketError error)
{ {
qCWarning(dcHardware) << "UPnP socket error:" << error << errorString(); qCWarning(dcHardware) << "UPnP socket error:" << error << m_socket->errorString();
} }
void UpnpDiscovery::readData() void UpnpDiscovery::readData()
@ -213,9 +185,9 @@ void UpnpDiscovery::readData()
QUrl location; QUrl location;
// read the answere from the multicast // read the answere from the multicast
while (hasPendingDatagrams()) { while (m_socket->hasPendingDatagrams()) {
data.resize(pendingDatagramSize()); data.resize(m_socket->pendingDatagramSize());
readDatagram(data.data(), data.size(), &hostAddress, &port); m_socket->readDatagram(data.data(), data.size(), &hostAddress, &port);
} }
if (data.contains("M-SEARCH") && !QNetworkInterface::allAddresses().contains(hostAddress)) { if (data.contains("M-SEARCH") && !QNetworkInterface::allAddresses().contains(hostAddress)) {
@ -434,3 +406,52 @@ void UpnpDiscovery::discoverTimeout()
m_discoverRequests.removeOne(discoveryRequest); m_discoverRequests.removeOne(discoveryRequest);
delete discoveryRequest; delete discoveryRequest;
} }
bool UpnpDiscovery::enable()
{
// Clean up
if (m_socket) {
delete m_socket;
m_socket = nullptr;
}
// Bind udp socket and join multicast group
m_socket = new QUdpSocket(this);
m_port = 1900;
m_host = QHostAddress("239.255.255.250");
m_socket->setSocketOption(QAbstractSocket::MulticastTtlOption,QVariant(1));
m_socket->setSocketOption(QAbstractSocket::MulticastLoopbackOption,QVariant(1));
if(!m_socket->bind(QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress)){
qCWarning(dcHardware()) << name() << "could not bind to port" << m_port;
delete m_socket;
m_socket = nullptr;
return false;
}
if(!m_socket->joinMulticastGroup(m_host)){
qCWarning(dcHardware()) << name() << "could not join multicast group" << m_host;
delete m_socket;
m_socket = nullptr;
return false;
}
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
connect(m_socket, &QUdpSocket::readyRead, this, &UpnpDiscovery::readData);
m_notificationTimer->start();
sendAliveMessage();
sendAliveMessage();
setEnabled(true);
return true;
}
bool UpnpDiscovery::disable()
{
// TODO:
setEnabled(false);
return true;
}

View File

@ -31,33 +31,38 @@
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QUrl> #include <QUrl>
#include "libguh.h"
#include "devicemanager.h"
#include "hardwareresource.h"
#include "upnpdiscoveryrequest.h" #include "upnpdiscoveryrequest.h"
#include "upnpdevicedescriptor.h" #include "upnpdevicedescriptor.h"
#include "devicemanager.h"
#include "libguh.h"
// Discovering UPnP devices reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf // Discovering UPnP devices reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
// guh basic device reference: http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf // guh basic device reference: http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf
class UpnpDiscoveryRequest; class UpnpDiscoveryRequest;
class LIBGUH_EXPORT UpnpDiscovery : public QUdpSocket class LIBGUH_EXPORT UpnpDiscovery : public HardwareResource
{ {
Q_OBJECT Q_OBJECT
public:
explicit UpnpDiscovery(QObject *parent = 0);
~UpnpDiscovery();
friend class HardwareManager;
public:
bool discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = "", const PluginId &pluginId = PluginId()); bool discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = "", const PluginId &pluginId = PluginId());
void sendToMulticast(const QByteArray &data); void sendToMulticast(const QByteArray &data);
private: private:
explicit UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent = 0);
~UpnpDiscovery();
QUdpSocket *m_socket = nullptr;
QHostAddress m_host; QHostAddress m_host;
qint16 m_port; qint16 m_port;
QTimer *m_notificationTimer; QTimer *m_notificationTimer = nullptr;
QNetworkAccessManager *m_networkAccessManager; QNetworkAccessManager *m_networkAccessManager = nullptr;
QList<UpnpDiscoveryRequest *> m_discoverRequests; QList<UpnpDiscoveryRequest *> m_discoverRequests;
QHash<QNetworkReply*,UpnpDeviceDescriptor> m_informationRequestList; QHash<QNetworkReply*,UpnpDeviceDescriptor> m_informationRequestList;
@ -77,6 +82,10 @@ private slots:
void sendByeByeMessage(); void sendByeByeMessage();
void sendAliveMessage(); void sendAliveMessage();
void discoverTimeout(); void discoverTimeout();
public slots:
bool enable();
bool disable();
}; };
#endif // UPNPDISCOVERY_H #endif // UPNPDISCOVERY_H

View File

@ -148,6 +148,7 @@
#include "devicemanager.h" #include "devicemanager.h"
#include "guhsettings.h" #include "guhsettings.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h" #include "hardware/radio433/radio433.h"
#include "network/upnp/upnpdiscovery.h" #include "network/upnp/upnpdiscovery.h"
@ -541,56 +542,6 @@ bool DevicePlugin::transmitData(int delay, QList<int> rawData, int repetitions)
} }
return false; return false;
} }
/*! Posts a request to obtain the contents of the target \a request and returns a new QNetworkReply object
* opened for reading which emits the replyReady() signal whenever new data arrives.
* The contents as well as associated headers will be downloaded.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa NetworkAccessManager::get()
*/
QNetworkReply *DevicePlugin::networkManagerGet(const QNetworkRequest &request)
{
if (requiredHardware().testFlag(HardwareResource::TypeNetworkManager)) {
return deviceManager()->m_hardwareManager->networkManager()->get(pluginId(), request);
} else {
qCWarning(dcDeviceManager) << "Network manager hardware resource not set for plugin" << pluginName();
}
return nullptr;
}
/*! Sends an HTTP POST request to the destination specified by \a request and returns a new QNetworkReply object
* opened for reading that will contain the reply sent by the server. The contents of the \a data will be
* uploaded to the server.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa NetworkAccessManager::post()
*/
QNetworkReply *DevicePlugin::networkManagerPost(const QNetworkRequest &request, const QByteArray &data)
{
if (requiredHardware().testFlag(HardwareResource::TypeNetworkManager)) {
return deviceManager()->m_hardwareManager->networkManager()->post(pluginId(), request, data);
} else {
qCWarning(dcDeviceManager) << "Network manager hardware resource not set for plugin" << pluginName();
}
return nullptr;
}
/*! Uploads the contents of \a data to the destination \a request and returnes a new QNetworkReply object that will be open for reply.
*
* \note The plugin has to delete the QNetworkReply with the function deleteLater().
*
* \sa NetworkAccessManager::put()
*/
QNetworkReply *DevicePlugin::networkManagerPut(const QNetworkRequest &request, const QByteArray &data)
{
if (requiredHardware().testFlag(HardwareResource::TypeNetworkManager)) {
return deviceManager()->m_hardwareManager->networkManager()->put(pluginId(), request, data);
} else {
qCWarning(dcDeviceManager) << "Network manager hardware resource not set for plugin" << pluginName();
}
return nullptr;
}
void DevicePlugin::setMetaData(const QJsonObject &metaData) void DevicePlugin::setMetaData(const QJsonObject &metaData)
{ {

View File

@ -119,11 +119,6 @@ protected:
// Bluetooth LE discovery // Bluetooth LE discovery
bool discoverBluetooth(); bool discoverBluetooth();
// Network manager
QNetworkReply *networkManagerGet(const QNetworkRequest &request);
QNetworkReply *networkManagerPost(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *networkManagerPut(const QNetworkRequest &request, const QByteArray &data);
private: private:
void setMetaData(const QJsonObject &metaData); void setMetaData(const QJsonObject &metaData);
void loadMetaData(); void loadMetaData();

View File

@ -1,7 +1,8 @@
#include "plugintimer.h" #include "plugintimer.h"
#include "loggingcategories.h"
PluginTimer::PluginTimer(int intervall, QObject *parent) : PluginTimer::PluginTimer(int intervall, QObject *parent) :
HardwareResource(HardwareResource::TypeTimer, parent), HardwareResource(HardwareResource::TypeTimer, "Plugin timer", parent),
m_intervall(intervall) m_intervall(intervall)
{ {
// FIXME: the timer should be able to emit timerEvents with different resolutions // FIXME: the timer should be able to emit timerEvents with different resolutions
@ -11,6 +12,8 @@ PluginTimer::PluginTimer(int intervall, QObject *parent) :
connect(m_timer, &QTimer::timeout, this, &PluginTimer::timerEvent); connect(m_timer, &QTimer::timeout, this, &PluginTimer::timerEvent);
setAvailable(true); setAvailable(true);
qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
} }
bool PluginTimer::enable() bool PluginTimer::enable()