QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
BluetoothWorker.cc
Go to the documentation of this file.
1#include "BluetoothWorker.h"
4
6 : QObject(parent)
7 , _device(config->device())
8 , _serviceUuid(QBluetoothUuid(config->serviceUuid()))
9 , _readCharacteristicUuid(config->readCharacteristicUuid())
10 , _writeCharacteristicUuid(config->writeCharacteristicUuid())
11 , _reconnectTimer(new QTimer(this))
12 , _serviceDiscoveryTimer(new QTimer(this))
13{
14 qCDebug(BluetoothLinkLog) << this;
15
17 _reconnectTimer->setSingleShot(true);
18 (void) connect(_reconnectTimer.data(), &QTimer::timeout, this, &BluetoothWorker::_reconnectTimeout);
19
21 _serviceDiscoveryTimer->setSingleShot(true);
22 (void) connect(_serviceDiscoveryTimer.data(), &QTimer::timeout, this, &BluetoothWorker::_serviceDiscoveryTimeout);
23}
24
26{
28
29 // Note: subclass destructors handle their own resource cleanup (socket/controller)
30 // since virtual dispatch is not available in base destructors.
31
32 QObject::disconnect();
33
34 if (_reconnectTimer) {
35 _reconnectTimer->stop();
36 }
39 }
40
41 qCDebug(BluetoothLinkLog) << this;
42}
43
45{
46 return _connected.load();
47}
48
50{
51 if (config->mode() == BluetoothConfiguration::BluetoothMode::ModeLowEnergy) {
52 return new BluetoothBleWorker(config, parent);
53 }
54 return new BluetoothClassicWorker(config, parent);
55}
56
61
63{
65
66 if (isConnected()) {
67 qCWarning(BluetoothLinkLog) << "Already connected to" << _device.name();
68 return;
69 }
70
72}
73
89
90void BluetoothWorker::writeData(const QByteArray &data)
91{
92 if (data.isEmpty()) {
93 qCWarning(BluetoothLinkLog) << "Write called with empty data";
94 return;
95 }
96
97 if (!isConnected()) {
98 emit errorOccurred(tr("Device is not connected"));
99 return;
100 }
101
102 onWriteData(data);
103}
104
106{
107 if (_intentionalDisconnect.load()) {
108 return;
109 }
110
112 qCWarning(BluetoothLinkLog) << "Max reconnection attempts (" << MAX_RECONNECT_ATTEMPTS << ") reached. Giving up.";
113 emit errorOccurred(tr("Max reconnection attempts reached"));
114 return;
115 }
116
118 qCDebug(BluetoothLinkLog) << "Attempting to reconnect (attempt" << _reconnectAttempts << "of" << MAX_RECONNECT_ATTEMPTS << ")";
119
120 const int nextInterval = qMin(RECONNECT_BASE_INTERVAL_MS * (1 << (_reconnectAttempts - 1)), MAX_RECONNECT_INTERVAL_MS);
121 if (_reconnectTimer) {
122 _reconnectTimer->setInterval(nextInterval);
123 }
124
128 }
129
130 connectLink();
131}
132
134{
135 qCWarning(BluetoothLinkLog) << "Service discovery timed out after" << SERVICE_DISCOVERY_TIMEOUT_MS << "ms";
137
139
140 emit errorOccurred(tr("Service discovery timed out"));
141}
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
BluetoothWorker(const BluetoothConfiguration *config, QObject *parent=nullptr)
static constexpr int SERVICE_DISCOVERY_TIMEOUT_MS