Skip to content
BluetoothLink.h 6.33 KiB
Newer Older
dogmaphobic's avatar
dogmaphobic committed
/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/*!
 * @file
 *   @brief Bluetooth connection for unmanned vehicles
 *   @author Gus Grubba <mavlink@grubba.com>
 *
 */

#ifndef BTLINK_H
#define BTLINK_H

#include <QString>
#include <QList>
#include <QMutex>
#include <QMutexLocker>
#include <QQueue>
#include <QByteArray>
#include <QBluetoothDeviceInfo>
#include <QtBluetooth/QBluetoothSocket>
dogmaphobic's avatar
dogmaphobic committed
#include <qbluetoothserviceinfo.h>
#include <qbluetoothservicediscoveryagent.h>
dogmaphobic's avatar
dogmaphobic committed

#include "QGCConfig.h"
#include "LinkManager.h"

class QBluetoothDeviceDiscoveryAgent;
dogmaphobic's avatar
dogmaphobic committed
class QBluetoothServiceDiscoveryAgent;
class BluetoothData
{
public:
    BluetoothData()
    {
    }
    BluetoothData(const BluetoothData& other)
    {
        *this = other;
    }
    bool operator==(const BluetoothData& other)
    {
dogmaphobic's avatar
dogmaphobic committed
#ifdef __ios__
        return uuid == other.uuid && name == other.name;
#else
        return name == other.name && address == other.address;
#endif
    }
    BluetoothData& operator=(const BluetoothData& other)
    {
        name = other.name;
dogmaphobic's avatar
dogmaphobic committed
#ifdef __ios__
        uuid = other.uuid;
#else
        address = other.address;
dogmaphobic's avatar
dogmaphobic committed
#endif
        return *this;
    }
    QString name;
dogmaphobic's avatar
dogmaphobic committed
#ifdef __ios__
    QBluetoothUuid uuid;
#else
    QString address;
dogmaphobic's avatar
dogmaphobic committed
#endif
dogmaphobic's avatar
dogmaphobic committed
class BluetoothConfiguration : public LinkConfiguration
{
    Q_OBJECT

public:

    BluetoothConfiguration(const QString& name);
    BluetoothConfiguration(BluetoothConfiguration* source);
    ~BluetoothConfiguration();

    Q_PROPERTY(QString      devName     READ devName    WRITE setDevName  NOTIFY devNameChanged)
    Q_PROPERTY(QString      address     READ address                      NOTIFY addressChanged)
    Q_PROPERTY(QStringList  nameList    READ nameList                     NOTIFY nameListChanged)
dogmaphobic's avatar
dogmaphobic committed
    Q_PROPERTY(bool         scanning    READ scanning                     NOTIFY scanningChanged)

    Q_INVOKABLE void        startScan   ();
    Q_INVOKABLE void        stopScan    ();

    QString     devName                 () { return _device.name; }
dogmaphobic's avatar
dogmaphobic committed
    QString     address                 ();
    QStringList nameList                () { return _nameList; }
dogmaphobic's avatar
dogmaphobic committed
    bool        scanning                () { return _deviceDiscover != NULL; }

    BluetoothData    device             () { return _device; }

    void        setDevName              (const QString& name);
dogmaphobic's avatar
dogmaphobic committed

    /// From LinkConfiguration
    LinkType    type                    () { return LinkConfiguration::TypeBluetooth; }
    void        copyFrom                (LinkConfiguration* source);
    void        loadSettings            (QSettings& settings, const QString& root);
    void        saveSettings            (QSettings& settings, const QString& root);
    void        updateSettings          ();
    bool        isAutoConnectAllowed    () { return false; }
dogmaphobic's avatar
dogmaphobic committed
    QString     settingsURL             () { return "BluetoothSettings.qml"; }

public slots:
    void        deviceDiscovered        (QBluetoothDeviceInfo info);
    void        doneScanning            ();

signals:
    void        newDevice               (QBluetoothDeviceInfo info);
    void        devNameChanged          ();
dogmaphobic's avatar
dogmaphobic committed
    void        addressChanged          ();
    void        nameListChanged         ();
dogmaphobic's avatar
dogmaphobic committed
    void        scanningChanged         ();

private:
    QBluetoothDeviceDiscoveryAgent*     _deviceDiscover;
    BluetoothData                       _device;
    QStringList                         _nameList;
    QList<BluetoothData>                _deviceList;
dogmaphobic's avatar
dogmaphobic committed
};

class BluetoothLink : public LinkInterface
{
    Q_OBJECT

    friend class BluetoothConfiguration;
    friend class LinkManager;

public:
    void    requestReset            () { }
    bool    isConnected             () const;
    QString getName                 () const;

    // Extensive statistics for scientific purposes
    qint64  getConnectionSpeed      () const;
    qint64  getCurrentInDataRate    () const;
    qint64  getCurrentOutDataRate   () const;

    void run();

    // These are left unimplemented in order to cause linker errors which indicate incorrect usage of
    // connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager.
    bool    connect                 (void);
    bool    disconnect              (void);

    LinkConfiguration* getLinkConfiguration() { return _config; }

public slots:
    void    readBytes               ();
    void    deviceConnected         ();
    void    deviceDisconnected      ();
    void    deviceError             (QBluetoothSocket::SocketError error);
dogmaphobic's avatar
dogmaphobic committed
#ifdef __ios__
    void    serviceDiscovered       (const QBluetoothServiceInfo &info);
    void    discoveryFinished       ();
    void    discoveryError          (QBluetoothServiceDiscoveryAgent::Error error);
#endif
dogmaphobic's avatar
dogmaphobic committed

protected:

    BluetoothConfiguration*     _config;
    bool                        _connectState;

private:
    // Links are only created/destroyed by LinkManager so constructor/destructor is not public
    BluetoothLink(BluetoothConfiguration* config);
    ~BluetoothLink();

    // From LinkInterface
    bool _connect               (void);
    void _disconnect            (void);

    bool _hardwareConnect       ();
    void _restartConnection     ();
    void _writeBytes            (const QByteArray bytes);
dogmaphobic's avatar
dogmaphobic committed
    void _createSocket          ();
dogmaphobic's avatar
dogmaphobic committed
    QBluetoothSocket*           _targetSocket;
#ifdef __ios__
    QBluetoothServiceDiscoveryAgent* _discoveryAgent;
#endif

    bool                        _shutDown;

dogmaphobic's avatar
dogmaphobic committed
};

#endif // BTLINK_H