First building version of hardware resource abstraction

This commit is contained in:
Simon Stürz 2017-12-20 15:00:29 +01:00 committed by Michael Zanetti
parent 5799a8d7bc
commit c2c7e0fbc2
54 changed files with 1665 additions and 1027 deletions

View File

@ -20,31 +20,34 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "bluetoothdiscoveryreply.h"
#include "bluetoothdiscoveryreplyimplementation.h"
#include <QTimer>
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<QBluetoothDeviceInfo> BluetoothDiscoveryReply::discoveredDevices() const
QList<QBluetoothDeviceInfo> 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<QBluetoothDeviceInfo> &discoveredDevices)
void BluetoothDiscoveryReplyImplementation::setDiscoveredDevices(const QList<QBluetoothDeviceInfo> &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);
}
}

View File

@ -0,0 +1,58 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHDISCOVERYREPLYIMPLEMENTATION_H
#define BLUETOOTHDISCOVERYREPLYIMPLEMENTATION_H
#include <QObject>
#include <QBluetoothDeviceInfo>
#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<QBluetoothDeviceInfo> discoveredDevices() const;
private:
bool m_finished = false;
BluetoothDiscoveryReplyError m_error = BluetoothDiscoveryReplyErrorNoError;
QList<QBluetoothDeviceInfo> m_discoveredDevices;
void setError(const BluetoothDiscoveryReplyError &error);
void setDiscoveredDevices(const QList<QBluetoothDeviceInfo> &discoveredDevices);
void setFinished();
};
}
#endif // BLUETOOTHDISCOVERYREPLYIMPLEMENTATION_H

View File

@ -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<QBluetoothUuid> BluetoothLowEnergyDevice::serviceUuids() const
QList<QBluetoothUuid> 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);
}
}

View File

@ -20,8 +20,8 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHLOWENERGYDEVICE_H
#define BLUETOOTHLOWENERGYDEVICE_H
#ifndef BLUETOOTHLOWENERGYDEVICEIMPLEMENTATION_H
#define BLUETOOTHLOWENERGYDEVICEIMPLEMENTATION_H
#include <QObject>
#include <QBluetoothDeviceInfo>
@ -29,15 +29,19 @@
#include <QBluetoothServiceInfo>
#include <QLowEnergyController>
#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

View File

@ -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<QBluetoothHostInfo> 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<BluetoothDiscoveryReply> reply = new BluetoothDiscoveryReply(this);
QPointer<BluetoothDiscoveryReplyImplementation> 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<BluetoothLowEnergyDevice> bluetoothDevice = new BluetoothLowEnergyDevice(deviceInfo, addressType, this);
QPointer<BluetoothLowEnergyDeviceImplementation> 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<BluetoothLowEnergyDevice> 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<BluetoothLowEnergyDevice> dPointer, m_devices) {
foreach (QPointer<BluetoothLowEnergyDeviceImplementation> 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<QBluetoothHostInfo> 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<QBluetoothDeviceDiscoveryAgent *>(sender());
qCWarning(dcBluetooth()) << "Discovery error:" << error << discoveryAgent->errorString();
}
bool BluetoothLowEnergyManager::enable()
bool BluetoothLowEnergyManagerImplementation::enable()
{
qCDebug(dcBluetooth()) << "Hardware resource enabled.";
setEnabled(true);
foreach (QPointer<BluetoothLowEnergyDevice> bluetoothDevice, m_devices) {
foreach (QPointer<BluetoothLowEnergyDeviceImplementation> bluetoothDevice, m_devices) {
bluetoothDevice->setEnabled(true);
}
return true;
}
bool BluetoothLowEnergyManager::disable()
bool BluetoothLowEnergyManagerImplementation::disable()
{
qCDebug(dcBluetooth()) << "Hardware resource disabled.";
setEnabled(false);
foreach (QPointer<BluetoothLowEnergyDevice> bluetoothDevice, m_devices) {
foreach (QPointer<BluetoothLowEnergyDeviceImplementation> bluetoothDevice, m_devices) {
bluetoothDevice->setEnabled(false);
}
return true;
}
}

View File

@ -20,8 +20,8 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHLOWENERGYMANAGER_H
#define BLUETOOTHLOWENERGYMANAGER_H
#ifndef BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H
#define BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H
#include <QTimer>
#include <QObject>
@ -31,32 +31,45 @@
#include <QBluetoothDeviceDiscoveryAgent>
#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<QPointer<BluetoothLowEnergyDevice>> m_devices;
QList<QPointer<BluetoothLowEnergyDeviceImplementation>> m_devices;
bool m_available = false;
bool m_enabled = false;
QList<QBluetoothDeviceDiscoveryAgent *> m_bluetoothDiscoveryAgents;
QList<QBluetoothDeviceInfo> m_discoveredDevices;
QPointer<BluetoothDiscoveryReply> m_currentReply;
QPointer<BluetoothDiscoveryReplyImplementation> m_currentReply;
private slots:
void onReconnectTimeout();
@ -70,4 +83,6 @@ public slots:
};
#endif // BLUETOOTHLOWENERGYMANAGER_H
}
#endif // BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H

View File

@ -191,3 +191,5 @@ const AvahiPoll* avahi_qt_poll_get(void)
#include "qt-watch.moc"

View File

@ -24,8 +24,13 @@
#include "qtavahiclient.h"
#include "loggingcategories.h"
#include "qtavahiservicebrowserimplementation.h"
#include "qtavahiservicebrowserimplementation_p.h"
#include <avahi-common/error.h>
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);
}
}

View File

@ -26,9 +26,9 @@
#include <QObject>
#include <avahi-client/client.h>
#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

View File

@ -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;
}
}

View File

@ -27,11 +27,12 @@
#include <QString>
#include <QObject>
#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

View File

@ -27,6 +27,8 @@
#include <QHash>
#include <QStringList>
namespace guhserver {
QtAvahiServicePrivate::QtAvahiServicePrivate() :
client(0),
group(0),
@ -80,3 +82,4 @@ AvahiStringList *QtAvahiServicePrivate::createTxtList(const QHash<QString, QStri
return list;
}
}

