diff --git a/libguh/hardware/bluetooth/bluetoothdiscoveryreply.cpp b/libguh-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp similarity index 69% rename from libguh/hardware/bluetooth/bluetoothdiscoveryreply.cpp rename to libguh-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp index 11335d36..acc368b9 100644 --- a/libguh/hardware/bluetooth/bluetoothdiscoveryreply.cpp +++ b/libguh-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp @@ -20,31 +20,34 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "bluetoothdiscoveryreply.h" +#include "bluetoothdiscoveryreplyimplementation.h" #include -bool BluetoothDiscoveryReply::isFinished() const +namespace guhserver { + +BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyImplementation(QObject *parent) : + BluetoothDiscoveryReply(parent) +{ + +} + +bool BluetoothDiscoveryReplyImplementation::isFinished() const { return m_finished; } -BluetoothDiscoveryReply::BluetoothDiscoveryReplyError BluetoothDiscoveryReply::error() const +BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyError BluetoothDiscoveryReplyImplementation::error() const { return m_error; } -QList BluetoothDiscoveryReply::discoveredDevices() const +QList BluetoothDiscoveryReplyImplementation::discoveredDevices() const { return m_discoveredDevices; } -BluetoothDiscoveryReply::BluetoothDiscoveryReply(QObject *parent) : QObject(parent) -{ - -} - -void BluetoothDiscoveryReply::setError(const BluetoothDiscoveryReply::BluetoothDiscoveryReplyError &error) +void BluetoothDiscoveryReplyImplementation::setError(const BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyError &error) { m_error = error; if (m_error != BluetoothDiscoveryReplyErrorNoError) { @@ -52,14 +55,16 @@ void BluetoothDiscoveryReply::setError(const BluetoothDiscoveryReply::BluetoothD } } -void BluetoothDiscoveryReply::setDiscoveredDevices(const QList &discoveredDevices) +void BluetoothDiscoveryReplyImplementation::setDiscoveredDevices(const QList &discoveredDevices) { m_discoveredDevices = discoveredDevices; } -void BluetoothDiscoveryReply::setFinished() +void BluetoothDiscoveryReplyImplementation::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); + QTimer::singleShot(0, this, &BluetoothDiscoveryReplyImplementation::finished); +} + } diff --git a/libguh-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h b/libguh-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h new file mode 100644 index 00000000..c81a2e06 --- /dev/null +++ b/libguh-core/hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h @@ -0,0 +1,58 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * 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 BLUETOOTHDISCOVERYREPLYIMPLEMENTATION_H +#define BLUETOOTHDISCOVERYREPLYIMPLEMENTATION_H + +#include +#include + +#include "hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h" + +namespace guhserver { + +class BluetoothDiscoveryReplyImplementation : public BluetoothDiscoveryReply +{ + Q_OBJECT + + friend class BluetoothLowEnergyManagerImplementation; + +public: + explicit BluetoothDiscoveryReplyImplementation(QObject *parent = nullptr); + + bool isFinished() const; + BluetoothDiscoveryReplyError error() const; + QList discoveredDevices() const; + +private: + bool m_finished = false; + BluetoothDiscoveryReplyError m_error = BluetoothDiscoveryReplyErrorNoError; + QList m_discoveredDevices; + + void setError(const BluetoothDiscoveryReplyError &error); + void setDiscoveredDevices(const QList &discoveredDevices); + void setFinished(); +}; + +} + +#endif // BLUETOOTHDISCOVERYREPLYIMPLEMENTATION_H diff --git a/libguh/hardware/bluetooth/bluetoothlowenergydevice.cpp b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp similarity index 69% rename from libguh/hardware/bluetooth/bluetoothlowenergydevice.cpp rename to libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp index f3d56fcc..f37a68a4 100644 --- a/libguh/hardware/bluetooth/bluetoothlowenergydevice.cpp +++ b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp @@ -20,38 +20,41 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "bluetoothlowenergydevice.h" +#include "bluetoothlowenergydeviceimplementation.h" #include "loggingcategories.h" -QString BluetoothLowEnergyDevice::name() const +namespace guhserver { + +QString BluetoothLowEnergyDeviceImplementation::name() const { return m_deviceInfo.name(); } -QBluetoothAddress BluetoothLowEnergyDevice::address() const +QBluetoothAddress BluetoothLowEnergyDeviceImplementation::address() const { return m_deviceInfo.address(); } -QLowEnergyController *BluetoothLowEnergyDevice::controller() const +QLowEnergyController *BluetoothLowEnergyDeviceImplementation::controller() const { return m_controller; } -BluetoothLowEnergyDevice::BluetoothLowEnergyDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) : - QObject(parent), m_deviceInfo(deviceInfo) +BluetoothLowEnergyDeviceImplementation::BluetoothLowEnergyDeviceImplementation(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) : + BluetoothLowEnergyDevice(parent), + m_deviceInfo(deviceInfo) { m_controller = new QLowEnergyController(address(), this); m_controller->setRemoteAddressType(addressType); - connect(m_controller, &QLowEnergyController::connected, this, &BluetoothLowEnergyDevice::onConnected); - connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothLowEnergyDevice::onDisconnected); - connect(m_controller, &QLowEnergyController::discoveryFinished, this, &BluetoothLowEnergyDevice::onServiceDiscoveryFinished); - connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothLowEnergyDevice::onStateChanged); + connect(m_controller, &QLowEnergyController::connected, this, &BluetoothLowEnergyDeviceImplementation::onConnected); + connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothLowEnergyDeviceImplementation::onDisconnected); + connect(m_controller, &QLowEnergyController::discoveryFinished, this, &BluetoothLowEnergyDeviceImplementation::onServiceDiscoveryFinished); + connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothLowEnergyDeviceImplementation::onStateChanged); connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onDeviceError(QLowEnergyController::Error))); } -void BluetoothLowEnergyDevice::setConnected(const bool &connected) +void BluetoothLowEnergyDeviceImplementation::setConnected(const bool &connected) { if (m_connected != connected) { m_connected = connected; @@ -60,7 +63,7 @@ void BluetoothLowEnergyDevice::setConnected(const bool &connected) } } -void BluetoothLowEnergyDevice::setEnabled(const bool &enabled) +void BluetoothLowEnergyDeviceImplementation::setEnabled(const bool &enabled) { m_enabled = enabled; @@ -73,7 +76,7 @@ void BluetoothLowEnergyDevice::setEnabled(const bool &enabled) } } -void BluetoothLowEnergyDevice::onConnected() +void BluetoothLowEnergyDeviceImplementation::onConnected() { setConnected(true); @@ -83,13 +86,13 @@ void BluetoothLowEnergyDevice::onConnected() } } -void BluetoothLowEnergyDevice::onDisconnected() +void BluetoothLowEnergyDeviceImplementation::onDisconnected() { qCWarning(dcBluetooth()) << "Device disconnected" << name() << address().toString(); setConnected(false); } -void BluetoothLowEnergyDevice::onServiceDiscoveryFinished() +void BluetoothLowEnergyDeviceImplementation::onServiceDiscoveryFinished() { qCDebug(dcBluetooth()) << "Service discovery finished for" << name() << address().toString(); foreach (const QBluetoothUuid &serviceUuid, m_controller->services()) { @@ -98,13 +101,13 @@ void BluetoothLowEnergyDevice::onServiceDiscoveryFinished() emit servicesDiscoveryFinished(); } -void BluetoothLowEnergyDevice::onStateChanged(const QLowEnergyController::ControllerState &state) +void BluetoothLowEnergyDeviceImplementation::onStateChanged(const QLowEnergyController::ControllerState &state) { qCDebug(dcBluetooth()) << "State changed for" << name() << address().toString() << state; emit stateChanged(state); } -void BluetoothLowEnergyDevice::connectDevice() +void BluetoothLowEnergyDeviceImplementation::connectDevice() { if (!m_enabled) return; @@ -116,17 +119,17 @@ void BluetoothLowEnergyDevice::connectDevice() m_controller->connectToDevice(); } -void BluetoothLowEnergyDevice::disconnectDevice() +void BluetoothLowEnergyDeviceImplementation::disconnectDevice() { m_controller->disconnectFromDevice(); } -bool BluetoothLowEnergyDevice::autoConnecting() const +bool BluetoothLowEnergyDeviceImplementation::autoConnecting() const { return m_autoConnecting; } -void BluetoothLowEnergyDevice::setAutoConnecting(const bool &autoConnecting) +void BluetoothLowEnergyDeviceImplementation::setAutoConnecting(const bool &autoConnecting) { if (m_autoConnecting != autoConnecting) { m_autoConnecting = autoConnecting; @@ -134,25 +137,27 @@ void BluetoothLowEnergyDevice::setAutoConnecting(const bool &autoConnecting) } } -bool BluetoothLowEnergyDevice::connected() const +bool BluetoothLowEnergyDeviceImplementation::connected() const { return m_connected; } -bool BluetoothLowEnergyDevice::discovered() const +bool BluetoothLowEnergyDeviceImplementation::discovered() const { return m_discovered; } -QList BluetoothLowEnergyDevice::serviceUuids() const +QList BluetoothLowEnergyDeviceImplementation::serviceUuids() const { return m_controller->services(); } -void BluetoothLowEnergyDevice::onDeviceError(const QLowEnergyController::Error &error) +void BluetoothLowEnergyDeviceImplementation::onDeviceError(const QLowEnergyController::Error &error) { if (connected()) qCWarning(dcBluetooth()) << "Device error:" << name() << address().toString() << ": " << error << m_controller->errorString(); emit errorOccured(error); } + +} diff --git a/libguh/hardware/bluetooth/bluetoothlowenergydevice.h b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h similarity index 84% rename from libguh/hardware/bluetooth/bluetoothlowenergydevice.h rename to libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h index 1cdf846d..8eb30b82 100644 --- a/libguh/hardware/bluetooth/bluetoothlowenergydevice.h +++ b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h @@ -20,8 +20,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifndef BLUETOOTHLOWENERGYDEVICE_H -#define BLUETOOTHLOWENERGYDEVICE_H +#ifndef BLUETOOTHLOWENERGYDEVICEIMPLEMENTATION_H +#define BLUETOOTHLOWENERGYDEVICEIMPLEMENTATION_H #include #include @@ -29,15 +29,19 @@ #include #include -#include "libguh.h" +#include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h" -class LIBGUH_EXPORT BluetoothLowEnergyDevice : public QObject +namespace guhserver { + +class BluetoothLowEnergyDeviceImplementation : public BluetoothLowEnergyDevice { Q_OBJECT - friend class BluetoothLowEnergyManager; + friend class BluetoothLowEnergyManagerImplementation; public: + explicit BluetoothLowEnergyDeviceImplementation(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::PublicAddress, QObject *parent = 0); + QString name() const; QBluetoothAddress address() const; @@ -54,7 +58,6 @@ public: QLowEnergyController *controller() const; private: - explicit BluetoothLowEnergyDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::PublicAddress, QObject *parent = 0); QBluetoothDeviceInfo m_deviceInfo; QLowEnergyController *m_controller = nullptr; @@ -84,4 +87,6 @@ private slots: void onDeviceError(const QLowEnergyController::Error &error); }; -#endif // BLUETOOTHLOWENERGYDEVICE_H +} + +#endif // BLUETOOTHLOWENERGYDEVICEIMPLEMENTATION_H diff --git a/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp similarity index 74% rename from libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp rename to libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp index 7b401a67..7c4980b4 100644 --- a/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp +++ b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp @@ -20,30 +20,70 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "bluetoothlowenergymanager.h" +#include "bluetoothlowenergymanagerimplementation.h" #include "loggingcategories.h" -BluetoothDiscoveryReply *BluetoothLowEnergyManager::discoverDevices(const int &interval) +namespace guhserver { + +BluetoothLowEnergyManagerImplementation::BluetoothLowEnergyManagerImplementation(PluginTimer *reconnectTimer, QObject *parent) : + BluetoothLowEnergyManager(parent), + m_reconnectTimer(reconnectTimer) +{ + // Check which bluetooth adapter are available + QList bluetoothAdapters = QBluetoothLocalDevice::allDevices(); + if (bluetoothAdapters.isEmpty()) { + qCWarning(dcBluetooth()) << "No bluetooth adapter found. Resource not available."; + m_available = false; + return; + } + + // Create a scanner for each adapter + foreach (const QBluetoothHostInfo &hostInfo, bluetoothAdapters) { + qCDebug(dcBluetooth()) << "Using adapter:" << hostInfo.name() << hostInfo.address().toString(); + QBluetoothLocalDevice localDevice(hostInfo.address()); + localDevice.powerOn(); + localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable); + QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(hostInfo.address(), this); + connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothLowEnergyManagerImplementation::onDeviceDiscovered); + connect(discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error))); + m_bluetoothDiscoveryAgents.append(discoveryAgent); + } + + // Discovery timer, interval depends on discovery call + m_timer = new QTimer(this); + m_timer->setSingleShot(true); + connect(m_timer, &QTimer::timeout, this, &BluetoothLowEnergyManagerImplementation::onDiscoveryTimeout); + + // Reconnect timer + connect(m_reconnectTimer, &PluginTimer::timeout, this, &BluetoothLowEnergyManagerImplementation::onReconnectTimeout); + + qCDebug(dcHardware()) << "-->" << name() << "created successfully."; + m_available = true; +} + + + +BluetoothDiscoveryReply *BluetoothLowEnergyManagerImplementation::discoverDevices(const int &interval) { // Create the reply for this discovery request - QPointer reply = new BluetoothDiscoveryReply(this); + QPointer reply = new BluetoothDiscoveryReplyImplementation(this); if (!available()) { qCWarning(dcBluetooth()) << "is not avilable."; - reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNotAvailable); + reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorNotAvailable); reply->setFinished(); return reply.data(); } if (!enabled()) { qCWarning(dcBluetooth()) << "is not enabled."; - reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNotEnabled); + reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorNotEnabled); reply->setFinished(); return reply.data(); } if (!m_currentReply.isNull()) { qCWarning(dcBluetooth()) << "resource busy. There is already a discovery running."; - reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorBusy); + reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorBusy); reply->setFinished(); return reply.data(); } @@ -73,15 +113,15 @@ BluetoothDiscoveryReply *BluetoothLowEnergyManager::discoverDevices(const int &i return reply.data(); } -BluetoothLowEnergyDevice *BluetoothLowEnergyManager::registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType) +BluetoothLowEnergyDevice *BluetoothLowEnergyManagerImplementation::registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType) { - QPointer bluetoothDevice = new BluetoothLowEnergyDevice(deviceInfo, addressType, this); + QPointer bluetoothDevice = new BluetoothLowEnergyDeviceImplementation(deviceInfo, addressType, this); qCDebug(dcBluetooth()) << "Register device" << bluetoothDevice->name() << bluetoothDevice->address().toString(); m_devices.append(bluetoothDevice); return bluetoothDevice.data(); } -void BluetoothLowEnergyManager::unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice) +void BluetoothLowEnergyManagerImplementation::unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice) { QPointer devicePointer(bluetoothDevice); if (devicePointer.isNull()) { @@ -91,7 +131,7 @@ void BluetoothLowEnergyManager::unregisterDevice(BluetoothLowEnergyDevice *bluet qCDebug(dcBluetooth()) << "Unregister device" << bluetoothDevice->name() << bluetoothDevice->address().toString(); - foreach (QPointer dPointer, m_devices) { + foreach (QPointer dPointer, m_devices) { if (devicePointer.data() == dPointer.data()) { m_devices.removeAll(dPointer); dPointer->deleteLater(); @@ -99,43 +139,26 @@ void BluetoothLowEnergyManager::unregisterDevice(BluetoothLowEnergyDevice *bluet } } -BluetoothLowEnergyManager::BluetoothLowEnergyManager(PluginTimer *reconnectTimer, QObject *parent) : - HardwareResource("Bluetooth LE manager", parent), - m_reconnectTimer(reconnectTimer) +bool BluetoothLowEnergyManagerImplementation::available() const { - // Check which bluetooth adapter are available - QList bluetoothAdapters = QBluetoothLocalDevice::allDevices(); - if (bluetoothAdapters.isEmpty()) { - qCWarning(dcBluetooth()) << "No bluetooth adapter found. Resource not available."; - setAvailable(false); - return; - } - - // Create a scanner for each adapter - foreach (const QBluetoothHostInfo &hostInfo, bluetoothAdapters) { - qCDebug(dcBluetooth()) << "Using adapter:" << hostInfo.name() << hostInfo.address().toString(); - QBluetoothLocalDevice localDevice(hostInfo.address()); - localDevice.powerOn(); - localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable); - QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(hostInfo.address(), this); - connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothLowEnergyManager::onDeviceDiscovered); - connect(discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error))); - m_bluetoothDiscoveryAgents.append(discoveryAgent); - } - - // Discovery timer, interval depends on discovery call - m_timer = new QTimer(this); - m_timer->setSingleShot(true); - connect(m_timer, &QTimer::timeout, this, &BluetoothLowEnergyManager::onDiscoveryTimeout); - - // Reconnect timer - connect(m_reconnectTimer, &PluginTimer::timeout, this, &BluetoothLowEnergyManager::onReconnectTimeout); - - qCDebug(dcHardware()) << "-->" << name() << "created successfully."; - setAvailable(true); + return m_available; } -void BluetoothLowEnergyManager::onReconnectTimeout() +bool BluetoothLowEnergyManagerImplementation::enabled() const +{ + return m_enabled; +} + +void BluetoothLowEnergyManagerImplementation::setEnabled(bool enabled) +{ + if (m_enabled == enabled) + return; + + m_enabled = enabled; + emit enabledChanged(m_enabled); +} + +void BluetoothLowEnergyManagerImplementation::onReconnectTimeout() { // Reconnect device if enabled and disconnected foreach (BluetoothLowEnergyDevice *device, m_devices) { @@ -145,7 +168,7 @@ void BluetoothLowEnergyManager::onReconnectTimeout() } } -void BluetoothLowEnergyManager::onDiscoveryTimeout() +void BluetoothLowEnergyManagerImplementation::onDiscoveryTimeout() { // Stop discovery on all adapters qCDebug(dcBluetooth()) << "Stop bluetooth discovery"; @@ -168,7 +191,7 @@ void BluetoothLowEnergyManager::onDiscoveryTimeout() m_currentReply.clear(); } -void BluetoothLowEnergyManager::onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo) +void BluetoothLowEnergyManagerImplementation::onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo) { // Add the device to the list if not already added bool alreadyAdded = false; @@ -185,32 +208,34 @@ void BluetoothLowEnergyManager::onDeviceDiscovered(const QBluetoothDeviceInfo &d } } -void BluetoothLowEnergyManager::onDiscoveryError(const QBluetoothDeviceDiscoveryAgent::Error &error) +void BluetoothLowEnergyManagerImplementation::onDiscoveryError(const QBluetoothDeviceDiscoveryAgent::Error &error) { QBluetoothDeviceDiscoveryAgent *discoveryAgent = static_cast(sender()); qCWarning(dcBluetooth()) << "Discovery error:" << error << discoveryAgent->errorString(); } -bool BluetoothLowEnergyManager::enable() +bool BluetoothLowEnergyManagerImplementation::enable() { qCDebug(dcBluetooth()) << "Hardware resource enabled."; setEnabled(true); - foreach (QPointer bluetoothDevice, m_devices) { + foreach (QPointer bluetoothDevice, m_devices) { bluetoothDevice->setEnabled(true); } return true; } -bool BluetoothLowEnergyManager::disable() +bool BluetoothLowEnergyManagerImplementation::disable() { qCDebug(dcBluetooth()) << "Hardware resource disabled."; setEnabled(false); - foreach (QPointer bluetoothDevice, m_devices) { + foreach (QPointer bluetoothDevice, m_devices) { bluetoothDevice->setEnabled(false); } return true; } + +} diff --git a/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h similarity index 73% rename from libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h rename to libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h index 21db2c29..eebfc11d 100644 --- a/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h +++ b/libguh-core/hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h @@ -20,8 +20,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifndef BLUETOOTHLOWENERGYMANAGER_H -#define BLUETOOTHLOWENERGYMANAGER_H +#ifndef BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H +#define BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H #include #include @@ -31,32 +31,45 @@ #include #include "plugintimer.h" -#include "hardwareresource.h" -#include "bluetoothdiscoveryreply.h" -#include "bluetoothlowenergydevice.h" -class BluetoothLowEnergyManager : public HardwareResource +#include "hardware/bluetoothlowenergy/bluetoothlowenergymanager.h" +#include "hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h" +#include "hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h" + +namespace guhserver { + +class BluetoothLowEnergyManagerImplementation : public BluetoothLowEnergyManager { Q_OBJECT - friend class HardwareManager; + friend class HardwareManagerImplementation; public: + explicit BluetoothLowEnergyManagerImplementation(PluginTimer *reconnectTimer, QObject *parent = nullptr); + BluetoothDiscoveryReply *discoverDevices(const int &interval = 5000); // Bluetooth device registration methods BluetoothLowEnergyDevice *registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::RandomAddress); void unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice); + bool available() const override; + bool enabled() const override; + +protected: + void setEnabled(bool enabled) override; + private: - explicit BluetoothLowEnergyManager(PluginTimer *reconnectTimer, QObject *parent = nullptr); PluginTimer *m_reconnectTimer = nullptr; QTimer *m_timer = nullptr; - QList> m_devices; + QList> m_devices; + + bool m_available = false; + bool m_enabled = false; QList m_bluetoothDiscoveryAgents; QList m_discoveredDevices; - QPointer m_currentReply; + QPointer m_currentReply; private slots: void onReconnectTimeout(); @@ -70,4 +83,6 @@ public slots: }; -#endif // BLUETOOTHLOWENERGYMANAGER_H +} + +#endif // BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H diff --git a/libguh/network/avahi/qt-watch.cpp b/libguh-core/hardware/network/avahi/qt-watch.cpp similarity index 99% rename from libguh/network/avahi/qt-watch.cpp rename to libguh-core/hardware/network/avahi/qt-watch.cpp index 6bca5789..5a831da1 100644 --- a/libguh/network/avahi/qt-watch.cpp +++ b/libguh-core/hardware/network/avahi/qt-watch.cpp @@ -191,3 +191,5 @@ const AvahiPoll* avahi_qt_poll_get(void) #include "qt-watch.moc" + + diff --git a/libguh/network/avahi/qt-watch.h b/libguh-core/hardware/network/avahi/qt-watch.h similarity index 100% rename from libguh/network/avahi/qt-watch.h rename to libguh-core/hardware/network/avahi/qt-watch.h diff --git a/libguh/network/avahi/qtavahiclient.cpp b/libguh-core/hardware/network/avahi/qtavahiclient.cpp similarity index 97% rename from libguh/network/avahi/qtavahiclient.cpp rename to libguh-core/hardware/network/avahi/qtavahiclient.cpp index 6410d2c3..dcf2b3a2 100644 --- a/libguh/network/avahi/qtavahiclient.cpp +++ b/libguh-core/hardware/network/avahi/qtavahiclient.cpp @@ -24,8 +24,13 @@ #include "qtavahiclient.h" #include "loggingcategories.h" +#include "qtavahiservicebrowserimplementation.h" +#include "qtavahiservicebrowserimplementation_p.h" + #include +namespace guhserver { + QtAvahiClient::QtAvahiClient(QObject *parent) : QObject(parent), m_poll(avahi_qt_poll_get()), @@ -128,3 +133,4 @@ void QtAvahiClient::onClientStateChanged(const QtAvahiClient::QtAvahiClientState emit clientStateChanged(m_state); } +} diff --git a/libguh/network/avahi/qtavahiclient.h b/libguh-core/hardware/network/avahi/qtavahiclient.h similarity index 93% rename from libguh/network/avahi/qtavahiclient.h rename to libguh-core/hardware/network/avahi/qtavahiclient.h index ae36b510..2d35c22a 100644 --- a/libguh/network/avahi/qtavahiclient.h +++ b/libguh-core/hardware/network/avahi/qtavahiclient.h @@ -26,9 +26,9 @@ #include #include -#include "libguh.h" +namespace guhserver { -class LIBGUH_EXPORT QtAvahiClient : public QObject +class QtAvahiClient : public QObject { Q_OBJECT Q_ENUMS(QtAvahiClientState) @@ -50,8 +50,8 @@ public: private: friend class QtAvahiService; - friend class QtAvahiServiceBrowser; - friend class QtAvahiServiceBrowserPrivate; + friend class QtAvahiServiceBrowserImplementation; + friend class QtAvahiServiceBrowserImplementationPrivate; const AvahiPoll *m_poll; AvahiClient *m_client; @@ -73,4 +73,6 @@ signals: }; +} + #endif // QTAVAHICLIENT_H diff --git a/libguh/network/avahi/qtavahiservice.cpp b/libguh-core/hardware/network/avahi/qtavahiservice.cpp similarity index 99% rename from libguh/network/avahi/qtavahiservice.cpp rename to libguh-core/hardware/network/avahi/qtavahiservice.cpp index d177a9dc..2aa81d16 100644 --- a/libguh/network/avahi/qtavahiservice.cpp +++ b/libguh-core/hardware/network/avahi/qtavahiservice.cpp @@ -52,6 +52,7 @@ #include "qtavahiservice_p.h" #include "loggingcategories.h" +namespace guhserver { /*! Constructs a new \l{QtAvahiService} with the given \a parent. */ QtAvahiService::QtAvahiService(QObject *parent) : @@ -272,3 +273,5 @@ QDebug operator <<(QDebug dbg, QtAvahiService *service) dbg << service->name() << ", " << service->serviceType() << ", " << service->port() << ") "; return dbg; } + +} diff --git a/libguh/network/avahi/qtavahiservice.h b/libguh-core/hardware/network/avahi/qtavahiservice.h similarity index 97% rename from libguh/network/avahi/qtavahiservice.h rename to libguh-core/hardware/network/avahi/qtavahiservice.h index 61f4da16..0dc977cb 100644 --- a/libguh/network/avahi/qtavahiservice.h +++ b/libguh-core/hardware/network/avahi/qtavahiservice.h @@ -27,11 +27,12 @@ #include #include -#include "libguh.h" + +namespace guhserver { class QtAvahiServicePrivate; -class LIBGUH_EXPORT QtAvahiService : public QObject +class QtAvahiService : public QObject { Q_OBJECT Q_ENUMS(QtAvahiServiceState) @@ -80,5 +81,6 @@ private: QDebug operator <<(QDebug dbg, QtAvahiService *service); +} #endif // QTAVAHISERVICE_H diff --git a/libguh/network/avahi/qtavahiservice_p.cpp b/libguh-core/hardware/network/avahi/qtavahiservice_p.cpp similarity index 99% rename from libguh/network/avahi/qtavahiservice_p.cpp rename to libguh-core/hardware/network/avahi/qtavahiservice_p.cpp index 6fb7aceb..7adef693 100644 --- a/libguh/network/avahi/qtavahiservice_p.cpp +++ b/libguh-core/hardware/network/avahi/qtavahiservice_p.cpp @@ -27,6 +27,8 @@ #include #include +namespace guhserver { + QtAvahiServicePrivate::QtAvahiServicePrivate() : client(0), group(0), @@ -80,3 +82,4 @@ AvahiStringList *QtAvahiServicePrivate::createTxtList(const QHash #include #include -class LIBGUH_EXPORT QtAvahiServicePrivate +namespace guhserver { + +class QtAvahiServicePrivate { public: QtAvahiServicePrivate(); @@ -55,5 +55,7 @@ public: }; +} + #endif // QTAVAHISERVICEPRIVATE_P diff --git a/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation.cpp b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation.cpp new file mode 100644 index 00000000..5bd01a74 --- /dev/null +++ b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation.cpp @@ -0,0 +1,130 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*! + \class QtAvahiServiceBrowserImplementation + \brief Allows to browse avahi services in the local network. + + \ingroup hardware + \inmodule libguh +*/ + +/*! \fn void QtAvahiServiceBrowserImplementation::serviceEntryAdded(const AvahiServiceEntry &entry); + This signal will be emitted when a new \a entry was added to the current entry list. +*/ + +/*! \fn void QtAvahiServiceBrowserImplementation::serviceEntryRemoved(const AvahiServiceEntry &entry); + This signal will be emitted when a new \a entry was removed from the current entry list. +*/ + +#include "qtavahiservicebrowserimplementation.h" +#include "qtavahiservicebrowserimplementation_p.h" +#include "loggingcategories.h" + +#include + +namespace guhserver { + +/*! Constructs a new \l{QtAvahiServiceBrowserImplementation} with the given \a parent. */ +QtAvahiServiceBrowserImplementation::QtAvahiServiceBrowserImplementation(QObject *parent) : + QtAvahiServiceBrowser(parent), + d_ptr(new QtAvahiServiceBrowserImplementationPrivate(new QtAvahiClient)) +{ + // TODO: check available here + m_available = true; + + connect(d_ptr->client, &QtAvahiClient::clientStateChanged, this, &QtAvahiServiceBrowserImplementation::onClientStateChanged); + + qCDebug(dcAvahi()) << "-->" << name() << "created successfully."; +} + +/*! Destructs this \l{QtAvahiServiceBrowserImplementation}. */ +QtAvahiServiceBrowserImplementation::~QtAvahiServiceBrowserImplementation() +{ + // Delete each service browser + foreach (const QString &serviceType, d_ptr->serviceBrowserTable.keys()) { + AvahiServiceBrowser *browser = d_ptr->serviceBrowserTable.take(serviceType); + if (browser) { + avahi_service_browser_free(browser); + } + } + + // Delete the service type browser + if (d_ptr->serviceTypeBrowser) + avahi_service_type_browser_free(d_ptr->serviceTypeBrowser); + + delete d_ptr; +} + +/*! Returns the current \l{AvahiServiceEntry} list of this \l{QtAvahiServiceBrowserImplementation}. */ +QList QtAvahiServiceBrowserImplementation::serviceEntries() const +{ + return m_serviceEntries; +} + +bool QtAvahiServiceBrowserImplementation::available() const +{ + return m_available; +} + +bool QtAvahiServiceBrowserImplementation::enabled() const +{ + return m_enabled; +} + +void QtAvahiServiceBrowserImplementation::onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state) +{ + if (state == QtAvahiClient::QtAvahiClientStateRunning) { + qCDebug(dcAvahi()) << "Service browser client connected."; + // Return if we already have a service type browser + if (d_ptr->serviceTypeBrowser) + return; + + d_ptr->serviceTypeBrowser = avahi_service_type_browser_new(d_ptr->client->m_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, (AvahiLookupFlags) 0, QtAvahiServiceBrowserImplementationPrivate::callbackServiceTypeBrowser, this); + } else if (state == QtAvahiClient::QtAvahiClientStateFailure) { + qCWarning(dcAvahi()) << name() << "client failure:" << d_ptr->client->errorString(); + } +} + +void QtAvahiServiceBrowserImplementation::setEnabled(bool enabled) +{ + if (m_enabled == enabled) { + qCDebug(dcAvahi()) << "Avahi Service Browser already" << (enabled ? "enabled" : "disabled") << "... Not changing state."; + return; + } + if (enabled) { + d_ptr->client->start(); + qCDebug(dcAvahi()) << "Avahi Service Browser enabled"; + } else { + d_ptr->client->stop(); + qCDebug(dcAvahi()) << "Avahi Service Browser disabled"; + } +} + +void QtAvahiServiceBrowserImplementation::createServiceBrowser(const char *serviceType) +{ + // create a new service browser for the given serviceType + AvahiServiceBrowser *browser = avahi_service_browser_new(d_ptr->client->m_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, serviceType, NULL, (AvahiLookupFlags) 0, QtAvahiServiceBrowserImplementationPrivate::callbackServiceBrowser, this); + d_ptr->serviceBrowserTable.insert(serviceType, browser); +} + +} diff --git a/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation.h b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation.h new file mode 100644 index 00000000..852f4fa3 --- /dev/null +++ b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation.h @@ -0,0 +1,81 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016 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 QTAVAHISERVICEBROWSERIMPLEMENTATION_H +#define QTAVAHISERVICEBROWSERIMPLEMENTATION_H + +#include +#include + +#include "qtavahiclient.h" + +#include "network/avahi/avahiserviceentry.h" +#include "network/avahi/qtavahiservicebrowser.h" + + +namespace guhserver { + +class QtAvahiServiceBrowserImplementationPrivate; + +class QtAvahiServiceBrowserImplementation : public QtAvahiServiceBrowser +{ + Q_OBJECT + + friend class HardwareManagerImplementation; + +public: + explicit QtAvahiServiceBrowserImplementation(QObject *parent = nullptr); + ~QtAvahiServiceBrowserImplementation(); + + QList serviceEntries() const; + + bool available() const override; + bool enabled() const override; + + +signals: + void serviceEntryAdded(const AvahiServiceEntry &entry); + void serviceEntryRemoved(const AvahiServiceEntry &entry); + +private slots: + void onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state); + +protected: + void setEnabled(bool enabled) override; + +private: + bool m_available = false; + bool m_enabled = false; + + QtAvahiServiceBrowserImplementationPrivate *d_ptr; + + QList m_serviceEntries; + QStringList m_serviceTypes; + + void createServiceBrowser(const char* serviceType); + + Q_DECLARE_PRIVATE(QtAvahiServiceBrowserImplementation) +}; + +} + +#endif // QTAVAHISERVICEBROWSERIMPLEMENTATION_H diff --git a/libguh/network/avahi/qtavahiservicebrowser_p.cpp b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation_p.cpp similarity index 70% rename from libguh/network/avahi/qtavahiservicebrowser_p.cpp rename to libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation_p.cpp index 23b41da3..f126a3c6 100644 --- a/libguh/network/avahi/qtavahiservicebrowser_p.cpp +++ b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation_p.cpp @@ -20,29 +20,31 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "qtavahiservicebrowser_p.h" -#include "qtavahiservicebrowser.h" -#include "avahiserviceentry.h" +#include "qtavahiservicebrowserimplementation_p.h" +#include "qtavahiservicebrowserimplementation.h" +#include "network/avahi/avahiserviceentry.h" #include "loggingcategories.h" #include #include -QtAvahiServiceBrowserPrivate::QtAvahiServiceBrowserPrivate(QtAvahiClient *client) : +namespace guhserver { + +QtAvahiServiceBrowserImplementationPrivate::QtAvahiServiceBrowserImplementationPrivate(QtAvahiClient *client) : client(client), - serviceTypeBrowser(NULL) + serviceTypeBrowser(nullptr) { } -QtAvahiServiceBrowserPrivate::~QtAvahiServiceBrowserPrivate() +QtAvahiServiceBrowserImplementationPrivate::~QtAvahiServiceBrowserImplementationPrivate() { foreach (AvahiServiceResolver *resolver, m_serviceResolvers) { avahi_service_resolver_free(resolver); } } -void QtAvahiServiceBrowserPrivate::callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) +void QtAvahiServiceBrowserImplementationPrivate::callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) { Q_UNUSED(browser) Q_UNUSED(interface) @@ -50,7 +52,7 @@ void QtAvahiServiceBrowserPrivate::callbackServiceTypeBrowser(AvahiServiceTypeBr Q_UNUSED(domain) Q_UNUSED(flags) - QtAvahiServiceBrowser *serviceBrowser = static_cast(userdata); + QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast(userdata); if (!serviceBrowser) return; @@ -76,12 +78,12 @@ void QtAvahiServiceBrowserPrivate::callbackServiceTypeBrowser(AvahiServiceTypeBr } } -void QtAvahiServiceBrowserPrivate::callbackServiceBrowser(AvahiServiceBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) +void QtAvahiServiceBrowserImplementationPrivate::callbackServiceBrowser(AvahiServiceBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) { Q_UNUSED(browser); Q_UNUSED(flags); - QtAvahiServiceBrowser *serviceBrowser = static_cast(userdata); + QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast(userdata); if (!serviceBrowser) return; @@ -89,15 +91,15 @@ void QtAvahiServiceBrowserPrivate::callbackServiceBrowser(AvahiServiceBrowser *b case AVAHI_BROWSER_NEW: { // Start resolving new service AvahiServiceResolver *resolver = avahi_service_resolver_new(serviceBrowser->d_ptr->client->m_client, - interface, - protocol, - name, - type, - domain, - AVAHI_PROTO_UNSPEC, - (AvahiLookupFlags) 0, - QtAvahiServiceBrowserPrivate::callbackServiceResolver, - serviceBrowser); + interface, + protocol, + name, + type, + domain, + AVAHI_PROTO_UNSPEC, + (AvahiLookupFlags) 0, + QtAvahiServiceBrowserImplementationPrivate::callbackServiceResolver, + serviceBrowser); if (resolver) { serviceBrowser->d_ptr->m_serviceResolvers.append(resolver); } else { @@ -109,7 +111,7 @@ void QtAvahiServiceBrowserPrivate::callbackServiceBrowser(AvahiServiceBrowser *b // Remove the service foreach (const AvahiServiceEntry &entry, serviceBrowser->m_serviceEntries) { // Check not only the name, but also the protocol - if (entry.name() == name && entry.protocol() == QtAvahiServiceBrowserPrivate::convertProtocol(protocol)) { + if (entry.name() == name && entry.protocol() == QtAvahiServiceBrowserImplementationPrivate::convertProtocol(protocol)) { serviceBrowser->m_serviceEntries.removeAll(entry); emit serviceBrowser->serviceEntryRemoved(entry); } @@ -140,13 +142,13 @@ void QtAvahiServiceBrowserPrivate::callbackServiceBrowser(AvahiServiceBrowser *b } -void QtAvahiServiceBrowserPrivate::callbackServiceResolver(AvahiServiceResolver *resolver, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) +void QtAvahiServiceBrowserImplementationPrivate::callbackServiceResolver(AvahiServiceResolver *resolver, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { Q_UNUSED(interface); Q_UNUSED(type); Q_UNUSED(txt); - QPointer serviceBrowser = static_cast(userdata); + QPointer serviceBrowser = static_cast(userdata); if (serviceBrowser.isNull()) return; @@ -158,8 +160,8 @@ void QtAvahiServiceBrowserPrivate::callbackServiceResolver(AvahiServiceResolver avahi_address_snprint(a, sizeof(a), address); // convert protocol - QAbstractSocket::NetworkLayerProtocol networkProtocol = QtAvahiServiceBrowserPrivate::convertProtocol(protocol); - QStringList txtList = QtAvahiServiceBrowserPrivate::convertTxtList(txt); + QAbstractSocket::NetworkLayerProtocol networkProtocol = QtAvahiServiceBrowserImplementationPrivate::convertProtocol(protocol); + QStringList txtList = QtAvahiServiceBrowserImplementationPrivate::convertTxtList(txt); // create the new resolved service entry AvahiServiceEntry entry = AvahiServiceEntry(name, @@ -181,7 +183,7 @@ void QtAvahiServiceBrowserPrivate::callbackServiceResolver(AvahiServiceResolver } -QStringList QtAvahiServiceBrowserPrivate::convertTxtList(AvahiStringList *txt) +QStringList QtAvahiServiceBrowserImplementationPrivate::convertTxtList(AvahiStringList *txt) { if (!txt) return QStringList(); @@ -198,7 +200,7 @@ QStringList QtAvahiServiceBrowserPrivate::convertTxtList(AvahiStringList *txt) return txtList; } -QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserPrivate::convertProtocol(const AvahiProtocol &protocol) +QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserImplementationPrivate::convertProtocol(const AvahiProtocol &protocol) { QAbstractSocket::NetworkLayerProtocol networkProtocol = QAbstractSocket::UnknownNetworkLayerProtocol; @@ -216,3 +218,4 @@ QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserPrivate::convertProto return networkProtocol; } +} diff --git a/libguh/network/avahi/qtavahiservicebrowser_p.h b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation_p.h similarity index 94% rename from libguh/network/avahi/qtavahiservicebrowser_p.h rename to libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation_p.h index 1ef3a9e0..07e22ad3 100644 --- a/libguh/network/avahi/qtavahiservicebrowser_p.h +++ b/libguh-core/hardware/network/avahi/qtavahiservicebrowserimplementation_p.h @@ -29,13 +29,17 @@ #include "qtavahiclient.h" #include "qtavahiservice.h" -#include "libguh.h" -class LIBGUH_EXPORT QtAvahiServiceBrowserPrivate + +namespace guhserver { + +class QtAvahiServiceTypeBrowserImplementation; + +class QtAvahiServiceBrowserImplementationPrivate { public: - QtAvahiServiceBrowserPrivate(QtAvahiClient *client); - ~QtAvahiServiceBrowserPrivate(); + QtAvahiServiceBrowserImplementationPrivate(QtAvahiClient *client); + ~QtAvahiServiceBrowserImplementationPrivate(); // Callback members static void callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser, @@ -80,4 +84,6 @@ public: QList m_serviceResolvers; }; +} + #endif // QTAVAHISERVICEBROWSERPRIVATE_H diff --git a/libguh-core/hardware/network/networkaccessmanagerimpl.cpp b/libguh-core/hardware/network/networkaccessmanagerimpl.cpp index f2c62bb9..b20b4048 100644 --- a/libguh-core/hardware/network/networkaccessmanagerimpl.cpp +++ b/libguh-core/hardware/network/networkaccessmanagerimpl.cpp @@ -21,7 +21,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! - \class NetworkAccessManager + \class NetworkAccessManagerImpl \brief Allows to send network requests and receive replies. \ingroup hardware @@ -32,12 +32,12 @@ */ -#include "networkaccessmanager.h" +#include "networkaccessmanagerimpl.h" #include "loggingcategories.h" -/*! Construct the hardware resource NetworkAccessManager with the given \a parent. */ -NetworkAccessManager::NetworkAccessManager(QNetworkAccessManager *networkManager, QObject *parent) : - HardwareResource("Network access manager" , parent), +/*! Construct the hardware resource NetworkAccessManagerImpl with the given \a parent. */ +NetworkAccessManagerImpl::NetworkAccessManagerImpl(QNetworkAccessManager *networkManager, QObject *parent) : + NetworkAccessManager(parent), m_manager(networkManager) { m_available = true; @@ -45,57 +45,57 @@ NetworkAccessManager::NetworkAccessManager(QNetworkAccessManager *networkManager qCDebug(dcHardware()) << "-->" << name() << "created successfully."; } -QNetworkReply *NetworkAccessManager::get(const QNetworkRequest &request) +QNetworkReply *NetworkAccessManagerImpl::get(const QNetworkRequest &request) { return m_manager->get(request); } -QNetworkReply *NetworkAccessManager::deleteResource(const QNetworkRequest &request) +QNetworkReply *NetworkAccessManagerImpl::deleteResource(const QNetworkRequest &request) { return m_manager->deleteResource(request); } -QNetworkReply *NetworkAccessManager::head(const QNetworkRequest &request) +QNetworkReply *NetworkAccessManagerImpl::head(const QNetworkRequest &request) { return m_manager->head(request); } -QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data) +QNetworkReply *NetworkAccessManagerImpl::post(const QNetworkRequest &request, QIODevice *data) { return m_manager->post(request, data); } -QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data) +QNetworkReply *NetworkAccessManagerImpl::post(const QNetworkRequest &request, const QByteArray &data) { return m_manager->post(request, data); } -QNetworkReply *NetworkAccessManager::post(const QNetworkRequest &request, QHttpMultiPart *multiPart) +QNetworkReply *NetworkAccessManagerImpl::post(const QNetworkRequest &request, QHttpMultiPart *multiPart) { return m_manager->post(request, multiPart); } -QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data) +QNetworkReply *NetworkAccessManagerImpl::put(const QNetworkRequest &request, QIODevice *data) { return m_manager->put(request, data); } -QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data) +QNetworkReply *NetworkAccessManagerImpl::put(const QNetworkRequest &request, const QByteArray &data) { return m_manager->put(request, data); } -QNetworkReply *NetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart) +QNetworkReply *NetworkAccessManagerImpl::put(const QNetworkRequest &request, QHttpMultiPart *multiPart) { return m_manager->put(request, multiPart); } -QNetworkReply *NetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data) +QNetworkReply *NetworkAccessManagerImpl::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data) { return m_manager->sendCustomRequest(request, verb, data); } -void NetworkAccessManager::setEnabled(bool enabled) +void NetworkAccessManagerImpl::setEnabled(bool enabled) { if (!m_available) { qCWarning(dcNetworkManager()) << "NetworkManager not available, cannot enable"; diff --git a/libguh-core/hardware/network/networkaccessmanagerimpl.h b/libguh-core/hardware/network/networkaccessmanagerimpl.h index a2c6f326..3408f093 100644 --- a/libguh-core/hardware/network/networkaccessmanagerimpl.h +++ b/libguh-core/hardware/network/networkaccessmanagerimpl.h @@ -66,6 +66,7 @@ private: bool m_enabled = false; QNetworkAccessManager *m_manager; + }; #endif // NETWORKACCESSMANAGER_H diff --git a/libguh-core/hardware/network/upnp/upnpdiscoveryimplementation.cpp b/libguh-core/hardware/network/upnp/upnpdiscoveryimplementation.cpp new file mode 100644 index 00000000..a8006b6e --- /dev/null +++ b/libguh-core/hardware/network/upnp/upnpdiscoveryimplementation.cpp @@ -0,0 +1,510 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 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 * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*! + \class UpnpDiscoveryImplementation + \brief Allows to detect UPnP devices in the network. + + \ingroup hardware + \inmodule libguh + + This resource allows plugins to discover UPnP devices in the network and receive notification messages. The resource + will bind a UDP socket to the multicast 239.255.255.250 on port 1900. + + The communication was implementet using following documentation: \l{http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf} + + \sa UpnpDevice, UpnpDeviceDescriptor +*/ + +/*! + \fn UpnpDiscoveryImplementation::upnpNotify(const QByteArray ¬ifyMessage) + This signal will be emitted when a UPnP NOTIFY message \a notifyMessage will be recognized. + \sa DevicePlugin::upnpNotifyReceived() + +*/ + +#include "guhsettings.h" +#include "loggingcategories.h" + +#include "upnpdiscoveryimplementation.h" +#include "upnpdiscoveryreplyimplementation.h" + +#include +#include +#include +#include + +namespace guhserver { + +/*! Construct the hardware resource UpnpDiscoveryImplementation with the given \a parent. */ +UpnpDiscoveryImplementation::UpnpDiscoveryImplementation(QNetworkAccessManager *networkAccessManager, QObject *parent) : + UpnpDiscovery(parent), + m_networkAccessManager(networkAccessManager) +{ + m_notificationTimer = new QTimer(this); + m_notificationTimer->setInterval(30000); + m_notificationTimer->setSingleShot(false); + connect(m_notificationTimer, &QTimer::timeout, this, &UpnpDiscoveryImplementation::notificationTimeout); + + m_available = true; + + qCDebug(dcHardware()) << "-->" << name() << "created successfully."; +} + +/*! Destruct this \l{UpnpDiscoveryImplementation} object. */ +UpnpDiscoveryImplementation::~UpnpDiscoveryImplementation() +{ + qCDebug(dcApplication) << "Shutting down \"UPnP Server\""; + sendByeByeMessage(); + if (m_socket) { + m_socket->waitForBytesWritten(1000); + m_socket->close(); + } +} + +UpnpDiscoveryReply *UpnpDiscoveryImplementation::discoverDevices(const QString &searchTarget, const QString &userAgent, const int &timeout) +{ + // Create the reply for this discovery request + QPointer reply = new UpnpDiscoveryReplyImplementation(searchTarget, userAgent, this); + + if (!available()) { + qCWarning(dcHardware()) << name() << "is not avilable."; + reply->setError(UpnpDiscoveryReplyImplementation::UpnpDiscoveryReplyErrorNotAvailable); + reply->setFinished(); + return reply.data(); + } + + if (!enabled()) { + qCWarning(dcHardware()) << name() << "is not enabled."; + reply->setError(UpnpDiscoveryReplyImplementation::UpnpDiscoveryReplyErrorNotEnabled); + reply->setFinished(); + return reply.data(); + } + + qCDebug(dcHardware) << name() << "discover" << searchTarget << userAgent; + + // Looks good so far, lets start a request + UpnpDiscoveryRequest *request = new UpnpDiscoveryRequest(this, reply.data()); + connect(request, &UpnpDiscoveryRequest::discoveryTimeout, this, &UpnpDiscoveryImplementation::discoverTimeout); + request->discover(timeout); + m_discoverRequests.append(request); + return reply.data(); +} + +void UpnpDiscoveryImplementation::requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor) +{ + QNetworkReply *replay = m_networkAccessManager->get(networkRequest); + connect(replay, &QNetworkReply::finished, this, &UpnpDiscoveryImplementation::replyFinished); + m_informationRequestList.insert(replay, upnpDeviceDescriptor); +} + +void UpnpDiscoveryImplementation::respondToSearchRequest(QHostAddress host, int port) +{ + // TODO: Once DeviceManager (and with that this can be moved into the server, use GuhCore's configuration manager instead of parsing the config here... + GuhSettings globalSettings(GuhSettings::SettingsRoleGlobal); + globalSettings.beginGroup("guhd"); + QByteArray uuid = globalSettings.value("uuid", QUuid()).toByteArray(); + globalSettings.endGroup(); + + globalSettings.beginGroup("WebServer"); + int serverPort = -1; + bool useSsl = false; + foreach (const QString &group, globalSettings.childGroups()) { + globalSettings.beginGroup(group); + QHostAddress serverInterface = QHostAddress(globalSettings.value("address").toString()); + if (serverInterface == host || serverInterface == QHostAddress("0.0.0.0")) { + serverPort = globalSettings.value("port", -1).toInt(); + useSsl = globalSettings.value("sslEnabled", true).toBool(); + } + globalSettings.endGroup(); + } + globalSettings.endGroup(); + + if (serverPort == -1) { + qCWarning(dcConnection) << "No matching WebServer configuration found. Discarding UPnP request!"; + return; + } + + foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { + foreach (QNetworkAddressEntry entry, interface.addressEntries()) { + // check IPv4 + if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) { + // check subnet + if (host.isInSubnet(QHostAddress::parseSubnet(entry.ip().toString() + "/24"))) { + QString locationString; + if (useSsl) { + locationString = "https://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; + } else { + locationString = "http://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; + } + + // http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf + QByteArray rootdeviceResponseMessage = QByteArray("HTTP/1.1 200 OK\r\n" + "CACHE-CONTROL: max-age=1900\r\n" + "DATE: " + QDateTime::currentDateTime().toString("ddd, dd MMM yyyy hh:mm:ss").toUtf8() + " GMT\r\n" + "EXT:\r\n" + "CONTENT-LENGTH:0\r\n" + "LOCATION: " + locationString.toUtf8() + "\r\n" + "SERVER: guh/" + QByteArray(GUH_VERSION_STRING) + " UPnP/1.1 \r\n" + "ST:upnp:rootdevice\r\n" + "USN:uuid:" + uuid + "::urn:schemas-upnp-org:device:Basic:1\r\n" + "\r\n"); + + //qCDebug(dcHardware) << QString("Sending response to %1:%2\n").arg(host.toString()).arg(port); + m_socket->writeDatagram(rootdeviceResponseMessage, host, port); + } + } + } + } +} + +/*! This method will be called to send the SSDP message \a data to the UPnP multicast.*/ +void UpnpDiscoveryImplementation::sendToMulticast(const QByteArray &data) +{ + if (!m_socket) + return; + + m_socket->writeDatagram(data, m_host, m_port); +} + +bool UpnpDiscoveryImplementation::available() const +{ + return m_available; +} + +bool UpnpDiscoveryImplementation::enabled() const +{ + return m_enabled; +} + +void UpnpDiscoveryImplementation::setEnabled(bool enabled) +{ + if (m_enabled == enabled) + return; + + m_enabled = enabled; + emit enabledChanged(m_enabled); +} + +void UpnpDiscoveryImplementation::error(QAbstractSocket::SocketError error) +{ + qCWarning(dcHardware) << name() << "socket error:" << error << m_socket->errorString(); +} + +void UpnpDiscoveryImplementation::readData() +{ + QByteArray data; + quint16 port; + QHostAddress hostAddress; + QUrl location; + + // read the answere from the multicast + while (m_socket->hasPendingDatagrams()) { + data.resize(m_socket->pendingDatagramSize()); + m_socket->readDatagram(data.data(), data.size(), &hostAddress, &port); + } + + if (data.contains("M-SEARCH") && !QNetworkInterface::allAddresses().contains(hostAddress)) { + respondToSearchRequest(hostAddress, port); + return; + } + + if (data.contains("NOTIFY") && !QNetworkInterface::allAddresses().contains(hostAddress)) { + emit upnpNotify(data); + return; + } + + // if the data contains the HTTP OK header... + if (data.contains("HTTP/1.1 200 OK")) { + const QStringList lines = QString(data).split("\r\n"); + foreach (const QString& line, lines) { + int separatorIndex = line.indexOf(':'); + QString key = line.left(separatorIndex).toUpper(); + QString value = line.mid(separatorIndex+1).trimmed(); + + // get location + if (key.contains("LOCATION") || key.contains("location") || key.contains("Location")) { + location = QUrl(value); + } + } + + UpnpDeviceDescriptor upnpDeviceDescriptor; + upnpDeviceDescriptor.setLocation(location); + upnpDeviceDescriptor.setHostAddress(hostAddress); + upnpDeviceDescriptor.setPort(location.port()); + + foreach (UpnpDiscoveryRequest *upnpDiscoveryRequest, m_discoverRequests) { + QNetworkRequest networkRequest = upnpDiscoveryRequest->createNetworkRequest(upnpDeviceDescriptor); + requestDeviceInformation(networkRequest, upnpDeviceDescriptor); + } + } +} + +void UpnpDiscoveryImplementation::replyFinished() +{ + QNetworkReply *reply = static_cast(sender()); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + switch (status) { + case(200):{ + QByteArray data = reply->readAll(); + UpnpDeviceDescriptor upnpDeviceDescriptor = m_informationRequestList.take(reply); + + // parse XML data + QXmlStreamReader xml(data); + while (!xml.atEnd() && !xml.hasError()) { + xml.readNext(); + if (xml.isStartDocument()) { + continue; + } + if (xml.isStartElement()) { + if (xml.name().toString() == "device") { + while (!xml.atEnd()) { + if (xml.name() == "deviceType" && xml.isStartElement()) { + upnpDeviceDescriptor.setDeviceType(xml.readElementText()); + } + if (xml.name() == "friendlyName" && xml.isStartElement()) { + upnpDeviceDescriptor.setFriendlyName(xml.readElementText()); + } + if (xml.name() == "manufacturer" && xml.isStartElement()) { + upnpDeviceDescriptor.setManufacturer(xml.readElementText()); + } + if (xml.name() == "manufacturerURL" && xml.isStartElement()) { + upnpDeviceDescriptor.setManufacturerURL(QUrl(xml.readElementText())); + } + if (xml.name() == "modelDescription" && xml.isStartElement()) { + upnpDeviceDescriptor.setModelDescription(xml.readElementText()); + } + if (xml.name() == "modelName" && xml.isStartElement()) { + upnpDeviceDescriptor.setModelName(xml.readElementText()); + } + if (xml.name() == "modelNumber" && xml.isStartElement()) { + upnpDeviceDescriptor.setModelNumber(xml.readElementText()); + } + if (xml.name() == "modelURL" && xml.isStartElement()) { + upnpDeviceDescriptor.setModelURL(QUrl(xml.readElementText())); + } + if (xml.name() == "serialNumber" && xml.isStartElement()) { + upnpDeviceDescriptor.setSerialNumber(xml.readElementText()); + } + if (xml.name() == "UDN" && xml.isStartElement()) { + upnpDeviceDescriptor.setUuid(xml.readElementText()); + } + if (xml.name() == "uuid" && xml.isStartElement()) { + upnpDeviceDescriptor.setUuid(xml.readElementText()); + } + if (xml.name() == "UPC" && xml.isStartElement()) { + upnpDeviceDescriptor.setUpc(xml.readElementText()); + } + xml.readNext(); + } + xml.readNext(); + } + } + } + + foreach (UpnpDiscoveryRequest *upnpDiscoveryRequest, m_discoverRequests) { + upnpDiscoveryRequest->addDeviceDescriptor(upnpDeviceDescriptor); + } + break; + } + default: + qCWarning(dcHardware) << name() << "HTTP request error" << reply->request().url().toString() << status; + m_informationRequestList.remove(reply); + } + + reply->deleteLater(); +} + +void UpnpDiscoveryImplementation::notificationTimeout() +{ + sendAliveMessage(); +} + +void UpnpDiscoveryImplementation::sendByeByeMessage() +{ + // TODO: Once DeviceManager (and with that this can be moved into the server, use GuhCore's configuration manager instead of parsing the config here... + GuhSettings globalSettings(GuhSettings::SettingsRoleGlobal); + globalSettings.beginGroup("guhd"); + QByteArray uuid = globalSettings.value("uuid", QUuid()).toByteArray(); + globalSettings.endGroup(); + + globalSettings.beginGroup("WebServer"); + foreach (const QString &group, globalSettings.childGroups()) { + globalSettings.beginGroup(group); + QHostAddress serverInterface = QHostAddress(globalSettings.value("address").toString()); + int serverPort = globalSettings.value("port", -1).toInt(); + bool useSsl = globalSettings.value("sslEnabled", true).toBool(); + globalSettings.endGroup(); + + foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { + foreach (QNetworkAddressEntry entry, interface.addressEntries()) { + if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol && (serverInterface == QHostAddress("0.0.0.0") || entry.ip() == serverInterface)) { + + QString locationString; + if (useSsl) { + locationString = "https://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; + } else { + locationString = "http://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; + } + + // http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf + QByteArray byebyeMessage = QByteArray("NOTIFY * HTTP/1.1\r\n" + "HOST:239.255.255.250:1900\r\n" + "CACHE-CONTROL: max-age=1900\r\n" + "LOCATION: " + locationString.toUtf8() + "\r\n" + "NT:urn:schemas-upnp-org:device:Basic:1\r\n" + "USN:uuid:" + uuid + "::urn:schemas-upnp-org:device:Basic:1\r\n" + "NTS: ssdp:byebye\r\n" + "SERVER: guh/" + QByteArray(GUH_VERSION_STRING) + " UPnP/1.1 \r\n" + "\r\n"); + + sendToMulticast(byebyeMessage); + } + } + } + } + globalSettings.endGroup(); +} + +void UpnpDiscoveryImplementation::sendAliveMessage() +{ + // TODO: Once DeviceManager (and with that this can be moved into the server, use GuhCore's configuration manager instead of parsing the config here... + GuhSettings globalSettings(GuhSettings::SettingsRoleGlobal); + globalSettings.beginGroup("guhd"); + QByteArray uuid = globalSettings.value("uuid", QUuid()).toByteArray(); + globalSettings.endGroup(); + + globalSettings.beginGroup("WebServer"); + foreach (const QString &group, globalSettings.childGroups()) { + globalSettings.beginGroup(group); + QHostAddress serverInterface = QHostAddress(globalSettings.value("address").toString()); + int serverPort = globalSettings.value("port", -1).toInt(); + bool useSsl = globalSettings.value("sslEnabled", true).toBool(); + globalSettings.endGroup(); + + foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { + foreach (QNetworkAddressEntry entry, interface.addressEntries()) { + if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol && (serverInterface == QHostAddress("0.0.0.0") || entry.ip() == serverInterface)) { + + QString locationString; + if (useSsl) { + locationString = "https://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; + } else { + locationString = "http://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; + } + + // http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf + QByteArray aliveMessage = QByteArray("NOTIFY * HTTP/1.1\r\n" + "HOST:239.255.255.250:1900\r\n" + "CACHE-CONTROL: max-age=1900\r\n" + "LOCATION: " + locationString.toUtf8() + "\r\n" + "NT:urn:schemas-upnp-org:device:Basic:1\r\n" + "USN:uuid:" + uuid + "::urn:schemas-upnp-org:device:Basic:1\r\n" + "NTS: ssdp:alive\r\n" + "SERVER: guh/" + QByteArray(GUH_VERSION_STRING) + " UPnP/1.1 \r\n" + "\r\n"); + + sendToMulticast(aliveMessage); + } + } + } + } + globalSettings.endGroup(); +} + +void UpnpDiscoveryImplementation::discoverTimeout() +{ + UpnpDiscoveryRequest *discoveryRequest = static_cast(sender()); + QPointer reply = discoveryRequest->reply(); + + 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(UpnpDiscoveryReplyImplementation::UpnpDiscoveryReplyErrorNoError); + reply->setFinished(); + } + + m_discoverRequests.removeOne(discoveryRequest); + delete discoveryRequest; +} + +bool UpnpDiscoveryImplementation::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; + m_available = false; + emit availableChanged(false); + delete m_socket; + m_socket = nullptr; + return false; + } + + if(!m_socket->joinMulticastGroup(m_host)){ + qCWarning(dcHardware()) << name() << "could not join multicast group" << m_host; + m_available = false; + emit availableChanged(false); + 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, &UpnpDiscoveryImplementation::readData); + + m_notificationTimer->start(); + + sendAliveMessage(); + sendAliveMessage(); + return true; +} + +bool UpnpDiscoveryImplementation::disable() +{ + sendByeByeMessage(); + m_socket->waitForBytesWritten(); + m_socket->close(); + delete m_socket; + m_socket = nullptr; + + m_notificationTimer->stop(); + + setEnabled(false); + return true; +} + +} diff --git a/libguh-core/hardware/network/upnp/upnpdiscoveryimplementation.h b/libguh-core/hardware/network/upnp/upnpdiscoveryimplementation.h new file mode 100644 index 00000000..c0337d94 --- /dev/null +++ b/libguh-core/hardware/network/upnp/upnpdiscoveryimplementation.h @@ -0,0 +1,97 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 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 UPNPDISCOVERYIMPLEMENTATION_H +#define UPNPDISCOVERYIMPLEMENTATION_H + +#include +#include +#include +#include +#include +#include +#include + +#include "upnpdiscoveryrequest.h" + +#include "network/upnp/upnpdiscovery.h" +#include "network/upnp/upnpdiscoveryreply.h" +#include "network/upnp/upnpdevicedescriptor.h" + +// 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 + +namespace guhserver { + +class UpnpDiscoveryImplementation : public UpnpDiscovery +{ + Q_OBJECT + +public: + explicit UpnpDiscoveryImplementation(QNetworkAccessManager *networkAccessManager, QObject *parent = nullptr); + ~UpnpDiscoveryImplementation(); + + UpnpDiscoveryReply *discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = QString(), const int &timeout = 5000); + void sendToMulticast(const QByteArray &data); + + bool available() const override; + bool enabled() const override; + +private: + QUdpSocket *m_socket = nullptr; + QHostAddress m_host; + qint16 m_port; + + QTimer *m_notificationTimer = nullptr; + + QNetworkAccessManager *m_networkAccessManager = nullptr; + + QList m_discoverRequests; + QHash m_informationRequestList; + + bool m_available = false; + bool m_enabled = false; + + void requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor); + void respondToSearchRequest(QHostAddress host, int port); + +protected: + void setEnabled(bool enabled) override; + +private slots: + void error(QAbstractSocket::SocketError error); + void readData(); + void replyFinished(); + void notificationTimeout(); + void sendByeByeMessage(); + void sendAliveMessage(); + void discoverTimeout(); + +public slots: + bool enable(); + bool disable(); + +}; + +} + +#endif // UPNPDISCOVERYIMPLEMENTATION_H diff --git a/libguh-core/hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp b/libguh-core/hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp new file mode 100644 index 00000000..99054e7c --- /dev/null +++ b/libguh-core/hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp @@ -0,0 +1,83 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * 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 "upnpdiscoveryreplyimplementation.h" + +#include + +namespace guhserver { + +UpnpDiscoveryReplyImplementation::UpnpDiscoveryReplyImplementation(const QString &searchTarget, const QString &userAgent, QObject *parent) : + UpnpDiscoveryReply(parent), + m_searchTarget(searchTarget), + m_userAgent(userAgent) +{ + +} + +QString UpnpDiscoveryReplyImplementation::searchTarget() const +{ + return m_searchTarget; +} + +QString UpnpDiscoveryReplyImplementation::userAgent() const +{ + return m_userAgent; +} + +UpnpDiscoveryReplyImplementation::UpnpDiscoveryReplyError UpnpDiscoveryReplyImplementation::error() const +{ + return m_error; +} + +bool UpnpDiscoveryReplyImplementation::isFinished() const +{ + return m_finished; +} + +QList UpnpDiscoveryReplyImplementation::deviceDescriptors() const +{ + return m_deviceDescriptors; +} + + +void UpnpDiscoveryReplyImplementation::setDeviceDescriptors(const QList &deviceDescriptors) +{ + m_deviceDescriptors = deviceDescriptors; +} + +void UpnpDiscoveryReplyImplementation::setError(const UpnpDiscoveryReplyImplementation::UpnpDiscoveryReplyError &error) +{ + m_error = error; + if (m_error != UpnpDiscoveryReplyErrorNoError) { + emit errorOccured(m_error); + } +} + +void UpnpDiscoveryReplyImplementation::setFinished() +{ + m_finished = true; + // Note: this makes sure the finished signal will be processed in the next event loop + QTimer::singleShot(0, this, &UpnpDiscoveryReplyImplementation::finished); +} + +} diff --git a/libguh-core/hardware/network/upnp/upnpdiscoveryreplyimplementation.h b/libguh-core/hardware/network/upnp/upnpdiscoveryreplyimplementation.h new file mode 100644 index 00000000..812b42a1 --- /dev/null +++ b/libguh-core/hardware/network/upnp/upnpdiscoveryreplyimplementation.h @@ -0,0 +1,72 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * 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 UPNPDISCOVERYREPLYIMPLEMENTATION_H +#define UPNPDISCOVERYREPLYIMPLEMENTATION_H + +#include + +#include "network/upnp/upnpdiscoveryreply.h" +#include "network/upnp/upnpdevicedescriptor.h" + +namespace guhserver { + +class UpnpDiscoveryReplyImplementation : public UpnpDiscoveryReply +{ + Q_OBJECT + + friend class UpnpDiscoveryImplementation; + +public: + explicit UpnpDiscoveryReplyImplementation(const QString &searchTarget, const QString &userAgent, QObject *parent = nullptr); + + QString searchTarget() const; + QString userAgent() const; + + UpnpDiscoveryReplyError error() const; + bool isFinished() const; + + QList deviceDescriptors() const; + +private: + + 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 // UPNPDISCOVERYREPLYIMPLEMENTATION_H diff --git a/libguh/network/upnp/upnpdiscoveryrequest.cpp b/libguh-core/hardware/network/upnp/upnpdiscoveryrequest.cpp similarity index 95% rename from libguh/network/upnp/upnpdiscoveryrequest.cpp rename to libguh-core/hardware/network/upnp/upnpdiscoveryrequest.cpp index fa97eb40..4d9cad7e 100644 --- a/libguh/network/upnp/upnpdiscoveryrequest.cpp +++ b/libguh-core/hardware/network/upnp/upnpdiscoveryrequest.cpp @@ -23,7 +23,9 @@ #include "upnpdiscoveryrequest.h" #include "loggingcategories.h" -UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer reply): +namespace guhserver { + +UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer reply): QObject(upnpDiscovery), m_upnpDiscovery(upnpDiscovery), m_reply(reply) @@ -79,7 +81,9 @@ QList UpnpDiscoveryRequest::deviceList() const return m_deviceList; } -QPointer UpnpDiscoveryRequest::reply() +QPointer UpnpDiscoveryRequest::reply() { return m_reply; } + +} diff --git a/libguh/network/upnp/upnpdiscoveryrequest.h b/libguh-core/hardware/network/upnp/upnpdiscoveryrequest.h similarity index 86% rename from libguh/network/upnp/upnpdiscoveryrequest.h rename to libguh-core/hardware/network/upnp/upnpdiscoveryrequest.h index 85045408..ecead133 100644 --- a/libguh/network/upnp/upnpdiscoveryrequest.h +++ b/libguh-core/hardware/network/upnp/upnpdiscoveryrequest.h @@ -27,30 +27,32 @@ #include #include -#include "upnpdiscovery.h" -#include "upnpdiscoveryreply.h" -#include "upnpdevicedescriptor.h" -#include "libguh.h" +#include "upnpdiscoveryreplyimplementation.h" +#include "network/upnp/upnpdiscovery.h" +#include "network/upnp/upnpdevicedescriptor.h" + #include "typeutils.h" class UpnpDiscovery; -class LIBGUH_EXPORT UpnpDiscoveryRequest : public QObject +namespace guhserver { + +class UpnpDiscoveryRequest : public QObject { Q_OBJECT public: - explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer reply); + explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer reply); void discover(const int &timeout); void addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor); QNetworkRequest createNetworkRequest(UpnpDeviceDescriptor deviveDescriptor); QList deviceList() const; - QPointer reply(); + QPointer reply(); private: UpnpDiscovery *m_upnpDiscovery; - QPointer m_reply; + QPointer m_reply; QTimer *m_timer = nullptr; QList m_deviceList; @@ -60,4 +62,6 @@ signals: }; +} + #endif // UPNPDISCOVERYREQUEST_H diff --git a/libguh-core/hardwaremanagerimplementation.cpp b/libguh-core/hardwaremanagerimplementation.cpp index 38e90098..799af48f 100644 --- a/libguh-core/hardwaremanagerimplementation.cpp +++ b/libguh-core/hardwaremanagerimplementation.cpp @@ -20,17 +20,14 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include "hardwaremanagerimplementation.h" -#include "hardware/plugintimermanagerimplementation.h" - -#include "plugintimer.h" #include "loggingcategories.h" -#include "hardware/radio433/radio433brennenstuhl.h" -#include "hardware/bluetooth/bluetoothlowenergymanager.h" + +#include "hardwaremanagerimplementation.h" +#include "hardware/network/upnp/upnpdiscoveryimplementation.h" #include "hardware/network/networkaccessmanagerimpl.h" -#include "network/upnp/upnpdiscovery.h" -#include "network/upnp/upnpdevicedescriptor.h" -#include "network/avahi/qtavahiservicebrowser.h" +#include "hardware/radio433/radio433brennenstuhl.h" +#include "hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h" +#include "hardware/network/avahi/qtavahiservicebrowserimplementation.h" namespace guhserver { @@ -51,22 +48,24 @@ HardwareManagerImplementation::HardwareManagerImplementation(QObject *parent) : // Network manager m_networkManager = new NetworkAccessManagerImpl(m_networkAccessManager, this); setResourceEnabled(m_networkManager, true); + if (m_networkManager->available()) + setResourceEnabled(m_networkManager, true); // UPnP discovery - m_upnpDiscovery = new UpnpDiscovery(m_networkAccessManager, this); - m_hardwareResources.append(m_upnpDiscovery); - m_upnpDiscovery->enable(); + m_upnpDiscovery = new UpnpDiscoveryImplementation(m_networkAccessManager, this); + if (m_upnpDiscovery->available()) + setResourceEnabled(m_upnpDiscovery, true); // Avahi Browser - m_avahiBrowser = new QtAvahiServiceBrowser(this); - m_hardwareResources.append(m_avahiBrowser); - m_avahiBrowser->enable(); + m_avahiBrowser = new QtAvahiServiceBrowserImplementation(this); + if (m_avahiBrowser->available()) + setResourceEnabled(m_avahiBrowser, true); // Bluetooth LE - m_bluetoothLowEnergyManager = new BluetoothLowEnergyManager(m_pluginTimerManager->registerTimer(10), this); - m_hardwareResources.append(m_bluetoothLowEnergyManager); - if (m_networkManager->available()) - m_networkManager->enable(); + m_bluetoothLowEnergyManager = new BluetoothLowEnergyManagerImplementation(m_pluginTimerManager->registerTimer(10), this); + if (m_bluetoothLowEnergyManager->available()) + setResourceEnabled(m_bluetoothLowEnergyManager, true); + qCDebug(dcHardware()) << "Hardware manager initialized successfully"; @@ -120,9 +119,9 @@ void HardwareManagerImplementation::EnableBluetooth(const bool &enabled) qCDebug(dcHardware()) << "Bluetooth hardware resource" << (enabled ? "enabled" : "disabled"); if (enabled) { - m_bluetoothLowEnergyManager->enable(); + setResourceEnabled(m_bluetoothLowEnergyManager, true); } else { - m_bluetoothLowEnergyManager->disable(); + setResourceEnabled(m_bluetoothLowEnergyManager, false); } } diff --git a/libguh-core/hardwaremanagerimplementation.h b/libguh-core/hardwaremanagerimplementation.h index c82e5361..1e036774 100644 --- a/libguh-core/hardwaremanagerimplementation.h +++ b/libguh-core/hardwaremanagerimplementation.h @@ -29,15 +29,17 @@ #include "hardwaremanager.h" +// FIXME: use forward declaration for timeTick +#include "hardware/plugintimermanagerimplementation.h" + class Radio433; -class PluginTimer; class UpnpDiscovery; -class PluginTimerManagerImplementation; class NetworkAccessManager; class UpnpDeviceDescriptor; class QtAvahiServiceBrowser; class BluetoothLowEnergyManager; + namespace guhserver { class HardwareManagerImplementation : public HardwareManager @@ -62,13 +64,16 @@ private: QNetworkAccessManager *m_networkAccessManager; // Hardware Resources - PluginTimerManager *m_pluginTimerManager = nullptr; + PluginTimerManagerImplementation *m_pluginTimerManager = nullptr; Radio433 *m_radio433 = nullptr; NetworkAccessManager *m_networkManager = nullptr; UpnpDiscovery *m_upnpDiscovery = nullptr; QtAvahiServiceBrowser *m_avahiBrowser = nullptr; BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr; +public slots: + void timeTick(); + }; } diff --git a/libguh-core/libguh-core.pro b/libguh-core/libguh-core.pro index 1e43dce5..2d79e7ec 100644 --- a/libguh-core/libguh-core.pro +++ b/libguh-core/libguh-core.pro @@ -5,7 +5,7 @@ include(../guh.pri) QT += sql INCLUDEPATH += $$top_srcdir/libguh $$top_srcdir jsonrpc -LIBS += -L$$top_builddir/libguh/ -lguh -lssl -lcrypto +LIBS += -L$$top_builddir/libguh/ -lguh -lssl -lcrypto -lavahi-common -lavahi-client target.path = /usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH') INSTALLS += target @@ -82,9 +82,19 @@ HEADERS += guhcore.h \ hardware/radio433/radio433brennenstuhl.h \ hardware/radio433/radio433transmitter.h \ hardware/radio433/radio433brennenstuhlgateway.h \ - hardware/bluetoothlowenergy/bluetoothlowenergymanager.h \ + hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h \ + hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.h \ + hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.h \ hardware/network/networkaccessmanagerimpl.h \ - + hardware/network/upnp/upnpdiscoveryimplementation.h \ + hardware/network/upnp/upnpdiscoveryrequest.h \ + hardware/network/upnp/upnpdiscoveryreplyimplementation.h \ + hardware/network/avahi/qt-watch.h \ + hardware/network/avahi/qtavahiclient.h \ + hardware/network/avahi/qtavahiservice.h \ + hardware/network/avahi/qtavahiservice_p.h \ + hardware/network/avahi/qtavahiservicebrowserimplementation.h \ + hardware/network/avahi/qtavahiservicebrowserimplementation_p.h \ SOURCES += guhcore.cpp \ @@ -150,6 +160,16 @@ SOURCES += guhcore.cpp \ hardware/radio433/radio433brennenstuhl.cpp \ hardware/radio433/radio433transmitter.cpp \ hardware/radio433/radio433brennenstuhlgateway.cpp \ - hardware/bluetoothlowenergy/bluetothlowenergymanager.cpp \ + hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.cpp \ + hardware/bluetoothlowenergy/bluetoothlowenergydeviceimplementation.cpp \ + hardware/bluetoothlowenergy/bluetoothdiscoveryreplyimplementation.cpp \ hardware/network/networkaccessmanagerimpl.cpp \ - + hardware/network/upnp/upnpdiscoveryimplementation.cpp \ + hardware/network/upnp/upnpdiscoveryrequest.cpp \ + hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp \ + hardware/network/avahi/qt-watch.cpp \ + hardware/network/avahi/qtavahiclient.cpp \ + hardware/network/avahi/qtavahiservice.cpp \ + hardware/network/avahi/qtavahiservice_p.cpp \ + hardware/network/avahi/qtavahiservicebrowserimplementation.cpp \ + hardware/network/avahi/qtavahiservicebrowserimplementation_p.cpp \ diff --git a/libguh-core/tcpserver.h b/libguh-core/tcpserver.h index 139b2a39..a009df34 100644 --- a/libguh-core/tcpserver.h +++ b/libguh-core/tcpserver.h @@ -32,7 +32,7 @@ #include #include "transportinterface.h" -#include "network/avahi/qtavahiservice.h" +#include "hardware/network/avahi/qtavahiservice.h" #include "loggingcategories.h" diff --git a/libguh-core/webserver.h b/libguh-core/webserver.h index a6e896fd..a8652025 100644 --- a/libguh-core/webserver.h +++ b/libguh-core/webserver.h @@ -34,7 +34,7 @@ #include #include -#include "network/avahi/qtavahiservice.h" +#include "hardware/network/avahi/qtavahiservice.h" #include "guhconfiguration.h" diff --git a/libguh-core/websocketserver.h b/libguh-core/websocketserver.h index e9a42848..220ce51e 100644 --- a/libguh-core/websocketserver.h +++ b/libguh-core/websocketserver.h @@ -28,7 +28,7 @@ #include #include -#include "network/avahi/qtavahiservice.h" +#include "hardware/network/avahi/qtavahiservice.h" #include "transportinterface.h" // Note: WebSocket Protocol from the Internet Engineering Task Force (IETF) -> RFC6455 V13: diff --git a/libguh/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp b/libguh/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp new file mode 100644 index 00000000..e30725ca --- /dev/null +++ b/libguh/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp @@ -0,0 +1,29 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * 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" + +BluetoothDiscoveryReply::BluetoothDiscoveryReply(QObject *parent) : + QObject(parent) +{ + +} diff --git a/libguh/hardware/bluetooth/bluetoothdiscoveryreply.h b/libguh/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h similarity index 79% rename from libguh/hardware/bluetooth/bluetoothdiscoveryreply.h rename to libguh/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h index 7ed0620d..a9884834 100644 --- a/libguh/hardware/bluetooth/bluetoothdiscoveryreply.h +++ b/libguh/hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h @@ -26,12 +26,12 @@ #include #include -class BluetoothDiscoveryReply : public QObject +#include "libguh.h" + +class LIBGUH_EXPORT BluetoothDiscoveryReply : public QObject { Q_OBJECT - friend class BluetoothLowEnergyManager; - public: enum BluetoothDiscoveryReplyError { BluetoothDiscoveryReplyErrorNoError, @@ -41,20 +41,12 @@ public: }; Q_ENUM(BluetoothDiscoveryReplyError) - bool isFinished() const; - BluetoothDiscoveryReplyError error() const; - QList discoveredDevices() const; - -private: explicit BluetoothDiscoveryReply(QObject *parent = nullptr); + virtual ~BluetoothDiscoveryReply() = default; - bool m_finished = false; - BluetoothDiscoveryReplyError m_error = BluetoothDiscoveryReplyErrorNoError; - QList m_discoveredDevices; - - void setError(const BluetoothDiscoveryReplyError &error); - void setDiscoveredDevices(const QList &discoveredDevices); - void setFinished(); + virtual bool isFinished() const = 0; + virtual BluetoothDiscoveryReplyError error() const = 0; + virtual QList discoveredDevices() const = 0; signals: void finished(); diff --git a/libguh/hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp b/libguh/hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp new file mode 100644 index 00000000..f986cb31 --- /dev/null +++ b/libguh/hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp @@ -0,0 +1,29 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 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 "bluetoothlowenergydevice.h" + +BluetoothLowEnergyDevice::BluetoothLowEnergyDevice(QObject *parent) : + QObject(parent) +{ + +} diff --git a/libguh/hardware/bluetoothlowenergy/bluetoothlowenergydevice.h b/libguh/hardware/bluetoothlowenergy/bluetoothlowenergydevice.h new file mode 100644 index 00000000..ea19c3e2 --- /dev/null +++ b/libguh/hardware/bluetoothlowenergy/bluetoothlowenergydevice.h @@ -0,0 +1,66 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 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 BLUETOOTHLOWENERGYDEVICE_H +#define BLUETOOTHLOWENERGYDEVICE_H + +#include +#include +#include +#include +#include + +#include "libguh.h" + +class LIBGUH_EXPORT BluetoothLowEnergyDevice : public QObject +{ + Q_OBJECT + +public: + explicit BluetoothLowEnergyDevice(QObject *parent = 0); + virtual ~BluetoothLowEnergyDevice() = default; + + virtual QString name() const = 0; + virtual QBluetoothAddress address() const = 0; + + virtual void connectDevice() = 0; + virtual void disconnectDevice() = 0; + + virtual bool autoConnecting() const = 0; + virtual void setAutoConnecting(const bool &autoConnecting) = 0; + + virtual bool connected() const = 0; + virtual bool discovered() const = 0; + + virtual QList serviceUuids() const = 0; + virtual QLowEnergyController *controller() const = 0; + +signals: + void connectedChanged(const bool &connected); + void autoConnectingChanged(const bool &autoConnecting); + void stateChanged(const QLowEnergyController::ControllerState &state); + void errorOccured(const QLowEnergyController::Error &error); + void servicesDiscoveryFinished(); + +}; + +#endif // BLUETOOTHLOWENERGYDEVICE_H diff --git a/libguh/hardware/bluetooth/bluetoothlowenergymanager.cpp b/libguh/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp similarity index 100% rename from libguh/hardware/bluetooth/bluetoothlowenergymanager.cpp rename to libguh/hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp diff --git a/libguh/hardware/bluetooth/bluetoothlowenergymanager.h b/libguh/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h similarity index 94% rename from libguh/hardware/bluetooth/bluetoothlowenergymanager.h rename to libguh/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h index f3dfc2d5..acb40061 100644 --- a/libguh/hardware/bluetooth/bluetoothlowenergymanager.h +++ b/libguh/hardware/bluetoothlowenergy/bluetoothlowenergymanager.h @@ -30,17 +30,20 @@ #include #include -#include "plugintimer.h" #include "hardwareresource.h" + #include "bluetoothdiscoveryreply.h" #include "bluetoothlowenergydevice.h" -class BluetoothLowEnergyManager : public HardwareResource +#include "libguh.h" + +class LIBGUH_EXPORT BluetoothLowEnergyManager : public HardwareResource { Q_OBJECT public: explicit BluetoothLowEnergyManager(QObject *parent = nullptr); + virtual ~BluetoothLowEnergyManager() = default; virtual BluetoothDiscoveryReply *discoverDevices(const int &interval = 5000) = 0; diff --git a/libguh/hardwareresource.h b/libguh/hardwareresource.h index 3475e71b..78916456 100644 --- a/libguh/hardwareresource.h +++ b/libguh/hardwareresource.h @@ -33,6 +33,7 @@ class HardwareResource : public QObject public: explicit HardwareResource(const QString &name, QObject *parent = nullptr); + virtual ~HardwareResource() = default; QString name() const; diff --git a/libguh/libguh.pro b/libguh/libguh.pro index f95ce691..f3dc5cd5 100644 --- a/libguh/libguh.pro +++ b/libguh/libguh.pro @@ -31,20 +31,19 @@ HEADERS += devicemanager.h \ network/upnp/upnpdiscovery.h \ network/upnp/upnpdevice.h \ network/upnp/upnpdevicedescriptor.h \ - network/upnp/upnpdiscoveryrequest.h \ network/upnp/upnpdiscoveryreply.h \ network/networkaccessmanager.h \ network/oauth2.h \ - network/avahi/qt-watch.h \ - network/avahi/avahiserviceentry.h \ - network/avahi/qtavahiclient.h \ - network/avahi/qtavahiservice.h \ - network/avahi/qtavahiservice_p.h \ network/avahi/qtavahiservicebrowser.h \ - network/avahi/qtavahiservicebrowser_p.h \ - hardware/bluetooth/bluetoothlowenergydevice.h \ - hardware/bluetooth/bluetoothdiscoveryreply.h \ - hardware/bluetooth/bluetoothlowenergymanager.h \ + network/avahi/avahiserviceentry.h \ + #network/avahi/qtavahiclient.h \ + #network/avahi/qt-watch.h \ + #network/avahi/qtavahiservice.h \ + #network/avahi/qtavahiservice_p.h \ + #network/avahi/qtavahiservicebrowser_p.h \ + hardware/bluetoothlowenergy/bluetoothlowenergydevice.h \ + hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h \ + hardware/bluetoothlowenergy/bluetoothlowenergymanager.h \ coap/coap.h \ coap/coappdu.h \ coap/coapoption.h \ @@ -87,20 +86,19 @@ SOURCES += devicemanager.cpp \ network/upnp/upnpdiscovery.cpp \ network/upnp/upnpdevice.cpp \ network/upnp/upnpdevicedescriptor.cpp \ - network/upnp/upnpdiscoveryrequest.cpp \ network/upnp/upnpdiscoveryreply.cpp \ network/networkaccessmanager.cpp \ network/oauth2.cpp \ - network/avahi/qt-watch.cpp \ network/avahi/avahiserviceentry.cpp \ - network/avahi/qtavahiclient.cpp \ - network/avahi/qtavahiservice.cpp \ - network/avahi/qtavahiservice_p.cpp \ network/avahi/qtavahiservicebrowser.cpp \ - network/avahi/qtavahiservicebrowser_p.cpp \ - hardware/bluetooth/bluetoothlowenergymanager.cpp \ - hardware/bluetooth/bluetoothlowenergydevice.cpp \ - hardware/bluetooth/bluetoothdiscoveryreply.cpp \ + #network/avahi/qt-watch.cpp \ + #network/avahi/qtavahiclient.cpp \ + #network/avahi/qtavahiservice.cpp \ + #network/avahi/qtavahiservice_p.cpp \ + #network/avahi/qtavahiservicebrowser_p.cpp \ + hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp \ + hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp \ + hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp \ coap/coap.cpp \ coap/coappdu.cpp \ coap/coapoption.cpp \ diff --git a/libguh/network/avahi/avahiserviceentry.h b/libguh/network/avahi/avahiserviceentry.h index 95db97ab..4e1a0443 100644 --- a/libguh/network/avahi/avahiserviceentry.h +++ b/libguh/network/avahi/avahiserviceentry.h @@ -27,6 +27,7 @@ #include #include #include + #include #include "libguh.h" diff --git a/libguh/network/avahi/qtavahiservicebrowser.cpp b/libguh/network/avahi/qtavahiservicebrowser.cpp index 938351e9..c18cabc9 100644 --- a/libguh/network/avahi/qtavahiservicebrowser.cpp +++ b/libguh/network/avahi/qtavahiservicebrowser.cpp @@ -37,81 +37,12 @@ */ #include "qtavahiservicebrowser.h" -#include "qtavahiservicebrowser_p.h" -#include "loggingcategories.h" - -#include /*! Constructs a new \l{QtAvahiServiceBrowser} with the given \a parent. */ QtAvahiServiceBrowser::QtAvahiServiceBrowser(QObject *parent) : - HardwareResource("Avahi service browser", parent), - d_ptr(new QtAvahiServiceBrowserPrivate(new QtAvahiClient)) + HardwareResource("Avahi service browser", parent) { - // TODO: check available here - m_available = true; - connect(d_ptr->client, &QtAvahiClient::clientStateChanged, this, &QtAvahiServiceBrowser::onClientStateChanged); - - qCDebug(dcAvahi()) << "-->" << name() << "created successfully."; } -/*! Destructs this \l{QtAvahiServiceBrowser}. */ -QtAvahiServiceBrowser::~QtAvahiServiceBrowser() -{ - // Delete each service browser - foreach (const QString &serviceType, d_ptr->serviceBrowserTable.keys()) { - AvahiServiceBrowser *browser = d_ptr->serviceBrowserTable.take(serviceType); - if (browser) { - avahi_service_browser_free(browser); - } - } - - // Delete the service type browser - if (d_ptr->serviceTypeBrowser) - avahi_service_type_browser_free(d_ptr->serviceTypeBrowser); - - delete d_ptr; -} - -/*! Returns the current \l{AvahiServiceEntry} list of this \l{QtAvahiServiceBrowser}. */ -QList QtAvahiServiceBrowser::serviceEntries() const -{ - return m_serviceEntries; -} - -void QtAvahiServiceBrowser::onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state) -{ - if (state == QtAvahiClient::QtAvahiClientStateRunning) { - qCDebug(dcAvahi()) << "Service browser client connected."; - // Return if we already have a service type browser - if (d_ptr->serviceTypeBrowser) - return; - - d_ptr->serviceTypeBrowser = avahi_service_type_browser_new(d_ptr->client->m_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, (AvahiLookupFlags) 0, QtAvahiServiceBrowserPrivate::callbackServiceTypeBrowser, this); - } else if (state == QtAvahiClient::QtAvahiClientStateFailure) { - qCWarning(dcAvahi()) << name() << "client failure:" << d_ptr->client->errorString(); - } -} - -void QtAvahiServiceBrowser::setEnabled(bool enabled) -{ - if (m_enabled == enabled) { - qCDebug(dcAvahi()) << "Avahi Service Browser already" << (enabled ? "enabled" : "disabled") << "... Not changing state."; - return; - } - if (enabled) { - d_ptr->client->start(); - qCDebug(dcAvahi()) << "Avahi Service Browser enabled"; - } else { - d_ptr->client->stop(); - qCDebug(dcAvahi()) << "Avahi Service Browser disabled"; - } -} - -void QtAvahiServiceBrowser::createServiceBrowser(const char *serviceType) -{ - // create a new service browser for the given serviceType - AvahiServiceBrowser *browser = avahi_service_browser_new(d_ptr->client->m_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, serviceType, NULL, (AvahiLookupFlags) 0, QtAvahiServiceBrowserPrivate::callbackServiceBrowser, this); - d_ptr->serviceBrowserTable.insert(serviceType, browser); -} diff --git a/libguh/network/avahi/qtavahiservicebrowser.h b/libguh/network/avahi/qtavahiservicebrowser.h index e6ff94a7..203746c5 100644 --- a/libguh/network/avahi/qtavahiservicebrowser.h +++ b/libguh/network/avahi/qtavahiservicebrowser.h @@ -28,45 +28,22 @@ #include "libguh.h" #include "hardwareresource.h" -#include "qtavahiclient.h" #include "avahiserviceentry.h" -class QtAvahiServiceBrowserPrivate; - class LIBGUH_EXPORT QtAvahiServiceBrowser : public HardwareResource { Q_OBJECT - friend class HardwareManager; - public: - QList serviceEntries() const; + explicit QtAvahiServiceBrowser(QObject *parent = nullptr); + virtual ~QtAvahiServiceBrowser() = default; + + virtual QList serviceEntries() const = 0; signals: void serviceEntryAdded(const AvahiServiceEntry &entry); void serviceEntryRemoved(const AvahiServiceEntry &entry); -private slots: - void onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state); - -protected: - virtual void setEnabled(bool enabled) override; - -private: - bool m_available = false; - bool m_enabled = false; - - explicit QtAvahiServiceBrowser(QObject *parent = nullptr); - ~QtAvahiServiceBrowser(); - - QtAvahiServiceBrowserPrivate *d_ptr; - - QList m_serviceEntries; - QStringList m_serviceTypes; - - void createServiceBrowser(const char* serviceType); - - Q_DECLARE_PRIVATE(QtAvahiServiceBrowser) }; #endif // QTAVAHISERVICEBROWSER_H diff --git a/libguh/network/upnp/upnpdiscovery.cpp b/libguh/network/upnp/upnpdiscovery.cpp index f9aac840..e74c249b 100644 --- a/libguh/network/upnp/upnpdiscovery.cpp +++ b/libguh/network/upnp/upnpdiscovery.cpp @@ -35,13 +35,6 @@ \sa UpnpDevice, UpnpDeviceDescriptor */ -/*! - \fn UpnpDiscovery::discoveryFinished(const QList &deviceDescriptorList, const PluginId & pluginId) - This signal will be emitted if the discovery call from a \l{DevicePlugin}{Plugin} with the given \a pluginId is finished. The found devices - will be passed with the \a deviceDescriptorList paramter. - \sa DevicePlugin::upnpDiscoveryFinished() - */ - /*! \fn UpnpDiscovery::upnpNotify(const QByteArray ¬ifyMessage) This signal will be emitted when a UPnP NOTIFY message \a notifyMessage will be recognized. @@ -49,443 +42,10 @@ */ #include "upnpdiscovery.h" -#include "loggingcategories.h" -#include "guhsettings.h" - -#include -#include -#include -#include /*! Construct the hardware resource UpnpDiscovery with the given \a parent. */ -UpnpDiscovery::UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent) : - HardwareResource("UPnP discovery", parent), - m_networkAccessManager(networkAccessManager) +UpnpDiscovery::UpnpDiscovery(QObject *parent) : + HardwareResource("UPnP discovery", parent) { - m_notificationTimer = new QTimer(this); - m_notificationTimer->setInterval(30000); - m_notificationTimer->setSingleShot(false); - connect(m_notificationTimer, &QTimer::timeout, this, &UpnpDiscovery::notificationTimeout); - m_available = true; - - qCDebug(dcHardware()) << "-->" << name() << "created successfully."; -} - -/*! Destruct this \l{UpnpDiscovery} object. */ -UpnpDiscovery::~UpnpDiscovery() -{ - qCDebug(dcApplication) << "Shutting down \"UPnP Server\""; - sendByeByeMessage(); - if (m_socket) { - m_socket->waitForBytesWritten(1000); - m_socket->close(); - } -} - -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() << "is not avilable."; - reply->setError(UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNotAvailable); - reply->setFinished(); - return reply.data(); - } - - if (!enabled()) { - qCWarning(dcHardware()) << name() << "is not enabled."; - reply->setError(UpnpDiscoveryReply::UpnpDiscoveryReplyErrorNotEnabled); - reply->setFinished(); - return reply.data(); - } - - qCDebug(dcHardware) << name() << "discover" << 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(timeout); - m_discoverRequests.append(request); - return reply.data(); -} - -void UpnpDiscovery::requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor) -{ - QNetworkReply *replay = m_networkAccessManager->get(networkRequest); - connect(replay, &QNetworkReply::finished, this, &UpnpDiscovery::replyFinished); - m_informationRequestList.insert(replay, upnpDeviceDescriptor); -} - -void UpnpDiscovery::respondToSearchRequest(QHostAddress host, int port) -{ - // TODO: Once DeviceManager (and with that this can be moved into the server, use GuhCore's configuration manager instead of parsing the config here... - GuhSettings globalSettings(GuhSettings::SettingsRoleGlobal); - globalSettings.beginGroup("guhd"); - QByteArray uuid = globalSettings.value("uuid", QUuid()).toByteArray(); - globalSettings.endGroup(); - - globalSettings.beginGroup("WebServer"); - int serverPort = -1; - bool useSsl = false; - foreach (const QString &group, globalSettings.childGroups()) { - globalSettings.beginGroup(group); - QHostAddress serverInterface = QHostAddress(globalSettings.value("address").toString()); - if (serverInterface == host || serverInterface == QHostAddress("0.0.0.0")) { - serverPort = globalSettings.value("port", -1).toInt(); - useSsl = globalSettings.value("sslEnabled", true).toBool(); - } - globalSettings.endGroup(); - } - globalSettings.endGroup(); - - if (serverPort == -1) { - qCWarning(dcConnection) << "No matching WebServer configuration found. Discarding UPnP request!"; - return; - } - - foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { - foreach (QNetworkAddressEntry entry, interface.addressEntries()) { - // check IPv4 - if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) { - // check subnet - if (host.isInSubnet(QHostAddress::parseSubnet(entry.ip().toString() + "/24"))) { - QString locationString; - if (useSsl) { - locationString = "https://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; - } else { - locationString = "http://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; - } - - // http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf - QByteArray rootdeviceResponseMessage = QByteArray("HTTP/1.1 200 OK\r\n" - "CACHE-CONTROL: max-age=1900\r\n" - "DATE: " + QDateTime::currentDateTime().toString("ddd, dd MMM yyyy hh:mm:ss").toUtf8() + " GMT\r\n" - "EXT:\r\n" - "CONTENT-LENGTH:0\r\n" - "LOCATION: " + locationString.toUtf8() + "\r\n" - "SERVER: guh/" + QByteArray(GUH_VERSION_STRING) + " UPnP/1.1 \r\n" - "ST:upnp:rootdevice\r\n" - "USN:uuid:" + uuid + "::urn:schemas-upnp-org:device:Basic:1\r\n" - "\r\n"); - - //qCDebug(dcHardware) << QString("Sending response to %1:%2\n").arg(host.toString()).arg(port); - m_socket->writeDatagram(rootdeviceResponseMessage, host, port); - } - } - } - } -} - -/*! This method will be called to send the SSDP message \a data to the UPnP multicast.*/ -void UpnpDiscovery::sendToMulticast(const QByteArray &data) -{ - if (!m_socket) - return; - - m_socket->writeDatagram(data, m_host, m_port); -} - -void UpnpDiscovery::error(QAbstractSocket::SocketError error) -{ - qCWarning(dcHardware) << name() << "socket error:" << error << m_socket->errorString(); -} - -void UpnpDiscovery::readData() -{ - QByteArray data; - quint16 port; - QHostAddress hostAddress; - QUrl location; - - // read the answere from the multicast - while (m_socket->hasPendingDatagrams()) { - data.resize(m_socket->pendingDatagramSize()); - m_socket->readDatagram(data.data(), data.size(), &hostAddress, &port); - } - - if (data.contains("M-SEARCH") && !QNetworkInterface::allAddresses().contains(hostAddress)) { - respondToSearchRequest(hostAddress, port); - return; - } - - if (data.contains("NOTIFY") && !QNetworkInterface::allAddresses().contains(hostAddress)) { - emit upnpNotify(data); - return; - } - - // if the data contains the HTTP OK header... - if (data.contains("HTTP/1.1 200 OK")) { - const QStringList lines = QString(data).split("\r\n"); - foreach (const QString& line, lines) { - int separatorIndex = line.indexOf(':'); - QString key = line.left(separatorIndex).toUpper(); - QString value = line.mid(separatorIndex+1).trimmed(); - - // get location - if (key.contains("LOCATION") || key.contains("location") || key.contains("Location")) { - location = QUrl(value); - } - } - - UpnpDeviceDescriptor upnpDeviceDescriptor; - upnpDeviceDescriptor.setLocation(location); - upnpDeviceDescriptor.setHostAddress(hostAddress); - upnpDeviceDescriptor.setPort(location.port()); - - foreach (UpnpDiscoveryRequest *upnpDiscoveryRequest, m_discoverRequests) { - QNetworkRequest networkRequest = upnpDiscoveryRequest->createNetworkRequest(upnpDeviceDescriptor); - requestDeviceInformation(networkRequest, upnpDeviceDescriptor); - } - } -} - -void UpnpDiscovery::replyFinished() -{ - QNetworkReply *reply = static_cast(sender()); - int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - - switch (status) { - case(200):{ - QByteArray data = reply->readAll(); - UpnpDeviceDescriptor upnpDeviceDescriptor = m_informationRequestList.take(reply); - - // parse XML data - QXmlStreamReader xml(data); - while (!xml.atEnd() && !xml.hasError()) { - xml.readNext(); - if (xml.isStartDocument()) { - continue; - } - if (xml.isStartElement()) { - if (xml.name().toString() == "device") { - while (!xml.atEnd()) { - if (xml.name() == "deviceType" && xml.isStartElement()) { - upnpDeviceDescriptor.setDeviceType(xml.readElementText()); - } - if (xml.name() == "friendlyName" && xml.isStartElement()) { - upnpDeviceDescriptor.setFriendlyName(xml.readElementText()); - } - if (xml.name() == "manufacturer" && xml.isStartElement()) { - upnpDeviceDescriptor.setManufacturer(xml.readElementText()); - } - if (xml.name() == "manufacturerURL" && xml.isStartElement()) { - upnpDeviceDescriptor.setManufacturerURL(QUrl(xml.readElementText())); - } - if (xml.name() == "modelDescription" && xml.isStartElement()) { - upnpDeviceDescriptor.setModelDescription(xml.readElementText()); - } - if (xml.name() == "modelName" && xml.isStartElement()) { - upnpDeviceDescriptor.setModelName(xml.readElementText()); - } - if (xml.name() == "modelNumber" && xml.isStartElement()) { - upnpDeviceDescriptor.setModelNumber(xml.readElementText()); - } - if (xml.name() == "modelURL" && xml.isStartElement()) { - upnpDeviceDescriptor.setModelURL(QUrl(xml.readElementText())); - } - if (xml.name() == "serialNumber" && xml.isStartElement()) { - upnpDeviceDescriptor.setSerialNumber(xml.readElementText()); - } - if (xml.name() == "UDN" && xml.isStartElement()) { - upnpDeviceDescriptor.setUuid(xml.readElementText()); - } - if (xml.name() == "uuid" && xml.isStartElement()) { - upnpDeviceDescriptor.setUuid(xml.readElementText()); - } - if (xml.name() == "UPC" && xml.isStartElement()) { - upnpDeviceDescriptor.setUpc(xml.readElementText()); - } - xml.readNext(); - } - xml.readNext(); - } - } - } - - foreach (UpnpDiscoveryRequest *upnpDiscoveryRequest, m_discoverRequests) { - upnpDiscoveryRequest->addDeviceDescriptor(upnpDeviceDescriptor); - } - break; - } - default: - qCWarning(dcHardware) << name() << "HTTP request error" << reply->request().url().toString() << status; - m_informationRequestList.remove(reply); - } - - reply->deleteLater(); -} - -void UpnpDiscovery::notificationTimeout() -{ - sendAliveMessage(); -} - -void UpnpDiscovery::sendByeByeMessage() -{ - // TODO: Once DeviceManager (and with that this can be moved into the server, use GuhCore's configuration manager instead of parsing the config here... - GuhSettings globalSettings(GuhSettings::SettingsRoleGlobal); - globalSettings.beginGroup("guhd"); - QByteArray uuid = globalSettings.value("uuid", QUuid()).toByteArray(); - globalSettings.endGroup(); - - globalSettings.beginGroup("WebServer"); - foreach (const QString &group, globalSettings.childGroups()) { - globalSettings.beginGroup(group); - QHostAddress serverInterface = QHostAddress(globalSettings.value("address").toString()); - int serverPort = globalSettings.value("port", -1).toInt(); - bool useSsl = globalSettings.value("sslEnabled", true).toBool(); - globalSettings.endGroup(); - - foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { - foreach (QNetworkAddressEntry entry, interface.addressEntries()) { - if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol && (serverInterface == QHostAddress("0.0.0.0") || entry.ip() == serverInterface)) { - - QString locationString; - if (useSsl) { - locationString = "https://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; - } else { - locationString = "http://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; - } - - // http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf - QByteArray byebyeMessage = QByteArray("NOTIFY * HTTP/1.1\r\n" - "HOST:239.255.255.250:1900\r\n" - "CACHE-CONTROL: max-age=1900\r\n" - "LOCATION: " + locationString.toUtf8() + "\r\n" - "NT:urn:schemas-upnp-org:device:Basic:1\r\n" - "USN:uuid:" + uuid + "::urn:schemas-upnp-org:device:Basic:1\r\n" - "NTS: ssdp:byebye\r\n" - "SERVER: guh/" + QByteArray(GUH_VERSION_STRING) + " UPnP/1.1 \r\n" - "\r\n"); - - sendToMulticast(byebyeMessage); - } - } - } - } - globalSettings.endGroup(); -} - -void UpnpDiscovery::sendAliveMessage() -{ - // TODO: Once DeviceManager (and with that this can be moved into the server, use GuhCore's configuration manager instead of parsing the config here... - GuhSettings globalSettings(GuhSettings::SettingsRoleGlobal); - globalSettings.beginGroup("guhd"); - QByteArray uuid = globalSettings.value("uuid", QUuid()).toByteArray(); - globalSettings.endGroup(); - - globalSettings.beginGroup("WebServer"); - foreach (const QString &group, globalSettings.childGroups()) { - globalSettings.beginGroup(group); - QHostAddress serverInterface = QHostAddress(globalSettings.value("address").toString()); - int serverPort = globalSettings.value("port", -1).toInt(); - bool useSsl = globalSettings.value("sslEnabled", true).toBool(); - globalSettings.endGroup(); - - foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) { - foreach (QNetworkAddressEntry entry, interface.addressEntries()) { - if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol && (serverInterface == QHostAddress("0.0.0.0") || entry.ip() == serverInterface)) { - - QString locationString; - if (useSsl) { - locationString = "https://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; - } else { - locationString = "http://" + entry.ip().toString() + ":" + QString::number(serverPort) + "/server.xml"; - } - - // http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf - QByteArray aliveMessage = QByteArray("NOTIFY * HTTP/1.1\r\n" - "HOST:239.255.255.250:1900\r\n" - "CACHE-CONTROL: max-age=1900\r\n" - "LOCATION: " + locationString.toUtf8() + "\r\n" - "NT:urn:schemas-upnp-org:device:Basic:1\r\n" - "USN:uuid:" + uuid + "::urn:schemas-upnp-org:device:Basic:1\r\n" - "NTS: ssdp:alive\r\n" - "SERVER: guh/" + QByteArray(GUH_VERSION_STRING) + " UPnP/1.1 \r\n" - "\r\n"); - - sendToMulticast(aliveMessage); - } - } - } - } - globalSettings.endGroup(); -} - -void UpnpDiscovery::discoverTimeout() -{ - UpnpDiscoveryRequest *discoveryRequest = static_cast(sender()); - QPointer reply = discoveryRequest->reply(); - - 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); - 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; - m_available = false; - emit availableChanged(false); - delete m_socket; - m_socket = nullptr; - return false; - } - - if(!m_socket->joinMulticastGroup(m_host)){ - qCWarning(dcHardware()) << name() << "could not join multicast group" << m_host; - m_available = false; - emit availableChanged(false); - 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(); - return true; -} - -bool UpnpDiscovery::disable() -{ - sendByeByeMessage(); - m_socket->waitForBytesWritten(); - m_socket->close(); - delete m_socket; - m_socket = nullptr; - - m_notificationTimer->stop(); - - setEnabled(false); - return true; } diff --git a/libguh/network/upnp/upnpdiscovery.h b/libguh/network/upnp/upnpdiscovery.h index 8ea0ad4d..0ee1437e 100644 --- a/libguh/network/upnp/upnpdiscovery.h +++ b/libguh/network/upnp/upnpdiscovery.h @@ -35,61 +35,25 @@ #include "devicemanager.h" #include "hardwareresource.h" #include "upnpdiscoveryreply.h" -#include "upnpdiscoveryrequest.h" #include "upnpdevicedescriptor.h" // 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 -class UpnpDiscoveryRequest; - class LIBGUH_EXPORT UpnpDiscovery : public HardwareResource { Q_OBJECT - friend class HardwareManager; - public: - UpnpDiscoveryReply *discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = QString(), const int &timeout = 5000); - void sendToMulticast(const QByteArray &data); + explicit UpnpDiscovery(QObject *parent = nullptr); + virtual ~UpnpDiscovery() = default; -private: - explicit UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent = nullptr); - ~UpnpDiscovery(); - - QUdpSocket *m_socket = nullptr; - QHostAddress m_host; - qint16 m_port; - - QTimer *m_notificationTimer = nullptr; - - QNetworkAccessManager *m_networkAccessManager = nullptr; - - QList m_discoverRequests; - QHash m_informationRequestList; - - void requestDeviceInformation(const QNetworkRequest &networkRequest, const UpnpDeviceDescriptor &upnpDeviceDescriptor); - void respondToSearchRequest(QHostAddress host, int port); + virtual UpnpDiscoveryReply *discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = QString(), const int &timeout = 5000) = 0; + virtual void sendToMulticast(const QByteArray &data) = 0; signals: void upnpNotify(const QByteArray ¬ifyMessage); -private slots: - void error(QAbstractSocket::SocketError error); - void readData(); - void replyFinished(); - void notificationTimeout(); - void sendByeByeMessage(); - void sendAliveMessage(); - void discoverTimeout(); - -private: - bool enable(); - bool disable(); - -private: - bool m_available = false; - bool m_enabled = false; }; #endif // UPNPDISCOVERY_H diff --git a/libguh/network/upnp/upnpdiscoveryreply.cpp b/libguh/network/upnp/upnpdiscoveryreply.cpp index fc657b8b..8552d706 100644 --- a/libguh/network/upnp/upnpdiscoveryreply.cpp +++ b/libguh/network/upnp/upnpdiscoveryreply.cpp @@ -22,57 +22,8 @@ #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) +UpnpDiscoveryReply::UpnpDiscoveryReply(QObject *parent) : + QObject(parent) { } - -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 index 0547f2aa..43229066 100644 --- a/libguh/network/upnp/upnpdiscoveryreply.h +++ b/libguh/network/upnp/upnpdiscoveryreply.h @@ -31,8 +31,6 @@ class UpnpDiscoveryReply : public QObject { Q_OBJECT - friend class UpnpDiscovery; - public: enum UpnpDiscoveryReplyError { UpnpDiscoveryReplyErrorNoError, @@ -42,28 +40,15 @@ public: }; Q_ENUM(UpnpDiscoveryReplyError) - QString searchTarget() const; - QString userAgent() const; + explicit UpnpDiscoveryReply(QObject *parent = nullptr); - UpnpDiscoveryReplyError error() const; - bool isFinished() const; + virtual QString searchTarget() const = 0; + virtual QString userAgent() const = 0; - QList deviceDescriptors() const; + virtual UpnpDiscoveryReplyError error() const = 0; + virtual bool isFinished() const = 0; -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(); + virtual QList deviceDescriptors() const = 0; signals: void finished(); diff --git a/plugins/mock/translations/de_DE.ts b/plugins/mock/translations/de_DE.ts index a41b9c91..8b82f386 100644 --- a/plugins/mock/translations/de_DE.ts +++ b/plugins/mock/translations/de_DE.ts @@ -12,230 +12,230 @@ MockDevice - + guh The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6) guh - + Mock Device The name of the DeviceClass (753f0d32-0468-4d08-82ed-1964aab03298) Mock Gerät - + http port The name of the paramType (d4f06047-125e-4479-9810-b54c189917f5) of Mock Device HTTP Port - + Mock Action 3 (async) The name of the ActionType fbae06d3-7666-483e-a39e-ec50fe89054e of deviceClass Mock Device Mock Aktion 3 (async) - + Mock Action 4 (broken) The name of the ActionType df3cf33d-26d5-4577-9132-9823bd33fad0 of deviceClass Mock Device Mock Aktion 4 (kaputt) - + Mock Action 5 (async, broken) The name of the ActionType bfe89a1d-3497-4121-8318-e77c37537219 of deviceClass Mock Device Mock Aktion 5 (async, kaputt) - + Mock Device (Auto created) The name of the DeviceClass (ab4257b3-7548-47ee-9bd4-7dc3004fd197) Mock Gerät (Auto erstellt) - + Mock Device (Push Button) The name of the DeviceClass (9e03144c-e436-4eea-82d9-ccb33ef778db) Mock Gerät (Drückknopf) - + Wait 3 second before you continue, the push button will be pressed automatically. The pairing info of deviceClass Mock Device (Push Button) Warte 3 Sekunden bevor du fortfährst, the Knopf wird automatisch gerückt. - + configParamInt The name of the paramType (e1f72121-a426-45e2-b475-8262b5cdf103) of Mock Devices configParamInt - + configParamBool The name of the paramType (c75723b6-ea4f-4982-9751-6c5e39c88145) of Mock Devices configParamBool - + async The name of the paramType (f2977061-4dd0-4ef5-85aa-3b7134743be3) of Mock Device async - + broken The name of the paramType (ae8f8901-f2c1-42a5-8111-6d2fc8e4c1e4) of Mock Device kaputt - + resultCount The name of the paramType (d222adb4-2f9c-4c3f-8655-76400d0fb6ce) of Mock Device Resultat Anzahl - + Dummy int state changed The name of the autocreated EventType (80baec19-54de-4948-ac46-31eabfaceb83) Int Zustand verändert - + Dummy int state The name of the ParamType of StateType (80baec19-54de-4948-ac46-31eabfaceb83) of DeviceClass Mock Device Dummy Int Zustand - + Dummy bool state changed The name of the autocreated EventType (9dd6a97c-dfd1-43dc-acbd-367932742310) Bool Zustand verändert - + Dummy bool state The name of the ParamType of StateType (9dd6a97c-dfd1-43dc-acbd-367932742310) of DeviceClass Mock Device Dummy Bool Zustand - + Mock Action 1 (with params) The name of the ActionType dea0f4e1-65e3-4981-8eaa-2701c53a9185 of deviceClass Mock Device Mock Aktion 1 (Mit Parametern) - + mockActionParam1 The name of the paramType (a2d3a256-a551-4712-a65b-ecd5a436a1cb) of Mock Device mockActionParam1 - + mockActionParam2 The name of the paramType (304a4899-18be-4e3b-94f4-d03be52f3233) of Mock Device mockActionParam2 - + Mock Action 2 (without params) The name of the ActionType defd3ed6-1a0d-400b-8879-a0202cf39935 of deviceClass Mock Device Mock Aktion (ohne Parameter - + mockParamInt The name of the paramType (0550e16d-60b9-4ba5-83f4-4d3cee656121) of Mock Device mockParamInt - + Mock Event 1 The name of the EventType 45bf3752-0fc6-46b9-89fd-ffd878b5b22b of deviceClass Mock Device (Auto created) Mock Event 1 - + Mock Event 2 The name of the EventType 863d5920-b1cf-4eb9-88bd-8f7b8583b1cf of deviceClass Mock Device (Auto created) Mock Event 2 - + color changed The name of the autocreated EventType (20dc7c22-c50e-42db-837c-2bbced939f8e) Farbe geändert - + color The name of the ParamType of StateType (20dc7c22-c50e-42db-837c-2bbced939f8e) of DeviceClass Mock Device (Push Button) Farbe - + Set color The name of the autocreated ActionType (20dc7c22-c50e-42db-837c-2bbced939f8e) Setze Farbe - + percentage changed The name of the autocreated EventType (72981c04-267a-4ba0-a59e-9921d2f3af9c) Prozent gändert - + percentage The name of the ParamType of StateType (72981c04-267a-4ba0-a59e-9921d2f3af9c) of DeviceClass Mock Device (Push Button) Prozent - + Set percentage The name of the autocreated ActionType (72981c04-267a-4ba0-a59e-9921d2f3af9c) Setze Prozentwert - + allowed values changed The name of the autocreated EventType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) Erlaubter Wert geändert - + allowed values The name of the ParamType of StateType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) of DeviceClass Mock Device (Push Button) Erlaubte Werte - + Set allowed values The name of the autocreated ActionType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) Setze erlaubten Wert - + double value changed The name of the autocreated EventType (53cd7c55-49b7-441b-b970-9048f20f0e2c) Double Wert geändert - + double value The name of the ParamType of StateType (53cd7c55-49b7-441b-b970-9048f20f0e2c) of DeviceClass Mock Device (Push Button) Double Wert - + Set double value The name of the autocreated ActionType (53cd7c55-49b7-441b-b970-9048f20f0e2c) Setze double Wert - - + + Set bool value The name of the autocreated ActionType (e680f7a4-b39e-46da-be41-fa3170fe3768) ---------- @@ -243,20 +243,20 @@ The name of the autocreated ActionType (d24ede5f-4064-4898-bb84-cfb533b1fbc0)Setze boll Wert - + Timeout action The name of the ActionType 54646e7c-bc54-4895-81a2-590d72d120f9 of deviceClass Mock Device (Push Button) Timeout Aktion - + Mock Device (Display Pin) The name of the DeviceClass (296f1fd4-e893-46b2-8a42-50d1bceb8730) Mock Gerät (Pin anzeigen) - - + + bool value changed The name of the autocreated EventType (e680f7a4-b39e-46da-be41-fa3170fe3768) ---------- @@ -264,8 +264,8 @@ The name of the autocreated EventType (d24ede5f-4064-4898-bb84-cfb533b1fbc0)Bool Wert geändert - - + + bool value The name of the ParamType of StateType (e680f7a4-b39e-46da-be41-fa3170fe3768) of DeviceClass Mock Device (Push Button) ---------- @@ -273,97 +273,97 @@ The name of the ParamType of StateType (d24ede5f-4064-4898-bb84-cfb533b1fbc0) of Bool Wert - + Text line The name of the paramType (e6acf0c7-4b8e-4296-ac62-855d20deb816) of Mock Device (InputTypes) Textzeile - + Text area The name of the paramType (716f0994-bc01-42b0-b64d-59236f7320d2) of Mock Device (InputTypes) Textfeld - + Password text The name of the paramType (e5c0d14b-c9f1-4aca-a56e-85bfa6977150) of Mock Device (InputTypes) Passwort Text - + Search text The name of the paramType (22add8c9-ee4f-43ad-8931-58e999313ac3) of Mock Device (InputTypes) Suchtext - + Mail address The name of the paramType (a8494faf-3a0f-4cf3-84b7-4b39148a838d) of Mock Device (InputTypes) Mail Adresse - + IPv4 address The name of the paramType (9e5f86a0-4bb3-4892-bff8-3fc4032af6e2) of Mock Device (InputTypes) IPv4 Adresse - + IPv6 address The name of the paramType (43bf3832-dd48-4090-a836-656e8b60216e) of Mock Device (InputTypes) IPv6 Adresse - + URL The name of the paramType (fa67229f-fcef-496f-b671-59a4b48f3ab5) of Mock Device (InputTypes) URL - + Mac address The name of the paramType (e93db587-7919-48f3-8c88-1651de63c765) of Mock Device (InputTypes) Mac Adresse - + Please enter the secret which normaly will be displayed on the device. For the mockdevice the pin is 243681. The pairing info of deviceClass Mock Device (Display Pin) Bitte geben sie den Pincode ein der normalerweise auf dem Gerät angezeit werden würde. In diesem fall lautet der Pincode 243681. - + Mock Devices The name of the plugin Mock Devices (727a4a9a-c187-446f-aadf-f1b2220607d1) Mock Gerät - + pin The name of the paramType (da820e07-22dc-4173-9c07-2f49a4e265f9) of Mock Device (Display Pin) Pin - + Mock Device (Parent) The name of the DeviceClass (a71fbde9-9a38-4bf8-beab-c8aade2608ba) Mock Gerät (Elternteil) - + Mock Device (Child) The name of the DeviceClass (40893c9f-bc47-40c1-8bf7-b390c7c1b4fc) Mock Gerät (Kind) - + parent uuid The name of the paramType (104b5288-404e-42d3-bf38-e40682e75681) of Mock Device (Child) Elternteil Uuid - + Mock Device (InputTypes) The name of the DeviceClass (515ffdf1-55e5-498d-9abc-4e2fe768f3a9) Mock Gerät (Eingabemethoden) diff --git a/plugins/mock/translations/en_US.ts b/plugins/mock/translations/en_US.ts index c631361a..ed068c24 100644 --- a/plugins/mock/translations/en_US.ts +++ b/plugins/mock/translations/en_US.ts @@ -12,230 +12,230 @@ MockDevice - + guh The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6) - + Mock Device The name of the DeviceClass (753f0d32-0468-4d08-82ed-1964aab03298) - + http port The name of the paramType (d4f06047-125e-4479-9810-b54c189917f5) of Mock Device - + Mock Action 3 (async) The name of the ActionType fbae06d3-7666-483e-a39e-ec50fe89054e of deviceClass Mock Device - + Mock Action 4 (broken) The name of the ActionType df3cf33d-26d5-4577-9132-9823bd33fad0 of deviceClass Mock Device - + Mock Action 5 (async, broken) The name of the ActionType bfe89a1d-3497-4121-8318-e77c37537219 of deviceClass Mock Device - + Mock Device (Auto created) The name of the DeviceClass (ab4257b3-7548-47ee-9bd4-7dc3004fd197) - + Mock Device (Push Button) The name of the DeviceClass (9e03144c-e436-4eea-82d9-ccb33ef778db) - + Wait 3 second before you continue, the push button will be pressed automatically. The pairing info of deviceClass Mock Device (Push Button) - + configParamInt The name of the paramType (e1f72121-a426-45e2-b475-8262b5cdf103) of Mock Devices - + configParamBool The name of the paramType (c75723b6-ea4f-4982-9751-6c5e39c88145) of Mock Devices - + async The name of the paramType (f2977061-4dd0-4ef5-85aa-3b7134743be3) of Mock Device - + broken The name of the paramType (ae8f8901-f2c1-42a5-8111-6d2fc8e4c1e4) of Mock Device - + resultCount The name of the paramType (d222adb4-2f9c-4c3f-8655-76400d0fb6ce) of Mock Device - + Dummy int state changed The name of the autocreated EventType (80baec19-54de-4948-ac46-31eabfaceb83) - + Dummy int state The name of the ParamType of StateType (80baec19-54de-4948-ac46-31eabfaceb83) of DeviceClass Mock Device - + Dummy bool state changed The name of the autocreated EventType (9dd6a97c-dfd1-43dc-acbd-367932742310) - + Dummy bool state The name of the ParamType of StateType (9dd6a97c-dfd1-43dc-acbd-367932742310) of DeviceClass Mock Device - + Mock Action 1 (with params) The name of the ActionType dea0f4e1-65e3-4981-8eaa-2701c53a9185 of deviceClass Mock Device - + mockActionParam1 The name of the paramType (a2d3a256-a551-4712-a65b-ecd5a436a1cb) of Mock Device - + mockActionParam2 The name of the paramType (304a4899-18be-4e3b-94f4-d03be52f3233) of Mock Device - + Mock Action 2 (without params) The name of the ActionType defd3ed6-1a0d-400b-8879-a0202cf39935 of deviceClass Mock Device - + mockParamInt The name of the paramType (0550e16d-60b9-4ba5-83f4-4d3cee656121) of Mock Device - + Mock Event 1 The name of the EventType 45bf3752-0fc6-46b9-89fd-ffd878b5b22b of deviceClass Mock Device (Auto created) - + Mock Event 2 The name of the EventType 863d5920-b1cf-4eb9-88bd-8f7b8583b1cf of deviceClass Mock Device (Auto created) - + color changed The name of the autocreated EventType (20dc7c22-c50e-42db-837c-2bbced939f8e) - + color The name of the ParamType of StateType (20dc7c22-c50e-42db-837c-2bbced939f8e) of DeviceClass Mock Device (Push Button) - + Set color The name of the autocreated ActionType (20dc7c22-c50e-42db-837c-2bbced939f8e) - + percentage changed The name of the autocreated EventType (72981c04-267a-4ba0-a59e-9921d2f3af9c) - + percentage The name of the ParamType of StateType (72981c04-267a-4ba0-a59e-9921d2f3af9c) of DeviceClass Mock Device (Push Button) - + Set percentage The name of the autocreated ActionType (72981c04-267a-4ba0-a59e-9921d2f3af9c) - + allowed values changed The name of the autocreated EventType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) - + allowed values The name of the ParamType of StateType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) of DeviceClass Mock Device (Push Button) - + Set allowed values The name of the autocreated ActionType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) - + double value changed The name of the autocreated EventType (53cd7c55-49b7-441b-b970-9048f20f0e2c) - + double value The name of the ParamType of StateType (53cd7c55-49b7-441b-b970-9048f20f0e2c) of DeviceClass Mock Device (Push Button) - + Set double value The name of the autocreated ActionType (53cd7c55-49b7-441b-b970-9048f20f0e2c) - - + + Set bool value The name of the autocreated ActionType (e680f7a4-b39e-46da-be41-fa3170fe3768) ---------- @@ -243,20 +243,20 @@ The name of the autocreated ActionType (d24ede5f-4064-4898-bb84-cfb533b1fbc0) - + Timeout action The name of the ActionType 54646e7c-bc54-4895-81a2-590d72d120f9 of deviceClass Mock Device (Push Button) - + Mock Device (Display Pin) The name of the DeviceClass (296f1fd4-e893-46b2-8a42-50d1bceb8730) - - + + bool value changed The name of the autocreated EventType (e680f7a4-b39e-46da-be41-fa3170fe3768) ---------- @@ -264,8 +264,8 @@ The name of the autocreated EventType (d24ede5f-4064-4898-bb84-cfb533b1fbc0) - - + + bool value The name of the ParamType of StateType (e680f7a4-b39e-46da-be41-fa3170fe3768) of DeviceClass Mock Device (Push Button) ---------- @@ -273,97 +273,97 @@ The name of the ParamType of StateType (d24ede5f-4064-4898-bb84-cfb533b1fbc0) of - + Text line The name of the paramType (e6acf0c7-4b8e-4296-ac62-855d20deb816) of Mock Device (InputTypes) - + Text area The name of the paramType (716f0994-bc01-42b0-b64d-59236f7320d2) of Mock Device (InputTypes) - + Password text The name of the paramType (e5c0d14b-c9f1-4aca-a56e-85bfa6977150) of Mock Device (InputTypes) - + Search text The name of the paramType (22add8c9-ee4f-43ad-8931-58e999313ac3) of Mock Device (InputTypes) - + Mail address The name of the paramType (a8494faf-3a0f-4cf3-84b7-4b39148a838d) of Mock Device (InputTypes) - + IPv4 address The name of the paramType (9e5f86a0-4bb3-4892-bff8-3fc4032af6e2) of Mock Device (InputTypes) - + IPv6 address The name of the paramType (43bf3832-dd48-4090-a836-656e8b60216e) of Mock Device (InputTypes) - + URL The name of the paramType (fa67229f-fcef-496f-b671-59a4b48f3ab5) of Mock Device (InputTypes) - + Mac address The name of the paramType (e93db587-7919-48f3-8c88-1651de63c765) of Mock Device (InputTypes) - + Please enter the secret which normaly will be displayed on the device. For the mockdevice the pin is 243681. The pairing info of deviceClass Mock Device (Display Pin) - + Mock Devices The name of the plugin Mock Devices (727a4a9a-c187-446f-aadf-f1b2220607d1) - + pin The name of the paramType (da820e07-22dc-4173-9c07-2f49a4e265f9) of Mock Device (Display Pin) - + Mock Device (Parent) The name of the DeviceClass (a71fbde9-9a38-4bf8-beab-c8aade2608ba) - + Mock Device (Child) The name of the DeviceClass (40893c9f-bc47-40c1-8bf7-b390c7c1b4fc) - + parent uuid The name of the paramType (104b5288-404e-42d3-bf38-e40682e75681) of Mock Device (Child) - + Mock Device (InputTypes) The name of the DeviceClass (515ffdf1-55e5-498d-9abc-4e2fe768f3a9) diff --git a/tests/auto/autotests.pri b/tests/auto/autotests.pri index c998199d..274266f1 100644 --- a/tests/auto/autotests.pri +++ b/tests/auto/autotests.pri @@ -7,7 +7,7 @@ INCLUDEPATH += $$top_srcdir/libguh \ $$top_srcdir/tests/auto/ LIBS += -L$$top_builddir/libguh/ -lguh -L$$top_builddir/plugins/mock/ \ - -L$$top_builddir/libguh-core/ -lguh-core -lssl -lcrypto -laws-iot-sdk-cpp -lmbedtls -lmbedx509 -lmbedcrypto + -L$$top_builddir/libguh-core/ -lguh-core -lssl -lcrypto -laws-iot-sdk-cpp -lmbedtls -lmbedx509 -lmbedcrypto -lavahi-common -lavahi-client SOURCES += ../guhtestbase.cpp \ diff --git a/tests/auto/guhtestbase.cpp b/tests/auto/guhtestbase.cpp index e57c529d..601cb9ae 100644 --- a/tests/auto/guhtestbase.cpp +++ b/tests/auto/guhtestbase.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include using namespace guhserver; diff --git a/tests/auto/guhtestbase.h b/tests/auto/guhtestbase.h index 4f379b8b..667af531 100644 --- a/tests/auto/guhtestbase.h +++ b/tests/auto/guhtestbase.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include extern DeviceClassId mockDeviceClassId; extern DeviceClassId mockDeviceAutoClassId; diff --git a/translations/guhd-de_DE.ts b/translations/guhd-de_DE.ts index 5b6e744a..89ee1a9f 100644 --- a/translations/guhd-de_DE.ts +++ b/translations/guhd-de_DE.ts @@ -4,7 +4,7 @@ main - + guh ( /[guːh]/ ) is an open source IoT (Internet of Things) server, which allows to control a lot of different devices from many different @@ -23,12 +23,12 @@ Szenen undVerhaltensweisen des Systems festzulegen. - + Run guhd in the foreground, not as daemon. Starte guhd im Vordergrund, nicht als Service. - + Debug categories to enable. Prefix with "No" to disable. Warnings from all categories will be printed unless explicitly muted with "NoWarnings". Categories are: @@ -36,22 +36,22 @@ Categories are: Es gibt folgende Kategorien: - + Enables all debug categories. This parameter overrides all debug category parameters. Aktiviere alle Debug-Kategorien. Dieser Parameter überschreibt alle anderen Debug-Kategorien Parameter. - + Specify a log file to write to, If this option is not specified, logs will be printed to the standard output. - + If specified, all D-Bus interfaces will be bound to the session bus instead of the system bus. - + No such debug category: Diese Debug-Kategorie existiert nicht: diff --git a/translations/guhd-en_US.ts b/translations/guhd-en_US.ts index 863daa0c..5c03ed17 100644 --- a/translations/guhd-en_US.ts +++ b/translations/guhd-en_US.ts @@ -4,7 +4,7 @@ main - + guh ( /[guːh]/ ) is an open source IoT (Internet of Things) server, which allows to control a lot of different devices from many different @@ -23,12 +23,12 @@ for your environment. - + Run guhd in the foreground, not as daemon. Run guhd in the foreground, not as daemon. - + Debug categories to enable. Prefix with "No" to disable. Warnings from all categories will be printed unless explicitly muted with "NoWarnings". Categories are: @@ -37,22 +37,22 @@ Categories are: Categories are: - + Enables all debug categories. This parameter overrides all debug category parameters. Enables all debug categories. This parameter overrides all debug category parameters. - + Specify a log file to write to, If this option is not specified, logs will be printed to the standard output. - + If specified, all D-Bus interfaces will be bound to the session bus instead of the system bus. - + No such debug category: No such debug category: