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