14 _setupClassicSocket();
19 qCDebug(BluetoothClassicWorkerLog) <<
"Attempting to connect to" <<
_device.name() <<
"Mode: Classic";
23 _socket->disconnect();
24 _socket->deleteLater();
28 _setupClassicSocket();
35 _socket->connectToService(
_device.address(), SPP_UUID);
40 if (_classicDiscovery && _classicDiscovery->isActive()) {
41 _classicDiscovery->stop();
45 _socket->disconnectFromService();
51 _writeClassicData(data);
56 if (_classicDiscovery && _classicDiscovery->isActive()) {
57 _classicDiscovery->stop();
72 _socket->disconnect();
73 if (_socket->state() == QBluetoothSocket::SocketState::ConnectedState) {
74 _socket->disconnectFromService();
76 _socket->deleteLater();
80void BluetoothClassicWorker::_setupClassicSocket()
86 _socket =
new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol,
this);
88 (void) connect(_socket.data(), &QBluetoothSocket::connected,
this, &BluetoothClassicWorker::_onSocketConnected);
89 (void) connect(_socket.data(), &QBluetoothSocket::disconnected,
this, &BluetoothClassicWorker::_onSocketDisconnected);
90 (void) connect(_socket.data(), &QBluetoothSocket::readyRead,
this, &BluetoothClassicWorker::_onSocketReadyRead);
91 (void) connect(_socket.data(), &QBluetoothSocket::errorOccurred,
this, &BluetoothClassicWorker::_onSocketErrorOccurred);
93 if (BluetoothClassicWorkerLog().isDebugEnabled()) {
94 (void) connect(_socket.data(), &QBluetoothSocket::bytesWritten,
this, &BluetoothClassicWorker::_onSocketBytesWritten);
96 (void) connect(_socket.data(), &QBluetoothSocket::stateChanged,
this,
97 [](QBluetoothSocket::SocketState state) {
98 qCDebug(BluetoothClassicWorkerLog) <<
"Bluetooth Socket State Changed:" << state;
103void BluetoothClassicWorker::_writeClassicData(
const QByteArray &data)
105 if (!_socket || !_socket->isWritable()) {
110 qint64 totalBytesWritten = 0;
111 while (totalBytesWritten < data.size()) {
112 const qint64 bytesWritten = _socket->write(data.constData() + totalBytesWritten,
113 data.size() - totalBytesWritten);
114 if (bytesWritten == -1) {
115 emit
errorOccurred(tr(
"Write failed: %1").arg(_socket->errorString()));
117 }
else if (bytesWritten == 0) {
121 totalBytesWritten += bytesWritten;
124 emit
dataSent(data.first(totalBytesWritten));
127void BluetoothClassicWorker::_onSocketConnected()
129 qCDebug(BluetoothClassicWorkerLog) <<
"=== Classic Bluetooth Connection Established ===" <<
_device.name();
130 qCDebug(BluetoothClassicWorkerLog) <<
" Address:" <<
_device.address().toString();
131 qCDebug(BluetoothClassicWorkerLog) <<
" Protocol: RFCOMM (SPP)";
139void BluetoothClassicWorker::_onSocketDisconnected()
141 qCDebug(BluetoothClassicWorkerLog) <<
"Socket disconnected from device:" <<
_device.name();
146 qCDebug(BluetoothClassicWorkerLog) <<
"Starting reconnect timer";
151void BluetoothClassicWorker::_onSocketReadyRead()
157 const QByteArray data = _socket->readAll();
158 if (!data.isEmpty()) {
159 qCDebug(BluetoothClassicWorkerVerboseLog) <<
_device.name() <<
"Received" << data.size() <<
"bytes";
164void BluetoothClassicWorker::_onSocketBytesWritten(qint64 bytes)
166 qCDebug(BluetoothClassicWorkerVerboseLog) <<
_device.name() <<
"Wrote" << bytes <<
"bytes";
169void BluetoothClassicWorker::_onSocketErrorOccurred(QBluetoothSocket::SocketError socketError)
178 qCWarning(BluetoothClassicWorkerLog) <<
"Socket error:" << socketError <<
errorString;
185 qCDebug(BluetoothClassicWorkerLog) <<
"Connection attempt failed, emitting disconnected signal";
190 if ((socketError == QBluetoothSocket::SocketError::ServiceNotFoundError) ||
191 (socketError == QBluetoothSocket::SocketError::UnsupportedProtocolError)) {
192 qCDebug(BluetoothClassicWorkerLog) <<
"Service-related error, attempting fallback discovery";
193 _startClassicServiceDiscovery();
197void BluetoothClassicWorker::_startClassicServiceDiscovery()
199 if (_classicDiscovery && _classicDiscovery->isActive()) {
203 if (!_classicDiscovery) {
204 _classicDiscovery =
new QBluetoothServiceDiscoveryAgent(
_device.address(),
this);
205 (void) connect(_classicDiscovery.data(), &QBluetoothServiceDiscoveryAgent::serviceDiscovered,
206 this, &BluetoothClassicWorker::_onClassicServiceDiscovered);
207 (void) connect(_classicDiscovery.data(), &QBluetoothServiceDiscoveryAgent::finished,
208 this, &BluetoothClassicWorker::_onClassicServiceDiscoveryFinished);
209 (void) connect(_classicDiscovery.data(), &QBluetoothServiceDiscoveryAgent::canceled,
210 this, &BluetoothClassicWorker::_onClassicServiceDiscoveryCanceled);
211 (void) connect(_classicDiscovery.data(), &QBluetoothServiceDiscoveryAgent::errorOccurred,
212 this, &BluetoothClassicWorker::_onClassicServiceDiscoveryError);
215 qCDebug(BluetoothClassicWorkerLog) <<
"Starting classic service discovery on" <<
_device.name();
216 _classicDiscoveredService = QBluetoothServiceInfo();
217 _classicDiscovery->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
225void BluetoothClassicWorker::_onClassicServiceDiscovered(
const QBluetoothServiceInfo &serviceInfo)
227 qCDebug(BluetoothClassicWorkerLog) <<
"Classic service discovered: UUIDs=" << serviceInfo.serviceClassUuids()
228 <<
"RFCOMM channel=" << serviceInfo.serverChannel()
229 <<
"L2CAP PSM=" << serviceInfo.protocolServiceMultiplexer();
231 const QList<QBluetoothUuid> serviceUuids = serviceInfo.serviceClassUuids();
232 const bool isSerial = serviceUuids.contains(QBluetoothUuid(QBluetoothUuid::ServiceClassUuid::SerialPort));
233 const bool hasRfcommChannel = serviceInfo.serverChannel() > 0;
235 if (isSerial || (hasRfcommChannel && !_classicDiscoveredService.isValid())) {
236 _classicDiscoveredService = serviceInfo;
240void BluetoothClassicWorker::_onClassicServiceDiscoveryFinished()
246 if (!_classicDiscoveredService.isValid()) {
247 qCWarning(BluetoothClassicWorkerLog) <<
"No suitable classic service found";
252 _setupClassicSocket();
255 qCDebug(BluetoothClassicWorkerLog) <<
"Connecting using discovered service";
256 _socket->connectToService(_classicDiscoveredService);
259void BluetoothClassicWorker::_onClassicServiceDiscoveryCanceled()
265 qCDebug(BluetoothClassicWorkerLog) <<
"Classic service discovery canceled";
268void BluetoothClassicWorker::_onClassicServiceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error
error)
274 const QString e = _classicDiscovery ? _classicDiscovery->errorString() : tr(
"Service discovery error: %1").arg(
error);
275 qCWarning(BluetoothClassicWorkerLog) << e;
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void onSetupConnection() override
void onWriteData(const QByteArray &data) override
~BluetoothClassicWorker() override
void onResetAfterConsecutiveFailures() override
void onServiceDiscoveryTimeout() override
void onConnectLink() override
void onDisconnectLink() override
void dataReceived(const QByteArray &data)
QPointer< QTimer > _serviceDiscoveryTimer
void dataSent(const QByteArray &data)
void errorOccurred(const QString &errorString)
QPointer< QTimer > _reconnectTimer
std::atomic< int > _reconnectAttempts
std::atomic< bool > _connected
const QBluetoothDeviceInfo _device
std::atomic< bool > _intentionalDisconnect