summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-08-15 15:49:23 +0200
committerAlex Blasche <alexander.blasche@digia.com>2014-08-18 15:40:33 +0200
commit0a612418620a56df2b7962fa871a5d70c2fff2da (patch)
tree71edef4baed6907ec901764f507827181769ad80
parent03cc3adf4ef6c73d4d395d8cbaee45cf4711ef63 (diff)
Add class documentation for QLowEnergyService
This class is part of the new Bluetooth Low Energy feature in Qt 5.4 Change-Id: If10cac1ac1312cb63137c854a4456bf2d646f630 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@digia.com>
-rw-r--r--src/bluetooth/doc/images/peripheral-structure.pngbin0 -> 74765 bytes
-rw-r--r--src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp28
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp9
-rw-r--r--src/bluetooth/qlowenergyservice.cpp246
-rw-r--r--src/bluetooth/qlowenergyservice.h11
5 files changed, 262 insertions, 32 deletions
diff --git a/src/bluetooth/doc/images/peripheral-structure.png b/src/bluetooth/doc/images/peripheral-structure.png
new file mode 100644
index 00000000..a42c74da
--- /dev/null
+++ b/src/bluetooth/doc/images/peripheral-structure.png
Binary files differ
diff --git a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
index c0c0f61a..abcf9dbb 100644
--- a/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
+++ b/src/bluetooth/doc/snippets/doc_src_qtbluetooth.cpp
@@ -51,6 +51,10 @@
#include <QtBluetooth/QBluetoothTransferRequest>
#include <QtBluetooth/QBluetoothTransferReply>
+#include <QtBluetooth/QLowEnergyController>
+#include <QtBluetooth/QLowEnergyService>
+#include <QtBluetooth/QLowEnergyCharacteristic>
+
//! [namespace]
QT_USE_NAMESPACE
//! [namespace]
@@ -64,6 +68,7 @@ public:
void startDeviceDiscovery();
void startServiceDiscovery();
void objectPush();
+ void btleSharedData();
public slots:
void deviceDiscovered(const QBluetoothDeviceInfo &device);
@@ -166,6 +171,29 @@ void MyClass::transferFinished(QBluetoothTransferReply* /*reply*/)
{
}
+void MyClass::btleSharedData()
+{
+ QBluetoothAddress remoteDevice;
+
+//! [data_share_qlowenergyservice]
+ QLowEnergyService *first, *second;
+ QLowEnergyController control(remoteDevice);
+ control.connectToDevice();
+
+ // waiting for connection
+
+ first = control.createServiceObject(QBluetoothUuid::BatteryService);
+ second = control.createServiceObject(QBluetoothUuid::BatteryService);
+ Q_ASSERT(first->state() == QLowEnergyService::DiscoveryRequired);
+ Q_ASSERT(first->state() == second->state());
+
+ first->discoverDetails();
+
+ Q_ASSERT(first->state() == QLowEnergyService::DiscoveringServices);
+ Q_ASSERT(first->state() == second->state());
+//! [data_share_qlowenergyservice]
+}
+
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 43b96dc8..6dd2ef5e 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -523,12 +523,19 @@ QList<QBluetoothUuid> QLowEnergyController::services() const
a \a parent parameter as default owner.
This function returns a null pointer if no service with
- \a serviceUuid can be found on the remote device.
+ \a serviceUuid can be found on the remote device or the controller
+ is disconnected.
This function can return instances for secondary services
too. The include relationships between services can be expressed
via \l QLowEnergyService::includedServices().
+ If this function is called multiple times using the same service UUID,
+ the returned \l QLowEnergyService instances share their internal
+ data. Therefore if one of the instances initiates the discovery
+ of the service details, the other instances automatically
+ transition into the discovery state too.
+
\sa services()
*/
QLowEnergyService *QLowEnergyController::createServiceObject(
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 725c82e9..166d211a 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -51,18 +51,167 @@
QT_BEGIN_NAMESPACE
/*!
- \enum QBluetoothDeviceInfo::ServiceType
+ \class QLowEnergyService
+ \inmodule QtBluetooth
+ \brief The QLowEnergyService class represents an individual service
+ on a Bluetooth Low Energy Device.
+
+ \since 5.4
+
+ QLowEnergyService provides access to the details of Bluetooth Low Energy
+ services. The class facilitates the discovery and publification of
+ service details, permits reading and writing of the contained data
+ and notifies about data changes.
+
+ \section1 Service Structure
+
+ A Bluetooth Low Energy peripheral device can contain multiple services.
+ In turn each service may include further services. This class represents a
+ single service of the peripheral device and is created via
+ \l QLowEnergyController::createServiceObject(). The \l type() indicates
+ whether this service is a primary (top-level) service or whether the
+ service is part of another service. Each service may contain one or more
+ characteristics and each characteristic may contain descriptors. The
+ resulting structure may look like the following diagram:
+
+ \image peripheral-structure.png Structure of a generic peripheral
+
+ A characteristic is the principle information carrier. It has a
+ \l {QLowEnergyCharacteristic::value()}{value()} and \l properties()
+ describing the access permissions for the value. The general purpose
+ of the contained descriptor is to further define the nature of the
+ characteristic. For example, it might specify how the value is meant to be
+ interpreted or whether it can notify the value consumer about value
+ changes.
+
+ \section1 Service Interaction
+
+ Once a service object was created for the first time, its details are yet to
+ be discovered. This is indicated by its current \l state() being \l DiscoveryRequired.
+ It is only possible to retrieve the \l serviceUuid() and \l serviceName().
+
+ The discovery of its included services, characteristics and descriptors
+ is triggered when calling \l discoverDetails(). During the discovery the
+ \l state() transitions from \l DiscoveryRequired via \l DiscoveringServices
+ to its final \l ServiceDiscovered state. This transition is advertised via
+ the \l stateChanged() signal. Once the details are known, all of the contained
+ characteristics, descriptors and included services are known and can be read
+ or written.
+
+ The values of characteristics and descriptors can be retrieved via
+ \l QLowEnergyCharacteristic and \l QLowEnergyDescriptor, respectively.
+ However writing those attributes requires the service object. The
+ \l writeCharacteristic() function attempts to write a new value to the given
+ characteristic. If the write attempt is successful, the \l characteristicChanged()
+ signal is emitted. A failure to write triggers the \l CharacteristicWriteError.
+ Writing a descriptor follows the same pattern.
+
+ \section1 Service Data Sharing
+
+ Each QLowEnergyService instance shares its internal states and information
+ with other QLowEnergyService instance of the same service. If one instance
+ initiates the discovery of the service details, all remaining instances
+ automatically follow. Therefore the following snippet always works:
+
+ \snippet doc_src_qtbluetooth.cpp data_share_qlowenergyservice
+
+ Other operations such as calls to \l writeCharacteristic(),
+ writeDescriptor() or the invalidation of the service due to the
+ related \l QLowEnergyController disconnecting from the device are shared
+ the same way.
+
+ \sa QLowEnergyController, QLowEnergyCharacteristic, QLowEnergyDescriptor
+ */
+
+/*!
+ \enum QLowEnergyService::ServiceType
This enum describes the type of the service.
\value PrimaryService The service is a top-level/primary service.
- If this type flag is not set the service is considered
+ If this type flag is not set, the service is considered
to be a secondary service. Each service may be included
- by another service which is indicated by \l IncludedService.
+ by another service which is indicated by IncludedService.
\value IncludedService The service is included by another service.
*/
/*!
+ \enum QLowEnergyService::ServiceError
+
+ This enum describes all possible error conditions during the service's
+ existence. The \l error() function returns the last occurred error.
+
+ \value NoError No error has occurred.
+ \value ServiceNotValidError The service object is invalid and has lost
+ its connection to the peripheral device.
+ \value OperationError An operation was attempted while the service was not ready.
+ An example might be the attempt to write to
+ the service while it was not yet in the
+ \l ServiceDiscovered \l state().
+ \value CharacteristicWriteError An attempt to write a new value to a characteristic
+ failed. For example, it might be triggered when attempting
+ to write to a read-only characteristic.
+ \value DescriptorWriteError An attempt to write a new value to a descriptor
+ failed. For example, it might be triggered when attempting
+ to write to a read-only descriptor.
+ */
+
+/*!
+ \enum QLowEnergyService::ServiceState
+
+ This enum describes the \l state() of the service object.
+
+ \value InvalidService A service can become invalid when it looses
+ the connection to the underlying device. Even though
+ the connection may be lost it retains its last information.
+ An invalid service cannot become valid anymore even if
+ the connection to the device is re-established.
+ \value DiscoveryRequired The service details are yet to be discovered by calling \l discoverDetails().
+ The only reliable pieces of information are its
+ \l serviceUuid() and \l serviceName().
+ \value DiscoveringServices The service details are being discovered.
+ \value ServiceDiscovered The service details have been discovered.
+ */
+
+/*!
+ \fn void QLowEnergyService::stateChanged(QLowEnergyService::ServiceState newState)
+
+ This signal is emitted when the service's state changes. The \a newState can also be
+ retrieved via \l state().
+
+ \sa state()
+ */
+
+/*!
+ \fn void QLowEnergyService::error(QLowEnergyService::ServiceError newError)
+
+ This signal is emitted when an error occurrs. The \a newError parameter
+ describes the error that occurred.
+ */
+
+/*!
+ \fn void QLowEnergyService::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue);
+
+ This signal is emitted when the value of \a characteristic
+ is successfully changed to \a newValue. The change may have been caused
+ by calling \l writeCharacteristic() or otherwise triggering a change
+ notification on the peripheral device.
+
+ \sa writeCharacteristic()
+ */
+
+/*!
+ \fn void QLowEnergyService::descriptorChanged(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue)
+
+ This signal is emitted when the value of \a descriptor
+ is successfully changed to \a newValue. The change may have been caused
+ by calling \l writeDescriptor() or otherwise triggering a change
+ notification on the peripheral device.
+
+ \sa writeDescriptor()
+ */
+
+/*!
\internal
QLowEnergyControllerPrivate creates instances of this class.
@@ -87,22 +236,24 @@ QLowEnergyService::QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p,
this, SIGNAL(descriptorChanged(QLowEnergyDescriptor,QByteArray)));
}
-
+/*!
+ Destroys the \l QLowEnergyService instance.
+ */
QLowEnergyService::~QLowEnergyService()
{
}
/*!
- Returns the uuids of all services which are included by the
+ Returns the UUIDs of all services which are included by the
current service.
It is possible that an included service contains yet another service. Such
second level includes have to be obtained via their relevant first level
- QLowEnergyService instance. Technically it is possible that this can create
+ QLowEnergyService instance. Technically, this could create
a circular dependency.
- \l {QLowEnergyController::createServiceObject} should be used to obtain
- service instances for each of the uuids.
+ \l {QLowEnergyController::createServiceObject()} should be used to obtain
+ service instances for each of the UUIDs.
\sa createServiceObject()
*/
@@ -111,11 +262,39 @@ QList<QBluetoothUuid> QLowEnergyService::includedServices() const
return d_ptr->includedServices;
}
+/*!
+ Returns the current state of the service.
+
+ If the device's service was instantiated for the first time, the object's
+ state is \l DiscoveryRequired. The state of all service objects which
+ point to the same service on the peripheral device are always equal.
+ This is caused by the shared nature of the internal object data.
+ Therefore any service object instance created after
+ the first one has a state equal to already existing instances.
+
+
+ A service becomes invalid if the \l QLowEnergyController disconnects
+ from the remote device. An invalid service retains its internal state
+ at the time of the disconnect event. This implies that once the service
+ details are discovered they can even be retrieved from an invalid
+ service. This permits scenarios where the device connection is established,
+ the service details are retrieved and the device immediately disconnected
+ to permit the next device to connect to the peripheral device.
+
+ However, under normal circumstances the connection should remain to avoid
+ repeated discovery of services and their details. The discovery may take
+ a while and the client can subscribe to ongoing change notifications.
+
+ \sa stateChanged()
+ */
QLowEnergyService::ServiceState QLowEnergyService::state() const
{
return d_ptr->state;
}
+/*!
+ Returns the type of the service.
+ */
QLowEnergyService::ServiceTypes QLowEnergyService::type() const
{
return d_ptr->type;
@@ -140,10 +319,10 @@ QLowEnergyCharacteristic QLowEnergyService::characteristic(const QBluetoothUuid
/*!
Returns all characteristics associated with this \c QLowEnergyService instance.
- The returned list will be empty if this service instance is invalid,
- \l discoverDetails() was not yet called or there are no known characteristics.
+ The returned list is empty if this service instance's \l discoverDetails()
+ was not yet called or there are no known characteristics.
- \sa characteristic(), state(), discoverDetails
+ \sa characteristic(), state(), discoverDetails()
*/
QList<QLowEnergyCharacteristic> QLowEnergyService::characteristics() const
@@ -160,12 +339,21 @@ QList<QLowEnergyCharacteristic> QLowEnergyService::characteristics() const
}
+/*!
+ Returns the UUID of the service; otherwise a null UUID.
+ */
QBluetoothUuid QLowEnergyService::serviceUuid() const
{
return d_ptr->uuid;
}
+/*!
+ Returns the name of the service; otherwise an empty string.
+
+ The returned name can only be retrieved if \l serviceUuid()
+ is a \l {https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx}{well-known UUID}.
+*/
QString QLowEnergyService::serviceName() const
{
bool ok = false;
@@ -183,6 +371,13 @@ QString QLowEnergyService::serviceName() const
}
+/*!
+ Initiates the discovery of the services, characteristics
+ and descriptors contained by the service. The discovery process is indicated
+ via the \l stateChanged() signal.
+
+ \sa state()
+ */
void QLowEnergyService::discoverDetails()
{
Q_D(QLowEnergyService);
@@ -200,16 +395,19 @@ void QLowEnergyService::discoverDetails()
d->controller->discoverServiceDetails(d->uuid);
}
+/*!
+ Returns the last occurred error or \l NoError.
+ */
QLowEnergyService::ServiceError QLowEnergyService::error() const
{
return d_ptr->lastError;
}
-
/*!
- Returns \c true if \a characteristic belongs to this service; otherwise \c false.
+ Returns \c true if \a characteristic belongs to this service;
+ otherwise \c false.
- A characteristic belongs to a service if \l {QLowEnergyService::characteristics()}
+ A characteristic belongs to a service if \l characteristics()
contains the \a characteristic.
*/
bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic) const
@@ -226,12 +424,11 @@ bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic)
}
/*!
- Writes \a newValue as value for the \a characteristic. If the operation is successful
- the \l characteristicChanged() signal will be emitted. \a newValue must contain the
- hexadecimal representation of new value.
+ Writes \a newValue as value for the \a characteristic. If the operation is successful,
+ the \l characteristicChanged() signal is emitted.
- A characteristic can only be written if this service is in the \l ServiceDiscovered state
- and \a characteristic is writable.
+ A characteristic can only be written if this service is in the \l ServiceDiscovered state,
+ belongs to the service and is writable.
*/
void QLowEnergyService::writeCharacteristic(
const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue)
@@ -287,12 +484,11 @@ bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const
}
/*!
- Writes \a newValue as value for \a descriptor. If the operation is successful
- the \l descriptorChanged() signal is emitted. \a newValue must contain the
- hexadecimal representation of new value.
+ Writes \a newValue as value for \a descriptor. If the operation is successful,
+ the \l descriptorChanged() signal is emitted.
- A descriptor can only be written if this service is in the \l ServiceDiscovered state
- and \a characteristic is writable.
+ A descriptor can only be written if this service is in the \l ServiceDiscovered state,
+ belongs to the service and is writable.
*/
void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
const QByteArray &newValue)
@@ -317,6 +513,4 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
newValue);
}
-
-
QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h
index d7033224..00f5e46c 100644
--- a/src/bluetooth/qlowenergyservice.h
+++ b/src/bluetooth/qlowenergyservice.h
@@ -61,15 +61,16 @@ public:
enum ServiceError {
NoError = 0,
- ServiceNotValidError,
- OperationError,
- CharacteristicWriteError, // emitted when writeCharacteristic() failed
- DescriptorWriteError // emitted when writeDescriptor() failed
+ ServiceNotValidError, //TODO check correct usage
+ OperationError, //TODO check correct usage
+ CharacteristicWriteError,
+ DescriptorWriteError
};
enum ServiceState {
- InvalidService = 0, // when underlying controller disconnects
+ InvalidService = 0,
DiscoveryRequired, // we know start/end handle but nothing more
+ //TODO Rename DiscoveringServices -> DiscoveringDetails or DiscoveringService
DiscoveringServices,// discoverDetails() called and running
ServiceDiscovered, // all details have been synchronized
};