Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qlowenergycharacteristic.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
#
include
"qlowenergycharacteristic.h"
5
#
include
"qlowenergyserviceprivate_p.h"
6
#
include
<
QHash
>
7
8
QT_BEGIN_NAMESPACE
9
10
QT_IMPL_METATYPE_EXTERN(QLowEnergyCharacteristic)
11
12
/*!
13
\class QLowEnergyCharacteristic
14
\inmodule QtBluetooth
15
\brief The QLowEnergyCharacteristic class stores information about a Bluetooth
16
Low Energy service characteristic.
17
18
\since 5.4
19
20
QLowEnergyCharacteristic provides information about a Bluetooth Low Energy
21
service characteristic's name(), uuid(), value(), properties(), and
22
descriptors(). To obtain the characteristic's specification
23
and information, it is necessary to connect to the device using the
24
QLowEnergyService and QLowEnergyController classes.
25
26
The characteristic value may be written via the \l QLowEnergyService instance
27
that manages the service to which this characteristic belongs. The
28
\l {QLowEnergyService::writeCharacteristic()} function writes the new value.
29
The \l {QLowEnergyService::characteristicWritten()} signal is emitted upon success.
30
The value() of this object is automatically updated accordingly.
31
32
Characteristics may contain none, one or more descriptors. They can be individually
33
retrieved using the \l descriptor() function. The \l descriptors() function returns
34
all descriptors as a list. The general purpose of a descriptor is to add contextual
35
information to the characteristic. For example, the descriptor might provide
36
format or range information specifying how the characteristic's value is to be\
37
interpreted.
38
39
\sa QLowEnergyService, QLowEnergyDescriptor
40
*/
41
42
/*!
43
\enum QLowEnergyCharacteristic::PropertyType
44
45
This enum describes the properties of a characteristic.
46
47
\value Unknown The type is not known.
48
\value Broadcasting Allow for the broadcasting of Generic Attributes (GATT) characteristic values.
49
\value Read Allow the characteristic values to be read.
50
\value WriteNoResponse Allow characteristic values without responses to be written.
51
\value Write Allow for characteristic values to be written.
52
\value Notify Permits notification of characteristic values.
53
\value Indicate Permits indications of characteristic values.
54
\value WriteSigned Permits signed writes of the GATT characteristic values.
55
\value ExtendedProperty Additional characteristic properties are defined in the characteristic's
56
extended properties descriptor.
57
58
It is not recommended to set both Notify and Indicate properties on the same characteristic
59
as the underlying Bluetooth stack behaviors differ from platform to platform. Please see
60
\l QLowEnergyCharacteristic::clientCharacteristicConfiguration
61
62
63
\sa properties()
64
*/
65
66
struct
QLowEnergyCharacteristicPrivate
67
{
68
QLowEnergyHandle handle;
69
};
70
71
/*!
72
Construct a new QLowEnergyCharacteristic. A default-constructed instance of
73
this class is always invalid.
74
75
\sa isValid()
76
*/
77
QLowEnergyCharacteristic::QLowEnergyCharacteristic():
78
d_ptr(
nullptr
)
79
{
80
81
}
82
83
/*!
84
Construct a new QLowEnergyCharacteristic that is a copy of \a other.
85
86
The two copies continue to share the same underlying data which does not detach
87
upon write.
88
*/
89
QLowEnergyCharacteristic::QLowEnergyCharacteristic(
const
QLowEnergyCharacteristic &other):
90
d_ptr(other.d_ptr)
91
{
92
if
(other.data) {
93
data =
new
QLowEnergyCharacteristicPrivate();
94
data->handle = other.data->handle;
95
}
96
}
97
98
/*!
99
\internal
100
*/
101
QLowEnergyCharacteristic::QLowEnergyCharacteristic(
102
QSharedPointer<QLowEnergyServicePrivate> p, QLowEnergyHandle handle):
103
d_ptr(p)
104
{
105
data =
new
QLowEnergyCharacteristicPrivate();
106
data->handle = handle;
107
}
108
109
/*!
110
Destroys the QLowEnergyCharacteristic object.
111
*/
112
QLowEnergyCharacteristic::~QLowEnergyCharacteristic()
113
{
114
delete
data;
115
}
116
117
/*!
118
Returns the human-readable name of the characteristic.
119
120
The name is based on the characteristic's \l uuid() which must have been
121
standardized. The complete list of characteristic types can be found
122
under \l {https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx}{Bluetooth.org Characteristics}.
123
124
The returned string is empty if the \l uuid() is unknown.
125
126
\sa QBluetoothUuid::characteristicToString()
127
*/
128
QString QLowEnergyCharacteristic::name()
const
129
{
130
return
QBluetoothUuid::characteristicToString(
131
static_cast
<QBluetoothUuid::CharacteristicType>(uuid().toUInt16()));
132
}
133
134
/*!
135
Returns the UUID of the characteristic if \l isValid() returns \c true; otherwise a
136
\l {QUuid::isNull()}{null} UUID.
137
*/
138
QBluetoothUuid QLowEnergyCharacteristic::uuid()
const
139
{
140
if
(d_ptr.isNull() || !data
141
|| !d_ptr->characteristicList.contains(data->handle))
142
return
QBluetoothUuid();
143
144
return
d_ptr->characteristicList[data->handle].uuid;
145
}
146
147
/*!
148
Returns the properties of the characteristic.
149
150
The properties define the access permissions for the characteristic.
151
*/
152
QLowEnergyCharacteristic::PropertyTypes QLowEnergyCharacteristic::properties()
const
153
{
154
if
(d_ptr.isNull() || !data
155
|| !d_ptr->characteristicList.contains(data->handle))
156
return
QLowEnergyCharacteristic::Unknown;
157
158
return
d_ptr->characteristicList[data->handle].properties;
159
}
160
161
/*!
162
Returns the cached value of the characteristic.
163
164
If the characteristic's \l properties() permit writing of new values,
165
the value can be updated using \l QLowEnergyService::writeCharacteristic().
166
167
The cache is updated during the associated service's
168
\l {QLowEnergyService::discoverDetails()} {detail discovery}, a successful
169
\l {QLowEnergyService::readCharacteristic()}{read}/\l {QLowEnergyService::writeCharacteristic()}{write}
170
operation or when an update notification is received.
171
172
The returned \l QByteArray always remains empty if the characteristic does not
173
have the \l {QLowEnergyCharacteristic::Read}{read permission}. In such cases only
174
the \l QLowEnergyService::characteristicChanged() or
175
\l QLowEnergyService::characteristicWritten() may provice information about the
176
value of this characteristic.
177
*/
178
QByteArray QLowEnergyCharacteristic::value()
const
179
{
180
if
(d_ptr.isNull() || !data
181
|| !d_ptr->characteristicList.contains(data->handle))
182
return
QByteArray();
183
184
return
d_ptr->characteristicList[data->handle].value;
185
}
186
187
/*!
188
\internal
189
190
Returns the handle of the characteristic's value attribute;
191
or \c 0 if the handle cannot be accessed on the platform or
192
if the characteristic is invalid.
193
194
\note On \macos and iOS handles can differ from 0, but these
195
values have no special meaning outside of internal/private API.
196
*/
197
QLowEnergyHandle QLowEnergyCharacteristic::handle()
const
198
{
199
if
(d_ptr.isNull() || !data
200
|| !d_ptr->characteristicList.contains(data->handle))
201
return
0;
202
203
return
d_ptr->characteristicList[data->handle].valueHandle;
204
}
205
206
/*!
207
Makes a copy of \a other and assigns it to this \l QLowEnergyCharacteristic object.
208
The two copies continue to share the same service and controller details.
209
*/
210
QLowEnergyCharacteristic &QLowEnergyCharacteristic::operator=(
const
QLowEnergyCharacteristic &other)
211
{
212
d_ptr = other.d_ptr;
213
214
if
(!other.data) {
215
if
(data) {
216
delete
data;
217
data =
nullptr
;
218
}
219
}
else
{
220
if
(!data)
221
data =
new
QLowEnergyCharacteristicPrivate();
222
223
data->handle = other.data->handle;
224
}
225
return
*
this
;
226
}
227
228
/*!
229
\fn bool QLowEnergyCharacteristic::operator==(const QLowEnergyCharacteristic &a,
230
const QLowEnergyCharacteristic &b)
231
\brief Returns \c true if \a a is equal to \a b, otherwise \c false.
232
233
Two \l QLowEnergyCharacteristic instances are considered to be equal if they refer to
234
the same characteristic on the same remote Bluetooth Low Energy device or both instances
235
have been default-constructed.
236
*/
237
238
/*!
239
\fn bool QLowEnergyCharacteristic::operator!=(const QLowEnergyCharacteristic &a,
240
const QLowEnergyCharacteristic &b)
241
\brief Returns \c true if \a a and \a b are not equal; otherwise \c
242
false.
243
244
Two QLowEnergyCharcteristic instances are considered to be equal if they refer to
245
the same characteristic on the same remote Bluetooth Low Energy device or both instances
246
have been default-constructed.
247
*/
248
249
/*!
250
\brief Returns \c true if \a a is equal to \a b; otherwise \c false.
251
\internal
252
253
Two \l QLowEnergyCharacteristic instances are considered to be equal if they refer to
254
the same characteristic on the same remote Bluetooth Low Energy device or both instances
255
have been default-constructed.
256
*/
257
bool
QLowEnergyCharacteristic::equals(
const
QLowEnergyCharacteristic &a,
258
const
QLowEnergyCharacteristic &b)
259
{
260
if
(a.d_ptr != b.d_ptr)
261
return
false
;
262
263
if
((a.data && !b.data) || (!a.data && b.data))
264
return
false
;
265
266
if
(!a.data)
267
return
true
;
268
269
if
(a.data->handle != b.data->handle)
270
return
false
;
271
272
return
true
;
273
}
274
275
/*!
276
Returns \c true if the QLowEnergyCharacteristic object is valid, otherwise returns \c false.
277
278
An invalid characteristic object is not associated with any service (default-constructed)
279
or the associated service is no longer valid due to a disconnect from
280
the underlying Bluetooth Low Energy device, for example. Once the object is invalid
281
it cannot become valid anymore.
282
283
\note If a \l QLowEnergyCharacteristic instance turns invalid due to a disconnect
284
from the underlying device, the information encapsulated by the current
285
instance remains as it was at the time of the disconnect. Therefore it can be
286
retrieved after the disconnect event.
287
*/
288
bool
QLowEnergyCharacteristic::isValid()
const
289
{
290
if
(d_ptr.isNull() || !data)
291
return
false
;
292
293
if
(d_ptr->state == QLowEnergyService::InvalidService)
294
return
false
;
295
296
return
true
;
297
}
298
299
/*!
300
\internal
301
302
Returns the handle of the characteristic or
303
\c 0 if the handle cannot be accessed on the platform or if the
304
characteristic is invalid.
305
306
\note On \macos and iOS handles can differ from 0, but these
307
values have no special meaning outside of internal/private API.
308
309
\sa isValid()
310
*/
311
QLowEnergyHandle QLowEnergyCharacteristic::attributeHandle()
const
312
{
313
if
(d_ptr.isNull() || !data)
314
return
0;
315
316
return
data->handle;
317
}
318
319
/*!
320
Returns the descriptor for \a uuid or an invalid \l QLowEnergyDescriptor instance.
321
322
\sa descriptors()
323
*/
324
QLowEnergyDescriptor QLowEnergyCharacteristic::descriptor(
const
QBluetoothUuid &uuid)
const
325
{
326
if
(d_ptr.isNull() || !data)
327
return
QLowEnergyDescriptor();
328
329
CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constFind(data->handle);
330
if
(charIt != d_ptr->characteristicList.constEnd()) {
331
const
QLowEnergyServicePrivate::CharData &charDetails = charIt.value();
332
333
DescriptorDataMap::const_iterator descIt = charDetails.descriptorList.constBegin();
334
for
( ; descIt != charDetails.descriptorList.constEnd(); ++descIt) {
335
const
QLowEnergyHandle descHandle = descIt.key();
336
const
QLowEnergyServicePrivate::DescData &descDetails = descIt.value();
337
338
if
(descDetails.uuid == uuid)
339
return
QLowEnergyDescriptor(d_ptr, data->handle, descHandle);
340
}
341
}
342
343
return
QLowEnergyDescriptor();
344
}
345
346
/*!
347
Returns the Client Characteristic Configuration Descriptor or an
348
invalid \l QLowEnergyDescriptor instance if no
349
Client Characteristic Configuration Descriptor exists.
350
351
BTLE characteristics can support notifications and/or indications.
352
In both cases, the peripheral will inform the central on
353
each change of the characteristic's value. In the BTLE
354
attribute protocol, notification messages are not confirmed
355
by the central, while indications are confirmed.
356
Notifications are considered faster, but unreliable, while
357
indications are slower and more reliable.
358
359
If a characteristic supports notification or indication,
360
these can be enabled by writing special bit patterns to the
361
Client Characteristic Configuration Descriptor.
362
For convenience, these bit patterns are provided as
363
\l QLowEnergyCharacteristic::CCCDDisable,
364
\l QLowEnergyCharacteristic::CCCDEnableNotification, and
365
\l QLowEnergyCharacteristic::CCCDEnableIndication.
366
367
Enabling e.g. notification for a characteristic named
368
\c mycharacteristic in a service called \c myservice
369
could be done using the following code.
370
\code
371
auto cccd = mycharacteristic.clientCharacteristicConfiguration();
372
if (!cccd.isValid()) {
373
// your error handling
374
return error;
375
}
376
myservice->writeDescriptor(cccd, QLowEnergyCharacteristic::CCCDEnableNotification);
377
\endcode
378
379
\note
380
Calling \c characteristic.clientCharacteristicConfiguration() is equivalent to calling
381
\c characteristic.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration).
382
383
\note
384
It is not recommended to use both notifications and indications on the same characteristic.
385
This applies to both server-side when setting up the characteristics, as well as client-side
386
when enabling them. The bluetooth stack behavior differs from platform to platform and the
387
cross-platform behavior will likely be inconsistent. As an example a Bluez Linux client might
388
unconditionally try to enable both mechanisms if both are supported, whereas a macOS client
389
might unconditionally enable just the notifications. If both are needed consider creating two
390
separate characteristics.
391
392
\since 6.2
393
\sa descriptor()
394
*/
395
QLowEnergyDescriptor QLowEnergyCharacteristic::clientCharacteristicConfiguration()
const
396
{
397
return
descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);
398
}
399
400
/*!
401
Returns the list of descriptors belonging to this characteristic; otherwise
402
an empty list.
403
404
\sa descriptor()
405
*/
406
QList<QLowEnergyDescriptor> QLowEnergyCharacteristic::descriptors()
const
407
{
408
QList<QLowEnergyDescriptor> result;
409
410
if
(d_ptr.isNull() || !data
411
|| !d_ptr->characteristicList.contains(data->handle))
412
return
result;
413
414
QList<QLowEnergyHandle> descriptorKeys = d_ptr->characteristicList[data->handle].
415
descriptorList.keys();
416
417
std::sort(descriptorKeys.begin(), descriptorKeys.end());
418
419
for
(
const
QLowEnergyHandle descHandle : std::as_const(descriptorKeys)) {
420
QLowEnergyDescriptor descriptor(d_ptr, data->handle, descHandle);
421
result.append(descriptor);
422
}
423
424
return
result;
425
}
426
427
/*!
428
\variable QLowEnergyCharacteristic::CCCDDisable
429
\since 6.2
430
431
Bit pattern to write into Client Characteristic Configuration Descriptor
432
to disable both notification and indication.
433
434
\sa QLowEnergyCharacteristic::clientCharacteristicConfiguration
435
*/
436
/*!
437
\variable QLowEnergyCharacteristic::CCCDEnableNotification
438
\since 6.2
439
440
Bit pattern to write into Client Characteristic Configuration Descriptor
441
to enable notification.
442
443
\sa QLowEnergyCharacteristic::clientCharacteristicConfiguration
444
*/
445
/*!
446
\variable QLowEnergyCharacteristic::CCCDEnableIndication
447
\since 6.2
448
449
Bit pattern to write into Client Characteristic Configuration Descriptor
450
to enable indication.
451
452
\sa QLowEnergyCharacteristic::clientCharacteristicConfiguration
453
*/
454
const
QByteArray QLowEnergyCharacteristic::CCCDDisable = QByteArray::fromHex(
"0000"
);
455
const
QByteArray QLowEnergyCharacteristic::CCCDEnableNotification = QByteArray::fromHex(
"0100"
);
456
const
QByteArray QLowEnergyCharacteristic::CCCDEnableIndication = QByteArray::fromHex(
"0200"
);
457
458
QT_END_NAMESPACE
qtconnectivity
src
bluetooth
qlowenergycharacteristic.cpp
Generated on
for Qt by
1.18.0