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
qlowenergycontroller.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
10
11#include <QtBluetooth/QBluetoothLocalDevice>
12#include <QtCore/QLoggingCategory>
13
14
15#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
19#elif defined(QT_ANDROID_BLUETOOTH)
22#elif defined(QT_WINRT_BLUETOOTH)
23#include "qtbluetoothglobal_p.h"
25#elif defined(Q_OS_DARWIN)
27#else
29#endif
30
31#include <algorithm>
32
34
37 QLowEnergyController__ControllerState)
39 QLowEnergyController__RemoteAddressType)
41
43#if defined(QT_ANDROID_BLUETOOTH)
44Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)
45#endif
46
295{
296 static bool initDone = false;
297 if (!initDone) {
298 qRegisterMetaType<QLowEnergyController::ControllerState>();
299 qRegisterMetaType<QLowEnergyController::Error>();
300 qRegisterMetaType<QLowEnergyConnectionParameters>();
301 qRegisterMetaType<QLowEnergyCharacteristic>();
302 qRegisterMetaType<QLowEnergyDescriptor>();
303 initDone = true;
304 }
305}
306
309 const QBluetoothAddress& localDevice = QBluetoothAddress{})
310{
311#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
312 // Central role
313 // The minimum Bluez DBus version for central role is 5.42, otherwise we
314 // fall back to kernel ATT backend. Application can also force the choice
315 // with an environment variable (see bluetoothdVersion())
316 //
317 // Peripheral role
318 // The DBus peripheral backend is the default, and for that we check the presence of
319 // the required DBus APIs and bluez version. The application may opt-out of the DBus
320 // peripheral role by setting the environment variable. The fall-back is the kernel ATT
321 // backend
322 //
323 // ### Qt 7 consider removing the non-dbus bluez (kernel ATT) support
324
325 QString adapterPathWithPeripheralSupport;
327 && bluetoothdVersion() >= QVersionNumber(5, 56)
328 && !qEnvironmentVariableIsSet("QT_BLUETOOTH_USE_KERNEL_PERIPHERAL")) {
329 adapterPathWithPeripheralSupport = adapterWithDBusPeripheralInterface(localDevice);
330 }
331
333 && bluetoothdVersion() >= QVersionNumber(5, 42)) {
334 qCDebug(QT_BT) << "Using BlueZ LE DBus API for central";
336 } else if (!adapterPathWithPeripheralSupport.isEmpty()) {
337 qCDebug(QT_BT) << "Using BlueZ LE DBus API for peripheral";
338 return new QLowEnergyControllerPrivateBluezDBus(adapterPathWithPeripheralSupport);
339 } else {
340 qCDebug(QT_BT) << "Using BlueZ kernel ATT interface for"
341 << (role == QLowEnergyController::CentralRole ? "central" : "peripheral");
343 }
344#elif defined(QT_ANDROID_BLUETOOTH)
345 Q_UNUSED(role);
346 Q_UNUSED(localDevice);
348#elif defined(QT_WINRT_BLUETOOTH)
349 Q_UNUSED(role);
350 Q_UNUSED(localDevice);
352#elif defined(Q_OS_DARWIN)
353 Q_UNUSED(role);
354 Q_UNUSED(localDevice);
356#else
357 Q_UNUSED(role);
358 Q_UNUSED(localDevice);
360#endif
361}
362
378QLowEnergyController::QLowEnergyController(
379 const QBluetoothDeviceInfo &remoteDevice,
380 const QBluetoothAddress &localDevice,
381 QObject *parent)
382 : QObject(parent)
383{
384 d_ptr = privateController(CentralRole);
385
387 d->q_ptr = this;
388 d->role = CentralRole;
389 d->deviceUuid = remoteDevice.deviceUuid();
390 d->remoteDevice = remoteDevice.address();
391
392 if (localDevice.isNull())
393 d->localAdapter = QBluetoothLocalDevice().address();
394 else
395 d->localAdapter = localDevice;
396
398 d->remoteName = remoteDevice.name();
399 d->init();
400}
401
413 QObject *parent)
414{
415 return new QLowEnergyController(remoteDevice, QBluetoothAddress(), parent);
416}
417
435 const QBluetoothAddress &localDevice,
436 QObject *parent)
437{
438 return new QLowEnergyController(remoteDevice, localDevice, parent);
439}
440
441
457
476 QObject *parent)
477{
478 return new QLowEnergyController(localDevice, parent);
479}
480
481QLowEnergyController::QLowEnergyController(const QBluetoothAddress &localDevice, QObject *parent)
482 : QObject(parent)
483{
484 d_ptr = privateController(PeripheralRole, localDevice);
485
487 d->q_ptr = this;
488 d->role = PeripheralRole;
489
490 if (localDevice.isNull())
491 d->localAdapter = QBluetoothLocalDevice().address();
492 else
493 d->localAdapter = localDevice;
494
495 d->init();
496}
497
502{
503 disconnectFromDevice(); //in case we were connected
504 delete d_ptr;
505}
506
521
534
551
559{
560 return d_ptr->remoteName;
561}
562
572
583
606
622{
624
625 if (role() != CentralRole) {
626 qCWarning(QT_BT) << "Connection can only be established while in central role";
627 return;
628 }
629
630 if (!d->isValidLocalAdapter()) {
631 qCWarning(QT_BT) << "connectToDevice() LE controller has invalid adapter";
633 return;
634 }
635
637 return;
638
639 d->connectToDevice();
640}
641
660{
662
664 return;
665
666 d->invalidateServices();
667 d->disconnectFromDevice();
668}
669
687{
689
690 if (d->role != CentralRole) {
691 qCWarning(QT_BT) << "Cannot discover services in peripheral role";
692 return;
693 }
695 return;
696
698 d->discoverServices();
699}
700
709QList<QBluetoothUuid> QLowEnergyController::services() const
710{
711 return d_ptr->serviceList.keys();
712}
713
739 const QBluetoothUuid &serviceUuid, QObject *parent)
740{
742
743 QLowEnergyService *service = nullptr;
744
745 ServiceDataMap::const_iterator it = d->serviceList.constFind(serviceUuid);
746 if (it != d->serviceList.constEnd()) {
747 const QSharedPointer<QLowEnergyServicePrivate> &serviceData = it.value();
748
749 service = new QLowEnergyService(serviceData, parent);
750 }
751
752 return service;
753}
754
777 const QLowEnergyAdvertisingData &advertisingData,
778 const QLowEnergyAdvertisingData &scanResponseData)
779{
781 if (role() != PeripheralRole) {
782 qCWarning(QT_BT) << "Cannot start advertising in central role" << state();
783 return;
784 }
785 if (state() != UnconnectedState) {
786 qCWarning(QT_BT) << "Cannot start advertising in state" << state();
787 return;
788 }
789 d->startAdvertising(parameters, advertisingData, scanResponseData);
790}
791
802{
804 if (state() != AdvertisingState) {
805 qCDebug(QT_BT) << "stopAdvertising called in state" << state();
806 return;
807 }
808 d->stopAdvertising();
809}
810
827 QObject *parent)
828{
829 if (role() != PeripheralRole) {
830 qCWarning(QT_BT) << "Services can only be added in the peripheral role";
831 return nullptr;
832 }
833 if (state() != UnconnectedState) {
834 qCWarning(QT_BT) << "Services can only be added in unconnected state";
835 return nullptr;
836 }
837 if (!service.isValid()) {
838 qCWarning(QT_BT) << "Not adding invalid service";
839 return nullptr;
840 }
841
842#if defined(QT_ANDROID_BLUETOOTH)
844 qCWarning(QT_BT_ANDROID) << "addService() failed due to missing permissions";
845 return nullptr;
846 }
847#endif
848
850 QLowEnergyService *newService = d->addServiceHelper(service);
851 if (newService)
852 newService->setParent(parent);
853
854 return newService;
855}
856
857
880{
881 switch (state()) {
882 case ConnectedState:
883 case DiscoveredState:
884 case DiscoveringState:
885 d_ptr->requestConnectionUpdate(parameters);
886 break;
887 default:
888 qCWarning(QT_BT) << "Connection update request only possible in connected state";
889 }
890}
891
899
905{
906 return d_ptr->errorString;
907}
908
918{
919 return d_ptr->role;
920}
921
945{
946 return d_ptr->mtu();
947}
948
964{
965 if (role() != CentralRole) {
966 qCWarning(QT_BT, "Invalid role (peripheral), cannot read RSSI");
967 return d_ptr->setError(RssiReadError); // This also emits.
968 }
969
970 switch (state()) {
971 case UnconnectedState:
972 case ConnectingState:
973 case ClosingState:
974 qCWarning(QT_BT, "Cannot read RSSI while not in 'Connected' state, connect first");
975 return d_ptr->setError(RssiReadError); // Will emit.
976 default:
977 d_ptr->readRssi();
978 }
979}
980
982
983#include "moc_qlowenergycontroller.cpp"
QT_BEGIN_NAMESPACE bool ensureAndroidPermission(QBluetoothPermission::CommunicationModes modes)
QString adapterWithDBusPeripheralInterface(const QBluetoothAddress &localAddress)
QVersionNumber bluetoothdVersion()
\inmodule QtBluetooth
\inmodule QtBluetooth
QBluetoothAddress address() const
Returns the address of the device.
QBluetoothUuid deviceUuid() const
Returns a unique identifier for a Bluetooth device without an address.
QString name() const
Returns the name assigned to the device.
\inmodule QtBluetooth
QBluetoothAddress address() const
Returns the MAC address of this Bluetooth device.
\inmodule QtBluetooth
The QLowEnergyAdvertisingData class represents the data to be broadcast during Bluetooth Low Energy a...
The QLowEnergyAdvertisingParameters class represents the parameters used for Bluetooth Low Energy adv...
The QLowEnergyConnectionParameters class is used when requesting or reporting an update of the parame...
QLowEnergyController::RemoteAddressType addressType
virtual int mtu() const =0
QLowEnergyController::Error error
void setError(QLowEnergyController::Error newError)
virtual void requestConnectionUpdate(const QLowEnergyConnectionParameters &params)=0
QLowEnergyController::ControllerState state
\inmodule QtBluetooth
RemoteAddressType
Indicates what type of Bluetooth address the remote device uses.
void connectToDevice()
Connects to the remote Bluetooth Low Energy device.
ControllerState
Indicates the state of the controller object.
static QLowEnergyController * createCentral(const QBluetoothDeviceInfo &remoteDevice, QObject *parent=nullptr)
Returns a new object of this class that is in the \l CentralRole and has the parent object parent.
Role
Indicates the role of the controller object.
Role role() const
Returns the role that this controller object is in.
void disconnectFromDevice()
Disconnects from the remote device.
~QLowEnergyController()
Destroys the QLowEnergyController instance.
QBluetoothAddress localAddress() const
Returns the address of the local Bluetooth adapter being used for the communication.
QString errorString() const
Returns a textual representation of the last occurred error.
void requestConnectionUpdate(const QLowEnergyConnectionParameters &parameters)
Requests the controller to update the connection according to parameters.
void stopAdvertising()
Stops advertising, if this object is currently in the advertising state.
QString remoteName() const
Returns the name of the remote Bluetooth Low Energy device, if the controller is in the \l CentralRol...
QLowEnergyService * addService(const QLowEnergyServiceData &service, QObject *parent=nullptr)
Constructs and returns a \l QLowEnergyService object with parent from service.
RemoteAddressType remoteAddressType() const
Returns the type of \l remoteAddress().
Error error() const
Returns the last occurred error or \l NoError.
static QLowEnergyController * createPeripheral(const QBluetoothAddress &localDevice, QObject *parent=nullptr)
Returns a new object of this class that is in the \l PeripheralRole and has the parent object parent ...
Error
Indicates all possible error conditions found during the controller's existence.
QList< QBluetoothUuid > services() const
Returns the list of services offered by the remote device, if the controller is in the \l CentralRole...
void discoverServices()
Initiates the service discovery process.
QLowEnergyService * createServiceObject(const QBluetoothUuid &service, QObject *parent=nullptr)
Creates an instance of the service represented by serviceUuid.
QBluetoothAddress remoteAddress() const
Returns the address of the remote Bluetooth Low Energy device.
ControllerState state() const
Returns the current state of the controller.
void readRssi()
readRssi() reads RSSI (received signal strength indicator) for a connected remote device.
void startAdvertising(const QLowEnergyAdvertisingParameters &parameters, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData=QLowEnergyAdvertisingData())
Starts advertising the data given in advertisingData and scanResponseData, using the parameters set i...
QBluetoothUuid remoteDeviceUuid() const
Returns the unique identifier of the remote Bluetooth Low Energy device.
int mtu() const
Returns the MTU size.
void setRemoteAddressType(RemoteAddressType type)
Sets the remote address type.
The QLowEnergyServiceData class is used to set up GATT service data. \inmodule QtBluetooth.
\inmodule QtBluetooth
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
const_iterator constEnd() const noexcept
Definition qset.h:143
const_iterator constFind(const T &value) const
Definition qset.h:161
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
static QLowEnergyControllerPrivate * privateController(QLowEnergyController::Role role, const QBluetoothAddress &localDevice=QBluetoothAddress{})
void registerQLowEnergyControllerMetaType()
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1384
GLenum type
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
#define Q_UNUSED(x)