View File

@ -29,13 +29,13 @@
#include "qtavahiservice.h"
#include "qtavahiclient.h"
#include "libguh.h"
#include <avahi-client/publish.h>
#include <avahi-common/error.h>
#include <avahi-common/alternative.h>
class LIBGUH_EXPORT QtAvahiServicePrivate
namespace guhserver {
class QtAvahiServicePrivate
{
public:
QtAvahiServicePrivate();
@ -55,5 +55,7 @@ public:
};
}
#endif // QTAVAHISERVICEPRIVATE_P

View File

@ -0,0 +1,130 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\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 <avahi-common/error.h>
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<AvahiServiceEntry> 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);
}
}

View File

@ -0,0 +1,81 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef QTAVAHISERVICEBROWSERIMPLEMENTATION_H
#define QTAVAHISERVICEBROWSERIMPLEMENTATION_H
#include <QObject>
#include <avahi-client/lookup.h>
#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<AvahiServiceEntry> 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<AvahiServiceEntry> m_serviceEntries;
QStringList m_serviceTypes;
void createServiceBrowser(const char* serviceType);
Q_DECLARE_PRIVATE(QtAvahiServiceBrowserImplementation)
};
}
#endif // QTAVAHISERVICEBROWSERIMPLEMENTATION_H

View File

@ -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 <avahi-common/strlst.h>
#include <avahi-common/error.h>
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<QtAvahiServiceBrowser *>(userdata);
QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(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<QtAvahiServiceBrowser *>(userdata);
QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(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<QtAvahiServiceBrowser> serviceBrowser = static_cast<QtAvahiServiceBrowser *>(userdata);
QPointer<QtAvahiServiceBrowserImplementation> serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(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;
}
}

View File

@ -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<AvahiServiceResolver *> m_serviceResolvers;
};
}
#endif // QTAVAHISERVICEBROWSERPRIVATE_H

View File

@ -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";

View File

@ -66,6 +66,7 @@ private:
bool m_enabled = false;
QNetworkAccessManager *m_manager;
};
#endif // NETWORKACCESSMANAGER_H

View File

@ -0,0 +1,510 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\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 &notifyMessage)
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 <QMetaObject>
#include <QNetworkInterface>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
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<UpnpDiscoveryReplyImplementation> 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<QNetworkReply *>(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<UpnpDiscoveryRequest*>(sender());
QPointer<UpnpDiscoveryReplyImplementation> 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;
}
}

View File

@ -0,0 +1,97 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef UPNPDISCOVERYIMPLEMENTATION_H
#define UPNPDISCOVERYIMPLEMENTATION_H
#include <QUrl>
#include <QTimer>
#include <QUdpSocket>
#include <QHostAddress>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#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<UpnpDiscoveryRequest *> m_discoverRequests;
QHash<QNetworkReply*, UpnpDeviceDescriptor> 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

View File

@ -0,0 +1,83 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "upnpdiscoveryreplyimplementation.h"
#include <QTimer>
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<UpnpDeviceDescriptor> UpnpDiscoveryReplyImplementation::deviceDescriptors() const
{
return m_deviceDescriptors;
}
void UpnpDiscoveryReplyImplementation::setDeviceDescriptors(const QList<UpnpDeviceDescriptor> &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);
}
}

View File

@ -0,0 +1,72 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef UPNPDISCOVERYREPLYIMPLEMENTATION_H
#define UPNPDISCOVERYREPLYIMPLEMENTATION_H
#include <QObject>
#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<UpnpDeviceDescriptor> deviceDescriptors() const;
private:
QString m_searchTarget;
QString m_userAgent;
QList<UpnpDeviceDescriptor> m_deviceDescriptors;
UpnpDiscoveryReplyError m_error = UpnpDiscoveryReplyErrorNoError;
bool m_finished = false;
// Methods for UpnpDiscovery
void setDeviceDescriptors(const QList<UpnpDeviceDescriptor> &deviceDescriptors);
void setError(const UpnpDiscoveryReplyError &error);
void setFinished();
signals:
void finished();
void errorOccured(const UpnpDiscoveryReplyError &error);
};
}
#endif // UPNPDISCOVERYREPLYIMPLEMENTATION_H

View File

@ -23,7 +23,9 @@
#include "upnpdiscoveryrequest.h"
#include "loggingcategories.h"
UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer<UpnpDiscoveryReply> reply):
namespace guhserver {
UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer<UpnpDiscoveryReplyImplementation> reply):
QObject(upnpDiscovery),
m_upnpDiscovery(upnpDiscovery),
m_reply(reply)
@ -79,7 +81,9 @@ QList<UpnpDeviceDescriptor> UpnpDiscoveryRequest::deviceList() const
return m_deviceList;
}
QPointer<UpnpDiscoveryReply> UpnpDiscoveryRequest::reply()
QPointer<UpnpDiscoveryReplyImplementation> UpnpDiscoveryRequest::reply()
{
return m_reply;
}
}

View File

@ -27,30 +27,32 @@
#include <QDebug>
#include <QMetaObject>
#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<UpnpDiscoveryReply> reply);
explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer<UpnpDiscoveryReplyImplementation> reply);
void discover(const int &timeout);
void addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor);
QNetworkRequest createNetworkRequest(UpnpDeviceDescriptor deviveDescriptor);
QList<UpnpDeviceDescriptor> deviceList() const;
QPointer<UpnpDiscoveryReply> reply();
QPointer<UpnpDiscoveryReplyImplementation> reply();
private:
UpnpDiscovery *m_upnpDiscovery;
QPointer<UpnpDiscoveryReply> m_reply;
QPointer<UpnpDiscoveryReplyImplementation> m_reply;
QTimer *m_timer = nullptr;
QList<UpnpDeviceDescriptor> m_deviceList;
@ -60,4 +62,6 @@ signals:
};
}
#endif // UPNPDISCOVERYREQUEST_H

