mirror of https://github.com/nymea/nymea.git
added Bluetooth LE discovery hardware resource (Qt >= 5.4.0)
parent
5ce4f5a914
commit
21ec58e871
|
|
@ -27,6 +27,7 @@ Architecture: any
|
|||
Depends: libqt5network5,
|
||||
libqt5gui5,
|
||||
libqt5sql5,
|
||||
libqt5bluetooth5,
|
||||
libguh1 (= ${binary:Version}),
|
||||
${shlibs:Depends},
|
||||
${misc:Depends}
|
||||
|
|
|
|||
6
guh.pri
6
guh.pri
|
|
@ -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
|
||||
|
|
|
|||
7
guh.pro
7
guh.pro
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
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 ¬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()
|
||||
{
|
||||
foreach (DevicePlugin *plugin, m_pluginTimerUsers) {
|
||||
|
|
|
|||
|
|
@ -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 ¬ifyData);
|
||||
|
||||
#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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue