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> #include <QTimer>
bool BluetoothDiscoveryReply::isFinished() const namespace guhserver {
BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyImplementation(QObject *parent) :
BluetoothDiscoveryReply(parent)
{
}
bool BluetoothDiscoveryReplyImplementation::isFinished() const
{ {
return m_finished; return m_finished;
} }
BluetoothDiscoveryReply::BluetoothDiscoveryReplyError BluetoothDiscoveryReply::error() const BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyError BluetoothDiscoveryReplyImplementation::error() const
{ {
return m_error; return m_error;
} }
QList<QBluetoothDeviceInfo> BluetoothDiscoveryReply::discoveredDevices() const QList<QBluetoothDeviceInfo> BluetoothDiscoveryReplyImplementation::discoveredDevices() const
{ {
return m_discoveredDevices; return m_discoveredDevices;
} }
BluetoothDiscoveryReply::BluetoothDiscoveryReply(QObject *parent) : QObject(parent) void BluetoothDiscoveryReplyImplementation::setError(const BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyError &error)
{
}
void BluetoothDiscoveryReply::setError(const BluetoothDiscoveryReply::BluetoothDiscoveryReplyError &error)
{ {
m_error = error; m_error = error;
if (m_error != BluetoothDiscoveryReplyErrorNoError) { 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; m_discoveredDevices = discoveredDevices;
} }
void BluetoothDiscoveryReply::setFinished() void BluetoothDiscoveryReplyImplementation::setFinished()
{ {
m_finished = true; m_finished = true;
// Note: this makes sure the finished signal will be processed in the next event loop // 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" #include "loggingcategories.h"
QString BluetoothLowEnergyDevice::name() const namespace guhserver {
QString BluetoothLowEnergyDeviceImplementation::name() const
{ {
return m_deviceInfo.name(); return m_deviceInfo.name();
} }
QBluetoothAddress BluetoothLowEnergyDevice::address() const QBluetoothAddress BluetoothLowEnergyDeviceImplementation::address() const
{ {
return m_deviceInfo.address(); return m_deviceInfo.address();
} }
QLowEnergyController *BluetoothLowEnergyDevice::controller() const QLowEnergyController *BluetoothLowEnergyDeviceImplementation::controller() const
{ {
return m_controller; return m_controller;
} }
BluetoothLowEnergyDevice::BluetoothLowEnergyDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) : BluetoothLowEnergyDeviceImplementation::BluetoothLowEnergyDeviceImplementation(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) :
QObject(parent), m_deviceInfo(deviceInfo) BluetoothLowEnergyDevice(parent),
m_deviceInfo(deviceInfo)
{ {
m_controller = new QLowEnergyController(address(), this); m_controller = new QLowEnergyController(address(), this);
m_controller->setRemoteAddressType(addressType); m_controller->setRemoteAddressType(addressType);
connect(m_controller, &QLowEnergyController::connected, this, &BluetoothLowEnergyDevice::onConnected); connect(m_controller, &QLowEnergyController::connected, this, &BluetoothLowEnergyDeviceImplementation::onConnected);
connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothLowEnergyDevice::onDisconnected); connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothLowEnergyDeviceImplementation::onDisconnected);
connect(m_controller, &QLowEnergyController::discoveryFinished, this, &BluetoothLowEnergyDevice::onServiceDiscoveryFinished); connect(m_controller, &QLowEnergyController::discoveryFinished, this, &BluetoothLowEnergyDeviceImplementation::onServiceDiscoveryFinished);
connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothLowEnergyDevice::onStateChanged); connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothLowEnergyDeviceImplementation::onStateChanged);
connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onDeviceError(QLowEnergyController::Error))); 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) { if (m_connected != connected) {
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; m_enabled = enabled;
@ -73,7 +76,7 @@ void BluetoothLowEnergyDevice::setEnabled(const bool &enabled)
} }
} }
void BluetoothLowEnergyDevice::onConnected() void BluetoothLowEnergyDeviceImplementation::onConnected()
{ {
setConnected(true); setConnected(true);
@ -83,13 +86,13 @@ void BluetoothLowEnergyDevice::onConnected()
} }
} }
void BluetoothLowEnergyDevice::onDisconnected() void BluetoothLowEnergyDeviceImplementation::onDisconnected()
{ {
qCWarning(dcBluetooth()) << "Device disconnected" << name() << address().toString(); qCWarning(dcBluetooth()) << "Device disconnected" << name() << address().toString();
setConnected(false); setConnected(false);
} }
void BluetoothLowEnergyDevice::onServiceDiscoveryFinished() void BluetoothLowEnergyDeviceImplementation::onServiceDiscoveryFinished()
{ {
qCDebug(dcBluetooth()) << "Service discovery finished for" << name() << address().toString(); qCDebug(dcBluetooth()) << "Service discovery finished for" << name() << address().toString();
foreach (const QBluetoothUuid &serviceUuid, m_controller->services()) { foreach (const QBluetoothUuid &serviceUuid, m_controller->services()) {
@ -98,13 +101,13 @@ void BluetoothLowEnergyDevice::onServiceDiscoveryFinished()
emit servicesDiscoveryFinished(); 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; qCDebug(dcBluetooth()) << "State changed for" << name() << address().toString() << state;
emit stateChanged(state); emit stateChanged(state);
} }
void BluetoothLowEnergyDevice::connectDevice() void BluetoothLowEnergyDeviceImplementation::connectDevice()
{ {
if (!m_enabled) if (!m_enabled)
return; return;
@ -116,17 +119,17 @@ void BluetoothLowEnergyDevice::connectDevice()
m_controller->connectToDevice(); m_controller->connectToDevice();
} }
void BluetoothLowEnergyDevice::disconnectDevice() void BluetoothLowEnergyDeviceImplementation::disconnectDevice()
{ {
m_controller->disconnectFromDevice(); m_controller->disconnectFromDevice();
} }
bool BluetoothLowEnergyDevice::autoConnecting() const bool BluetoothLowEnergyDeviceImplementation::autoConnecting() const
{ {
return m_autoConnecting; return m_autoConnecting;
} }
void BluetoothLowEnergyDevice::setAutoConnecting(const bool &autoConnecting) void BluetoothLowEnergyDeviceImplementation::setAutoConnecting(const bool &autoConnecting)
{ {
if (m_autoConnecting != autoConnecting) { if (m_autoConnecting != autoConnecting) {
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; return m_connected;
} }
bool BluetoothLowEnergyDevice::discovered() const bool BluetoothLowEnergyDeviceImplementation::discovered() const
{ {
return m_discovered; return m_discovered;
} }
QList<QBluetoothUuid> BluetoothLowEnergyDevice::serviceUuids() const QList<QBluetoothUuid> BluetoothLowEnergyDeviceImplementation::serviceUuids() const
{ {
return m_controller->services(); return m_controller->services();
} }
void BluetoothLowEnergyDevice::onDeviceError(const QLowEnergyController::Error &error) void BluetoothLowEnergyDeviceImplementation::onDeviceError(const QLowEnergyController::Error &error)
{ {
if (connected()) if (connected())
qCWarning(dcBluetooth()) << "Device error:" << name() << address().toString() << ": " << error << m_controller->errorString(); qCWarning(dcBluetooth()) << "Device error:" << name() << address().toString() << ": " << error << m_controller->errorString();
emit errorOccured(error); emit errorOccured(error);
} }
}

View File

@ -20,8 +20,8 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHLOWENERGYDEVICE_H #ifndef BLUETOOTHLOWENERGYDEVICEIMPLEMENTATION_H
#define BLUETOOTHLOWENERGYDEVICE_H #define BLUETOOTHLOWENERGYDEVICEIMPLEMENTATION_H
#include <QObject> #include <QObject>
#include <QBluetoothDeviceInfo> #include <QBluetoothDeviceInfo>
@ -29,15 +29,19 @@
#include <QBluetoothServiceInfo> #include <QBluetoothServiceInfo>
#include <QLowEnergyController> #include <QLowEnergyController>
#include "libguh.h" #include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h"
class LIBGUH_EXPORT BluetoothLowEnergyDevice : public QObject namespace guhserver {
class BluetoothLowEnergyDeviceImplementation : public BluetoothLowEnergyDevice
{ {
Q_OBJECT Q_OBJECT
friend class BluetoothLowEnergyManager; friend class BluetoothLowEnergyManagerImplementation;
public: public:
explicit BluetoothLowEnergyDeviceImplementation(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::PublicAddress, QObject *parent = 0);
QString name() const; QString name() const;
QBluetoothAddress address() const; QBluetoothAddress address() const;
@ -54,7 +58,6 @@ public:
QLowEnergyController *controller() const; QLowEnergyController *controller() const;
private: private:
explicit BluetoothLowEnergyDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::PublicAddress, QObject *parent = 0);
QBluetoothDeviceInfo m_deviceInfo; QBluetoothDeviceInfo m_deviceInfo;
QLowEnergyController *m_controller = nullptr; QLowEnergyController *m_controller = nullptr;
@ -84,4 +87,6 @@ private slots:
void onDeviceError(const QLowEnergyController::Error &error); 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" #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 // Create the reply for this discovery request
QPointer<BluetoothDiscoveryReply> reply = new BluetoothDiscoveryReply(this); QPointer<BluetoothDiscoveryReplyImplementation> reply = new BluetoothDiscoveryReplyImplementation(this);
if (!available()) { if (!available()) {
qCWarning(dcBluetooth()) << "is not avilable."; qCWarning(dcBluetooth()) << "is not avilable.";
reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNotAvailable); reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorNotAvailable);
reply->setFinished(); reply->setFinished();
return reply.data(); return reply.data();
} }
if (!enabled()) { if (!enabled()) {
qCWarning(dcBluetooth()) << "is not enabled."; qCWarning(dcBluetooth()) << "is not enabled.";
reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNotEnabled); reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorNotEnabled);
reply->setFinished(); reply->setFinished();
return reply.data(); return reply.data();
} }
if (!m_currentReply.isNull()) { if (!m_currentReply.isNull()) {
qCWarning(dcBluetooth()) << "resource busy. There is already a discovery running."; qCWarning(dcBluetooth()) << "resource busy. There is already a discovery running.";
reply->setError(BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorBusy); reply->setError(BluetoothDiscoveryReplyImplementation::BluetoothDiscoveryReplyErrorBusy);
reply->setFinished(); reply->setFinished();
return reply.data(); return reply.data();
} }
@ -73,15 +113,15 @@ BluetoothDiscoveryReply *BluetoothLowEnergyManager::discoverDevices(const int &i
return reply.data(); 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(); qCDebug(dcBluetooth()) << "Register device" << bluetoothDevice->name() << bluetoothDevice->address().toString();
m_devices.append(bluetoothDevice); m_devices.append(bluetoothDevice);
return bluetoothDevice.data(); return bluetoothDevice.data();
} }
void BluetoothLowEnergyManager::unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice) void BluetoothLowEnergyManagerImplementation::unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice)
{ {
QPointer<BluetoothLowEnergyDevice> devicePointer(bluetoothDevice); QPointer<BluetoothLowEnergyDevice> devicePointer(bluetoothDevice);
if (devicePointer.isNull()) { if (devicePointer.isNull()) {
@ -91,7 +131,7 @@ void BluetoothLowEnergyManager::unregisterDevice(BluetoothLowEnergyDevice *bluet
qCDebug(dcBluetooth()) << "Unregister device" << bluetoothDevice->name() << bluetoothDevice->address().toString(); 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()) { if (devicePointer.data() == dPointer.data()) {
m_devices.removeAll(dPointer); m_devices.removeAll(dPointer);
dPointer->deleteLater(); dPointer->deleteLater();
@ -99,43 +139,26 @@ void BluetoothLowEnergyManager::unregisterDevice(BluetoothLowEnergyDevice *bluet
} }
} }
BluetoothLowEnergyManager::BluetoothLowEnergyManager(PluginTimer *reconnectTimer, QObject *parent) : bool BluetoothLowEnergyManagerImplementation::available() const
HardwareResource("Bluetooth LE manager", parent),
m_reconnectTimer(reconnectTimer)
{ {
// Check which bluetooth adapter are available return m_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);
} }
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 // Reconnect device if enabled and disconnected
foreach (BluetoothLowEnergyDevice *device, m_devices) { foreach (BluetoothLowEnergyDevice *device, m_devices) {
@ -145,7 +168,7 @@ void BluetoothLowEnergyManager::onReconnectTimeout()
} }
} }
void BluetoothLowEnergyManager::onDiscoveryTimeout() void BluetoothLowEnergyManagerImplementation::onDiscoveryTimeout()
{ {
// Stop discovery on all adapters // Stop discovery on all adapters
qCDebug(dcBluetooth()) << "Stop bluetooth discovery"; qCDebug(dcBluetooth()) << "Stop bluetooth discovery";
@ -168,7 +191,7 @@ void BluetoothLowEnergyManager::onDiscoveryTimeout()
m_currentReply.clear(); 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 // Add the device to the list if not already added
bool alreadyAdded = false; 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()); QBluetoothDeviceDiscoveryAgent *discoveryAgent = static_cast<QBluetoothDeviceDiscoveryAgent *>(sender());
qCWarning(dcBluetooth()) << "Discovery error:" << error << discoveryAgent->errorString(); qCWarning(dcBluetooth()) << "Discovery error:" << error << discoveryAgent->errorString();
} }
bool BluetoothLowEnergyManager::enable() bool BluetoothLowEnergyManagerImplementation::enable()
{ {
qCDebug(dcBluetooth()) << "Hardware resource enabled."; qCDebug(dcBluetooth()) << "Hardware resource enabled.";
setEnabled(true); setEnabled(true);
foreach (QPointer<BluetoothLowEnergyDevice> bluetoothDevice, m_devices) { foreach (QPointer<BluetoothLowEnergyDeviceImplementation> bluetoothDevice, m_devices) {
bluetoothDevice->setEnabled(true); bluetoothDevice->setEnabled(true);
} }
return true; return true;
} }
bool BluetoothLowEnergyManager::disable() bool BluetoothLowEnergyManagerImplementation::disable()
{ {
qCDebug(dcBluetooth()) << "Hardware resource disabled."; qCDebug(dcBluetooth()) << "Hardware resource disabled.";
setEnabled(false); setEnabled(false);
foreach (QPointer<BluetoothLowEnergyDevice> bluetoothDevice, m_devices) { foreach (QPointer<BluetoothLowEnergyDeviceImplementation> bluetoothDevice, m_devices) {
bluetoothDevice->setEnabled(false); bluetoothDevice->setEnabled(false);
} }
return true; return true;
} }
}

