First version of bluetooth manager

This commit is contained in:
Simon Stürz 2017-11-22 20:00:55 +01:00 committed by Michael Zanetti
parent 89b860a7eb
commit 19a4223906
16 changed files with 120 additions and 254 deletions

View File

@ -23,6 +23,35 @@
#include "bluetoothlowenergymanager.h"
#include "loggingcategories.h"
bool BluetoothLowEnergyManager::discoverDevices(QPointer<QObject> caller, const QString &callbackMethod)
{
if (!available()) {
qCWarning(dcHardware()) << name() << "is not avilable.";
return false;
}
if (!enabled()) {
qCWarning(dcHardware()) << name() << "is not enabled.";
return false;
}
if (m_timer->isActive()) {
qCWarning(dcHardware()) << name() << "discovery already running.";
return false;
}
m_discoveredDevices.clear();
m_currentReply.caller = caller;
m_currentReply.callbackMethod = callbackMethod;
// Start discovery on all adapters
qCDebug(dcHardware()) << name() << "Start bluetooth discovery";
foreach (QBluetoothDeviceDiscoveryAgent *discoveryAgent, m_bluetoothDiscoveryAgents) {
discoveryAgent->start();
}
return true;
}
BluetoothLowEnergyManager::BluetoothLowEnergyManager(QObject *parent) :
HardwareResource(HardwareResource::TypeBluetoothLE, "Bluetooth LE manager", parent)
{
@ -36,38 +65,80 @@ BluetoothLowEnergyManager::BluetoothLowEnergyManager(QObject *parent) :
// Create a scanner for each adapter
foreach (const QBluetoothHostInfo &hostInfo, bluetoothAdapters) {
qCDebug(dcHardware()) << name() << "Adapter:" << hostInfo.name() << hostInfo.address().toString();
m_bluetoothScanners.append(new BluetoothScanner(hostInfo.address(), this));
qCDebug(dcHardware()) << name() << "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
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
m_timer->setInterval(5000);
// // Check if Bluetooth is available on this device
// if (!localDevice.isValid()) {
// qCWarning(dcHardware()) << "No Bluetooth device found.";
// setAvailable(false);
// return false;
// }
// // Turn Bluetooth on
// localDevice.powerOn();
// // Make it visible to others
// localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
connect(m_timer, &QTimer::timeout, this, &BluetoothLowEnergyManager::discoveryTimeout);
qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
setAvailable(true);
}
void BluetoothLowEnergyManager::discoveryTimeout()
{
// Start discovery on all adapters
qCDebug(dcHardware()) << name() << "Stop bluetooth discovery";
foreach (QBluetoothDeviceDiscoveryAgent *discoveryAgent, m_bluetoothDiscoveryAgents) {
discoveryAgent->stop();
}
qCDebug(dcHardware()) << name() << "Discovery finished. Found"<< m_discoveredDevices.count() << "Bluetooth devices.";
if (m_currentReply.caller.isNull()) {
qCWarning(dcHardware()) << name() << "The reciver of the discovery request does not exist any more.";
} else {
// Invoke the method containing the discovered devicelist
// FIXME: check the callback method paramters during compililation
QMetaObject::invokeMethod(m_currentReply.caller.data(), m_currentReply.callbackMethod.toLatin1().data(), Q_ARG(QList<QBluetoothDeviceInfo>, m_discoveredDevices));
}
}
void BluetoothLowEnergyManager::onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo)
{
// Add the device to the list if not already added
bool alreadyAdded = false;
foreach (const QBluetoothDeviceInfo &device, m_discoveredDevices) {
if (device.address() == deviceInfo.address()) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
qCDebug(dcHardware()) << name() << "device discovered" << deviceInfo.name() <<deviceInfo.address().toString();
m_discoveredDevices.append(deviceInfo);
}
}
void BluetoothLowEnergyManager::onDiscoveryError(const QBluetoothDeviceDiscoveryAgent::Error &error)
{
QBluetoothDeviceDiscoveryAgent *discoveryAgent = static_cast<QBluetoothDeviceDiscoveryAgent *>(sender());
qCWarning(dcHardware()) << name() << "Discovery error:" << error << discoveryAgent->errorString();
}
bool BluetoothLowEnergyManager::enable()
{
// TODO: enable all devices created by this
// TODO: enable all devices and trigger reconnect
setEnabled(true);
return true;
}
bool BluetoothLowEnergyManager::disable()
{
// TODO: disable reconnect and disconnect all devices
setEnabled(false);
return true;
}

