QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
BluetoothWorker.cc
Go to the documentation of this file.
1#include "BluetoothWorker.h"
5
6QGC_LOGGING_CATEGORY(BluetoothWorkerLog, "Comms.Bluetooth.BluetoothWorker")
7
9 : QObject(parent)
10 , _device(config->device())
11 , _serviceUuid(QBluetoothUuid(config->serviceUuid()))
12 , _readCharacteristicUuid(config->readCharacteristicUuid())
13 , _writeCharacteristicUuid(config->writeCharacteristicUuid())
14 , _reconnectTimer(new QTimer(this))
15 , _serviceDiscoveryTimer(new QTimer(this))
16{
17 qCDebug(BluetoothWorkerLog) << this;
18
19 _reconnectTimer->setInterval(RECONNECT_BASE_INTERVAL_MS);
20 _reconnectTimer->setSingleShot(true);
21 (void) connect(_reconnectTimer.data(), &QTimer::timeout, this, &BluetoothWorker::_reconnectTimeout);
22
23 _serviceDiscoveryTimer->setInterval(SERVICE_DISCOVERY_TIMEOUT_MS);
24 _serviceDiscoveryTimer->setSingleShot(true);
25 (void) connect(_serviceDiscoveryTimer.data(), &QTimer::timeout, this, &BluetoothWorker::_serviceDiscoveryTimeout);
26}
27
29{
31
32 // Note: subclass destructors handle their own resource cleanup (socket/controller)
33 // since virtual dispatch is not available in base destructors.
34
35 QObject::disconnect();
36
37 if (_reconnectTimer) {
38 _reconnectTimer->stop();
39 }
42 }
43
44 qCDebug(BluetoothWorkerLog) << this;
45}
46
48{
49 return _connected.load();
50}
51
53{
55 return new BluetoothBleWorker(config, parent);
56 }
57 return new BluetoothClassicWorker(config, parent);
58}
59
64
66{
68
69 if (isConnected()) {
70 qCWarning(BluetoothWorkerLog) << "Already connected to" << _device.name();
71 return;
72 }
73
75}
76
92
93void BluetoothWorker::writeData(const QByteArray &data)
94{
95 if (data.isEmpty()) {
96 qCWarning(BluetoothWorkerLog) << "Write called with empty data";
97 return;
98 }
99
100 if (!isConnected()) {
101 emit errorOccurred(tr("Device is not connected"));
102 return;
103 }
104
105 onWriteData(data);
106}
107
109{
110 if (_intentionalDisconnect.load()) {
111 return;
112 }
113
115 qCWarning(BluetoothWorkerLog) << "Max reconnection attempts (" << MAX_RECONNECT_ATTEMPTS << ") reached. Giving up.";
116 emit errorOccurred(tr("Max reconnection attempts reached"));
117 return;
118 }
119
121 qCDebug(BluetoothWorkerLog) << "Attempting to reconnect (attempt" << _reconnectAttempts << "of" << MAX_RECONNECT_ATTEMPTS << ")";
122
123 const int nextInterval = qMin(RECONNECT_BASE_INTERVAL_MS * (1 << (_reconnectAttempts - 1)), MAX_RECONNECT_INTERVAL_MS);
124 if (_reconnectTimer) {
125 _reconnectTimer->setInterval(nextInterval);
126 }
127
131 }
132
133 connectLink();
134}
135
137{
138 qCWarning(BluetoothWorkerLog) << "Service discovery timed out after" << SERVICE_DISCOVERY_TIMEOUT_MS << "ms";
140
142
143 emit errorOccurred(tr("Service discovery timed out"));
144}
#define QGC_LOGGING_CATEGORY(name, categoryStr)
BluetoothMode mode() const
static constexpr int MAX_RECONNECT_INTERVAL_MS
virtual void onSetupConnection()=0
void writeData(const QByteArray &data)
QPointer< QTimer > _serviceDiscoveryTimer
void errorOccurred(const QString &errorString)
virtual void onWriteData(const QByteArray &data)=0
static constexpr int MAX_CONSECUTIVE_FAILURES
virtual void onResetAfterConsecutiveFailures()=0
virtual void onConnectLink()=0
static constexpr int MAX_RECONNECT_ATTEMPTS
QPointer< QTimer > _reconnectTimer
void _serviceDiscoveryTimeout()
virtual void onServiceDiscoveryTimeout()=0
std::atomic< int > _reconnectAttempts
static BluetoothWorker * create(const BluetoothConfiguration *config, QObject *parent=nullptr)
std::atomic< bool > _connected
bool isConnected() const
const QBluetoothDeviceInfo _device
~BluetoothWorker() override
virtual void onDisconnectLink()=0
std::atomic< bool > _intentionalDisconnect
static constexpr int RECONNECT_BASE_INTERVAL_MS
static constexpr int SERVICE_DISCOVERY_TIMEOUT_MS