View File

@ -20,8 +20,8 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHLOWENERGYMANAGER_H #ifndef BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H
#define BLUETOOTHLOWENERGYMANAGER_H #define BLUETOOTHLOWENERGYMANAGERIMPLEMENTATION_H
#include <QTimer> #include <QTimer>
#include <QObject> #include <QObject>
@ -31,32 +31,45 @@
#include <QBluetoothDeviceDiscoveryAgent> #include <QBluetoothDeviceDiscoveryAgent>
#include "plugintimer.h" #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 Q_OBJECT
friend class HardwareManager; friend class HardwareManagerImplementation;
public: public:
explicit BluetoothLowEnergyManagerImplementation(PluginTimer *reconnectTimer, QObject *parent = nullptr);
BluetoothDiscoveryReply *discoverDevices(const int &interval = 5000); BluetoothDiscoveryReply *discoverDevices(const int &interval = 5000);
// Bluetooth device registration methods // Bluetooth device registration methods
BluetoothLowEnergyDevice *registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::RandomAddress); BluetoothLowEnergyDevice *registerDevice(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType = QLowEnergyController::RandomAddress);
void unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice); void unregisterDevice(BluetoothLowEnergyDevice *bluetoothDevice);
bool available() const override;
bool enabled() const override;
protected:
void setEnabled(bool enabled) override;
private: private:
explicit BluetoothLowEnergyManager(PluginTimer *reconnectTimer, QObject *parent = nullptr);
PluginTimer *m_reconnectTimer = nullptr; PluginTimer *m_reconnectTimer = nullptr;
QTimer *m_timer = 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<QBluetoothDeviceDiscoveryAgent *> m_bluetoothDiscoveryAgents;
QList<QBluetoothDeviceInfo> m_discoveredDevices; QList<QBluetoothDeviceInfo> m_discoveredDevices;
QPointer<BluetoothDiscoveryReply> m_currentReply; QPointer<BluetoothDiscoveryReplyImplementation> m_currentReply;
private slots: private slots:
void onReconnectTimeout(); 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" #include "qt-watch.moc"