View File

@ -23,11 +23,20 @@
#ifndef BLUETOOTHLOWENERGYMANAGER_H
#define BLUETOOTHLOWENERGYMANAGER_H
#include <QTimer>
#include <QObject>
#include <QPointer>
#include <QBluetoothDeviceInfo>
#include <QBluetoothLocalDevice>
#include <QBluetoothDeviceDiscoveryAgent>
#include "hardwareresource.h"
#include "bluetoothscanner.h"
struct BluetoothDiscoveryReply
{
QPointer<QObject> caller;
QString callbackMethod;
};
class BluetoothLowEnergyManager : public HardwareResource
{
@ -36,13 +45,25 @@ class BluetoothLowEnergyManager : public HardwareResource
friend class HardwareManager;
public:
bool discoverDevices(QPointer<QObject> caller = QPointer<QObject>(), const QString &callbackMethod = QString());
private:
explicit BluetoothLowEnergyManager(QObject *parent = nullptr);
QList<BluetoothScanner *> m_bluetoothScanners;
QTimer *m_timer = nullptr;
QList<QBluetoothDeviceDiscoveryAgent *> m_bluetoothDiscoveryAgents;
QList<QBluetoothDeviceInfo> m_discoveredDevices;
BluetoothDiscoveryReply m_currentReply;
signals:
private slots:
void onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo);
void onDiscoveryError(const QBluetoothDeviceDiscoveryAgent::Error &error);
void discoveryTimeout();
public slots:
bool enable();
bool disable();

View File

@ -1,112 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 BluetoothScanner
\brief Allows to discover bluetooth low energy devices.
\ingroup hardware
\inmodule libguh
The bluetooth scanner hardware resource allows to discover bluetooth low energy devices.
*/
/*!
* \fn BluetoothScanner::bluetoothDiscoveryFinished(const PluginId &pluginId, const QList<QBluetoothDeviceInfo> &deviceInfos)
* This signal will be emitted whenever a bluetooth discover for the plugin with the given \a pluginId is finished.
* The passed list of \a deviceInfos contains the information of the discovered devices.
*/
#include "bluetoothscanner.h"
#include "loggingcategories.h"
/*! Construct the hardware resource BluetoothScanner with the given \a parent. */
BluetoothScanner::BluetoothScanner(const QBluetoothAddress &adapterAddress, QObject *parent) :
QObject(parent),
m_adapterAddress(adapterAddress)
{
m_timer = new QTimer(this);
m_timer->setSingleShot(true);
m_timer->setInterval(5000);
connect(m_timer, &QTimer::timeout, this, &BluetoothScanner::discoveryTimeout);
m_discoveryAgent = new QBluetoothDeviceDiscoveryAgent(m_adapterAddress, this);
connect(m_discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothScanner::deviceDiscovered);
connect(m_discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onError(QBluetoothDeviceDiscoveryAgent::Error)));
}
/*! Returns true, if the discovering agent currently is running. */
bool BluetoothScanner::isRunning()
{
return m_discoveryAgent->isActive();
}
/*! This method will start the discovering process for the plugin with the given \a pluginId.
* Returns true if the discovery could be started. */
bool BluetoothScanner::discover(const PluginId &pluginId)
{
if (m_available && !m_discoveryAgent->isActive()) {
m_pluginId = pluginId;
m_deviceInfos.clear();
m_discoveryAgent->start();
m_timer->start();
qCDebug(dcHardware) << "Bluetooth discovery started...";
return true;
}
return false;
}
void BluetoothScanner::deviceDiscovered(const QBluetoothDeviceInfo &device)
{
// check if this is a LE device
bool bluetoothLE = false;
if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
bluetoothLE = true;
}
qCDebug(dcHardware) << "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();
qCWarning(dcHardware) << "Bluetooth discovery error:" << m_discoveryAgent->errorString();
}
void BluetoothScanner::discoveryTimeout()
{
qCDebug(dcHardware) << "Bluetooth discovery finished.";
m_discoveryAgent->stop();
emit bluetoothDiscoveryFinished(m_pluginId, m_deviceInfos);
}

