BluetoothLink.h 5.73 KB
Newer Older
1 2 3 4 5 6 7 8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
dogmaphobic's avatar
dogmaphobic committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28


/*!
 * @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
29 30
#include <qbluetoothserviceinfo.h>
#include <qbluetoothservicediscoveryagent.h>
dogmaphobic's avatar
dogmaphobic committed
31 32 33 34 35

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

class QBluetoothDeviceDiscoveryAgent;
dogmaphobic's avatar
dogmaphobic committed
36
class QBluetoothServiceDiscoveryAgent;
dogmaphobic's avatar
dogmaphobic committed
37

38 39 40 41 42 43 44 45 46 47 48 49
class BluetoothData
{
public:
    BluetoothData()
    {
    }
    BluetoothData(const BluetoothData& other)
    {
        *this = other;
    }
    bool operator==(const BluetoothData& other)
    {
dogmaphobic's avatar
dogmaphobic committed
50 51 52 53 54
#ifdef __ios__
        return uuid == other.uuid && name == other.name;
#else
        return name == other.name && address == other.address;
#endif
55 56 57 58
    }
    BluetoothData& operator=(const BluetoothData& other)
    {
        name = other.name;
dogmaphobic's avatar
dogmaphobic committed
59 60 61
#ifdef __ios__
        uuid = other.uuid;
#else
62
        address = other.address;
dogmaphobic's avatar
dogmaphobic committed
63
#endif
64 65 66
        return *this;
    }
    QString name;
dogmaphobic's avatar
dogmaphobic committed
67 68 69
#ifdef __ios__
    QBluetoothUuid uuid;
#else
70
    QString address;
dogmaphobic's avatar
dogmaphobic committed
71
#endif
72 73
};

dogmaphobic's avatar
dogmaphobic committed
74 75 76 77 78 79 80 81 82 83
class BluetoothConfiguration : public LinkConfiguration
{
    Q_OBJECT

public:

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

84 85 86
    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
87 88 89 90 91
    Q_PROPERTY(bool         scanning    READ scanning                     NOTIFY scanningChanged)

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

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

97 98 99
    BluetoothData    device             () { return _device; }

    void        setDevName              (const QString& name);
dogmaphobic's avatar
dogmaphobic committed
100 101 102 103 104 105 106

    /// 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          ();
107
    bool        isAutoConnectAllowed    () { return false; }
dogmaphobic's avatar
dogmaphobic committed
108 109 110 111 112 113 114 115
    QString     settingsURL             () { return "BluetoothSettings.qml"; }

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

signals:
    void        newDevice               (QBluetoothDeviceInfo info);
116
    void        devNameChanged          ();
dogmaphobic's avatar
dogmaphobic committed
117
    void        addressChanged          ();
118
    void        nameListChanged         ();
dogmaphobic's avatar
dogmaphobic committed
119 120 121 122
    void        scanningChanged         ();

private:
    QBluetoothDeviceDiscoveryAgent*     _deviceDiscover;
123 124 125
    BluetoothData                       _device;
    QStringList                         _nameList;
    QList<BluetoothData>                _deviceList;
dogmaphobic's avatar
dogmaphobic committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
};

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
159 160 161 162 163
#ifdef __ios__
    void    serviceDiscovered       (const QBluetoothServiceInfo &info);
    void    discoveryFinished       ();
    void    discoveryError          (QBluetoothServiceDiscoveryAgent::Error error);
#endif
dogmaphobic's avatar
dogmaphobic committed
164 165 166 167 168 169 170 171

protected:

    BluetoothConfiguration*     _config;
    bool                        _connectState;

private:
    // Links are only created/destroyed by LinkManager so constructor/destructor is not public
172
    BluetoothLink(SharedLinkConfigurationPointer& config);
dogmaphobic's avatar
dogmaphobic committed
173 174 175 176 177 178 179 180
    ~BluetoothLink();

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

    bool _hardwareConnect       ();
    void _restartConnection     ();
181 182

private slots:
183
    void _writeBytes            (const QByteArray bytes);
184 185

private:
dogmaphobic's avatar
dogmaphobic committed
186
    void _createSocket          ();
dogmaphobic's avatar
dogmaphobic committed
187 188 189

private:

dogmaphobic's avatar
dogmaphobic committed
190 191 192 193 194 195 196
    QBluetoothSocket*           _targetSocket;
#ifdef __ios__
    QBluetoothServiceDiscoveryAgent* _discoveryAgent;
#endif

    bool                        _shutDown;

dogmaphobic's avatar
dogmaphobic committed
197 198 199
};

#endif // BTLINK_H