4#include <QtCore/QCoreApplication>
5#include <QtCore/QPermissions>
6#include <QtCore/QThread>
13 , _workerThread(new QThread(this))
15 Q_ASSERT(_bluetoothConfig);
16 if (!_bluetoothConfig) {
17 qCCritical(BluetoothLinkLog) <<
"Invalid BluetoothConfiguration";
23 qCDebug(BluetoothLinkLog) <<
this;
25 const QString threadName = (_bluetoothConfig->mode() == BluetoothConfiguration::BluetoothMode::ModeLowEnergy)
26 ? QStringLiteral(
"BLE_%1") : QStringLiteral(
"Bluetooth_%1");
27 _workerThread->setObjectName(threadName.arg(_bluetoothConfig->name()));
29 _worker->moveToThread(_workerThread.data());
32 (void) connect(_workerThread.data(), &QThread::finished, _worker.data(), &QObject::deleteLater);
49 if (_workerThread->isRunning() && _connectedCache && _worker) {
50 (void) QMetaObject::invokeMethod(_worker,
"disconnectLink", Qt::QueuedConnection);
53 _workerThread->quit();
54 if (!_workerThread->wait(5000)) {
55 qCWarning(BluetoothLinkLog) <<
"Worker thread did not stop within timeout, terminating";
56 _workerThread->terminate();
57 (void) _workerThread->wait(1000);
61 qCDebug(BluetoothLinkLog) <<
this;
66 return _connectedCache;
69bool BluetoothLink::_connect()
74 if (_bluetoothConfig) {
75 _bluetoothConfig->stopScan();
77 return QMetaObject::invokeMethod(_worker.data(),
"connectLink", Qt::QueuedConnection);
83 (void) QMetaObject::invokeMethod(_worker.data(),
"disconnectLink", Qt::QueuedConnection);
87void BluetoothLink::_onConnected()
89 _connectedCache =
true;
90 _disconnectedEmitted =
false;
94void BluetoothLink::_onDisconnected()
96 _connectedCache =
false;
97 if (!_disconnectedEmitted.exchange(
true)) {
102void BluetoothLink::_onErrorOccurred(
const QString &
errorString)
104 qCWarning(BluetoothLinkLog) <<
"Communication error:" <<
errorString;
106 if (!_bluetoothConfig) {
111 const QString linkType = (_bluetoothConfig->mode() == BluetoothConfiguration::BluetoothMode::ModeLowEnergy)
112 ? tr(
"Bluetooth Low Energy") : tr(
"Bluetooth");
115 tr(
"Link %1: (Device: %2) %3").arg(_bluetoothConfig->name(),
116 _bluetoothConfig->device().name(),
120void BluetoothLink::_onDataReceived(
const QByteArray &data)
125void BluetoothLink::_onDataSent(
const QByteArray &data)
130void BluetoothLink::_onRssiUpdated(qint16 rssi)
132 if (_bluetoothConfig) {
133 _bluetoothConfig->setConnectedRssi(rssi);
137void BluetoothLink::_writeBytes(
const QByteArray &bytes)
140 (void) QMetaObject::invokeMethod(_worker.data(),
"writeData", Qt::QueuedConnection, Q_ARG(QByteArray, bytes));
144void BluetoothLink::_checkPermission()
146 QBluetoothPermission permission;
147 permission.setCommunicationModes(QBluetoothPermission::Access);
149 const Qt::PermissionStatus permissionStatus = QCoreApplication::instance()->checkPermission(permission);
150 if (permissionStatus == Qt::PermissionStatus::Undetermined) {
151 QCoreApplication::instance()->requestPermission(permission,
this, [
this](
const QPermission &perm) {
152 _handlePermissionStatus(perm.status());
155 _handlePermissionStatus(permissionStatus);
159void BluetoothLink::_handlePermissionStatus(Qt::PermissionStatus permissionStatus)
161 if (permissionStatus != Qt::PermissionStatus::Granted) {
162 qCWarning(BluetoothLinkLog) <<
"Bluetooth Permission Denied";
163 _onErrorOccurred(tr(
"Bluetooth Permission Denied"));
168 qCDebug(BluetoothLinkLog) <<
"Bluetooth Permission Granted";
170 if (_workerThread && !_workerThread->isRunning()) {
171 _workerThread->start();
172 if (!_workerThread->isRunning()) {
173 qCCritical(BluetoothLinkLog) <<
"Failed to start worker thread";
174 _onErrorOccurred(tr(
"Failed to start Bluetooth worker thread"));
175 _worker->deleteLater();
std::shared_ptr< LinkConfiguration > SharedLinkConfigurationPtr
void errorOccurred(const QString &errorString)
BluetoothLink(SharedLinkConfigurationPtr &config, QObject *parent=nullptr)
bool isConnected() const override
void disconnect() override
~BluetoothLink() override
void dataReceived(const QByteArray &data)
void dataSent(const QByteArray &data)
void errorOccurred(const QString &errorString)
void rssiUpdated(qint16 rssi)
static BluetoothWorker * create(const BluetoothConfiguration *config, QObject *parent=nullptr)
The link interface defines the interface for all links used to communicate with the ground station ap...
void bytesReceived(LinkInterface *link, const QByteArray &data)
void communicationError(const QString &title, const QString &error)
void bytesSent(LinkInterface *link, const QByteArray &data)