added Bluetooth LE discovery hardware resource (Qt >= 5.4.0)
This commit is contained in:
parent
5ce4f5a914
commit
21ec58e871
1
debian/control
vendored
1
debian/control
vendored
@ -27,6 +27,7 @@ Architecture: any
|
|||||||
Depends: libqt5network5,
|
Depends: libqt5network5,
|
||||||
libqt5gui5,
|
libqt5gui5,
|
||||||
libqt5sql5,
|
libqt5sql5,
|
||||||
|
libqt5bluetooth5,
|
||||||
libguh1 (= ${binary:Version}),
|
libguh1 (= ${binary:Version}),
|
||||||
${shlibs:Depends},
|
${shlibs:Depends},
|
||||||
${misc:Depends}
|
${misc:Depends}
|
||||||
|
|||||||
6
guh.pri
6
guh.pri
@ -14,6 +14,12 @@ QT+= network
|
|||||||
QMAKE_CXXFLAGS += -Werror
|
QMAKE_CXXFLAGS += -Werror
|
||||||
CONFIG += c++11
|
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
|
# Enable coverage option
|
||||||
coverage {
|
coverage {
|
||||||
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0
|
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -O0
|
||||||
|
|||||||
7
guh.pro
7
guh.pro
@ -12,6 +12,13 @@ SUBDIRS += libguh server plugins
|
|||||||
message("Building guh tests disabled")
|
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
|
server.depends = libguh plugins
|
||||||
plugins.depends = libguh
|
plugins.depends = libguh
|
||||||
tests.depends = libguh
|
tests.depends = libguh
|
||||||
|
|||||||
117
libguh/bluetooth/bluetoothscanner.cpp
Normal file
117
libguh/bluetooth/bluetoothscanner.cpp
Normal 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);
|
||||||
|
}
|
||||||
59
libguh/bluetooth/bluetoothscanner.h
Normal file
59
libguh/bluetooth/bluetoothscanner.h
Normal 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
|
||||||
@ -213,6 +213,22 @@ DeviceManager::DeviceManager(QObject *parent) :
|
|||||||
|
|
||||||
m_networkManager = new NetworkManager(this);
|
m_networkManager = new NetworkManager(this);
|
||||||
connect(m_networkManager, &NetworkManager::replyReady, this, &DeviceManager::replyReady);
|
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. */
|
/*! Destructor of the DeviceManager. Each loaded \l{DevicePlugin} will be deleted. */
|
||||||
@ -1168,6 +1184,17 @@ void DeviceManager::upnpNotifyReceived(const QByteArray ¬ifyData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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()
|
void DeviceManager::timerEvent()
|
||||||
{
|
{
|
||||||
foreach (DevicePlugin *plugin, m_pluginTimerUsers) {
|
foreach (DevicePlugin *plugin, m_pluginTimerUsers) {
|
||||||
|
|||||||
@ -32,6 +32,10 @@
|
|||||||
|
|
||||||
#include "network/networkmanager.h"
|
#include "network/networkmanager.h"
|
||||||
|
|
||||||
|
#ifdef BLUETOOTH_LE
|
||||||
|
#include "bluetooth/bluetoothscanner.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QPluginLoader>
|
#include <QPluginLoader>
|
||||||
@ -51,7 +55,9 @@ public:
|
|||||||
HardwareResourceRadio433 = 0x01,
|
HardwareResourceRadio433 = 0x01,
|
||||||
HardwareResourceRadio868 = 0x02,
|
HardwareResourceRadio868 = 0x02,
|
||||||
HardwareResourceTimer = 0x04,
|
HardwareResourceTimer = 0x04,
|
||||||
HardwareResourceNetworkManager = 0x08
|
HardwareResourceNetworkManager = 0x08,
|
||||||
|
HardwareResourceUpnpDisovery = 0x16,
|
||||||
|
HardwareResourceBluetoothLE = 0x32
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(HardwareResources, HardwareResource)
|
Q_DECLARE_FLAGS(HardwareResources, HardwareResource)
|
||||||
|
|
||||||
@ -146,6 +152,14 @@ private slots:
|
|||||||
|
|
||||||
void radio433SignalReceived(QList<int> rawData);
|
void radio433SignalReceived(QList<int> rawData);
|
||||||
void replyReady(const PluginId &pluginId, QNetworkReply *reply);
|
void replyReady(const PluginId &pluginId, QNetworkReply *reply);
|
||||||
|
|
||||||
|
void upnpDiscoveryFinished(const QList<UpnpDeviceDescriptor> &deviceDescriptorList, const PluginId &pluginId);
|
||||||
|
void upnpNotifyReceived(const QByteArray ¬ifyData);
|
||||||
|
|
||||||
|
#ifdef BLUETOOTH_LE
|
||||||
|
void bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos);
|
||||||
|
#endif
|
||||||
|
|
||||||
void timerEvent();
|
void timerEvent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -172,6 +186,10 @@ private:
|
|||||||
QList<DevicePlugin *> m_pluginTimerUsers;
|
QList<DevicePlugin *> m_pluginTimerUsers;
|
||||||
NetworkManager *m_networkManager;
|
NetworkManager *m_networkManager;
|
||||||
|
|
||||||
|
#ifdef BLUETOOTH_LE
|
||||||
|
BluetoothScanner *m_bluetoothScanner;
|
||||||
|
#endif
|
||||||
|
|
||||||
QHash<QUuid, QPair<DeviceClassId, ParamList> > m_pairingsJustAdd;
|
QHash<QUuid, QPair<DeviceClassId, ParamList> > m_pairingsJustAdd;
|
||||||
QHash<QUuid, QPair<DeviceClassId, DeviceDescriptorId> > m_pairingsDiscovery;
|
QHash<QUuid, QPair<DeviceClassId, DeviceDescriptorId> > m_pairingsDiscovery;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,11 @@ QT += network
|
|||||||
target.path = /usr/lib
|
target.path = /usr/lib
|
||||||
INSTALLS += target
|
INSTALLS += target
|
||||||
|
|
||||||
|
contains(DEFINES, BLUETOOTH_LE) {
|
||||||
|
SOURCES += bluetooth/bluetoothscanner.cpp
|
||||||
|
HEADERS += bluetooth/bluetoothscanner.h
|
||||||
|
}
|
||||||
|
|
||||||
SOURCES += plugin/device.cpp \
|
SOURCES += plugin/device.cpp \
|
||||||
plugin/deviceclass.cpp \
|
plugin/deviceclass.cpp \
|
||||||
plugin/deviceplugin.cpp \
|
plugin/deviceplugin.cpp \
|
||||||
|
|||||||
@ -649,6 +649,30 @@ QNetworkReply *DevicePlugin::networkManagerPut(const QNetworkRequest &request, c
|
|||||||
return nullptr;
|
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 DevicePlugin::verifyFields(const QStringList &fields, const QJsonObject &value) const
|
||||||
{
|
{
|
||||||
QStringList ret;
|
QStringList ret;
|
||||||
|
|||||||
@ -31,6 +31,10 @@
|
|||||||
#include "types/vendor.h"
|
#include "types/vendor.h"
|
||||||
#include "types/param.h"
|
#include "types/param.h"
|
||||||
|
|
||||||
|
#ifdef BLUETOOTH_LE
|
||||||
|
#include <QBluetoothDeviceInfo>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
@ -71,6 +75,10 @@ public:
|
|||||||
|
|
||||||
virtual void networkManagerReplyReady(QNetworkReply *reply) {Q_UNUSED(reply)}
|
virtual void networkManagerReplyReady(QNetworkReply *reply) {Q_UNUSED(reply)}
|
||||||
|
|
||||||
|
#ifdef BLUETOOTH_LE
|
||||||
|
virtual void bluetoothDiscoveryFinished(const QList<QBluetoothDeviceInfo> &deviceInfos) {Q_UNUSED(deviceInfos)}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
virtual QList<ParamType> configurationDescription() const;
|
virtual QList<ParamType> configurationDescription() const;
|
||||||
DeviceManager::DeviceError setConfiguration(const ParamList &configuration);
|
DeviceManager::DeviceError setConfiguration(const ParamList &configuration);
|
||||||
@ -101,6 +109,11 @@ protected:
|
|||||||
// Radio 433
|
// Radio 433
|
||||||
bool transmitData(int delay, QList<int> rawData);
|
bool transmitData(int delay, QList<int> rawData);
|
||||||
|
|
||||||
|
// Bluetooth LE discovery
|
||||||
|
#ifdef BLUETOOTH_LE
|
||||||
|
bool discoverBluetooth();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Network manager
|
// Network manager
|
||||||
QNetworkReply *networkManagerGet(const QNetworkRequest &request);
|
QNetworkReply *networkManagerGet(const QNetworkRequest &request);
|
||||||
QNetworkReply *networkManagerPost(const QNetworkRequest &request, const QByteArray &data);
|
QNetworkReply *networkManagerPost(const QNetworkRequest &request, const QByteArray &data);
|
||||||
|
|||||||
Reference in New Issue
Block a user