diff options
author | Christian Kandeler <christian.kandeler@theqtcompany.com> | 2015-10-14 16:54:47 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@theqtcompany.com> | 2015-11-17 15:40:02 +0000 |
commit | a5f362af452555b5aaa4585be82053029e4b25c0 (patch) | |
tree | eae7edea0537c8fe55226628fc3d5618741cf04f /src/bluetooth/qlowenergycontroller.cpp | |
parent | eb59027d32c7904a129b16c786df1dc2097ab9c9 (diff) |
Bluetooth: Introduce API for LE advertising.
And provide an implementation for BlueZ.
Change-Id: I302aee7c43b77016d9e1e7a0d5bcbf00096abf76
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src/bluetooth/qlowenergycontroller.cpp')
-rw-r--r-- | src/bluetooth/qlowenergycontroller.cpp | 176 |
1 files changed, 161 insertions, 15 deletions
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp index 62e8f7e3..9a9327a5 100644 --- a/src/bluetooth/qlowenergycontroller.cpp +++ b/src/bluetooth/qlowenergycontroller.cpp @@ -35,11 +35,14 @@ #include "qlowenergycontroller_p.h" #include <QtBluetooth/QBluetoothLocalDevice> +#include <QtCore/QLoggingCategory> #include <algorithm> QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + /*! \class QLowEnergyController \inmodule QtBluetooth @@ -49,9 +52,7 @@ QT_BEGIN_NAMESPACE \since 5.4 QLowEnergyController acts as the entry point for Bluetooth Low Energy - development. Each QLowEnergyController instance acts as placeholder - towards a remote Low Energy device enabling connection control, - service discovery and state tracking. + development. Bluetooth Low Energy defines two types of devices; the peripheral and the central. Each role performs a different task. The peripheral device @@ -62,12 +63,12 @@ QT_BEGIN_NAMESPACE the sensor is the peripheral device and the mobile phone acts as the central device. - At the moment Qt only supports the central role and therefore the remote - device can only be a device acting as a peripheral. This implies that the local - device acts within the boundaries of the central role as per the Bluetooth 4.0 - specification. + A controller in the central role is created via the \l createCentral() factory method. + Such an object essentially acts as a placeholder towards a remote Low Energy peripheral + device, enabling features such as service discovery and state tracking. - The first step is to establish a connection via \l connectToDevice(). + After having created a controller object in the central role, the first step is to establish + a connection via \l connectToDevice(). Once the connection has been established, the controller's \l state() changes to \l QLowEnergyController::ConnectedState and the \l connected() signal is emitted. It is important to mention that some platforms such as @@ -93,7 +94,20 @@ QT_BEGIN_NAMESPACE connection becomes invalid as soon as the controller disconnects from the remote Bluetooth Low Energy device. + A controller in the peripheral role is created via the \l createPeripheral() factory method. + Such an object acts as a peripheral device itself, enabling features such as advertising + services and allowing clients to get notified about changes to characteristic values. + + \omit + After having created a controller object in the peripheral role, the first step is to + populate the set of GATT services offered to client devices [not yet implemented]. + Afterwards, one would call \l startAdvertising() to let the device broadcast some data + and, depending on the type of advertising being done, also listen for incoming connections + from GATT clients. + \endomit + \sa QLowEnergyService, QLowEnergyCharacteristic, QLowEnergyDescriptor + \sa QLowEnergyAdvertisingParameters, QLowEnergyAdvertisingData */ /*! @@ -113,6 +127,8 @@ QT_BEGIN_NAMESPACE there is no local Bluetooth device. \value ConnectionError The attempt to connect to the remote device failed. This value was introduced by Qt 5.5. + \value AdvertisingError The attempt to start advertising failed. + This value was introduced by Qt 5.7. */ /*! @@ -128,6 +144,7 @@ QT_BEGIN_NAMESPACE \value DiscoveredState The controller has discovered all services offered by the remote device. \value ClosingState The controller is about to be disconnected from the remote device. + \value AdvertisingState The controller is currently advertising data. */ /*! @@ -135,26 +152,47 @@ QT_BEGIN_NAMESPACE Indicates what type of Bluetooth address the remote device uses. - \value PublicAddress The peripheral uses a public Bluetooth address. + \value PublicAddress The remote device uses a public Bluetooth address. \value RandomAddress A random address is a Bluetooth Low Energy security feature. Peripherals using such addresses may frequently change their Bluetooth address. This information is needed when trying to connect to a peripheral. */ +/*! + \enum QLowEnergyController::Role + + Indicates the role of the controller object. + + \value CentralRole + The controller acts as a client interacting with a remote device which is in the peripheral + role. The controller can initiate connections, discover services and + read and write characteristics. + \value PeripheralRole + The controller can be used to advertise services and handle incoming + connections and client requests, acting as a GATT server. A remote device connected to + the controller is in the central role. + + \sa QLowEnergyController::createCentral() + \sa QLowEnergyController::createPeripheral() + \since 5.7 + \note The peripheral role is currently only supported on Linux. + */ + /*! \fn void QLowEnergyController::connected() This signal is emitted when the controller successfully connects to the remote - Low Energy device. + Low Energy device (if the controller is in the \l CentralRole) or if a remote Low Energy + device connected to the controller (if the controller is in the \l PeripheralRole). */ /*! \fn void QLowEnergyController::disconnected() This signal is emitted when the controller disconnects from the remote - Low Energy device. + Low Energy device or vice versa. */ /*! @@ -181,6 +219,8 @@ QT_BEGIN_NAMESPACE This signal is emitted each time a new service is discovered. The \a newService parameter contains the UUID of the found service. + This signal can only be emitted if the controller is in the \c CentralRole. + \sa discoverServices(), discoveryFinished() */ @@ -191,6 +231,8 @@ QT_BEGIN_NAMESPACE The signal is not emitted if the discovery process finishes with an error. + This signal can only be emitted if the controller is in the \l CentralRole. + \sa discoverServices(), error() */ @@ -225,11 +267,14 @@ void QLowEnergyControllerPrivate::setError( case QLowEnergyController::ConnectionError: errorString = QLowEnergyController::tr("Error occurred trying to connect to remote device."); break; - case QLowEnergyController::NoError: - return; + case QLowEnergyController::AdvertisingError: + errorString = QLowEnergyController::tr("Error occurred trying to start advertising"); + break; case QLowEnergyController::UnknownError: errorString = QLowEnergyController::tr("Unknown Error"); break; + case QLowEnergyController::NoError: + return; } emit q->error(newError); @@ -409,6 +454,7 @@ QLowEnergyController::QLowEnergyController( { Q_D(QLowEnergyController); d->q_ptr = this; + d->role = CentralRole; d->remoteDevice = remoteDevice; d->localAdapter = QBluetoothLocalDevice().address(); d->addressType = QLowEnergyController::PublicAddress; @@ -425,6 +471,7 @@ QLowEnergyController::QLowEnergyController( the connection management. \since 5.5 + \obsolete */ QLowEnergyController::QLowEnergyController( const QBluetoothDeviceInfo &remoteDeviceInfo, @@ -433,6 +480,7 @@ QLowEnergyController::QLowEnergyController( { Q_D(QLowEnergyController); d->q_ptr = this; + d->role = CentralRole; d->remoteDevice = remoteDeviceInfo.address(); d->localAdapter = QBluetoothLocalDevice().address(); d->addressType = QLowEnergyController::PublicAddress; @@ -462,11 +510,47 @@ QLowEnergyController::QLowEnergyController( { Q_D(QLowEnergyController); d->q_ptr = this; + d->role = CentralRole; d->remoteDevice = remoteDevice; d->localAdapter = localDevice; } /*! + Returns a new object of this class that is in the \l CentralRole. + The \a remoteDevice refers to the device that a connection will be established to later. + * + The controller uses the local default Bluetooth adapter for the connection management. + \sa QLowEnergyController::CentralRole + */ +QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothDeviceInfo &remoteDevice, + QObject *parent) +{ + return new QLowEnergyController(remoteDevice, parent); +} + + +/*! + Returns a new object of this class that is in the \l PeripheralRole. + Typically, the next step is to call \l startAdvertising() on the returned object. + * + The controller uses the local default Bluetooth adapter for the connection management. + \sa QLowEnergyController::PeripheralRole + */ +QLowEnergyController *QLowEnergyController::createPeripheral(QObject *parent) +{ + return new QLowEnergyController(parent); +} + +QLowEnergyController::QLowEnergyController(QObject *parent) + : QObject(parent), d_ptr(new QLowEnergyControllerPrivate()) +{ + Q_D(QLowEnergyController); + d->q_ptr = this; + d->role = PeripheralRole; + d->localAdapter = QBluetoothLocalDevice().address(); +} + +/*! Destroys the QLowEnergyController instance. */ QLowEnergyController::~QLowEnergyController() @@ -492,6 +576,11 @@ QBluetoothAddress QLowEnergyController::localAddress() const /*! Returns the address of the remote Bluetooth Low Energy device. + + For a controller in the \l CentralRole, this value will always be the one passed in when + the controller object was created. For a controller in the \l PeripheralRole, this value + is the address of the currently connected client device. In particular, this address will + be invalid if the controller is not currently in the \l ConnectedState. */ QBluetoothAddress QLowEnergyController::remoteAddress() const { @@ -499,7 +588,8 @@ QBluetoothAddress QLowEnergyController::remoteAddress() const } /*! - Returns the name of the remote Bluetooth Low Energy device. + Returns the name of the remote Bluetooth Low Energy device, if the controller is in the + \l CentralRole. Otherwise the result is unspecified. \since 5.5 */ @@ -611,6 +701,10 @@ void QLowEnergyController::discoverServices() { Q_D(QLowEnergyController); + if (d->role != PeripheralRole) { + qCWarning(QT_BT) << "Cannot discover services in peripheral role"; + return; + } if (d->state != QLowEnergyController::ConnectedState) return; @@ -619,7 +713,8 @@ void QLowEnergyController::discoverServices() } /*! - Returns the list of services offered by the remote device. + Returns the list of services offered by the remote device, if the controller is in + the \l CentralRole. Otherwise, the result is unspecified. The list contains all primary and secondary services. @@ -672,6 +767,49 @@ QLowEnergyService *QLowEnergyController::createServiceObject( } /*! + Starts advertising the data given in \a advertisingData and \a scanResponseData, using + the parameters set in \a parameters. The controller has to be in the \l PeripheralRole. + \omit + If \a parameters indicates that the advertisement should be connectable, then this call + also starts listening for incoming client connections. + \endomit + + Providing \a scanResponseData is not required, as it is not applicable for certain + configurations of \c parameters. + + If this object is currently not in the \l UnconnectedState, nothing happens. + \note Advertising will stop automatically once a client connects to the local device. + */ +void QLowEnergyController::startAdvertising(const QLowEnergyAdvertisingParameters ¶meters, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) +{ + Q_D(QLowEnergyController); + if (role() != PeripheralRole) { + qCWarning(QT_BT) << "Cannot start advertising in central role" << state(); + return; + } + if (state() != UnconnectedState) { + qCWarning(QT_BT) << "Cannot start advertising in state" << state(); + return; + } + d->startAdvertising(parameters, advertisingData, scanResponseData); +} + +/*! + Stops advertising, if this object is currently in the advertising state. + */ +void QLowEnergyController::stopAdvertising() +{ + Q_D(QLowEnergyController); + if (state() != AdvertisingState) { + qCDebug(QT_BT) << "stopAdvertising called in state" << state(); + return; + } + d->stopAdvertising(); +} + +/*! Returns the last occurred error or \l NoError. */ QLowEnergyController::Error QLowEnergyController::error() const @@ -688,4 +826,12 @@ QString QLowEnergyController::errorString() const return d_ptr->errorString; } +/*! + Returns the role that this controller object is in. + */ +QLowEnergyController::Role QLowEnergyController::role() const +{ + return d_ptr->role; +} + QT_END_NAMESPACE |