View File

@ -1,64 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 BLUETOOTHSCANNER_H
#define BLUETOOTHSCANNER_H
#include <QObject>
#include <QDebug>
#include <QTimer>
#include <QtBluetooth>
#include <QBluetoothHostInfo>
#include <QBluetoothDeviceInfo>
#include <QBluetoothAddress>
#include <QBluetoothLocalDevice>
#include <QBluetoothDeviceDiscoveryAgent>
#include "libguh.h"
#include "typeutils.h"
class LIBGUH_EXPORT BluetoothScanner : public QObject
{
Q_OBJECT
public:
explicit BluetoothScanner(const QBluetoothAddress &adapterAddress, QObject *parent = 0);
bool isRunning();
bool discover(const PluginId &pluginId);
private:
QBluetoothAddress m_adapterAddress;
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 // BLUETOOTHSCANNER_H

View File

@ -745,22 +745,6 @@ DeviceManager::DeviceError DeviceManager::removeConfiguredDevice(const DeviceId
}
m_devicePlugins.value(device->pluginId())->deviceRemoved(device);
// check if this plugin still needs the guhTimer call
bool pluginNeedsTimer = false;
foreach (Device* d, m_configuredDevices) {
if (d->pluginId() == device->pluginId()) {
pluginNeedsTimer = true;
break;
}
}
// if this plugin doesn't need any longer the guhTimer call
if (!pluginNeedsTimer) {
m_pluginTimerUsers.removeAll(plugin(device->pluginId()));
if (m_pluginTimerUsers.isEmpty()) {
m_hardwareManager->pluginTimer()->disable();
}
}
device->deleteLater();
GuhSettings settings(GuhSettings::SettingsRoleDevices);
@ -1220,18 +1204,6 @@ void DeviceManager::slotDeviceSetupFinished(Device *device, DeviceManager::Devic
storeConfiguredDevices();
}
DevicePlugin *plugin = m_devicePlugins.value(device->pluginId());
if (plugin->requiredHardware().testFlag(HardwareResource::TypeTimer)) {
if (!m_hardwareManager->pluginTimer()->enabled()) {
m_hardwareManager->pluginTimer()->enable();
// Additionally fire off one event to initialize stuff
QTimer::singleShot(0, this, SLOT(timerEvent()));
}
if (!m_pluginTimerUsers.contains(plugin)) {
m_pluginTimerUsers.append(plugin);
}
}
// if this is a async device edit result
if (m_asyncDeviceReconfiguration.contains(device)) {
m_asyncDeviceReconfiguration.removeAll(device);
@ -1465,19 +1437,6 @@ DeviceManager::DeviceSetupStatus DeviceManager::setupDevice(Device *device)
return status;
}
if (plugin->requiredHardware().testFlag(HardwareResource::TypeTimer)) {
if (!m_hardwareManager->pluginTimer()->enabled()) {
m_hardwareManager->pluginTimer()->enable();
// Additionally fire off one event to initialize stuff
QTimer::singleShot(0, this, SLOT(timerEvent()));
}
if (!m_pluginTimerUsers.contains(plugin)) {
m_pluginTimerUsers.append(plugin);
}
}
connect(device, SIGNAL(stateValueChanged(QUuid,QVariant)), this, SLOT(slotDeviceStateValueChanged(QUuid,QVariant)));
device->setupCompleted();

View File

@ -185,7 +185,6 @@ private:
QHash<DeviceDescriptorId, DeviceDescriptor> m_discoveredDevices;
QHash<PluginId, DevicePlugin*> m_devicePlugins;
QList<DevicePlugin *> m_pluginTimerUsers;
HardwareManager *m_hardwareManager;

View File

@ -24,7 +24,6 @@
#include "plugintimer.h"
#include "loggingcategories.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h"
#include "network/networkaccessmanager.h"
#include "network/upnp/upnpdiscovery.h"

View File

@ -75,7 +75,6 @@ signals:
void hardwareResourceAvailableChanged(const HardwareResource::Type &hardwareResourceType, const bool &available);
void hardwareResourceEnabledChanged(const HardwareResource::Type &hardwareResourceType, const bool &enabled);
};