View File

@ -24,8 +24,13 @@
#include "qtavahiclient.h" #include "qtavahiclient.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "qtavahiservicebrowserimplementation.h"
#include "qtavahiservicebrowserimplementation_p.h"
#include <avahi-common/error.h> #include <avahi-common/error.h>
namespace guhserver {
QtAvahiClient::QtAvahiClient(QObject *parent) : QtAvahiClient::QtAvahiClient(QObject *parent) :
QObject(parent), QObject(parent),
m_poll(avahi_qt_poll_get()), m_poll(avahi_qt_poll_get()),
@ -128,3 +133,4 @@ void QtAvahiClient::onClientStateChanged(const QtAvahiClient::QtAvahiClientState
emit clientStateChanged(m_state); emit clientStateChanged(m_state);
} }
}

View File

@ -26,9 +26,9 @@
#include <QObject> #include <QObject>
#include <avahi-client/client.h> #include <avahi-client/client.h>
#include "libguh.h" namespace guhserver {
class LIBGUH_EXPORT QtAvahiClient : public QObject class QtAvahiClient : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS(QtAvahiClientState) Q_ENUMS(QtAvahiClientState)
@ -50,8 +50,8 @@ public:
private: private:
friend class QtAvahiService; friend class QtAvahiService;
friend class QtAvahiServiceBrowser; friend class QtAvahiServiceBrowserImplementation;
friend class QtAvahiServiceBrowserPrivate; friend class QtAvahiServiceBrowserImplementationPrivate;
const AvahiPoll *m_poll; const AvahiPoll *m_poll;
AvahiClient *m_client; AvahiClient *m_client;
@ -73,4 +73,6 @@ signals:
}; };
}
#endif // QTAVAHICLIENT_H #endif // QTAVAHICLIENT_H

View File

@ -52,6 +52,7 @@
#include "qtavahiservice_p.h" #include "qtavahiservice_p.h"
#include "loggingcategories.h" #include "loggingcategories.h"
namespace guhserver {
/*! Constructs a new \l{QtAvahiService} with the given \a parent. */ /*! Constructs a new \l{QtAvahiService} with the given \a parent. */
QtAvahiService::QtAvahiService(QObject *parent) : QtAvahiService::QtAvahiService(QObject *parent) :
@ -272,3 +273,5 @@ QDebug operator <<(QDebug dbg, QtAvahiService *service)
dbg << service->name() << ", " << service->serviceType() << ", " << service->port() << ") "; dbg << service->name() << ", " << service->serviceType() << ", " << service->port() << ") ";
return dbg; return dbg;
} }
}

View File

@ -27,11 +27,12 @@
#include <QString> #include <QString>
#include <QObject> #include <QObject>
#include "libguh.h"
namespace guhserver {
class QtAvahiServicePrivate; class QtAvahiServicePrivate;
class LIBGUH_EXPORT QtAvahiService : public QObject class QtAvahiService : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS(QtAvahiServiceState) Q_ENUMS(QtAvahiServiceState)
@ -80,5 +81,6 @@ private:
QDebug operator <<(QDebug dbg, QtAvahiService *service); QDebug operator <<(QDebug dbg, QtAvahiService *service);
}
#endif // QTAVAHISERVICE_H #endif // QTAVAHISERVICE_H

View File

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

View File

@ -29,13 +29,13 @@
#include "qtavahiservice.h" #include "qtavahiservice.h"
#include "qtavahiclient.h" #include "qtavahiclient.h"
#include "libguh.h"
#include <avahi-client/publish.h> #include <avahi-client/publish.h>
#include <avahi-common/error.h> #include <avahi-common/error.h>
#include <avahi-common/alternative.h> #include <avahi-common/alternative.h>
class LIBGUH_EXPORT QtAvahiServicePrivate namespace guhserver {
class QtAvahiServicePrivate
{ {
public: public:
QtAvahiServicePrivate(); QtAvahiServicePrivate();
@ -55,5 +55,7 @@ public:
}; };
}
#endif // QTAVAHISERVICEPRIVATE_P #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 "qtavahiservicebrowserimplementation_p.h"
#include "qtavahiservicebrowser.h" #include "qtavahiservicebrowserimplementation.h"
#include "avahiserviceentry.h" #include "network/avahi/avahiserviceentry.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include <avahi-common/strlst.h> #include <avahi-common/strlst.h>
#include <avahi-common/error.h> #include <avahi-common/error.h>
QtAvahiServiceBrowserPrivate::QtAvahiServiceBrowserPrivate(QtAvahiClient *client) : namespace guhserver {
QtAvahiServiceBrowserImplementationPrivate::QtAvahiServiceBrowserImplementationPrivate(QtAvahiClient *client) :
client(client), client(client),
serviceTypeBrowser(NULL) serviceTypeBrowser(nullptr)
{ {
} }
QtAvahiServiceBrowserPrivate::~QtAvahiServiceBrowserPrivate() QtAvahiServiceBrowserImplementationPrivate::~QtAvahiServiceBrowserImplementationPrivate()
{ {
foreach (AvahiServiceResolver *resolver, m_serviceResolvers) { foreach (AvahiServiceResolver *resolver, m_serviceResolvers) {
avahi_service_resolver_free(resolver); 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(browser)
Q_UNUSED(interface) Q_UNUSED(interface)
@ -50,7 +52,7 @@ void QtAvahiServiceBrowserPrivate::callbackServiceTypeBrowser(AvahiServiceTypeBr
Q_UNUSED(domain) Q_UNUSED(domain)
Q_UNUSED(flags) Q_UNUSED(flags)
QtAvahiServiceBrowser *serviceBrowser = static_cast<QtAvahiServiceBrowser *>(userdata); QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(userdata);
if (!serviceBrowser) if (!serviceBrowser)
return; 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(browser);
Q_UNUSED(flags); Q_UNUSED(flags);
QtAvahiServiceBrowser *serviceBrowser = static_cast<QtAvahiServiceBrowser *>(userdata); QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(userdata);
if (!serviceBrowser) if (!serviceBrowser)
return; return;
@ -89,15 +91,15 @@ void QtAvahiServiceBrowserPrivate::callbackServiceBrowser(AvahiServiceBrowser *b
case AVAHI_BROWSER_NEW: { case AVAHI_BROWSER_NEW: {
// Start resolving new service // Start resolving new service
AvahiServiceResolver *resolver = avahi_service_resolver_new(serviceBrowser->d_ptr->client->m_client, AvahiServiceResolver *resolver = avahi_service_resolver_new(serviceBrowser->d_ptr->client->m_client,
interface, interface,
protocol, protocol,
name, name,
type, type,
domain, domain,
AVAHI_PROTO_UNSPEC, AVAHI_PROTO_UNSPEC,
(AvahiLookupFlags) 0, (AvahiLookupFlags) 0,
QtAvahiServiceBrowserPrivate::callbackServiceResolver, QtAvahiServiceBrowserImplementationPrivate::callbackServiceResolver,
serviceBrowser); serviceBrowser);
if (resolver) { if (resolver) {
serviceBrowser->d_ptr->m_serviceResolvers.append(resolver); serviceBrowser->d_ptr->m_serviceResolvers.append(resolver);
} else { } else {
@ -109,7 +111,7 @@ void QtAvahiServiceBrowserPrivate::callbackServiceBrowser(AvahiServiceBrowser *b
// Remove the service // Remove the service
foreach (const AvahiServiceEntry &entry, serviceBrowser->m_serviceEntries) { foreach (const AvahiServiceEntry &entry, serviceBrowser->m_serviceEntries) {
// Check not only the name, but also the protocol // 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); serviceBrowser->m_serviceEntries.removeAll(entry);
emit serviceBrowser->serviceEntryRemoved(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(interface);
Q_UNUSED(type); Q_UNUSED(type);
Q_UNUSED(txt); Q_UNUSED(txt);
QPointer<QtAvahiServiceBrowser> serviceBrowser = static_cast<QtAvahiServiceBrowser *>(userdata); QPointer<QtAvahiServiceBrowserImplementation> serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(userdata);
if (serviceBrowser.isNull()) if (serviceBrowser.isNull())
return; return;
@ -158,8 +160,8 @@ void QtAvahiServiceBrowserPrivate::callbackServiceResolver(AvahiServiceResolver
avahi_address_snprint(a, sizeof(a), address); avahi_address_snprint(a, sizeof(a), address);
// convert protocol // convert protocol
QAbstractSocket::NetworkLayerProtocol networkProtocol = QtAvahiServiceBrowserPrivate::convertProtocol(protocol); QAbstractSocket::NetworkLayerProtocol networkProtocol = QtAvahiServiceBrowserImplementationPrivate::convertProtocol(protocol);
QStringList txtList = QtAvahiServiceBrowserPrivate::convertTxtList(txt); QStringList txtList = QtAvahiServiceBrowserImplementationPrivate::convertTxtList(txt);
// create the new resolved service entry // create the new resolved service entry
AvahiServiceEntry entry = AvahiServiceEntry(name, AvahiServiceEntry entry = AvahiServiceEntry(name,
@ -181,7 +183,7 @@ void QtAvahiServiceBrowserPrivate::callbackServiceResolver(AvahiServiceResolver
} }
QStringList QtAvahiServiceBrowserPrivate::convertTxtList(AvahiStringList *txt) QStringList QtAvahiServiceBrowserImplementationPrivate::convertTxtList(AvahiStringList *txt)
{ {
if (!txt) if (!txt)
return QStringList(); return QStringList();
@ -198,7 +200,7 @@ QStringList QtAvahiServiceBrowserPrivate::convertTxtList(AvahiStringList *txt)
return txtList; return txtList;
} }
QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserPrivate::convertProtocol(const AvahiProtocol &protocol) QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserImplementationPrivate::convertProtocol(const AvahiProtocol &protocol)
{ {
QAbstractSocket::NetworkLayerProtocol networkProtocol = QAbstractSocket::UnknownNetworkLayerProtocol; QAbstractSocket::NetworkLayerProtocol networkProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
@ -216,3 +218,4 @@ QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserPrivate::convertProto
return networkProtocol; return networkProtocol;
} }
}

View File

@ -29,13 +29,17 @@
#include "qtavahiclient.h" #include "qtavahiclient.h"
#include "qtavahiservice.h" #include "qtavahiservice.h"
#include "libguh.h"
class LIBGUH_EXPORT QtAvahiServiceBrowserPrivate
namespace guhserver {
class QtAvahiServiceTypeBrowserImplementation;
class QtAvahiServiceBrowserImplementationPrivate
{ {
public: public:
QtAvahiServiceBrowserPrivate(QtAvahiClient *client); QtAvahiServiceBrowserImplementationPrivate(QtAvahiClient *client);
~QtAvahiServiceBrowserPrivate(); ~QtAvahiServiceBrowserImplementationPrivate();
// Callback members // Callback members
static void callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser, static void callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser,
@ -80,4 +84,6 @@ public:
QList<AvahiServiceResolver *> m_serviceResolvers; QList<AvahiServiceResolver *> m_serviceResolvers;
}; };
}
#endif // QTAVAHISERVICEBROWSERPRIVATE_H #endif // QTAVAHISERVICEBROWSERPRIVATE_H

View File

@ -21,7 +21,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*! /*!
\class NetworkAccessManager \class NetworkAccessManagerImpl
\brief Allows to send network requests and receive replies. \brief Allows to send network requests and receive replies.
\ingroup hardware \ingroup hardware
@ -32,12 +32,12 @@
*/ */
#include "networkaccessmanager.h" #include "networkaccessmanagerimpl.h"
#include "loggingcategories.h" #include "loggingcategories.h"
/*! Construct the hardware resource NetworkAccessManager with the given \a parent. */ /*! Construct the hardware resource NetworkAccessManagerImpl with the given \a parent. */
NetworkAccessManager::NetworkAccessManager(QNetworkAccessManager *networkManager, QObject *parent) : NetworkAccessManagerImpl::NetworkAccessManagerImpl(QNetworkAccessManager *networkManager, QObject *parent) :
HardwareResource("Network access manager" , parent), NetworkAccessManager(parent),
m_manager(networkManager) m_manager(networkManager)
{ {
m_available = true; m_available = true;
@ -45,57 +45,57 @@ NetworkAccessManager::NetworkAccessManager(QNetworkAccessManager *networkManager
qCDebug(dcHardware()) << "-->" << name() << "created successfully."; qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
} }
QNetworkReply *NetworkAccessManager::get(const QNetworkRequest &request) QNetworkReply *NetworkAccessManagerImpl::get(const QNetworkRequest &request)
{ {
return m_manager->get(request); return m_manager->get(request);
} }
QNetworkReply *NetworkAccessManager::deleteResource(const QNetworkRequest &request) QNetworkReply *NetworkAccessManagerImpl::deleteResource(const QNetworkRequest &request)
{ {
return m_manager->deleteResource(request); return m_manager->deleteResource(request);
} }
QNetworkReply *NetworkAccessManager::head(const QNetworkRequest &request) QNetworkReply *NetworkAccessManagerImpl::head(const QNetworkRequest &request)
{ {
return m_manager->head(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); 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); 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); 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); 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); 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); 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); return m_manager->sendCustomRequest(request, verb, data);
} }
void NetworkAccessManager::setEnabled(bool enabled) void NetworkAccessManagerImpl::setEnabled(bool enabled)
{ {
if (!m_available) { if (!m_available) {
qCWarning(dcNetworkManager()) << "NetworkManager not available, cannot enable"; qCWarning(dcNetworkManager()) << "NetworkManager not available, cannot enable";

View File

@ -66,6 +66,7 @@ private:
bool m_enabled = false; bool m_enabled = false;
QNetworkAccessManager *m_manager; QNetworkAccessManager *m_manager;
}; };
#endif // NETWORKACCESSMANAGER_H #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 "upnpdiscoveryrequest.h"
#include "loggingcategories.h" #include "loggingcategories.h"
UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer<UpnpDiscoveryReply> reply): namespace guhserver {
UpnpDiscoveryRequest::UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer<UpnpDiscoveryReplyImplementation> reply):
QObject(upnpDiscovery), QObject(upnpDiscovery),
m_upnpDiscovery(upnpDiscovery), m_upnpDiscovery(upnpDiscovery),
m_reply(reply) m_reply(reply)
@ -79,7 +81,9 @@ QList<UpnpDeviceDescriptor> UpnpDiscoveryRequest::deviceList() const
return m_deviceList; return m_deviceList;
} }
QPointer<UpnpDiscoveryReply> UpnpDiscoveryRequest::reply() QPointer<UpnpDiscoveryReplyImplementation> UpnpDiscoveryRequest::reply()
{ {
return m_reply; return m_reply;
} }
}

View File

@ -27,30 +27,32 @@
#include <QDebug> #include <QDebug>
#include <QMetaObject> #include <QMetaObject>
#include "upnpdiscovery.h" #include "upnpdiscoveryreplyimplementation.h"
#include "upnpdiscoveryreply.h" #include "network/upnp/upnpdiscovery.h"
#include "upnpdevicedescriptor.h" #include "network/upnp/upnpdevicedescriptor.h"
#include "libguh.h"
#include "typeutils.h" #include "typeutils.h"
class UpnpDiscovery; class UpnpDiscovery;
class LIBGUH_EXPORT UpnpDiscoveryRequest : public QObject namespace guhserver {
class UpnpDiscoveryRequest : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer<UpnpDiscoveryReply> reply); explicit UpnpDiscoveryRequest(UpnpDiscovery *upnpDiscovery, QPointer<UpnpDiscoveryReplyImplementation> reply);
void discover(const int &timeout); void discover(const int &timeout);
void addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor); void addDeviceDescriptor(const UpnpDeviceDescriptor &deviceDescriptor);
QNetworkRequest createNetworkRequest(UpnpDeviceDescriptor deviveDescriptor); QNetworkRequest createNetworkRequest(UpnpDeviceDescriptor deviveDescriptor);
QList<UpnpDeviceDescriptor> deviceList() const; QList<UpnpDeviceDescriptor> deviceList() const;
QPointer<UpnpDiscoveryReply> reply(); QPointer<UpnpDiscoveryReplyImplementation> reply();
private: private:
UpnpDiscovery *m_upnpDiscovery; UpnpDiscovery *m_upnpDiscovery;
QPointer<UpnpDiscoveryReply> m_reply; QPointer<UpnpDiscoveryReplyImplementation> m_reply;
QTimer *m_timer = nullptr; QTimer *m_timer = nullptr;
QList<UpnpDeviceDescriptor> m_deviceList; QList<UpnpDeviceDescriptor> m_deviceList;
@ -60,4 +62,6 @@ signals:
}; };
}
#endif // UPNPDISCOVERYREQUEST_H #endif // UPNPDISCOVERYREQUEST_H

View File

@ -20,17 +20,14 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "hardwaremanagerimplementation.h"
#include "hardware/plugintimermanagerimplementation.h"
#include "plugintimer.h"
#include "loggingcategories.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 "hardware/network/networkaccessmanagerimpl.h"
#include "network/upnp/upnpdiscovery.h" #include "hardware/radio433/radio433brennenstuhl.h"
#include "network/upnp/upnpdevicedescriptor.h" #include "hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h"
#include "network/avahi/qtavahiservicebrowser.h" #include "hardware/network/avahi/qtavahiservicebrowserimplementation.h"
namespace guhserver { namespace guhserver {
@ -51,22 +48,24 @@ HardwareManagerImplementation::HardwareManagerImplementation(QObject *parent) :
// Network manager // Network manager
m_networkManager = new NetworkAccessManagerImpl(m_networkAccessManager, this); m_networkManager = new NetworkAccessManagerImpl(m_networkAccessManager, this);
setResourceEnabled(m_networkManager, true); setResourceEnabled(m_networkManager, true);
if (m_networkManager->available())
setResourceEnabled(m_networkManager, true);
// UPnP discovery // UPnP discovery
m_upnpDiscovery = new UpnpDiscovery(m_networkAccessManager, this); m_upnpDiscovery = new UpnpDiscoveryImplementation(m_networkAccessManager, this);
m_hardwareResources.append(m_upnpDiscovery); if (m_upnpDiscovery->available())
m_upnpDiscovery->enable(); setResourceEnabled(m_upnpDiscovery, true);
// Avahi Browser // Avahi Browser
m_avahiBrowser = new QtAvahiServiceBrowser(this); m_avahiBrowser = new QtAvahiServiceBrowserImplementation(this);
m_hardwareResources.append(m_avahiBrowser); if (m_avahiBrowser->available())
m_avahiBrowser->enable(); setResourceEnabled(m_avahiBrowser, true);
// Bluetooth LE // Bluetooth LE
m_bluetoothLowEnergyManager = new BluetoothLowEnergyManager(m_pluginTimerManager->registerTimer(10), this); m_bluetoothLowEnergyManager = new BluetoothLowEnergyManagerImplementation(m_pluginTimerManager->registerTimer(10), this);
m_hardwareResources.append(m_bluetoothLowEnergyManager); if (m_bluetoothLowEnergyManager->available())
if (m_networkManager->available()) setResourceEnabled(m_bluetoothLowEnergyManager, true);
m_networkManager->enable();
qCDebug(dcHardware()) << "Hardware manager initialized successfully"; qCDebug(dcHardware()) << "Hardware manager initialized successfully";
@ -120,9 +119,9 @@ void HardwareManagerImplementation::EnableBluetooth(const bool &enabled)
qCDebug(dcHardware()) << "Bluetooth hardware resource" << (enabled ? "enabled" : "disabled"); qCDebug(dcHardware()) << "Bluetooth hardware resource" << (enabled ? "enabled" : "disabled");
if (enabled) { if (enabled) {
m_bluetoothLowEnergyManager->enable(); setResourceEnabled(m_bluetoothLowEnergyManager, true);
} else { } else {
m_bluetoothLowEnergyManager->disable(); setResourceEnabled(m_bluetoothLowEnergyManager, false);
} }
} }

View File

@ -29,15 +29,17 @@
#include "hardwaremanager.h" #include "hardwaremanager.h"
// FIXME: use forward declaration for timeTick
#include "hardware/plugintimermanagerimplementation.h"
class Radio433; class Radio433;
class PluginTimer;
class UpnpDiscovery; class UpnpDiscovery;
class PluginTimerManagerImplementation;
class NetworkAccessManager; class NetworkAccessManager;
class UpnpDeviceDescriptor; class UpnpDeviceDescriptor;
class QtAvahiServiceBrowser; class QtAvahiServiceBrowser;
class BluetoothLowEnergyManager; class BluetoothLowEnergyManager;
namespace guhserver { namespace guhserver {
class HardwareManagerImplementation : public HardwareManager class HardwareManagerImplementation : public HardwareManager
@ -62,13 +64,16 @@ private:
QNetworkAccessManager *m_networkAccessManager; QNetworkAccessManager *m_networkAccessManager;
// Hardware Resources // Hardware Resources
PluginTimerManager *m_pluginTimerManager = nullptr; PluginTimerManagerImplementation *m_pluginTimerManager = nullptr;
Radio433 *m_radio433 = nullptr; Radio433 *m_radio433 = nullptr;
NetworkAccessManager *m_networkManager = nullptr; NetworkAccessManager *m_networkManager = nullptr;
UpnpDiscovery *m_upnpDiscovery = nullptr; UpnpDiscovery *m_upnpDiscovery = nullptr;
QtAvahiServiceBrowser *m_avahiBrowser = nullptr; QtAvahiServiceBrowser *m_avahiBrowser = nullptr;
BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr; BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr;
public slots:
void timeTick();
}; };
} }

View File

@ -5,7 +5,7 @@ include(../guh.pri)
QT += sql QT += sql
INCLUDEPATH += $$top_srcdir/libguh $$top_srcdir jsonrpc 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') target.path = /usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')
INSTALLS += target INSTALLS += target
@ -82,9 +82,19 @@ HEADERS += guhcore.h \
hardware/radio433/radio433brennenstuhl.h \ hardware/radio433/radio433brennenstuhl.h \
hardware/radio433/radio433transmitter.h \ hardware/radio433/radio433transmitter.h \
hardware/radio433/radio433brennenstuhlgateway.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/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 \ SOURCES += guhcore.cpp \
@ -150,6 +160,16 @@ SOURCES += guhcore.cpp \
hardware/radio433/radio433brennenstuhl.cpp \ hardware/radio433/radio433brennenstuhl.cpp \
hardware/radio433/radio433transmitter.cpp \ hardware/radio433/radio433transmitter.cpp \
hardware/radio433/radio433brennenstuhlgateway.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/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 <QDebug>
#include "transportinterface.h" #include "transportinterface.h"
#include "network/avahi/qtavahiservice.h" #include "hardware/network/avahi/qtavahiservice.h"
#include "loggingcategories.h" #include "loggingcategories.h"

View File

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

View File

@ -28,7 +28,7 @@
#include <QWebSocket> #include <QWebSocket>
#include <QWebSocketServer> #include <QWebSocketServer>
#include "network/avahi/qtavahiservice.h" #include "hardware/network/avahi/qtavahiservice.h"
#include "transportinterface.h" #include "transportinterface.h"
// Note: WebSocket Protocol from the Internet Engineering Task Force (IETF) -> RFC6455 V13: // 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 <QObject>
#include <QBluetoothDeviceInfo> #include <QBluetoothDeviceInfo>
class BluetoothDiscoveryReply : public QObject #include "libguh.h"
class LIBGUH_EXPORT BluetoothDiscoveryReply : public QObject
{ {
Q_OBJECT Q_OBJECT
friend class BluetoothLowEnergyManager;
public: public:
enum BluetoothDiscoveryReplyError { enum BluetoothDiscoveryReplyError {
BluetoothDiscoveryReplyErrorNoError, BluetoothDiscoveryReplyErrorNoError,
@ -41,20 +41,12 @@ public:
}; };
Q_ENUM(BluetoothDiscoveryReplyError) Q_ENUM(BluetoothDiscoveryReplyError)
bool isFinished() const;
BluetoothDiscoveryReplyError error() const;
QList<QBluetoothDeviceInfo> discoveredDevices() const;
private:
explicit BluetoothDiscoveryReply(QObject *parent = nullptr); explicit BluetoothDiscoveryReply(QObject *parent = nullptr);
virtual ~BluetoothDiscoveryReply() = default;
bool m_finished = false; virtual bool isFinished() const = 0;
BluetoothDiscoveryReplyError m_error = BluetoothDiscoveryReplyErrorNoError; virtual BluetoothDiscoveryReplyError error() const = 0;
QList<QBluetoothDeviceInfo> m_discoveredDevices; virtual QList<QBluetoothDeviceInfo> discoveredDevices() const = 0;
void setError(const BluetoothDiscoveryReplyError &error);
void setDiscoveredDevices(const QList<QBluetoothDeviceInfo> &discoveredDevices);
void setFinished();
signals: signals:
void finished(); 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 <QBluetoothLocalDevice>
#include <QBluetoothDeviceDiscoveryAgent> #include <QBluetoothDeviceDiscoveryAgent>
#include "plugintimer.h"
#include "hardwareresource.h" #include "hardwareresource.h"
#include "bluetoothdiscoveryreply.h" #include "bluetoothdiscoveryreply.h"
#include "bluetoothlowenergydevice.h" #include "bluetoothlowenergydevice.h"
class BluetoothLowEnergyManager : public HardwareResource #include "libguh.h"
class LIBGUH_EXPORT BluetoothLowEnergyManager : public HardwareResource
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit BluetoothLowEnergyManager(QObject *parent = nullptr); explicit BluetoothLowEnergyManager(QObject *parent = nullptr);
virtual ~BluetoothLowEnergyManager() = default;
virtual BluetoothDiscoveryReply *discoverDevices(const int &interval = 5000) = 0; virtual BluetoothDiscoveryReply *discoverDevices(const int &interval = 5000) = 0;

View File

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

View File

@ -31,20 +31,19 @@ HEADERS += devicemanager.h \
network/upnp/upnpdiscovery.h \ network/upnp/upnpdiscovery.h \
network/upnp/upnpdevice.h \ network/upnp/upnpdevice.h \
network/upnp/upnpdevicedescriptor.h \ network/upnp/upnpdevicedescriptor.h \
network/upnp/upnpdiscoveryrequest.h \
network/upnp/upnpdiscoveryreply.h \ network/upnp/upnpdiscoveryreply.h \
network/networkaccessmanager.h \ network/networkaccessmanager.h \
network/oauth2.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.h \
network/avahi/qtavahiservicebrowser_p.h \ network/avahi/avahiserviceentry.h \
hardware/bluetooth/bluetoothlowenergydevice.h \ #network/avahi/qtavahiclient.h \
hardware/bluetooth/bluetoothdiscoveryreply.h \ #network/avahi/qt-watch.h \
hardware/bluetooth/bluetoothlowenergymanager.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/coap.h \
coap/coappdu.h \ coap/coappdu.h \
coap/coapoption.h \ coap/coapoption.h \
@ -87,20 +86,19 @@ SOURCES += devicemanager.cpp \
network/upnp/upnpdiscovery.cpp \ network/upnp/upnpdiscovery.cpp \
network/upnp/upnpdevice.cpp \ network/upnp/upnpdevice.cpp \
network/upnp/upnpdevicedescriptor.cpp \ network/upnp/upnpdevicedescriptor.cpp \
network/upnp/upnpdiscoveryrequest.cpp \
network/upnp/upnpdiscoveryreply.cpp \ network/upnp/upnpdiscoveryreply.cpp \
network/networkaccessmanager.cpp \ network/networkaccessmanager.cpp \
network/oauth2.cpp \ network/oauth2.cpp \
network/avahi/qt-watch.cpp \
network/avahi/avahiserviceentry.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.cpp \
network/avahi/qtavahiservicebrowser_p.cpp \ #network/avahi/qt-watch.cpp \
hardware/bluetooth/bluetoothlowenergymanager.cpp \ #network/avahi/qtavahiclient.cpp \
hardware/bluetooth/bluetoothlowenergydevice.cpp \ #network/avahi/qtavahiservice.cpp \
hardware/bluetooth/bluetoothdiscoveryreply.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/coap.cpp \
coap/coappdu.cpp \ coap/coappdu.cpp \
coap/coapoption.cpp \ coap/coapoption.cpp \

View File

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

View File

@ -37,81 +37,12 @@
*/ */
#include "qtavahiservicebrowser.h" #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. */ /*! Constructs a new \l{QtAvahiServiceBrowser} with the given \a parent. */
QtAvahiServiceBrowser::QtAvahiServiceBrowser(QObject *parent) : QtAvahiServiceBrowser::QtAvahiServiceBrowser(QObject *parent) :
HardwareResource("Avahi service browser", parent), HardwareResource("Avahi service browser", parent)
d_ptr(new QtAvahiServiceBrowserPrivate(new QtAvahiClient))
{ {
// 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 "libguh.h"
#include "hardwareresource.h" #include "hardwareresource.h"
#include "qtavahiclient.h"
#include "avahiserviceentry.h" #include "avahiserviceentry.h"
class QtAvahiServiceBrowserPrivate;
class LIBGUH_EXPORT QtAvahiServiceBrowser : public HardwareResource class LIBGUH_EXPORT QtAvahiServiceBrowser : public HardwareResource
{ {
Q_OBJECT Q_OBJECT
friend class HardwareManager;
public: public:
QList<AvahiServiceEntry> serviceEntries() const; explicit QtAvahiServiceBrowser(QObject *parent = nullptr);
virtual ~QtAvahiServiceBrowser() = default;
virtual QList<AvahiServiceEntry> serviceEntries() const = 0;
signals: signals:
void serviceEntryAdded(const AvahiServiceEntry &entry); void serviceEntryAdded(const AvahiServiceEntry &entry);
void serviceEntryRemoved(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 #endif // QTAVAHISERVICEBROWSER_H

View File

@ -35,13 +35,6 @@
\sa UpnpDevice, UpnpDeviceDescriptor \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) \fn UpnpDiscovery::upnpNotify(const QByteArray &notifyMessage)
This signal will be emitted when a UPnP NOTIFY message \a notifyMessage will be recognized. This signal will be emitted when a UPnP NOTIFY message \a notifyMessage will be recognized.
@ -49,443 +42,10 @@
*/ */
#include "upnpdiscovery.h" #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. */ /*! Construct the hardware resource UpnpDiscovery with the given \a parent. */
UpnpDiscovery::UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent) : UpnpDiscovery::UpnpDiscovery(QObject *parent) :
HardwareResource("UPnP discovery", parent), HardwareResource("UPnP discovery", parent)
m_networkAccessManager(networkAccessManager)
{ {
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 "devicemanager.h"
#include "hardwareresource.h" #include "hardwareresource.h"
#include "upnpdiscoveryreply.h" #include "upnpdiscoveryreply.h"
#include "upnpdiscoveryrequest.h"
#include "upnpdevicedescriptor.h" #include "upnpdevicedescriptor.h"
// Discovering UPnP devices reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf // Discovering UPnP devices reference: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
// guh basic device reference: http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf // guh basic device reference: http://upnp.org/specs/basic/UPnP-basic-Basic-v1-Device.pdf
class UpnpDiscoveryRequest;
class LIBGUH_EXPORT UpnpDiscovery : public HardwareResource class LIBGUH_EXPORT UpnpDiscovery : public HardwareResource
{ {
Q_OBJECT Q_OBJECT
friend class HardwareManager;
public: public:
UpnpDiscoveryReply *discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = QString(), const int &timeout = 5000); explicit UpnpDiscovery(QObject *parent = nullptr);
void sendToMulticast(const QByteArray &data); virtual ~UpnpDiscovery() = default;
private: virtual UpnpDiscoveryReply *discoverDevices(const QString &searchTarget = "ssdp:all", const QString &userAgent = QString(), const int &timeout = 5000) = 0;
explicit UpnpDiscovery(QNetworkAccessManager *networkAccessManager, QObject *parent = nullptr); virtual void sendToMulticast(const QByteArray &data) = 0;
~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);
signals: signals:
void upnpNotify(const QByteArray &notifyMessage); 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 #endif // UPNPDISCOVERY_H

View File

@ -22,57 +22,8 @@
#include "upnpdiscoveryreply.h" #include "upnpdiscoveryreply.h"
#include <QTimer> UpnpDiscoveryReply::UpnpDiscoveryReply(QObject *parent) :
QObject(parent)
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)
{ {
} }
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 Q_OBJECT
friend class UpnpDiscovery;
public: public:
enum UpnpDiscoveryReplyError { enum UpnpDiscoveryReplyError {
UpnpDiscoveryReplyErrorNoError, UpnpDiscoveryReplyErrorNoError,
@ -42,28 +40,15 @@ public:
}; };
Q_ENUM(UpnpDiscoveryReplyError) Q_ENUM(UpnpDiscoveryReplyError)
QString searchTarget() const; explicit UpnpDiscoveryReply(QObject *parent = nullptr);
QString userAgent() const;
UpnpDiscoveryReplyError error() const; virtual QString searchTarget() const = 0;
bool isFinished() const; virtual QString userAgent() const = 0;
QList<UpnpDeviceDescriptor> deviceDescriptors() const; virtual UpnpDiscoveryReplyError error() const = 0;
virtual bool isFinished() const = 0;
private: virtual QList<UpnpDeviceDescriptor> deviceDescriptors() const = 0;
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();
signals: signals:
void finished(); void finished();

View File

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

View File

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

View File

@ -7,7 +7,7 @@ INCLUDEPATH += $$top_srcdir/libguh \
$$top_srcdir/tests/auto/ $$top_srcdir/tests/auto/
LIBS += -L$$top_builddir/libguh/ -lguh -L$$top_builddir/plugins/mock/ \ 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 \ SOURCES += ../guhtestbase.cpp \

View File

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

View File

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

View File

@ -4,7 +4,7 @@
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../server/main.cpp" line="159"/> <location filename="../server/main.cpp" line="160"/>
<source> <source>
guh ( /[guːh]/ ) is an open source IoT (Internet of Things) server, guh ( /[guːh]/ ) is an open source IoT (Internet of Things) server,
which allows to control a lot of different devices from many different which allows to control a lot of different devices from many different
@ -23,12 +23,12 @@ Szenen undVerhaltensweisen des Systems festzulegen.
</translation> </translation>
</message> </message>
<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> <source>Run guhd in the foreground, not as daemon.</source>
<translation>Starte guhd im Vordergrund, nicht als Service.</translation> <translation>Starte guhd im Vordergrund, nicht als Service.</translation>
</message> </message>
<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;. <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> Categories are:</source>
@ -36,22 +36,22 @@ Categories are:</source>
Es gibt folgende Kategorien:</translation> Es gibt folgende Kategorien:</translation>
</message> </message>
<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> <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> <translation>Aktiviere alle Debug-Kategorien. Dieser Parameter überschreibt alle anderen Debug-Kategorien Parameter.</translation>
</message> </message>
<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> <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> <translation type="unfinished"></translation>
</message> </message>
<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> <source>If specified, all D-Bus interfaces will be bound to the session bus instead of the system bus.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../server/main.cpp" line="236"/> <location filename="../server/main.cpp" line="237"/>
<source>No such debug category:</source> <source>No such debug category:</source>
<translation>Diese Debug-Kategorie existiert nicht:</translation> <translation>Diese Debug-Kategorie existiert nicht:</translation>
</message> </message>

View File

@ -4,7 +4,7 @@
<context> <context>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../server/main.cpp" line="159"/> <location filename="../server/main.cpp" line="160"/>
<source> <source>
guh ( /[guːh]/ ) is an open source IoT (Internet of Things) server, guh ( /[guːh]/ ) is an open source IoT (Internet of Things) server,
which allows to control a lot of different devices from many different which allows to control a lot of different devices from many different
@ -23,12 +23,12 @@ for your environment.
</translation> </translation>
</message> </message>
<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> <source>Run guhd in the foreground, not as daemon.</source>
<translation>Run guhd in the foreground, not as daemon.</translation> <translation>Run guhd in the foreground, not as daemon.</translation>
</message> </message>
<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;. <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> Categories are:</source>
@ -37,22 +37,22 @@ Categories are:</source>
Categories are:</translation> Categories are:</translation>
</message> </message>
<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> <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> <translation>Enables all debug categories. This parameter overrides all debug category parameters.</translation>
</message> </message>
<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> <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> <translation type="unfinished"></translation>
</message> </message>
<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> <source>If specified, all D-Bus interfaces will be bound to the session bus instead of the system bus.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../server/main.cpp" line="236"/> <location filename="../server/main.cpp" line="237"/>
<source>No such debug category:</source> <source>No such debug category:</source>
<translation>No such debug category:</translation> <translation>No such debug category:</translation>
</message> </message>