View File

@ -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);
}
}

View File

@ -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();
};
}

View File

@ -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 \

View File

@ -32,7 +32,7 @@
#include <QDebug>
#include "transportinterface.h"
#include "network/avahi/qtavahiservice.h"
#include "hardware/network/avahi/qtavahiservice.h"
#include "loggingcategories.h"

View File

@ -34,7 +34,7 @@
#include <QSslConfiguration>
#include <QSslKey>
#include "network/avahi/qtavahiservice.h"
#include "hardware/network/avahi/qtavahiservice.h"
#include "guhconfiguration.h"

View File

@ -28,7 +28,7 @@
#include <QWebSocket>
#include <QWebSocketServer>
#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:

View File

@ -0,0 +1,29 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "bluetoothdiscoveryreply.h"
BluetoothDiscoveryReply::BluetoothDiscoveryReply(QObject *parent) :
QObject(parent)
{
}

View File

@ -26,12 +26,12 @@
#include <QObject>
#include <QBluetoothDeviceInfo>
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<QBluetoothDeviceInfo> discoveredDevices() const;
private:
explicit BluetoothDiscoveryReply(QObject *parent = nullptr);
virtual ~BluetoothDiscoveryReply() = default;
bool m_finished = false;
BluetoothDiscoveryReplyError m_error = BluetoothDiscoveryReplyErrorNoError;
QList<QBluetoothDeviceInfo> m_discoveredDevices;
void setError(const BluetoothDiscoveryReplyError &error);
void setDiscoveredDevices(const QList<QBluetoothDeviceInfo> &discoveredDevices);
void setFinished();
virtual bool isFinished() const = 0;
virtual BluetoothDiscoveryReplyError error() const = 0;
virtual QList<QBluetoothDeviceInfo> discoveredDevices() const = 0;
signals:
void finished();

View File

@ -0,0 +1,29 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "bluetoothlowenergydevice.h"
BluetoothLowEnergyDevice::BluetoothLowEnergyDevice(QObject *parent) :
QObject(parent)
{
}

View File

@ -0,0 +1,66 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHLOWENERGYDEVICE_H
#define BLUETOOTHLOWENERGYDEVICE_H
#include <QObject>
#include <QBluetoothDeviceInfo>
#include <QBluetoothAddress>
#include <QBluetoothServiceInfo>
#include <QLowEnergyController>
#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<QBluetoothUuid> 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

View File

@ -30,17 +30,20 @@
#include <QBluetoothLocalDevice>
#include <QBluetoothDeviceDiscoveryAgent>
#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;

View File

@ -33,6 +33,7 @@ class HardwareResource : public QObject
public:
explicit HardwareResource(const QString &name, QObject *parent = nullptr);
virtual ~HardwareResource() = default;
QString name() const;

View File

@ -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 \

View File

@ -27,6 +27,7 @@
#include <QString>
#include <QHostAddress>
#include <QAbstractSocket>
#include <avahi-client/publish.h>
#include "libguh.h"

View File