View File

@ -43,7 +43,6 @@ HEADERS += devicemanager.h \
network/avahi/qtavahiservice_p.h \
network/avahi/qtavahiservicebrowser.h \
network/avahi/qtavahiservicebrowser_p.h \
bluetooth/bluetoothscanner.h \
bluetooth/bluetoothlowenergydevice.h \
coap/coap.h \
coap/coappdu.h \
@ -100,7 +99,6 @@ SOURCES += devicemanager.cpp \
network/avahi/qtavahiservice_p.cpp \
network/avahi/qtavahiservicebrowser.cpp \
network/avahi/qtavahiservicebrowser_p.cpp \
bluetooth/bluetoothscanner.cpp \
bluetooth/bluetoothlowenergydevice.cpp \
coap/coap.cpp \
coap/coappdu.cpp \

View File

@ -48,6 +48,10 @@ QtAvahiServiceBrowser::QtAvahiServiceBrowser(QObject *parent) :
d_ptr(new QtAvahiServiceBrowserPrivate(new QtAvahiClient))
{
connect(d_ptr->client, &QtAvahiClient::clientStateChanged, this, &QtAvahiServiceBrowser::onClientStateChanged);
// TODO: check available here
setAvailable(true);
qCDebug(dcHardware()) << "-->" << name() << "created successfully.";
}

View File

@ -148,7 +148,7 @@
#include "devicemanager.h"
#include "guhsettings.h"
#include "bluetooth/bluetoothscanner.h"
#include "hardware/radio433/radio433.h"
#include "network/upnp/upnpdiscovery.h"

View File

@ -43,8 +43,8 @@
#include <QPair>
#include <QBluetoothDeviceInfo>
class DeviceManager;
class Device;
class DeviceManager;
class LIBGUH_EXPORT DevicePlugin: public QObject
{
@ -66,8 +66,6 @@ public:
QTranslator *translator();
bool setLocale(const QLocale &locale);
virtual HardwareResource::Types requiredHardware() const = 0;
virtual void startMonitoringAutoDevices();
virtual DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params);

View File

@ -61,11 +61,6 @@ DevicePluginMock::~DevicePluginMock()
{
}
HardwareResource::Types DevicePluginMock::requiredHardware() const
{
return HardwareResource::TypeTimer;
}
DeviceManager::DeviceError DevicePluginMock::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
if (deviceClassId == mockDeviceClassId || deviceClassId == mockDeviceAutoDeviceClassId) {

View File

@ -41,7 +41,6 @@ public:
explicit DevicePluginMock();
~DevicePluginMock();
HardwareResource::Types requiredHardware() const override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;

View File

@ -4,7 +4,7 @@
<context>
<name>DevicePluginMock</name>
<message>
<location filename="../devicepluginmock.cpp" line="219"/>
<location filename="../devicepluginmock.cpp" line="214"/>
<source>Display pin!! The pin is 243681</source>
<translation>Pin anzeigen!! Der pin lautet 243581</translation>
</message>

View File

@ -4,7 +4,7 @@
<context>
<name>DevicePluginMock</name>
<message>
<location filename="../devicepluginmock.cpp" line="219"/>
<location filename="../devicepluginmock.cpp" line="214"/>
<source>Display pin!! The pin is 243681</source>
<translation type="unfinished"></translation>
</message>