Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
bluetooth-le-overview.qdoc
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5\ingroup technology-apis
6\title Bluetooth Low Energy Overview
7\page qtbluetooth-le-overview.html
8\brief The Qt Bluetooth Low Energy API enables communication between Bluetooth
9Low Energy devices.
10
11\tableofcontents
12
13 The Qt Bluetooth Low Energy API supports the peripheral/server and central/client roles.
14 It is supported on all major Qt platforms. The only exception is the missing peripheral role
15 support on Windows.
16
17 \section1 What Is Bluetooth Low Energy
18
19 Bluetooth Low Energy, also known as Bluetooth Smart, is a wireless computer
20 network technology, which was officially introduced in 2011. It works on the same
21 2.4 GHz frequency as ”classic” Bluetooth. The main difference is, as stated by its technology name,
22 low energy consumption. It provides an opportunity for Bluetooth Low Energy devices to
23 operate for months, even years, on coin-cell batteries. The technology was introduced by
24 \l {https://www.bluetooth.org/en-us/specification/adopted-specifications}{Bluetooth v4.0}.
25 Devices which support this technology are called Bluetooth Smart Ready Devices.
26 The key features of the technology are:
27
28 \list
29 \li Ultra-low peak, average and idle mode power consumption
30 \li Ability to run for years on standard, coin-cell batteries
31 \li Low cost
32 \li Multi-vendor interoperability
33 \li Enhanced range
34 \endlist
35
36 Bluetooth Low Energy uses a client-server architecture. The server (also
37 known as peripheral) offers services such as temperature or heart rate
38 and advertises them. The client (known as central
39 device) connects to the server and reads the values advertised by the server.
40 An example might be an apartment with Bluetooth Smart Ready sensors such
41 as a thermostat, humidity or pressure sensor. Those sensors are peripheral
42 devices advertising the environment values of the apartment. At the same time
43 a mobile phone or computer might connect to those sensors, retrieve their
44 values and present them as part of a larger environment control application
45 to the user.
46
47 \section1 Basic Service Structure
48
49 Bluetooth Low Energy is based on two protocols: ATT (Attribute Protocol)
50 and GATT (Generic Attribute Profile). They specify the communication layers
51 used by every Bluetooth Smart Ready device.
52
53 \section2 ATT Protocol
54
55 The basic building block of ATT is an \e attribute. Each attribute consists of
56 three elements:
57
58 \list
59 \li a value - the payload or desirable piece of information
60 \li a UUID - the type of attribute (used by GATT)
61 \li a 16-bit handle - a unique identifier for the attribute
62 \endlist
63
64 The server stores the attributes and the client uses the ATT protocol to
65 read and write values on the server.
66
67 \section2 GATT Profile
68
69 GATT defines grouping for a set of attributes by applying a meaning to predefined
70 UUIDs. The table below shows an example service exposing a heart rate
71 on a particular day. The actual values are stored inside the two characteristics:
72
73 \table
74 \header
75 \li Handle
76 \li UUID
77 \li Value
78 \li Description
79 \row
80 \li 0x0001
81 \li 0x2800
82 \li UUID 0x180D
83 \li Begin Heart Rate service
84 \row
85 \li 0x0002
86 \li 0x2803
87 \li UUID 0x2A37, Value handle: 0x0003
88 \li Characteristic of type \e {Heart Rate Measurement (HRM)}
89 \row
90 \li 0x0003
91 \li 0x2A37
92 \li 65 bpm
93 \li Heart rate value
94 \row
95 \li 0x0004
96 \li 0x2803
97 \li UUID 0x2A08, Value handle: 0x0005
98 \li Characteristic of type Date Time
99 \row
100 \li 0x0005
101 \li 0x2A08
102 \li 18/08/2014 11:00
103 \li Date and Time of the measurement
104 \row
105 \li 0x0006
106 \li 0x2800
107 \li UUID xxxxxx
108 \li Begin next service
109 \row
110 \li ...
111 \li ...
112 \li ...
113 \li ...
114 \endtable
115
116 GATT specifies that the above used UUID \c 0x2800 marks the begin of a service definition.
117 Every attribute following \c 0x2800 is part of the service until the next \c 0x2800 or the
118 end is encountered. In similar ways the well known UUID \c 0x2803 states that a characteristic
119 is to be found and each of the characteristics has a type defining the nature of the value.
120 The example above uses the UUIDs \c 0x2A08 (Date Time) and \c 0x2A37 (Heart Rate Measurement).
121 Each of the above UUIDs is defined by the \l {https://bluetooth.org}{Bluetooth Special Interest Group}.
122 and can be found in the
123 \l{https://www.bluetooth.com/specifications/assigned-numbers}{GATT specifications}. While it
124 is advisable to use pre-defined UUIDs where available it is entirely possible to use new and not
125 yet used UUIDs for characteristic and service types.
126
127 In general, each service may consist of one or more characteristics. A characteristic
128 contains data and can be further described by descriptors, which provide additional
129 information or means of manipulating the characteristic. All services, characteristics and
130 descriptors are recognized by their 128-bit UUID. Finally, it is possible to include
131 services inside of services (see picture below).
132
133 \image peripheral-structure.png
134
135 \section1 Using Qt Bluetooth Low Energy API
136
137 This section describes how to use the Bluetooth Low Energy API provided by Qt.
138 On the client side, the API permits creating connections to peripheral devices, discovering
139 their services, as well as reading and writing data stored on the device.
140 On the server side, it allows to set up services, advertise them, and get notified when the
141 client writes characteristics.
142 The example code below is taken from the \l {heartrate-game}{Heart Rate Game} and
143 \l {heartrate-server}{Heart Rate Server} examples.
144
145 \section2 Establishing a Connection
146
147 To be able to read and write the characteristics of the Bluetooth Low Energy peripheral device,
148 it is necessary to find and connect the device. This requires the peripheral device to advertise
149 its presence and services. We start the device discovery with the help of the
150 \l QBluetoothDeviceDiscoveryAgent class. We connect to its \l {QBluetoothDeviceDiscoveryAgent::deviceDiscovered()}
151 signal and start the search with \l {QBluetoothDeviceDiscoveryAgent::start()}{start()}:
152
153 \snippet heartrate-game/devicefinder.cpp devicediscovery-1
154 \snippet heartrate-game/devicefinder.cpp devicediscovery-2
155
156 Since we are only interested in Low Energy devices we filter the device type within the
157 receiving slot. The device type can be ascertained using the \l QBluetoothDeviceInfo::coreConfigurations()
158 flag. The \l {QBluetoothDeviceDiscoveryAgent::}{deviceDiscovered()} signal
159 may be emitted multiple times for the same device as more details are
160 discovered. Here we match these device discoveries so that the user only
161 sees the individual devices:
162
163 \snippet heartrate-game/devicefinder.cpp devicediscovery-3
164 \snippet heartrate-game/devicefinder.cpp devicediscovery-4
165
166 Once the address of the peripheral device is known we use the \l QLowEnergyController class.
167 This class is the entry point for all Bluetooth Low Energy development. The constructor of the class
168 accepts the remote device's \l QBluetoothAddress. Finally we set up the customary slots and
169 directly connect to the device using
170 \l {QLowEnergyController::connectToDevice()}{connectToDevice()}:
171
172 \snippet heartrate-game/devicehandler.cpp Connect-Signals-1
173 \snippet heartrate-game/devicehandler.cpp Connect-Signals-2
174
175 \section2 Service Search
176
177 The above code snippet shows how the application initiates the service discovery once the
178 connection has been established.
179
180 The \c serviceDiscovered() slot below is triggered as a result of the
181 \l {QLowEnergyController::serviceDiscovered()} signal and provides an intermittent progress report.
182 Since we are talking about the heart listener app which monitors HeartRate devices in the vicinity
183 we ignore any service that is not of type \l QBluetoothUuid::ServiceClassUuid::HeartRate.
184
185 \snippet heartrate-game/devicehandler.cpp Filter HeartRate service 1
186
187 Eventually the \l {QLowEnergyController::discoveryFinished()} signal is emitted to indicate
188 the successful completion of the service discovery. Provided a HeartRate service was found,
189 a \l QLowEnergyService instance is created to represent the service. The returned service object
190 provides the required signals for update notifications and the discovery of service details
191 is triggered using \l QLowEnergyService::discoverDetails():
192
193 \snippet heartrate-game/devicehandler.cpp Filter HeartRate service 2
194
195 During the detail search the service's \l {QLowEnergyService::state()}{state()} transitions
196 from \l {QLowEnergyService::RemoteService}{RemoteService} to
197 \l {QLowEnergyService::RemoteServiceDiscovering}{RemoteServiceDiscovering} and eventually ends with
198 \l {QLowEnergyService::RemoteServiceDiscovered}{RemoteServiceDiscovered}:
199
200 \snippet heartrate-game/devicehandler.cpp Find HRM characteristic
201
202 \section2 Interaction with the Peripheral Device
203
204 In the code example above, the desired characteristic is of type
205 \l {QBluetoothUuid::CharacteristicType::HeartRateMeasurement}{HeartRateMeasurement}. Since the application measures
206 the heart rate changes, it must enable change notifications for the characteristic.
207 Note that not all characteristics provide change notifications. Since the HeartRate characteristic
208 has been standardized it is possible to assume that notifications can be received. Ultimately
209 \l QLowEnergyCharacteristic::properties() must have the \l {QLowEnergyCharacteristic::Notify} flag
210 set and a descriptor of type \l {QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration} must exist to confirm
211 the availability of an appropriate notification.
212
213 Finally, we process the value of the HeartRate characteristic, as per Bluetooth Low Energy standard:
214
215 \snippet heartrate-game/devicehandler.cpp Reading value
216
217 In general a characteristic value is a series of bytes. The precise interpretation of
218 those bytes depends on the characteristic type and value structure.
219 A significant number has been standardized by the
220 \l {https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx}{Bluetooth SIG} whereas others
221 may follow a custom protocol. The above code snippet demonstrates how to the read the standardized
222 HeartRate value.
223
224 \section2 Advertising Services
225
226 If we are implementing a GATT server application on a peripheral device, we need to define the
227 services we want to offer to central devices and advertise them:
228
229 \snippet heartrate-server/main.cpp Advertising Data
230 \snippet heartrate-server/main.cpp Start Advertising
231
232 Now potential clients can connect to our device, discover the provided service and
233 register themselves to get notified of changes to the characteristic value.
234 This part of the API was already covered by the above sections.
235
236 \section2 Implementing a Service on the Peripheral Device
237
238 The first step is to define the service, its characteristics and descriptors. This is achieved
239 using the \l QLowEnergyServiceData, \l QLowEnergyCharacteristicData and
240 \l QLowEnergyDescriptorData classes. These classes act as containers or building blocks for the
241 essential information that comprises the to-be-defined Bluetooth Low Energy service.
242 The code snippet below defines a simple HeartRate service which publishes
243 the measured beats per minute. An example where such a service could be used is a wrist watch.
244
245 \snippet heartrate-server/main.cpp Service Data
246
247 The resulting \c serviceData object can be published as described in the
248 \l {Advertising Services} section above. Despite the partial information overlap between the
249 information wrapped by \l QLowEnergyServiceData and \l QLowEnergyAdvertisingData the two classes
250 serve two very different tasks. The advertising data is published to nearby devices and often
251 limited in scope due to its size restriction of 29 bytes. Therefore they are not always 100%
252 complete. By comparison the service data contained inside of \l QLowEnergyServiceData provides
253 the complete set of service data and only becomes visible to the connecting client when a
254 connection with an active service discovery has been performed.
255
256 The next section demonstrates how the service can update the heart rate value. Depending on the
257 nature of the service it may have to comply with the official service definition
258 as defined on \l {https://www.bluetooth.org}. Other services may be completely custom. The
259 heart rate service was adopted and its specification can be found under
260 \l {https://www.bluetooth.com/specifications/adopted-specifications}.
261
262 \snippet heartrate-server/main.cpp Provide Heartbeat
263
264 In general characteristic and descriptor value updates on the peripheral device use the same
265 methods as connecting Bluetooth Low Energy devices.
266
267 \note To use \l{Qt Bluetooth} (in both central and peripheral roles) on iOS, you have to provide
268 an Info.plist file containing the usage description. According to the CoreBluetooth's
269 documentation: \e {Your app will crash if its Info.plist doesn’t include usage description
270 keys for the types of data it needs to access. To access Core Bluetooth APIs on apps linked
271 on or after iOS 13, include the NSBluetoothAlwaysUsageDescription key. In iOS 12 and earlier,
272 include NSBluetoothPeripheralUsageDescription to access Bluetooth peripheral data.}
273*/