added Bluetooth LE discovery hardware resource (Qt >= 5.4.0)

pull/135/head
Simon Stürz 2015-03-02 14:05:46 +01:00 committed by Michael Zanetti
parent 5ce4f5a914
commit 21ec58e871
10 changed files with 278 additions and 1 deletions

1
debian/control vendored
View File

@ -27,6 +27,7 @@ Architecture: any
Depends: libqt5network5,
libqt5gui5,
libqt5sql5,
libqt5bluetooth5,
libguh1 (= ${binary:Version}),
${shlibs:Depends},
${misc:Depends}

View File

@ -14,6 +14,12 @@ QT+= network
QMAKE_CXXFLAGS += -Werror
CONFIG += c++11
# Check for Bluetoot LE support (Qt >= 5.4.0)
!contains(QT_VERSION, ^5\\.[0-3]\\..*) {
QT += bluetooth
DEFINES += BLUETOOTH_LE
}
# Enable coverage option
coverage {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0

View File

@ -12,6 +12,13 @@ SUBDIRS += libguh server plugins
message("Building guh tests disabled")
}
# Bluetooth LE support
contains(DEFINES, BLUETOOTH_LE) {
message("Bluetooth LE available (Qt $${QT_VERSION}).")
} else {
message("Bluetooth LE not available (Qt $${QT_VERSION}).")
}
server.depends = libguh plugins
plugins.depends = libguh
tests.depends = libguh

View File

@ -0,0 +1,117 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "bluetoothscanner.h"
BluetoothScanner::BluetoothScanner(QObject *parent) :
QObject(parent)
{
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
m_timer->setInterval(10000);
connect(m_timer, &QTimer::timeout, this, &BluetoothScanner::discoveryTimeout);
}
bool BluetoothScanner::isAvailable()
{
//Using default Bluetooth adapter
QBluetoothLocalDevice localDevice;
// Check if Bluetooth is available on this device
if (!localDevice.isValid()) {
qWarning() << "ERROR: no bluetooth device found.";
m_available = false;
return false;
}
// Turn Bluetooth on
localDevice.powerOn();
// Make it visible to others
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
// Get connected devices
QList<QBluetoothHostInfo> remotes = localDevice.allDevices();
if (remotes.isEmpty()) {
qWarning() << "ERROR: no bluetooth host info found.";
m_available = false;
return false;
}
QBluetoothHostInfo hostInfo = remotes.first();
// Create a discovery agent and connect to its signals
m_discoveryAgent = new QBluetoothDeviceDiscoveryAgent(hostInfo.address(), this);
connect(m_discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothScanner::deviceDiscovered);
connect(m_discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onError(QBluetoothDeviceDiscoveryAgent::Error)));
qDebug() << "--> Bluetooth discovery created successfully.";
m_available = true;
return true;
}
bool BluetoothScanner::isRunning()
{
return m_discoveryAgent->isActive();
}
bool BluetoothScanner::discover(const PluginId &pluginId)
{
if (m_available && !m_discoveryAgent->isActive()) {
m_pluginId = pluginId;
m_deviceInfos.clear();
m_discoveryAgent->start();
m_timer->start();
qDebug() << "Bluetooth discovery started...";
return true;
}
return false;
}
void BluetoothScanner::deviceDiscovered(const QBluetoothDeviceInfo &device)
{
// check if this is LE device
bool bluetoothLE = false;
if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
bluetoothLE = true;
}
qDebug() << "Bluetooth device discovered:" << device.name() << device.address() << "LE:" << bluetoothLE;
m_deviceInfos.append(device);
}
void BluetoothScanner::onError(QBluetoothDeviceDiscoveryAgent::Error error)
{
Q_UNUSED(error);
m_available = false;
if (m_timer->isActive()) {
m_timer->stop();
}
if (isRunning()) {
m_discoveryAgent->stop();
}
qWarning() << "ERROR: Bluetooth discovery:" << m_discoveryAgent->errorString();
}
void BluetoothScanner::discoveryTimeout()
{
qDebug() << "Bluetooth discovery finished.";
m_discoveryAgent->stop();
emit bluetoothDiscoveryFinished(m_pluginId, m_deviceInfos);
}

View File

@ -0,0 +1,59 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BLUETOOTHLE_H
#define BLUETOOTHLE_H
#include <QObject>
#include <QDebug>
#include <QTimer>
#include <QtBluetooth>
#include <QBluetoothHostInfo>
#include <QBluetoothDeviceInfo>
#include <QBluetoothAddress>
#include <QBluetoothLocalDevice>
#include <QBluetoothDeviceDiscoveryAgent>
#include "typeutils.h"
class BluetoothScanner : public QObject
{
Q_OBJECT
public:
explicit BluetoothScanner(QObject *parent = 0);
bool isAvailable();
bool isRunning();
bool discover(const PluginId &pluginId);
private:
QBluetoothDeviceDiscoveryAgent *m_discoveryAgent;
QList<QBluetoothDeviceInfo> m_deviceInfos;
QTimer *m_timer;
bool m_available;
PluginId m_pluginId;
signals:
void bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos);
private slots:
void deviceDiscovered(const QBluetoothDeviceInfo &device);
void onError(QBluetoothDeviceDiscoveryAgent::Error error);
void discoveryTimeout();
};
#endif // BLUETOOTHLE_H

View File

