TCPLink.h 5.53 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1
/*=====================================================================
2

Don Gagne's avatar
Don Gagne committed
3
 QGroundControl Open Source Ground Control Station
4

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

Don Gagne's avatar
Don Gagne committed
7
 This file is part of the QGROUNDCONTROL project
8

Don Gagne's avatar
Don Gagne committed
9 10 11 12
 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.
13

Don Gagne's avatar
Don Gagne committed
14 15 16 17
 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.
18

Don Gagne's avatar
Don Gagne committed
19 20
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
21

Don Gagne's avatar
Don Gagne committed
22 23
 ======================================================================*/

24 25 26 27
/// @file
///     @brief TCP link type for SITL support
///
///     @author Don Gagne <don@thegagnes.com>
Don Gagne's avatar
Don Gagne committed
28 29 30 31 32 33 34 35 36 37

#ifndef TCPLINK_H
#define TCPLINK_H

#include <QString>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QHostAddress>
#include <LinkInterface.h>
38
#include "QGCConfig.h"
39
#include "LinkManager.h"
Don Gagne's avatar
Don Gagne committed
40

41 42 43 44 45 46
// 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
47 48
//#define TCPLINK_READWRITE_DEBUG   // Use to debug data reads/writes

49 50
class TCPLinkUnitTest;

51 52 53 54
#define QGC_TCP_PORT 5760

class TCPConfiguration : public LinkConfiguration
{
Don Gagne's avatar
Don Gagne committed
55 56
    Q_OBJECT

57 58
public:

59 60 61
    Q_PROPERTY(quint16  port    READ port   WRITE setPort   NOTIFY portChanged)
    Q_PROPERTY(QString  host    READ host   WRITE setHost   NOTIFY hostChanged)

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
    /*!
     * @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; }
100
    const QString       host      () { return _address.toString(); }
101 102 103 104 105 106 107

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

    /// From LinkConfiguration
111 112 113 114 115 116
    LinkType    type            () { return LinkConfiguration::TypeTcp; }
    void        copyFrom        (LinkConfiguration* source);
    void        loadSettings    (QSettings& settings, const QString& root);
    void        saveSettings    (QSettings& settings, const QString& root);
    void        updateSettings  ();
    QString     settingsURL     () { return "TcpSettings.qml"; }
117

118 119 120 121
signals:
    void portChanged();
    void hostChanged();

122 123 124 125 126
private:
    QHostAddress _address;
    quint16 _port;
};

Don Gagne's avatar
Don Gagne committed
127 128 129
class TCPLink : public LinkInterface
{
    Q_OBJECT
130

131
    friend class TCPLinkUnitTest;
132
    friend class TCPConfiguration;
133
    friend class LinkManager;
134

135
public:
136
    QTcpSocket* getSocket(void) { return _socket; }
137

138 139
    void signalBytesWritten(void);

140 141 142 143
    // LinkInterface methods
    virtual QString getName(void) const;
    virtual bool    isConnected(void) const;
    virtual void    requestReset(void) {};
144 145 146 147 148

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

150 151 152 153
    // 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);
154

Don Gagne's avatar
Don Gagne committed
155
public slots:
156

157
    // From LinkInterface
158
    void writeBytes(const char* data, qint64 length);
159 160
    void waitForBytesWritten(int msecs);
    void waitForReadyRead(int msecs);
161 162 163 164 165 166 167

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

    // From LinkInterface
    virtual void readBytes(void);

Don Gagne's avatar
Don Gagne committed
168
protected:
169 170
    // From LinkInterface->QThread
    virtual void run(void);
171

Don Gagne's avatar
Don Gagne committed
172
private:
173 174 175
    // Links are only created/destroyed by LinkManager so constructor/destructor is not public
    TCPLink(TCPConfiguration* config);
    ~TCPLink();
176

177
    // From LinkInterface
178
    virtual bool _connect(void);
Don Gagne's avatar
Don Gagne committed
179
    virtual void _disconnect(void);
180 181 182

    bool _hardwareConnect();
    void _restartConnection();
183

Don Gagne's avatar
Don Gagne committed
184
#ifdef TCPLINK_READWRITE_DEBUG
185
    void _writeDebugBytes(const char *data, qint16 size);
Don Gagne's avatar
Don Gagne committed
186
#endif
187

188 189 190
    TCPConfiguration* _config;
    QTcpSocket*       _socket;
    bool              _socketIsConnected;
191

192 193 194 195 196 197 198 199
    quint64 _bitsSentTotal;
    quint64 _bitsSentCurrent;
    quint64 _bitsSentMax;
    quint64 _bitsReceivedTotal;
    quint64 _bitsReceivedCurrent;
    quint64 _bitsReceivedMax;
    quint64 _connectionStartTime;
    QMutex  _statisticsMutex;
Don Gagne's avatar
Don Gagne committed
200 201 202
};

#endif // TCPLINK_H