TCPLink.h 5.04 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
9

Don Gagne's avatar
Don Gagne committed
10

11 12 13 14
/// @file
///     @brief TCP link type for SITL support
///
///     @author Don Gagne <don@thegagnes.com>
Don Gagne's avatar
Don Gagne committed
15

16
#pragma once
Don Gagne's avatar
Don Gagne committed
17 18 19 20 21 22 23

#include <QString>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QHostAddress>
#include <LinkInterface.h>
24
#include "QGCConfig.h"
25
#include "LinkManager.h"
Don Gagne's avatar
Don Gagne committed
26

27 28 29 30 31 32
// Even though QAbstractSocket::SocketError is used in a signal by Qt, Qt doesn't declare it as a meta type.
// This in turn causes debug output to be kicked out about not being able to queue the signal. We declare it
// as a meta type to silence that.
#include <QMetaType>
#include <QTcpSocket>

Don Gagne's avatar
Don Gagne committed
33 34
//#define TCPLINK_READWRITE_DEBUG   // Use to debug data reads/writes

35
class TCPLinkTest;
36

37 38 39 40
#define QGC_TCP_PORT 5760

class TCPConfiguration : public LinkConfiguration
{
Don Gagne's avatar
Don Gagne committed
41 42
    Q_OBJECT

43 44
public:

45 46 47
    Q_PROPERTY(quint16  port    READ port   WRITE setPort   NOTIFY portChanged)
    Q_PROPERTY(QString  host    READ host   WRITE setHost   NOTIFY hostChanged)

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    /*!
     * @brief Regular constructor
     *
     * @param[in] name Configuration (user friendly) name
     */
    TCPConfiguration(const QString& name);

    /*!
     * @brief Copy contructor
     *
     * When manipulating data, you create a copy of the configuration, edit it
     * and then transfer its content to the original (using copyFrom() below). Use this
     * contructor to create an editable copy.
     *
     * @param[in] source Original configuration
     */
    TCPConfiguration(TCPConfiguration* source);

    /*!
     * @brief The TCP port
     *
     * @return Port number
     */
    quint16 port   () { return _port; }

    /*!
     * @brief Set the TCP port
     *
     * @param[in] port Port number
     */
    void setPort   (quint16 port);

    /*!
     * @brief The host address
     *
     * @return Host address
     */
    const QHostAddress& address   () { return _address; }
86
    const QString       host      () { return _address.toString(); }
87 88 89 90 91 92 93

    /*!
     * @brief Set the host address
     *
     * @param[in] address Host address
     */
    void setAddress (const QHostAddress& address);
94
    void setHost    (const QString host);
95 96

    /// From LinkConfiguration
97 98
    LinkType    type            () { return LinkConfiguration::TypeTcp; }
    void        copyFrom        (LinkConfiguration* source);
99
    bool        isHighLatencyAllowed () { return true; }
100 101 102 103
    void        loadSettings    (QSettings& settings, const QString& root);
    void        saveSettings    (QSettings& settings, const QString& root);
    void        updateSettings  ();
    QString     settingsURL     () { return "TcpSettings.qml"; }
104
    QString     settingsTitle   () { return tr("TCP Link Settings"); }
105

106 107 108 109
signals:
    void portChanged();
    void hostChanged();

110 111 112 113 114
private:
    QHostAddress _address;
    quint16 _port;
};

Don Gagne's avatar
Don Gagne committed
115 116 117
class TCPLink : public LinkInterface
{
    Q_OBJECT
118

119
    friend class TCPLinkTest;
120
    friend class TCPConfiguration;
121
    friend class LinkManager;
122

123
public:
124
    QTcpSocket* getSocket(void) { return _socket; }
125

126 127
    void signalBytesWritten(void);

128 129 130 131
    // LinkInterface methods
    virtual QString getName(void) const;
    virtual bool    isConnected(void) const;
    virtual void    requestReset(void) {};
132 133 134 135 136

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

138 139 140 141
    // 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);
142

143
private slots:
144
    // From LinkInterface
145
    void _writeBytes(const QByteArray data);
146 147

public slots:
148 149
    void waitForBytesWritten(int msecs);
    void waitForReadyRead(int msecs);
150 151 152 153 154 155 156

protected slots:
    void _socketError(QAbstractSocket::SocketError socketError);

    // From LinkInterface
    virtual void readBytes(void);

Don Gagne's avatar
Don Gagne committed
157
protected:
158 159
    // From LinkInterface->QThread
    virtual void run(void);
160

Don Gagne's avatar
Don Gagne committed
161
private:
162
    // Links are only created/destroyed by LinkManager so constructor/destructor is not public
163
    TCPLink(SharedLinkConfigurationPointer& config);
164
    ~TCPLink();
165

166
    // From LinkInterface
167
    virtual bool _connect(void);
Don Gagne's avatar
Don Gagne committed
168
    virtual void _disconnect(void);
169 170 171

    bool _hardwareConnect();
    void _restartConnection();
172

Don Gagne's avatar
Don Gagne committed
173
#ifdef TCPLINK_READWRITE_DEBUG
174
    void _writeDebugBytes(const QByteArray data);
Don Gagne's avatar
Don Gagne committed
175
#endif
176

177
    TCPConfiguration* _tcpConfig;
178 179
    QTcpSocket*       _socket;
    bool              _socketIsConnected;
180

181 182 183 184 185 186 187 188
    quint64 _bitsSentTotal;
    quint64 _bitsSentCurrent;
    quint64 _bitsSentMax;
    quint64 _bitsReceivedTotal;
    quint64 _bitsReceivedCurrent;
    quint64 _bitsReceivedMax;
    quint64 _connectionStartTime;
    QMutex  _statisticsMutex;
Don Gagne's avatar
Don Gagne committed
189 190
};