@ -213,6 +213,22 @@ DeviceManager::DeviceManager(QObject *parent) :
m_networkManager = new NetworkManager(this);
connect(m_networkManager, &NetworkManager::replyReady, this, &DeviceManager::replyReady);
// UPnP discovery
m_upnpDiscovery = new UpnpDiscovery(this);
connect(m_upnpDiscovery, &UpnpDiscovery::discoveryFinished, this, &DeviceManager::upnpDiscoveryFinished);
connect(m_upnpDiscovery, &UpnpDiscovery::upnpNotify, this, &DeviceManager::upnpNotifyReceived);
// Bluetooth LE
#ifdef BLUETOOTH_LE
m_bluetoothScanner = new BluetoothScanner(this);
if (!m_bluetoothScanner->isAvailable()) {
delete m_bluetoothScanner;
m_bluetoothScanner = 0;
} else {
connect(m_bluetoothScanner, &BluetoothScanner::bluetoothDiscoveryFinished, this, &DeviceManager::bluetoothDiscoveryFinished);
}
#endif
}
/*! Destructor of the DeviceManager. Each loaded \l{DevicePlugin} will be deleted. */
@ -1168,6 +1184,17 @@ void DeviceManager::upnpNotifyReceived(const QByteArray &notifyData)
}
}
#ifdef BLUETOOTH_LE
void DeviceManager::bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos)
{
foreach (DevicePlugin *devicePlugin, m_devicePlugins) {
if (devicePlugin->requiredHardware().testFlag(HardwareResourceBluetoothLE) && devicePlugin->pluginId() == pluginId) {
devicePlugin->bluetoothDiscoveryFinished(deviceInfos);
}
}
}
#endif
void DeviceManager::timerEvent()
{
foreach (DevicePlugin *plugin, m_pluginTimerUsers) {

View File

@ -32,6 +32,10 @@
#include "network/networkmanager.h"
#ifdef BLUETOOTH_LE
#include "bluetooth/bluetoothscanner.h"
#endif
#include <QObject>
#include <QTimer>
#include <QPluginLoader>
@ -51,7 +55,9 @@ public:
HardwareResourceRadio433 = 0x01,
HardwareResourceRadio868 = 0x02,
HardwareResourceTimer = 0x04,
HardwareResourceNetworkManager = 0x08
HardwareResourceNetworkManager = 0x08,
HardwareResourceUpnpDisovery = 0x16,
HardwareResourceBluetoothLE = 0x32
};
Q_DECLARE_FLAGS(HardwareResources, HardwareResource)
@ -146,6 +152,14 @@ private slots:
void radio433SignalReceived(QList<int> rawData);
void replyReady(const PluginId &pluginId, QNetworkReply *reply);
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId);
void upnpNotifyReceived(const QByteArray &notifyData);
#ifdef BLUETOOTH_LE
void bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos);
#endif
void timerEvent();
private:
@ -172,6 +186,10 @@ private:
QList<DevicePlugin *> m_pluginTimerUsers;
NetworkManager *m_networkManager;
#ifdef BLUETOOTH_LE
BluetoothScanner *m_bluetoothScanner;
#endif
QHash<QUuid, QPair<DeviceClassId, ParamList> > m_pairingsJustAdd;
QHash<QUuid, QPair<DeviceClassId, DeviceDescriptorId> > m_pairingsDiscovery;

View File

@ -8,6 +8,11 @@ QT += network
target.path = /usr/lib
INSTALLS += target
contains(DEFINES, BLUETOOTH_LE) {
SOURCES += bluetooth/bluetoothscanner.cpp
HEADERS += bluetooth/bluetoothscanner.h
}
SOURCES += plugin/device.cpp \
plugin/deviceclass.cpp \
plugin/deviceplugin.cpp \

View File

@ -649,6 +649,30 @@ QNetworkReply *DevicePlugin::networkManagerPut(const QNetworkRequest &request, c
return nullptr;
}
/*!
Starts a SSDP search for a certain \a searchTarget (ST). Certain UPnP devices need a special ST (i.e. "udap:rootservice"
for LG Smart Tv's), otherwise they will not respond on the SSDP search. Each HTTP request to this device needs sometimes
also a special \a userAgent, which will be written into the HTTP header.
\sa DevicePlugin::requiredHardware(), DevicePlugin::upnpDiscoveryFinished()
*/
void DevicePlugin::upnpDiscover(QString searchTarget, QString userAgent)
{
if(requiredHardware().testFlag(DeviceManager::HardwareResourceUpnpDisovery)){
deviceManager()->m_upnpDiscovery->discoverDevices(searchTarget, userAgent, pluginId());
}
}
#ifdef BLUETOOTH_LE
bool DevicePlugin::discoverBluetooth()
{
if(requiredHardware().testFlag(DeviceManager::HardwareResourceBluetoothLE)){
return deviceManager()->m_bluetoothScanner->discover(pluginId());
}
return false;
}
#endif
QStringList DevicePlugin::verifyFields(const QStringList &fields, const QJsonObject &value) const
{
QStringList ret;

View File

@ -31,6 +31,10 @@
#include "types/vendor.h"
#include "types/param.h"
#ifdef BLUETOOTH_LE
#include <QBluetoothDeviceInfo>
#endif
#include <QObject>
#include <QJsonObject>
@ -71,6 +75,10 @@ public:
virtual void networkManagerReplyReady(QNetworkReply *reply) {Q_UNUSED(reply)}
#ifdef BLUETOOTH_LE
virtual void bluetoothDiscoveryFinished(const QList<QBluetoothDeviceInfo> &deviceInfos) {Q_UNUSED(deviceInfos)}
#endif
// Configuration
virtual QList<ParamType> configurationDescription() const;
DeviceManager::DeviceError setConfiguration(const ParamList &configuration);
@ -101,6 +109,11 @@ protected:
// Radio 433
bool transmitData(int delay, QList<int> rawData);
// Bluetooth LE discovery
#ifdef BLUETOOTH_LE
bool discoverBluetooth();
#endif
// Network manager
QNetworkReply *networkManagerGet(const QNetworkRequest &request);
QNetworkReply *networkManagerPost(const QNetworkRequest &request, const QByteArray &data);