@ -37,81 +37,12 @@
*/
#include "qtavahiservicebrowser.h"
#include "qtavahiservicebrowser_p.h"
#include "loggingcategories.h"
#include <avahi-common/error.h>
/*! 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<AvahiServiceEntry> 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);
}

View File

@ -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<AvahiServiceEntry> serviceEntries() const;
explicit QtAvahiServiceBrowser(QObject *parent = nullptr);
virtual ~QtAvahiServiceBrowser() = default;
virtual QList<AvahiServiceEntry> 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<AvahiServiceEntry> m_serviceEntries;
QStringList m_serviceTypes;
void createServiceBrowser(const char* serviceType);
Q_DECLARE_PRIVATE(QtAvahiServiceBrowser)
};
#endif // QTAVAHISERVICEBROWSER_H

View File

@ -35,13 +35,6 @@
\sa UpnpDevice, UpnpDeviceDescriptor
*/
/*!
\fn UpnpDiscovery::discoveryFinished(const QList<UpnpDeviceDescriptor> &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 &notifyMessage)
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 <QMetaObject>
#include <QNetworkInterface>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
/*! 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<UpnpDiscoveryReply> 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<QNetworkReply *>(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<UpnpDiscoveryRequest*>(sender());
QPointer<UpnpDiscoveryReply> 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;
}

View File

@ -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<UpnpDiscoveryRequest *> m_discoverRequests;
QHash<QNetworkReply*, UpnpDeviceDescriptor> 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 &notifyMessage);
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

View File

@ -22,57 +22,8 @@
#include "upnpdiscoveryreply.h"
#include <QTimer>
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<UpnpDeviceDescriptor> 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<UpnpDeviceDescriptor> &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);
}

View File

@ -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<UpnpDeviceDescriptor> 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<UpnpDeviceDescriptor> m_deviceDescriptors;
UpnpDiscoveryReplyError m_error = UpnpDiscoveryReplyErrorNoError;
bool m_finished = false;
// Methods for UpnpDiscovery
void setDeviceDescriptors(const QList<UpnpDeviceDescriptor> &deviceDescriptors);
void setError(const UpnpDiscoveryReplyError &error);
void setFinished();
virtual QList<UpnpDeviceDescriptor> deviceDescriptors() const = 0;
signals:
void finished();

View File

@ -12,230 +12,230 @@
<context>
<name>MockDevice</name>
<message>
<location filename="../plugininfo.h" line="100"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="100"/>
<source>guh</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation>guh</translation>
</message>
<message>
<location filename="../plugininfo.h" line="103"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="103"/>
<source>Mock Device</source>
<extracomment>The name of the DeviceClass (753f0d32-0468-4d08-82ed-1964aab03298)</extracomment>
<translation>Mock Gerät</translation>
</message>
<message>
<location filename="../plugininfo.h" line="106"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="106"/>
<source>http port</source>
<extracomment>The name of the paramType (d4f06047-125e-4479-9810-b54c189917f5) of Mock Device</extracomment>
<translation>HTTP Port</translation>
</message>
<message>
<location filename="../plugininfo.h" line="142"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="142"/>
<source>Mock Action 3 (async)</source>
<extracomment>The name of the ActionType fbae06d3-7666-483e-a39e-ec50fe89054e of deviceClass Mock Device</extracomment>
<translation>Mock Aktion 3 (async)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="145"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="145"/>
<source>Mock Action 4 (broken)</source>
<extracomment>The name of the ActionType df3cf33d-26d5-4577-9132-9823bd33fad0 of deviceClass Mock Device</extracomment>
<translation>Mock Aktion 4 (kaputt)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="148"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="148"/>
<source>Mock Action 5 (async, broken)</source>
<extracomment>The name of the ActionType bfe89a1d-3497-4121-8318-e77c37537219 of deviceClass Mock Device</extracomment>
<translation>Mock Aktion 5 (async, kaputt)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="154"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="154"/>
<source>Mock Device (Auto created)</source>
<extracomment>The name of the DeviceClass (ab4257b3-7548-47ee-9bd4-7dc3004fd197)</extracomment>
<translation>Mock Gerät (Auto erstellt)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="166"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="166"/>
<source>Mock Device (Push Button)</source>
<extracomment>The name of the DeviceClass (9e03144c-e436-4eea-82d9-ccb33ef778db)</extracomment>
<translation>Mock Gerät (Drückknopf)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="163"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="163"/>
<source>Wait 3 second before you continue, the push button will be pressed automatically.</source>
<extracomment>The pairing info of deviceClass Mock Device (Push Button)</extracomment>
<translation>Warte 3 Sekunden bevor du fortfährst, the Knopf wird automatisch gerückt.</translation>
</message>
<message>
<location filename="../plugininfo.h" line="94"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="94"/>
<source>configParamInt</source>
<extracomment>The name of the paramType (e1f72121-a426-45e2-b475-8262b5cdf103) of Mock Devices</extracomment>
<translation>configParamInt</translation>
</message>
<message>
<location filename="../plugininfo.h" line="97"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="97"/>
<source>configParamBool</source>
<extracomment>The name of the paramType (c75723b6-ea4f-4982-9751-6c5e39c88145) of Mock Devices</extracomment>
<translation>configParamBool</translation>
</message>
<message>
<location filename="../plugininfo.h" line="109"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="109"/>
<source>async</source>
<extracomment>The name of the paramType (f2977061-4dd0-4ef5-85aa-3b7134743be3) of Mock Device</extracomment>
<translation>async</translation>
</message>
<message>
<location filename="../plugininfo.h" line="112"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="112"/>
<source>broken</source>
<extracomment>The name of the paramType (ae8f8901-f2c1-42a5-8111-6d2fc8e4c1e4) of Mock Device</extracomment>
<translation>kaputt</translation>
</message>
<message>
<location filename="../plugininfo.h" line="115"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="115"/>
<source>resultCount</source>
<extracomment>The name of the paramType (d222adb4-2f9c-4c3f-8655-76400d0fb6ce) of Mock Device</extracomment>
<translation>Resultat Anzahl</translation>
</message>
<message>
<location filename="../plugininfo.h" line="118"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="118"/>
<source>Dummy int state changed</source>
<extracomment>The name of the autocreated EventType (80baec19-54de-4948-ac46-31eabfaceb83)</extracomment>
<translation>Int Zustand verändert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="121"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="121"/>
<source>Dummy int state</source>
<extracomment>The name of the ParamType of StateType (80baec19-54de-4948-ac46-31eabfaceb83) of DeviceClass Mock Device</extracomment>
<translation>Dummy Int Zustand</translation>
</message>
<message>
<location filename="../plugininfo.h" line="124"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="124"/>
<source>Dummy bool state changed</source>
<extracomment>The name of the autocreated EventType (9dd6a97c-dfd1-43dc-acbd-367932742310)</extracomment>
<translation>Bool Zustand verändert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="127"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="127"/>
<source>Dummy bool state</source>
<extracomment>The name of the ParamType of StateType (9dd6a97c-dfd1-43dc-acbd-367932742310) of DeviceClass Mock Device</extracomment>
<translation>Dummy Bool Zustand</translation>
</message>
<message>
<location filename="../plugininfo.h" line="130"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="130"/>
<source>Mock Action 1 (with params)</source>
<extracomment>The name of the ActionType dea0f4e1-65e3-4981-8eaa-2701c53a9185 of deviceClass Mock Device</extracomment>
<translation>Mock Aktion 1 (Mit Parametern)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="133"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="133"/>
<source>mockActionParam1</source>
<extracomment>The name of the paramType (a2d3a256-a551-4712-a65b-ecd5a436a1cb) of Mock Device</extracomment>
<translation>mockActionParam1</translation>
</message>
<message>
<location filename="../plugininfo.h" line="136"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="136"/>
<source>mockActionParam2</source>
<extracomment>The name of the paramType (304a4899-18be-4e3b-94f4-d03be52f3233) of Mock Device</extracomment>
<translation>mockActionParam2</translation>
</message>
<message>
<location filename="../plugininfo.h" line="139"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="139"/>
<source>Mock Action 2 (without params)</source>
<extracomment>The name of the ActionType defd3ed6-1a0d-400b-8879-a0202cf39935 of deviceClass Mock Device</extracomment>
<translation>Mock Aktion (ohne Parameter</translation>
</message>
<message>
<location filename="../plugininfo.h" line="151"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="151"/>
<source>mockParamInt</source>
<extracomment>The name of the paramType (0550e16d-60b9-4ba5-83f4-4d3cee656121) of Mock Device</extracomment>
<translation>mockParamInt</translation>
</message>
<message>
<location filename="../plugininfo.h" line="157"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="157"/>
<source>Mock Event 1</source>
<extracomment>The name of the EventType 45bf3752-0fc6-46b9-89fd-ffd878b5b22b of deviceClass Mock Device (Auto created)</extracomment>
<translation>Mock Event 1</translation>
</message>
<message>
<location filename="../plugininfo.h" line="160"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="160"/>
<source>Mock Event 2</source>
<extracomment>The name of the EventType 863d5920-b1cf-4eb9-88bd-8f7b8583b1cf of deviceClass Mock Device (Auto created)</extracomment>
<translation>Mock Event 2</translation>
</message>
<message>
<location filename="../plugininfo.h" line="169"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="169"/>
<source>color changed</source>
<extracomment>The name of the autocreated EventType (20dc7c22-c50e-42db-837c-2bbced939f8e)</extracomment>
<translation>Farbe geändert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="172"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="172"/>
<source>color</source>
<extracomment>The name of the ParamType of StateType (20dc7c22-c50e-42db-837c-2bbced939f8e) of DeviceClass Mock Device (Push Button)</extracomment>
<translation>Farbe</translation>
</message>
<message>
<location filename="../plugininfo.h" line="175"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="175"/>
<source>Set color</source>
<extracomment>The name of the autocreated ActionType (20dc7c22-c50e-42db-837c-2bbced939f8e)</extracomment>
<translation>Setze Farbe</translation>
</message>
<message>
<location filename="../plugininfo.h" line="178"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="178"/>
<source>percentage changed</source>
<extracomment>The name of the autocreated EventType (72981c04-267a-4ba0-a59e-9921d2f3af9c)</extracomment>
<translation>Prozent gändert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="181"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="181"/>
<source>percentage</source>
<extracomment>The name of the ParamType of StateType (72981c04-267a-4ba0-a59e-9921d2f3af9c) of DeviceClass Mock Device (Push Button)</extracomment>
<translation>Prozent</translation>
</message>
<message>
<location filename="../plugininfo.h" line="184"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="184"/>
<source>Set percentage</source>
<extracomment>The name of the autocreated ActionType (72981c04-267a-4ba0-a59e-9921d2f3af9c)</extracomment>
<translation>Setze Prozentwert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="187"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="187"/>
<source>allowed values changed</source>
<extracomment>The name of the autocreated EventType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b)</extracomment>
<translation>Erlaubter Wert geändert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="190"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="190"/>
<source>allowed values</source>
<extracomment>The name of the ParamType of StateType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) of DeviceClass Mock Device (Push Button)</extracomment>
<translation>Erlaubte Werte</translation>
</message>
<message>
<location filename="../plugininfo.h" line="193"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="193"/>
<source>Set allowed values</source>
<extracomment>The name of the autocreated ActionType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b)</extracomment>
<translation>Setze erlaubten Wert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="196"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="196"/>
<source>double value changed</source>
<extracomment>The name of the autocreated EventType (53cd7c55-49b7-441b-b970-9048f20f0e2c)</extracomment>
<translation>Double Wert geändert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="199"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="199"/>
<source>double value</source>
<extracomment>The name of the ParamType of StateType (53cd7c55-49b7-441b-b970-9048f20f0e2c) of DeviceClass Mock Device (Push Button)</extracomment>
<translation>Double Wert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="202"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="202"/>
<source>Set double value</source>
<extracomment>The name of the autocreated ActionType (53cd7c55-49b7-441b-b970-9048f20f0e2c)</extracomment>
<translation>Setze double Wert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="211"/>
<location filename="../plugininfo.h" line="235"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="211"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="235"/>
<source>Set bool value</source>
<extracomment>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)</e
<translation>Setze boll Wert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="214"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="214"/>
<source>Timeout action</source>
<extracomment>The name of the ActionType 54646e7c-bc54-4895-81a2-590d72d120f9 of deviceClass Mock Device (Push Button)</extracomment>
<translation>Timeout Aktion</translation>
</message>
<message>
<location filename="../plugininfo.h" line="220"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="220"/>
<source>Mock Device (Display Pin)</source>
<extracomment>The name of the DeviceClass (296f1fd4-e893-46b2-8a42-50d1bceb8730)</extracomment>
<translation>Mock Gerät (Pin anzeigen)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="205"/>
<location filename="../plugininfo.h" line="229"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="205"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="229"/>
<source>bool value changed</source>
<extracomment>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)</ex
<translation>Bool Wert geändert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="208"/>
<location filename="../plugininfo.h" line="232"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="208"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="232"/>
<source>bool value</source>
<extracomment>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
<translation>Bool Wert</translation>
</message>
<message>
<location filename="../plugininfo.h" line="247"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="247"/>
<source>Text line</source>
<extracomment>The name of the paramType (e6acf0c7-4b8e-4296-ac62-855d20deb816) of Mock Device (InputTypes)</extracomment>
<translation>Textzeile</translation>
</message>
<message>
<location filename="../plugininfo.h" line="250"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="250"/>
<source>Text area</source>
<extracomment>The name of the paramType (716f0994-bc01-42b0-b64d-59236f7320d2) of Mock Device (InputTypes)</extracomment>
<translation>Textfeld</translation>
</message>
<message>
<location filename="../plugininfo.h" line="253"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="253"/>
<source>Password text</source>
<extracomment>The name of the paramType (e5c0d14b-c9f1-4aca-a56e-85bfa6977150) of Mock Device (InputTypes)</extracomment>
<translation>Passwort Text</translation>
</message>
<message>
<location filename="../plugininfo.h" line="256"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="256"/>
<source>Search text</source>
<extracomment>The name of the paramType (22add8c9-ee4f-43ad-8931-58e999313ac3) of Mock Device (InputTypes)</extracomment>
<translation>Suchtext</translation>
</message>
<message>
<location filename="../plugininfo.h" line="259"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="259"/>
<source>Mail address</source>
<extracomment>The name of the paramType (a8494faf-3a0f-4cf3-84b7-4b39148a838d) of Mock Device (InputTypes)</extracomment>
<translation>Mail Adresse</translation>
</message>
<message>
<location filename="../plugininfo.h" line="262"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="262"/>
<source>IPv4 address</source>
<extracomment>The name of the paramType (9e5f86a0-4bb3-4892-bff8-3fc4032af6e2) of Mock Device (InputTypes)</extracomment>
<translation>IPv4 Adresse</translation>
</message>
<message>
<location filename="../plugininfo.h" line="265"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="265"/>
<source>IPv6 address</source>
<extracomment>The name of the paramType (43bf3832-dd48-4090-a836-656e8b60216e) of Mock Device (InputTypes)</extracomment>
<translation>IPv6 Adresse</translation>
</message>
<message>
<location filename="../plugininfo.h" line="268"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="268"/>
<source>URL</source>
<extracomment>The name of the paramType (fa67229f-fcef-496f-b671-59a4b48f3ab5) of Mock Device (InputTypes)</extracomment>
<translation>URL</translation>
</message>
<message>
<location filename="../plugininfo.h" line="271"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="271"/>
<source>Mac address</source>
<extracomment>The name of the paramType (e93db587-7919-48f3-8c88-1651de63c765) of Mock Device (InputTypes)</extracomment>
<translation>Mac Adresse</translation>
</message>
<message>
<location filename="../plugininfo.h" line="217"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="217"/>
<source>Please enter the secret which normaly will be displayed on the device. For the mockdevice the pin is 243681.</source>
<extracomment>The pairing info of deviceClass Mock Device (Display Pin)</extracomment>
<translation>Bitte geben sie den Pincode ein der normalerweise auf dem Gerät angezeit werden würde. In diesem fall lautet der Pincode 243681.</translation>
</message>
<message>
<location filename="../plugininfo.h" line="91"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="91"/>
<source>Mock Devices</source>
<extracomment>The name of the plugin Mock Devices (727a4a9a-c187-446f-aadf-f1b2220607d1)</extracomment>
<translation>Mock Gerät</translation>
</message>
<message>
<location filename="../plugininfo.h" line="223"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="223"/>
<source>pin</source>
<extracomment>The name of the paramType (da820e07-22dc-4173-9c07-2f49a4e265f9) of Mock Device (Display Pin)</extracomment>
<translation>Pin</translation>
</message>
<message>
<location filename="../plugininfo.h" line="226"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="226"/>
<source>Mock Device (Parent)</source>
<extracomment>The name of the DeviceClass (a71fbde9-9a38-4bf8-beab-c8aade2608ba)</extracomment>
<translation>Mock Gerät (Elternteil)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="238"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="238"/>
<source>Mock Device (Child)</source>
<extracomment>The name of the DeviceClass (40893c9f-bc47-40c1-8bf7-b390c7c1b4fc)</extracomment>
<translation>Mock Gerät (Kind)</translation>
</message>
<message>
<location filename="../plugininfo.h" line="241"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="241"/>
<source>parent uuid</source>
<extracomment>The name of the paramType (104b5288-404e-42d3-bf38-e40682e75681) of Mock Device (Child)</extracomment>
<translation>Elternteil Uuid</translation>
</message>
<message>
<location filename="../plugininfo.h" line="244"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="244"/>
<source>Mock Device (InputTypes)</source>
<extracomment>The name of the DeviceClass (515ffdf1-55e5-498d-9abc-4e2fe768f3a9)</extracomment>
<translation>Mock Gerät (Eingabemethoden)</translation>

View File

@ -12,230 +12,230 @@
<context>
<name>MockDevice</name>
<message>
<location filename="../plugininfo.h" line="100"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="100"/>
<source>guh</source>
<extracomment>The name of the vendor (2062d64d-3232-433c-88bc-0d33c0ba2ba6)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="103"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="103"/>
<source>Mock Device</source>
<extracomment>The name of the DeviceClass (753f0d32-0468-4d08-82ed-1964aab03298)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="106"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="106"/>
<source>http port</source>
<extracomment>The name of the paramType (d4f06047-125e-4479-9810-b54c189917f5) of Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="142"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="142"/>
<source>Mock Action 3 (async)</source>
<extracomment>The name of the ActionType fbae06d3-7666-483e-a39e-ec50fe89054e of deviceClass Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="145"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="145"/>
<source>Mock Action 4 (broken)</source>
<extracomment>The name of the ActionType df3cf33d-26d5-4577-9132-9823bd33fad0 of deviceClass Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="148"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="148"/>
<source>Mock Action 5 (async, broken)</source>
<extracomment>The name of the ActionType bfe89a1d-3497-4121-8318-e77c37537219 of deviceClass Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="154"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="154"/>
<source>Mock Device (Auto created)</source>
<extracomment>The name of the DeviceClass (ab4257b3-7548-47ee-9bd4-7dc3004fd197)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="166"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="166"/>
<source>Mock Device (Push Button)</source>
<extracomment>The name of the DeviceClass (9e03144c-e436-4eea-82d9-ccb33ef778db)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="163"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="163"/>
<source>Wait 3 second before you continue, the push button will be pressed automatically.</source>
<extracomment>The pairing info of deviceClass Mock Device (Push Button)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="94"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="94"/>
<source>configParamInt</source>
<extracomment>The name of the paramType (e1f72121-a426-45e2-b475-8262b5cdf103) of Mock Devices</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="97"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="97"/>
<source>configParamBool</source>
<extracomment>The name of the paramType (c75723b6-ea4f-4982-9751-6c5e39c88145) of Mock Devices</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="109"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="109"/>
<source>async</source>
<extracomment>The name of the paramType (f2977061-4dd0-4ef5-85aa-3b7134743be3) of Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="112"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="112"/>
<source>broken</source>
<extracomment>The name of the paramType (ae8f8901-f2c1-42a5-8111-6d2fc8e4c1e4) of Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="115"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="115"/>
<source>resultCount</source>
<extracomment>The name of the paramType (d222adb4-2f9c-4c3f-8655-76400d0fb6ce) of Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="118"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="118"/>
<source>Dummy int state changed</source>
<extracomment>The name of the autocreated EventType (80baec19-54de-4948-ac46-31eabfaceb83)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="121"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="121"/>
<source>Dummy int state</source>
<extracomment>The name of the ParamType of StateType (80baec19-54de-4948-ac46-31eabfaceb83) of DeviceClass Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="124"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="124"/>
<source>Dummy bool state changed</source>
<extracomment>The name of the autocreated EventType (9dd6a97c-dfd1-43dc-acbd-367932742310)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="127"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="127"/>
<source>Dummy bool state</source>
<extracomment>The name of the ParamType of StateType (9dd6a97c-dfd1-43dc-acbd-367932742310) of DeviceClass Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="130"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="130"/>
<source>Mock Action 1 (with params)</source>
<extracomment>The name of the ActionType dea0f4e1-65e3-4981-8eaa-2701c53a9185 of deviceClass Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="133"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="133"/>
<source>mockActionParam1</source>
<extracomment>The name of the paramType (a2d3a256-a551-4712-a65b-ecd5a436a1cb) of Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="136"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="136"/>
<source>mockActionParam2</source>
<extracomment>The name of the paramType (304a4899-18be-4e3b-94f4-d03be52f3233) of Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="139"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="139"/>
<source>Mock Action 2 (without params)</source>
<extracomment>The name of the ActionType defd3ed6-1a0d-400b-8879-a0202cf39935 of deviceClass Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="151"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="151"/>
<source>mockParamInt</source>
<extracomment>The name of the paramType (0550e16d-60b9-4ba5-83f4-4d3cee656121) of Mock Device</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="157"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="157"/>
<source>Mock Event 1</source>
<extracomment>The name of the EventType 45bf3752-0fc6-46b9-89fd-ffd878b5b22b of deviceClass Mock Device (Auto created)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="160"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="160"/>
<source>Mock Event 2</source>
<extracomment>The name of the EventType 863d5920-b1cf-4eb9-88bd-8f7b8583b1cf of deviceClass Mock Device (Auto created)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="169"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="169"/>
<source>color changed</source>
<extracomment>The name of the autocreated EventType (20dc7c22-c50e-42db-837c-2bbced939f8e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="172"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="172"/>
<source>color</source>
<extracomment>The name of the ParamType of StateType (20dc7c22-c50e-42db-837c-2bbced939f8e) of DeviceClass Mock Device (Push Button)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="175"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="175"/>
<source>Set color</source>
<extracomment>The name of the autocreated ActionType (20dc7c22-c50e-42db-837c-2bbced939f8e)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="178"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="178"/>
<source>percentage changed</source>
<extracomment>The name of the autocreated EventType (72981c04-267a-4ba0-a59e-9921d2f3af9c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="181"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="181"/>
<source>percentage</source>
<extracomment>The name of the ParamType of StateType (72981c04-267a-4ba0-a59e-9921d2f3af9c) of DeviceClass Mock Device (Push Button)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="184"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="184"/>
<source>Set percentage</source>
<extracomment>The name of the autocreated ActionType (72981c04-267a-4ba0-a59e-9921d2f3af9c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="187"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="187"/>
<source>allowed values changed</source>
<extracomment>The name of the autocreated EventType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="190"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="190"/>
<source>allowed values</source>
<extracomment>The name of the ParamType of StateType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b) of DeviceClass Mock Device (Push Button)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="193"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="193"/>
<source>Set allowed values</source>
<extracomment>The name of the autocreated ActionType (05f63f9c-f61e-4dcf-ad55-3f13fde2765b)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="196"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="196"/>
<source>double value changed</source>
<extracomment>The name of the autocreated EventType (53cd7c55-49b7-441b-b970-9048f20f0e2c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="199"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="199"/>
<source>double value</source>
<extracomment>The name of the ParamType of StateType (53cd7c55-49b7-441b-b970-9048f20f0e2c) of DeviceClass Mock Device (Push Button)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="202"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="202"/>
<source>Set double value</source>
<extracomment>The name of the autocreated ActionType (53cd7c55-49b7-441b-b970-9048f20f0e2c)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="211"/>
<location filename="../plugininfo.h" line="235"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="211"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="235"/>
<source>Set bool value</source>
<extracomment>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)</e
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="214"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="214"/>
<source>Timeout action</source>
<extracomment>The name of the ActionType 54646e7c-bc54-4895-81a2-590d72d120f9 of deviceClass Mock Device (Push Button)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="220"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="220"/>
<source>Mock Device (Display Pin)</source>
<extracomment>The name of the DeviceClass (296f1fd4-e893-46b2-8a42-50d1bceb8730)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="205"/>
<location filename="../plugininfo.h" line="229"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="205"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="229"/>
<source>bool value changed</source>
<extracomment>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)</ex
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="208"/>
<location filename="../plugininfo.h" line="232"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="208"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="232"/>
<source>bool value</source>
<extracomment>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
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="247"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="247"/>
<source>Text line</source>
<extracomment>The name of the paramType (e6acf0c7-4b8e-4296-ac62-855d20deb816) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="250"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="250"/>
<source>Text area</source>
<extracomment>The name of the paramType (716f0994-bc01-42b0-b64d-59236f7320d2) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="253"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="253"/>
<source>Password text</source>
<extracomment>The name of the paramType (e5c0d14b-c9f1-4aca-a56e-85bfa6977150) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="256"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="256"/>
<source>Search text</source>
<extracomment>The name of the paramType (22add8c9-ee4f-43ad-8931-58e999313ac3) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="259"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="259"/>
<source>Mail address</source>
<extracomment>The name of the paramType (a8494faf-3a0f-4cf3-84b7-4b39148a838d) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="262"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="262"/>
<source>IPv4 address</source>
<extracomment>The name of the paramType (9e5f86a0-4bb3-4892-bff8-3fc4032af6e2) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="265"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="265"/>
<source>IPv6 address</source>
<extracomment>The name of the paramType (43bf3832-dd48-4090-a836-656e8b60216e) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="268"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="268"/>
<source>URL</source>
<extracomment>The name of the paramType (fa67229f-fcef-496f-b671-59a4b48f3ab5) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="271"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="271"/>
<source>Mac address</source>
<extracomment>The name of the paramType (e93db587-7919-48f3-8c88-1651de63c765) of Mock Device (InputTypes)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="217"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="217"/>
<source>Please enter the secret which normaly will be displayed on the device. For the mockdevice the pin is 243681.</source>
<extracomment>The pairing info of deviceClass Mock Device (Display Pin)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="91"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="91"/>
<source>Mock Devices</source>
<extracomment>The name of the plugin Mock Devices (727a4a9a-c187-446f-aadf-f1b2220607d1)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="223"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="223"/>
<source>pin</source>
<extracomment>The name of the paramType (da820e07-22dc-4173-9c07-2f49a4e265f9) of Mock Device (Display Pin)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="226"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="226"/>
<source>Mock Device (Parent)</source>
<extracomment>The name of the DeviceClass (a71fbde9-9a38-4bf8-beab-c8aade2608ba)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="238"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="238"/>
<source>Mock Device (Child)</source>
<extracomment>The name of the DeviceClass (40893c9f-bc47-40c1-8bf7-b390c7c1b4fc)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="241"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="241"/>
<source>parent uuid</source>
<extracomment>The name of the paramType (104b5288-404e-42d3-bf38-e40682e75681) of Mock Device (Child)</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../plugininfo.h" line="244"/>
<location filename="../../../../build-guh-Desktop-Debug/plugins/mock/plugininfo.h" line="244"/>
<source>Mock Device (InputTypes)</source>
<extracomment>The name of the DeviceClass (515ffdf1-55e5-498d-9abc-4e2fe768f3a9)</extracomment>
<translation type="unfinished"></translation>

View File

@ -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 \

View File

@ -35,6 +35,7 @@
#include <QtTest>
#include <QDebug>
#include <QMetaType>
#include <QNetworkRequest>
#include <QNetworkReply>
using namespace guhserver;

View File

@ -34,6 +34,8 @@
#include <QVariantMap>
#include <QSignalSpy>
#include <QtTest>
#include <QNetworkRequest>
#include <QNetworkReply>
extern DeviceClassId mockDeviceClassId;
extern DeviceClassId mockDeviceAutoClassId;

View File

@ -4,7 +4,7 @@
<context>
<name>main</name>
<message>
<location filename="../server/main.cpp" line="159"/>
<location filename="../server/main.cpp" line="160"/>
<source>
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.
</translation>
</message>
<message>
<location filename="../server/main.cpp" line="171"/>
<location filename="../server/main.cpp" line="172"/>
<source>Run guhd in the foreground, not as daemon.</source>
<translation>Starte guhd im Vordergrund, nicht als Service.</translation>
</message>
<message>
<location filename="../server/main.cpp" line="174"/>
<location filename="../server/main.cpp" line="175"/>
<source>Debug categories to enable. Prefix with &quot;No&quot; to disable. Warnings from all categories will be printed unless explicitly muted with &quot;NoWarnings&quot;.
Categories are:</source>
@ -36,22 +36,22 @@ Categories are:</source>
Es gibt folgende Kategorien:</translation>
</message>
<message>
<location filename="../server/main.cpp" line="191"/>
<location filename="../server/main.cpp" line="192"/>
<source>Enables all debug categories. This parameter overrides all debug category parameters.</source>
<translation>Aktiviere alle Debug-Kategorien. Dieser Parameter überschreibt alle anderen Debug-Kategorien Parameter.</translation>
</message>
<message>
<location filename="../server/main.cpp" line="196"/>
<location filename="../server/main.cpp" line="197"/>
<source>Specify a log file to write to, If this option is not specified, logs will be printed to the standard output.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../server/main.cpp" line="199"/>
<location filename="../server/main.cpp" line="200"/>
<source>If specified, all D-Bus interfaces will be bound to the session bus instead of the system bus.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../server/main.cpp" line="236"/>
<location filename="../server/main.cpp" line="237"/>
<source>No such debug category:</source>
<translation>Diese Debug-Kategorie existiert nicht:</translation>
</message>

View File

@ -4,7 +4,7 @@
<context>
<name>main</name>
<message>
<location filename="../server/main.cpp" line="159"/>
<location filename="../server/main.cpp" line="160"/>
<source>
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.
</translation>
</message>
<message>
<location filename="../server/main.cpp" line="171"/>
<location filename="../server/main.cpp" line="172"/>
<source>Run guhd in the foreground, not as daemon.</source>
<translation>Run guhd in the foreground, not as daemon.</translation>
</message>
<message>
<location filename="../server/main.cpp" line="174"/>
<location filename="../server/main.cpp" line="175"/>
<source>Debug categories to enable. Prefix with &quot;No&quot; to disable. Warnings from all categories will be printed unless explicitly muted with &quot;NoWarnings&quot;.
Categories are:</source>
@ -37,22 +37,22 @@ Categories are:</source>
Categories are:</translation>
</message>
<message>
<location filename="../server/main.cpp" line="191"/>
<location filename="../server/main.cpp" line="192"/>
<source>Enables all debug categories. This parameter overrides all debug category parameters.</source>
<translation>Enables all debug categories. This parameter overrides all debug category parameters.</translation>
</message>
<message>
<location filename="../server/main.cpp" line="196"/>
<location filename="../server/main.cpp" line="197"/>
<source>Specify a log file to write to, If this option is not specified, logs will be printed to the standard output.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../server/main.cpp" line="199"/>
<location filename="../server/main.cpp" line="200"/>
<source>If specified, all D-Bus interfaces will be bound to the session bus instead of the system bus.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../server/main.cpp" line="236"/>
<location filename="../server/main.cpp" line="237"/>
<source>No such debug category:</source>
<translation>No such debug category:</translation>
</message>