Commit 09b22dd6 authored by dogmaphobic's avatar dogmaphobic

Bluetooth Cleanup

parent ec3047af
...@@ -36,6 +36,7 @@ linux { ...@@ -36,6 +36,7 @@ linux {
CONFIG += AndroidBuild MobileBuild CONFIG += AndroidBuild MobileBuild
DEFINES += __android__ DEFINES += __android__
DEFINES += __STDC_LIMIT_MACROS DEFINES += __STDC_LIMIT_MACROS
DEFINES += QGC_ENABLE_BLUETOOTH
target.path = $$DESTDIR target.path = $$DESTDIR
} else { } else {
error("Unsuported Linux toolchain, only GCC 32- or 64-bit is supported") error("Unsuported Linux toolchain, only GCC 32- or 64-bit is supported")
......
...@@ -44,6 +44,18 @@ exists(user_config.pri):infile(user_config.pri, CONFIG) { ...@@ -44,6 +44,18 @@ exists(user_config.pri):infile(user_config.pri, CONFIG) {
message($$sprintf("Using user-supplied additional config: '%1' specified in user_config.pri", $$fromfile(user_config.pri, CONFIG))) message($$sprintf("Using user-supplied additional config: '%1' specified in user_config.pri", $$fromfile(user_config.pri, CONFIG)))
} }
# Bluetooth
contains (DEFINES, QGC_DISABLE_BLUETOOTH) {
message("Skipping support for Bluetooth (manual override from command line)")
DEFINES -= QGC_ENABLE_BLUETOOTH
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, QGC_DISABLE_BLUETOOTH) {
message("Skipping support for Bluetooth (manual override from user_config.pri)")
DEFINES -= QGC_ENABLE_BLUETOOTH
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, QGC_ENABLE_BLUETOOTH) {
message("Including support for Bluetooth (manual override from user_config.pri)")
DEFINES += QGC_ENABLE_BLUETOOTH
}
LinuxBuild { LinuxBuild {
CONFIG += link_pkgconfig CONFIG += link_pkgconfig
} }
...@@ -74,7 +86,7 @@ QT += \ ...@@ -74,7 +86,7 @@ QT += \
serialport \ serialport \
} }
MobileBuild { contains(DEFINES, QGC_ENABLE_BLUETOOTH) {
QT += \ QT += \
bluetooth \ bluetooth \
} }
...@@ -284,7 +296,7 @@ WindowsBuild { ...@@ -284,7 +296,7 @@ WindowsBuild {
HEADERS += src/stable_headers.h HEADERS += src/stable_headers.h
} }
MobileBuild { contains(DEFINES, QGC_ENABLE_BLUETOOTH) {
HEADERS += \ HEADERS += \
src/comm/BluetoothLink.h \ src/comm/BluetoothLink.h \
} }
...@@ -402,7 +414,7 @@ SOURCES += \ ...@@ -402,7 +414,7 @@ SOURCES += \
src/ui/SerialConfigurationWindow.cc \ src/ui/SerialConfigurationWindow.cc \
} }
MobileBuild { contains(DEFINES, QGC_ENABLE_BLUETOOTH) {
SOURCES += \ SOURCES += \
src/comm/BluetoothLink.cc \ src/comm/BluetoothLink.cc \
} }
......
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
#include <QStyleFactory> #include <QStyleFactory>
#include <QAction> #include <QAction>
#ifdef QGC_ENABLE_BLUETOOTH
#include <QBluetoothLocalDevice>
#endif
#include <QDebug> #include <QDebug>
#include "VideoStreaming.h" #include "VideoStreaming.h"
...@@ -170,6 +174,7 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) ...@@ -170,6 +174,7 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
, _testHighDPI(false) , _testHighDPI(false)
#endif #endif
, _toolbox(NULL) , _toolbox(NULL)
, _bluetoothAvailable(false)
{ {
Q_ASSERT(_app == NULL); Q_ASSERT(_app == NULL);
_app = this; _app = this;
...@@ -319,6 +324,15 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) ...@@ -319,6 +324,15 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting)
settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION); settings.setValue(_settingsVersionKey, QGC_SETTINGS_VERSION);
} }
// Initialize Bluetooth
#ifdef QGC_ENABLE_BLUETOOTH
QBluetoothLocalDevice localDevice;
if (localDevice.isValid())
{
_bluetoothAvailable = true;
}
#endif
// Initialize Video Streaming // Initialize Video Streaming
initializeVideoStreaming(argc, argv); initializeVideoStreaming(argc, argv);
......
/*===================================================================== /*=====================================================================
QGroundControl Open Source Ground Control Station QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> (c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful, QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>. along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/ ======================================================================*/
/** /**
...@@ -72,35 +72,35 @@ class QGCApplication : public ...@@ -72,35 +72,35 @@ class QGCApplication : public
#endif #endif
{ {
Q_OBJECT Q_OBJECT
public: public:
QGCApplication(int &argc, char* argv[], bool unitTesting); QGCApplication(int &argc, char* argv[], bool unitTesting);
~QGCApplication(); ~QGCApplication();
/// @brief Sets the persistent flag to delete all settings the next time QGroundControl is started. /// @brief Sets the persistent flag to delete all settings the next time QGroundControl is started.
void deleteAllSettingsNextBoot(void); void deleteAllSettingsNextBoot(void);
/// @brief Clears the persistent flag to delete all settings the next time QGroundControl is started. /// @brief Clears the persistent flag to delete all settings the next time QGroundControl is started.
void clearDeleteAllSettingsNextBoot(void); void clearDeleteAllSettingsNextBoot(void);
/// @brief Returns the location of user visible saved file associated with QGroundControl /// @brief Returns the location of user visible saved file associated with QGroundControl
QString savedFilesLocation(void); QString savedFilesLocation(void);
/// @brief Sets the location of user visible saved file associated with QGroundControl /// @brief Sets the location of user visible saved file associated with QGroundControl
void setSavedFilesLocation(QString& location); void setSavedFilesLocation(QString& location);
/// @brief Location to save and load parameter files from. /// @brief Location to save and load parameter files from.
QString savedParameterFilesLocation(void); QString savedParameterFilesLocation(void);
/// @brief Location to save and load mavlink log files from /// @brief Location to save and load mavlink log files from
QString mavlinkLogFilesLocation(void); QString mavlinkLogFilesLocation(void);
/// @brief Validates that the specified location will work for the saved files location. /// @brief Validates that the specified location will work for the saved files location.
bool validatePossibleSavedFilesLocation(QString& location); bool validatePossibleSavedFilesLocation(QString& location);
/// @return true: Prompt to save log file when vehicle goes away /// @return true: Prompt to save log file when vehicle goes away
bool promptFlightDataSave(void); bool promptFlightDataSave(void);
/// @return true: Prompt to save log file even if vehicle was not armed /// @return true: Prompt to save log file even if vehicle was not armed
bool promptFlightDataSaveNotArmed(void); bool promptFlightDataSaveNotArmed(void);
...@@ -109,13 +109,13 @@ public: ...@@ -109,13 +109,13 @@ public:
/// @brief Returns truee if unit test are being run /// @brief Returns truee if unit test are being run
bool runningUnitTests(void) { return _runningUnitTests; } bool runningUnitTests(void) { return _runningUnitTests; }
/// @return true: dark ui style, false: light ui style /// @return true: dark ui style, false: light ui style
bool styleIsDark(void) { return _styleIsDark; } bool styleIsDark(void) { return _styleIsDark; }
/// Set the current UI style /// Set the current UI style
void setStyle(bool styleIsDark); void setStyle(bool styleIsDark);
/// Used to report a missing Parameter. Warning will be displayed to user. Method may be called /// Used to report a missing Parameter. Warning will be displayed to user. Method may be called
/// multiple times. /// multiple times.
void reportMissingParameter(int componentId, const QString& name); void reportMissingParameter(int componentId, const QString& name);
...@@ -123,26 +123,29 @@ public: ...@@ -123,26 +123,29 @@ public:
/// Show a non-modal message to the user /// Show a non-modal message to the user
void showMessage(const QString& message); void showMessage(const QString& message);
/// @return true: Fake ui into showing mobile interface /// @return true: Fake ui into showing mobile interface
bool fakeMobile(void) { return _fakeMobile; } bool fakeMobile(void) { return _fakeMobile; }
#ifdef QT_DEBUG #ifdef QT_DEBUG
bool testHighDPI(void) { return _testHighDPI; } bool testHighDPI(void) { return _testHighDPI; }
#endif #endif
// Still working on getting rid of this and using dependency injection instead for everything // Still working on getting rid of this and using dependency injection instead for everything
QGCToolbox* toolbox(void) { return _toolbox; } QGCToolbox* toolbox(void) { return _toolbox; }
/// Do we have Bluetooth Support?
bool isBluetoothAvailable() { return _bluetoothAvailable; }
public slots: public slots:
/// You can connect to this slot to show an information message box from a different thread. /// You can connect to this slot to show an information message box from a different thread.
void informationMessageBoxOnMainThread(const QString& title, const QString& msg); void informationMessageBoxOnMainThread(const QString& title, const QString& msg);
/// You can connect to this slot to show a warning message box from a different thread. /// You can connect to this slot to show a warning message box from a different thread.
void warningMessageBoxOnMainThread(const QString& title, const QString& msg); void warningMessageBoxOnMainThread(const QString& title, const QString& msg);
/// You can connect to this slot to show a critical message box from a different thread. /// You can connect to this slot to show a critical message box from a different thread.
void criticalMessageBoxOnMainThread(const QString& title, const QString& msg); void criticalMessageBoxOnMainThread(const QString& title, const QString& msg);
void showFlyView(void); void showFlyView(void);
void showPlanView(void); void showPlanView(void);
void showSetupView(void); void showSetupView(void);
...@@ -158,14 +161,14 @@ signals: ...@@ -158,14 +161,14 @@ signals:
/// Signals that the style has changed /// Signals that the style has changed
/// @param darkStyle true: dark style, false: light style /// @param darkStyle true: dark style, false: light style
void styleChanged(bool darkStyle); void styleChanged(bool darkStyle);
/// This is connected to MAVLinkProtocol::checkForLostLogFiles. We signal this to ourselves to call the slot /// This is connected to MAVLinkProtocol::checkForLostLogFiles. We signal this to ourselves to call the slot
/// on the MAVLinkProtocol thread; /// on the MAVLinkProtocol thread;
void checkForLostLogFiles(void); void checkForLostLogFiles(void);
public: public:
// Although public, these methods are internal and should only be called by UnitTest code // Although public, these methods are internal and should only be called by UnitTest code
/// @brief Perform initialize which is common to both normal application running and unit tests. /// @brief Perform initialize which is common to both normal application running and unit tests.
/// Although public should only be called by main. /// Although public should only be called by main.
void _initCommon(void); void _initCommon(void);
...@@ -173,7 +176,7 @@ public: ...@@ -173,7 +176,7 @@ public:
/// @brief Intialize the application for normal application boot. Or in other words we are not going to run /// @brief Intialize the application for normal application boot. Or in other words we are not going to run
/// unit tests. Although public should only be called by main. /// unit tests. Although public should only be called by main.
bool _initForNormalAppBoot(void); bool _initForNormalAppBoot(void);
/// @brief Intialize the application for normal application boot. Or in other words we are not going to run /// @brief Intialize the application for normal application boot. Or in other words we are not going to run
/// unit tests. Although public should only be called by main. /// unit tests. Although public should only be called by main.
bool _initForUnitTests(void); bool _initForUnitTests(void);
...@@ -182,12 +185,12 @@ public: ...@@ -182,12 +185,12 @@ public:
void _showSetupParameters(void); void _showSetupParameters(void);
void _showSetupSummary(void); void _showSetupSummary(void);
void _showSetupVehicleComponent(VehicleComponent* vehicleComponent); void _showSetupVehicleComponent(VehicleComponent* vehicleComponent);
static QGCApplication* _app; ///< Our own singleton. Should be reference directly by qgcApp static QGCApplication* _app; ///< Our own singleton. Should be reference directly by qgcApp
private slots: private slots:
void _missingParamsDisplay(void); void _missingParamsDisplay(void);
private: private:
void _loadCurrentStyle(void); void _loadCurrentStyle(void);
QObject* _rootQmlObject(void); QObject* _rootQmlObject(void);
...@@ -195,36 +198,38 @@ private: ...@@ -195,36 +198,38 @@ private:
#ifdef __mobile__ #ifdef __mobile__
QQmlApplicationEngine* _qmlAppEngine; QQmlApplicationEngine* _qmlAppEngine;
#endif #endif
static const char* _settingsVersionKey; ///< Settings key which hold settings version static const char* _settingsVersionKey; ///< Settings key which hold settings version
static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted
static const char* _savedFilesLocationKey; ///< Settings key for user visible saved files location static const char* _savedFilesLocationKey; ///< Settings key for user visible saved files location
static const char* _promptFlightDataSave; ///< Settings key for promptFlightDataSave static const char* _promptFlightDataSave; ///< Settings key for promptFlightDataSave
static const char* _promptFlightDataSaveNotArmed; ///< Settings key for promptFlightDataSaveNotArmed static const char* _promptFlightDataSaveNotArmed; ///< Settings key for promptFlightDataSaveNotArmed
static const char* _styleKey; ///< Settings key for UI style static const char* _styleKey; ///< Settings key for UI style
static const char* _defaultSavedFileDirectoryName; ///< Default name for user visible save file directory static const char* _defaultSavedFileDirectoryName; ///< Default name for user visible save file directory
static const char* _savedFileMavlinkLogDirectoryName; ///< Name of mavlink log subdirectory static const char* _savedFileMavlinkLogDirectoryName; ///< Name of mavlink log subdirectory
static const char* _savedFileParameterDirectoryName; ///< Name of parameter subdirectory static const char* _savedFileParameterDirectoryName; ///< Name of parameter subdirectory
bool _runningUnitTests; ///< true: running unit tests, false: normal app bool _runningUnitTests; ///< true: running unit tests, false: normal app
static const char* _darkStyleFile; static const char* _darkStyleFile;
static const char* _lightStyleFile; static const char* _lightStyleFile;
bool _styleIsDark; ///< true: dark style, false: light style bool _styleIsDark; ///< true: dark style, false: light style
static const int _missingParamsDelayedDisplayTimerTimeout = 1000; ///< Timeout to wait for next missing fact to come in before display static const int _missingParamsDelayedDisplayTimerTimeout = 1000; ///< Timeout to wait for next missing fact to come in before display
QTimer _missingParamsDelayedDisplayTimer; ///< Timer use to delay missing fact display QTimer _missingParamsDelayedDisplayTimer; ///< Timer use to delay missing fact display
QStringList _missingParams; ///< List of missing facts to be displayed QStringList _missingParams; ///< List of missing facts to be displayed
bool _fakeMobile; ///< true: Fake ui into displaying mobile interface bool _fakeMobile; ///< true: Fake ui into displaying mobile interface
#ifdef QT_DEBUG #ifdef QT_DEBUG
bool _testHighDPI; ///< true: double fonts sizes for simulating high dpi devices bool _testHighDPI; ///< true: double fonts sizes for simulating high dpi devices
#endif #endif
QGCToolbox* _toolbox; QGCToolbox* _toolbox;
bool _bluetoothAvailable;
/// Unit Test have access to creating and destroying singletons /// Unit Test have access to creating and destroying singletons
friend class UnitTest; friend class UnitTest;
}; };
......
...@@ -34,42 +34,26 @@ This file is part of the QGROUNDCONTROL project ...@@ -34,42 +34,26 @@ This file is part of the QGROUNDCONTROL project
#include <QDebug> #include <QDebug>
#include <iostream> #include <iostream>
#include <QtBluetooth/QBluetoothSocket>
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent> #include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
#include <QtBluetooth/QBluetoothLocalDevice> #include <QtBluetooth/QBluetoothLocalDevice>
#include <QtBluetooth/QBluetoothUuid> #include <QtBluetooth/QBluetoothUuid>
#include <QtBluetooth/QBluetoothSocket>
#include "BluetoothLink.h" #include "BluetoothLink.h"
#include "QGC.h" #include "QGC.h"
/*
static void print_device_info(QBluetoothDeviceInfo info)
{
qDebug() << "Bluetooth: " << info.name();
qDebug() << " Services:" << info.serviceClasses();
qDebug() << " Major Classs:" << info.majorDeviceClass();
qDebug() << " Minor Classs:" << info.minorDeviceClass();
qDebug() << " RSSI:" << info.rssi();
qDebug() << " UUID:" << info.deviceUuid();
qDebug() << " Service UUID:" << info.serviceUuids();
qDebug() << " Core Config:" << info.coreConfigurations();
qDebug() << " Valid:" << info.isValid();
qDebug() << " Address:" << info.address().toString();
}
*/
BluetoothLink::BluetoothLink(BluetoothConfiguration* config) BluetoothLink::BluetoothLink(BluetoothConfiguration* config)
: _connectState(false) : _connectState(false)
, _targetSocket(NULL) , _targetSocket(NULL)
, _targetDevice(NULL) #ifdef __ios__
, _running(false) , _discoveryAgent(NULL)
#endif
, _shutDown(false)
{ {
Q_ASSERT(config != NULL); Q_ASSERT(config != NULL);
_config = config; _config = config;
_config->setLink(this); _config->setLink(this);
// We're doing it wrong - because the Qt folks got the API wrong: //moveToThread(this);
// http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
moveToThread(this);
} }
BluetoothLink::~BluetoothLink() BluetoothLink::~BluetoothLink()
...@@ -77,19 +61,18 @@ BluetoothLink::~BluetoothLink() ...@@ -77,19 +61,18 @@ BluetoothLink::~BluetoothLink()
// Disconnect link from configuration // Disconnect link from configuration
_config->setLink(NULL); _config->setLink(NULL);
_disconnect(); _disconnect();
// Tell the thread to exit #ifdef __ios__
_running = false; if(_discoveryAgent) {
quit(); _shutDown = true;
// Wait for it to exit _discoveryAgent->stop();
wait(); _discoveryAgent->deleteLater();
this->deleteLater(); _discoveryAgent = NULL;
}
#endif
} }
void BluetoothLink::run() void BluetoothLink::run()
{ {
if(_running && _hardwareConnect()) {
exec();
}
} }
void BluetoothLink::_restartConnection() void BluetoothLink::_restartConnection()
...@@ -142,17 +125,17 @@ void BluetoothLink::readBytes() ...@@ -142,17 +125,17 @@ void BluetoothLink::readBytes()
void BluetoothLink::_disconnect(void) void BluetoothLink::_disconnect(void)
{ {
_running = false; #ifdef __ios__
quit(); if(_discoveryAgent) {
wait(); _shutDown = true;
if(_targetDevice) _discoveryAgent->stop();
{ _discoveryAgent->deleteLater();
delete _targetDevice; _discoveryAgent = NULL;
_targetDevice = NULL;
} }
#endif
if(_targetSocket) if(_targetSocket)
{ {
_targetSocket->deleteLater(); delete _targetSocket;
_targetSocket = NULL; _targetSocket = NULL;
emit disconnected(); emit disconnected();
} }
...@@ -161,43 +144,86 @@ void BluetoothLink::_disconnect(void) ...@@ -161,43 +144,86 @@ void BluetoothLink::_disconnect(void)
bool BluetoothLink::_connect(void) bool BluetoothLink::_connect(void)
{ {
if(this->isRunning() || _running) _hardwareConnect();
{
_running = false;
quit();
wait();
}
if(_targetDevice)
{
delete _targetDevice;
_targetDevice = NULL;
}
//-- Start Thread
_running = true;
start(NormalPriority);
return true; return true;
} }
bool BluetoothLink::_hardwareConnect() bool BluetoothLink::_hardwareConnect()
{
#ifdef __ios__
if(_discoveryAgent) {
_shutDown = true;
_discoveryAgent->stop();
_discoveryAgent->deleteLater();
_discoveryAgent = NULL;
}
_discoveryAgent = new QBluetoothServiceDiscoveryAgent(this);
QObject::connect(_discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
QObject::connect(_discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished()));
QObject::connect(_discoveryAgent, SIGNAL(canceled()), this, SLOT(discoveryFinished()));
QObject::connect(_discoveryAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)),this, SLOT(discoveryError(QBluetoothServiceDiscoveryAgent::Error)));
_shutDown = false;
_discoveryAgent->start();
#else
_createSocket();
_targetSocket->connectToService(QBluetoothAddress(_config->device().address), QBluetoothUuid(QBluetoothUuid::Rfcomm));
#endif
return true;
}
void BluetoothLink::_createSocket()
{ {
if(_targetSocket) if(_targetSocket)
{ {
delete _targetSocket; delete _targetSocket;
_targetSocket = NULL; _targetSocket = NULL;
} }
_targetDevice = new QBluetoothDeviceInfo(QBluetoothAddress(_config->device().address), _config->device().name, _config->device().bits);
_targetDevice->setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
_targetSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); _targetSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this);
_targetSocket->moveToThread(this);
//print_device_info(*_targetDevice);
QObject::connect(_targetSocket, SIGNAL(connected()), this, SLOT(deviceConnected())); QObject::connect(_targetSocket, SIGNAL(connected()), this, SLOT(deviceConnected()));
QObject::connect(_targetSocket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(deviceError(QBluetoothSocket::SocketError))); QObject::connect(_targetSocket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(deviceError(QBluetoothSocket::SocketError)));
QObject::connect(_targetSocket, SIGNAL(readyRead()), this, SLOT(readBytes())); QObject::connect(_targetSocket, SIGNAL(readyRead()), this, SLOT(readBytes()));
QObject::connect(_targetSocket, SIGNAL(disconnected()), this, SLOT(deviceDisconnected())); QObject::connect(_targetSocket, SIGNAL(disconnected()), this, SLOT(deviceDisconnected()));
_targetSocket->connectToService(_targetDevice->address(), QBluetoothUuid(QBluetoothUuid::Rfcomm));
return true;
} }
#ifdef __ios__
void BluetoothLink::discoveryError(QBluetoothServiceDiscoveryAgent::Error error)
{
qDebug() << "Discovery error:" << error;
qDebug() << _discoveryAgent->errorString();
}
#endif
#ifdef __ios__
void BluetoothLink::serviceDiscovered(const QBluetoothServiceInfo& info)
{
if(!info.device().name().isEmpty() && !_targetSocket)
{
if(_config->device().uuid == info.device().deviceUuid() && _config->device().name == info.device().name())
{
_createSocket();
_targetSocket->connectToService(info);
}
}
}
#endif
#ifdef __ios__
void BluetoothLink::discoveryFinished()
{
if(_discoveryAgent && !_shutDown)
{
_shutDown = true;
_discoveryAgent->deleteLater();
_discoveryAgent = NULL;
if(!_targetSocket)
{
_connectState = false;
emit communicationError("Could not locate Bluetooth device:", _config->device().name);
}
}
}
#endif
void BluetoothLink::deviceConnected() void BluetoothLink::deviceConnected()
{ {
_connectState = true; _connectState = true;
...@@ -274,18 +300,25 @@ void BluetoothConfiguration::copyFrom(LinkConfiguration *source) ...@@ -274,18 +300,25 @@ void BluetoothConfiguration::copyFrom(LinkConfiguration *source)
void BluetoothConfiguration::saveSettings(QSettings& settings, const QString& root) void BluetoothConfiguration::saveSettings(QSettings& settings, const QString& root)
{ {
settings.beginGroup(root); settings.beginGroup(root);
settings.setValue("name", _device.name); settings.setValue("deviceName", _device.name);
settings.setValue("address", _device.address); #ifdef __ios__
settings.setValue("bits", _device.bits); settings.setValue("uuid", _device.uuid.toString());
#else
settings.setValue("address",_device.address);
#endif
settings.endGroup(); settings.endGroup();
} }
void BluetoothConfiguration::loadSettings(QSettings& settings, const QString& root) void BluetoothConfiguration::loadSettings(QSettings& settings, const QString& root)
{ {
settings.beginGroup(root); settings.beginGroup(root);
_device.name = settings.value("name", _device.name).toString(); _device.name = settings.value("deviceName", _device.name).toString();
#ifdef __ios__
QString suuid = settings.value("uuid", _device.uuid.toString()).toString();
_device.uuid = QUuid(suuid);
#else
_device.address = settings.value("address", _device.address).toString(); _device.address = settings.value("address", _device.address).toString();
_device.bits = settings.value("bits", _device.bits).toUInt(); #endif
settings.endGroup(); settings.endGroup();
} }
...@@ -337,10 +370,11 @@ void BluetoothConfiguration::deviceDiscovered(QBluetoothDeviceInfo info) ...@@ -337,10 +370,11 @@ void BluetoothConfiguration::deviceDiscovered(QBluetoothDeviceInfo info)
{ {
BluetoothData data; BluetoothData data;
data.name = info.name(); data.name = info.name();
#ifdef __ios__
data.uuid = info.deviceUuid();
#else
data.address = info.address().toString(); data.address = info.address().toString();
data.bits |= ((qint32)info.serviceClasses() << 13); // Service Class #endif
data.bits |= ((qint32)info.majorDeviceClass() << 8); // CLASS MAJOR
data.bits |= ((qint32)info.minorDeviceClass() << 2); // CLASS MINOR
if(!_deviceList.contains(data)) if(!_deviceList.contains(data))
{ {
_deviceList += data; _deviceList += data;
...@@ -369,9 +403,19 @@ void BluetoothConfiguration::setDevName(const QString &name) ...@@ -369,9 +403,19 @@ void BluetoothConfiguration::setDevName(const QString &name)
{ {
_device = data; _device = data;
emit devNameChanged(); emit devNameChanged();
#ifndef __ios__
emit addressChanged(); emit addressChanged();
#endif
return; return;
} }
} }
} }
QString BluetoothConfiguration::address()
{
#ifdef __ios__
return QString("");
#else
return _device.address;
#endif
}
...@@ -39,18 +39,20 @@ This file is part of the QGROUNDCONTROL project ...@@ -39,18 +39,20 @@ This file is part of the QGROUNDCONTROL project
#include <QByteArray> #include <QByteArray>
#include <QBluetoothDeviceInfo> #include <QBluetoothDeviceInfo>
#include <QtBluetooth/QBluetoothSocket> #include <QtBluetooth/QBluetoothSocket>
#include <qbluetoothserviceinfo.h>
#include <qbluetoothservicediscoveryagent.h>
#include "QGCConfig.h" #include "QGCConfig.h"
#include "LinkManager.h" #include "LinkManager.h"
class QBluetoothDeviceDiscoveryAgent; class QBluetoothDeviceDiscoveryAgent;
class QBluetoothServiceDiscoveryAgent;
class BluetoothData class BluetoothData
{ {
public: public:
BluetoothData() BluetoothData()
{ {
bits = 0;
} }
BluetoothData(const BluetoothData& other) BluetoothData(const BluetoothData& other)
{ {
...@@ -58,18 +60,28 @@ public: ...@@ -58,18 +60,28 @@ public:
} }
bool operator==(const BluetoothData& other) bool operator==(const BluetoothData& other)
{ {
return bits == other.bits && name == other.name && address == other.address; #ifdef __ios__
return uuid == other.uuid && name == other.name;
#else
return name == other.name && address == other.address;
#endif
} }
BluetoothData& operator=(const BluetoothData& other) BluetoothData& operator=(const BluetoothData& other)
{ {
bits = other.bits;
name = other.name; name = other.name;
#ifdef __ios__
uuid = other.uuid;
#else
address = other.address; address = other.address;
#endif
return *this; return *this;
} }
quint32 bits;
QString name; QString name;
#ifdef __ios__
QBluetoothUuid uuid;
#else
QString address; QString address;
#endif
}; };
class BluetoothConfiguration : public LinkConfiguration class BluetoothConfiguration : public LinkConfiguration
...@@ -91,7 +103,7 @@ public: ...@@ -91,7 +103,7 @@ public:
Q_INVOKABLE void stopScan (); Q_INVOKABLE void stopScan ();
QString devName () { return _device.name; } QString devName () { return _device.name; }
QString address () { return _device.address; } QString address ();
QStringList nameList () { return _nameList; } QStringList nameList () { return _nameList; }
bool scanning () { return _deviceDiscover != NULL; } bool scanning () { return _deviceDiscover != NULL; }
...@@ -159,6 +171,11 @@ public slots: ...@@ -159,6 +171,11 @@ public slots:
void deviceConnected (); void deviceConnected ();
void deviceDisconnected (); void deviceDisconnected ();
void deviceError (QBluetoothSocket::SocketError error); void deviceError (QBluetoothSocket::SocketError error);
#ifdef __ios__
void serviceDiscovered (const QBluetoothServiceInfo &info);
void discoveryFinished ();
void discoveryError (QBluetoothServiceDiscoveryAgent::Error error);
#endif
protected: protected:
...@@ -177,12 +194,17 @@ private: ...@@ -177,12 +194,17 @@ private:
bool _hardwareConnect (); bool _hardwareConnect ();
void _restartConnection (); void _restartConnection ();
void _sendBytes (const char* data, qint64 size); void _sendBytes (const char* data, qint64 size);
void _createSocket ();
private: private:
QBluetoothSocket* _targetSocket; QBluetoothSocket* _targetSocket;
QBluetoothDeviceInfo* _targetDevice; #ifdef __ios__
bool _running; QBluetoothServiceDiscoveryAgent* _discoveryAgent;
#endif
bool _shutDown;
}; };
#endif // BTLINK_H #endif // BTLINK_H
...@@ -36,7 +36,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -36,7 +36,7 @@ This file is part of the QGROUNDCONTROL project
#ifndef __mobile__ #ifndef __mobile__
#include "LogReplayLink.h" #include "LogReplayLink.h"
#endif #endif
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
#include "BluetoothLink.h" #include "BluetoothLink.h"
#endif #endif
#ifdef QT_DEBUG #ifdef QT_DEBUG
...@@ -103,7 +103,7 @@ LinkConfiguration* LinkConfiguration::createSettings(int type, const QString& na ...@@ -103,7 +103,7 @@ LinkConfiguration* LinkConfiguration::createSettings(int type, const QString& na
case LinkConfiguration::TypeTcp: case LinkConfiguration::TypeTcp:
config = new TCPConfiguration(name); config = new TCPConfiguration(name);
break; break;
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
case LinkConfiguration::TypeBluetooth: case LinkConfiguration::TypeBluetooth:
config = new BluetoothConfiguration(name); config = new BluetoothConfiguration(name);
break; break;
...@@ -141,10 +141,10 @@ LinkConfiguration* LinkConfiguration::duplicateSettings(LinkConfiguration* sourc ...@@ -141,10 +141,10 @@ LinkConfiguration* LinkConfiguration::duplicateSettings(LinkConfiguration* sourc
case TypeTcp: case TypeTcp:
dupe = new TCPConfiguration(dynamic_cast<TCPConfiguration*>(source)); dupe = new TCPConfiguration(dynamic_cast<TCPConfiguration*>(source));
break; break;
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
case TypeBluetooth: case TypeBluetooth:
dupe = new BluetoothConfiguration(dynamic_cast<BluetoothConfiguration*>(source)); dupe = new BluetoothConfiguration(dynamic_cast<BluetoothConfiguration*>(source));
break; break;
#endif #endif
#ifndef __mobile__ #ifndef __mobile__
case TypeLogReplay: case TypeLogReplay:
......
...@@ -64,7 +64,7 @@ public: ...@@ -64,7 +64,7 @@ public:
#endif #endif
TypeUdp, ///< UDP Link TypeUdp, ///< UDP Link
TypeTcp, ///< TCP Link TypeTcp, ///< TCP Link
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
TypeBluetooth, ///< Bluetooth Link TypeBluetooth, ///< Bluetooth Link
#endif #endif
#if 0 #if 0
......
...@@ -39,10 +39,9 @@ This file is part of the QGROUNDCONTROL project ...@@ -39,10 +39,9 @@ This file is part of the QGROUNDCONTROL project
#include "LinkManager.h" #include "LinkManager.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "QGCApplication.h"
#include "UDPLink.h" #include "UDPLink.h"
#include "TCPLink.h" #include "TCPLink.h"
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
#include "BluetoothLink.h" #include "BluetoothLink.h"
#endif #endif
...@@ -125,7 +124,7 @@ LinkInterface* LinkManager::createConnectedLink(LinkConfiguration* config) ...@@ -125,7 +124,7 @@ LinkInterface* LinkManager::createConnectedLink(LinkConfiguration* config)
case LinkConfiguration::TypeTcp: case LinkConfiguration::TypeTcp:
pLink = new TCPLink(dynamic_cast<TCPConfiguration*>(config)); pLink = new TCPLink(dynamic_cast<TCPConfiguration*>(config));
break; break;
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
case LinkConfiguration::TypeBluetooth: case LinkConfiguration::TypeBluetooth:
pLink = new BluetoothLink(dynamic_cast<BluetoothConfiguration*>(config)); pLink = new BluetoothLink(dynamic_cast<BluetoothConfiguration*>(config));
break; break;
...@@ -361,7 +360,7 @@ void LinkManager::loadLinkConfigurationList() ...@@ -361,7 +360,7 @@ void LinkManager::loadLinkConfigurationList()
case LinkConfiguration::TypeTcp: case LinkConfiguration::TypeTcp:
pLink = (LinkConfiguration*)new TCPConfiguration(name); pLink = (LinkConfiguration*)new TCPConfiguration(name);
break; break;
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
case LinkConfiguration::TypeBluetooth: case LinkConfiguration::TypeBluetooth:
pLink = (LinkConfiguration*)new BluetoothConfiguration(name); pLink = (LinkConfiguration*)new BluetoothConfiguration(name);
break; break;
...@@ -708,7 +707,7 @@ QStringList LinkManager::linkTypeStrings(void) const ...@@ -708,7 +707,7 @@ QStringList LinkManager::linkTypeStrings(void) const
#endif #endif
list += "UDP"; list += "UDP";
list += "TCP"; list += "TCP";
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
list += "Bluetooth"; list += "Bluetooth";
#endif #endif
#ifdef QT_DEBUG #ifdef QT_DEBUG
...@@ -839,7 +838,7 @@ void LinkManager::_fixUnnamed(LinkConfiguration* config) ...@@ -839,7 +838,7 @@ void LinkManager::_fixUnnamed(LinkConfiguration* config)
} }
} }
break; break;
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
case LinkConfiguration::TypeBluetooth: { case LinkConfiguration::TypeBluetooth: {
BluetoothConfiguration* tconfig = dynamic_cast<BluetoothConfiguration*>(config); BluetoothConfiguration* tconfig = dynamic_cast<BluetoothConfiguration*>(config);
if(tconfig) { if(tconfig) {
...@@ -888,3 +887,8 @@ bool LinkManager::isAutoconnectLink(LinkInterface* link) ...@@ -888,3 +887,8 @@ bool LinkManager::isAutoconnectLink(LinkInterface* link)
{ {
return _autoconnectConfigurations.contains(link->getLinkConfiguration()); return _autoconnectConfigurations.contains(link->getLinkConfiguration());
} }
bool LinkManager::isBluetoothAvailable(void)
{
return qgcApp()->isBluetoothAvailable();
}
...@@ -80,6 +80,7 @@ public: ...@@ -80,6 +80,7 @@ public:
Q_PROPERTY(bool autoconnectPixhawk READ autoconnectPixhawk WRITE setAutoconnectPixhawk NOTIFY autoconnectPixhawkChanged) Q_PROPERTY(bool autoconnectPixhawk READ autoconnectPixhawk WRITE setAutoconnectPixhawk NOTIFY autoconnectPixhawkChanged)
Q_PROPERTY(bool autoconnect3DRRadio READ autoconnect3DRRadio WRITE setAutoconnect3DRRadio NOTIFY autoconnect3DRRadioChanged) Q_PROPERTY(bool autoconnect3DRRadio READ autoconnect3DRRadio WRITE setAutoconnect3DRRadio NOTIFY autoconnect3DRRadioChanged)
Q_PROPERTY(bool autoconnectPX4Flow READ autoconnectPX4Flow WRITE setAutoconnectPX4Flow NOTIFY autoconnectPX4FlowChanged) Q_PROPERTY(bool autoconnectPX4Flow READ autoconnectPX4Flow WRITE setAutoconnectPX4Flow NOTIFY autoconnectPX4FlowChanged)
Q_PROPERTY(bool isBluetoothAvailable READ isBluetoothAvailable CONSTANT)
/// LinkInterface Accessor /// LinkInterface Accessor
Q_PROPERTY(QmlObjectListModel* links READ links CONSTANT) Q_PROPERTY(QmlObjectListModel* links READ links CONSTANT)
...@@ -104,12 +105,13 @@ public: ...@@ -104,12 +105,13 @@ public:
// Property accessors // Property accessors
bool anyConnectedLinks(void); bool anyConnectedLinks (void);
bool anyActiveLinks(void); bool anyActiveLinks (void);
bool autoconnectUDP(void) { return _autoconnectUDP; } bool autoconnectUDP (void) { return _autoconnectUDP; }
bool autoconnectPixhawk(void) { return _autoconnectPixhawk; } bool autoconnectPixhawk (void) { return _autoconnectPixhawk; }
bool autoconnect3DRRadio(void) { return _autoconnect3DRRadio; } bool autoconnect3DRRadio (void) { return _autoconnect3DRRadio; }
bool autoconnectPX4Flow(void) { return _autoconnectPX4Flow; } bool autoconnectPX4Flow (void) { return _autoconnectPX4Flow; }
bool isBluetoothAvailable (void);
QmlObjectListModel* links (void) { return &_links; } QmlObjectListModel* links (void) { return &_links; }
QmlObjectListModel* linkConfigurations (void) { return &_linkConfigurations; } QmlObjectListModel* linkConfigurations (void) { return &_linkConfigurations; }
......
...@@ -49,7 +49,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -49,7 +49,7 @@ This file is part of the QGROUNDCONTROL project
#endif #endif
#endif #endif
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
#include <QtBluetooth/QBluetoothSocket> #include <QtBluetooth/QBluetoothSocket>
#endif #endif
...@@ -139,7 +139,7 @@ int main(int argc, char *argv[]) ...@@ -139,7 +139,7 @@ int main(int argc, char *argv[])
#ifndef __ios__ #ifndef __ios__
qRegisterMetaType<QSerialPort::SerialPortError>(); qRegisterMetaType<QSerialPort::SerialPortError>();
#endif #endif
#ifdef __mobile__ #ifdef QGC_ENABLE_BLUETOOTH
qRegisterMetaType<QBluetoothSocket::SocketError>(); qRegisterMetaType<QBluetoothSocket::SocketError>();
qRegisterMetaType<QBluetoothServiceInfo>(); qRegisterMetaType<QBluetoothServiceInfo>();
#endif #endif
......
...@@ -39,9 +39,16 @@ Item { ...@@ -39,9 +39,16 @@ Item {
// No need // No need
} }
QGCLabel {
text: "Bluetooth Not Available"
visible: !QGroundControl.linkManager.isBluetoothAvailable
anchors.centerIn: parent
}
Column { Column {
id: btColumn id: btColumn
spacing: ScreenTools.defaultFontPixelHeight / 2 spacing: ScreenTools.defaultFontPixelHeight / 2
visible: QGroundControl.linkManager.isBluetoothAvailable
ExclusiveGroup { id: linkGroup } ExclusiveGroup { id: linkGroup }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment