LinkManager.h 9.78 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 10


11 12
/// @file
///     @author Lorenz Meier <mavteam@student.ethz.ch>
pixhawk's avatar
pixhawk committed
13

14
#pragma once
pixhawk's avatar
pixhawk committed
15 16

#include <QList>
17
#include <QMultiMap>
18
#include <QMutex>
19

20
#include "LinkConfiguration.h"
21
#include "LinkInterface.h"
Don Gagne's avatar
Don Gagne committed
22
#include "QGCLoggingCategory.h"
23
#include "QGCToolbox.h"
Don Gagne's avatar
Don Gagne committed
24
#include "MAVLinkProtocol.h"
Gus Grubba's avatar
Gus Grubba committed
25
#if !defined(__mobile__)
Don Gagne's avatar
Don Gagne committed
26
#include "LogReplayLink.h"
27
#include "UdpIODevice.h"
dogmaphobic's avatar
dogmaphobic committed
28
#endif
Don Gagne's avatar
Don Gagne committed
29
#include "QmlObjectListModel.h"
30

Gus Grubba's avatar
Gus Grubba committed
31
#ifndef NO_SERIAL_LINK
Don Gagne's avatar
Don Gagne committed
32
    #include "SerialLink.h"
dogmaphobic's avatar
dogmaphobic committed
33
#endif
34

35
#ifdef QT_DEBUG
Don Gagne's avatar
Don Gagne committed
36
    #include "MockLink.h"
37
#endif
38

Don Gagne's avatar
Don Gagne committed
39
Q_DECLARE_LOGGING_CATEGORY(LinkManagerLog)
Don Gagne's avatar
Don Gagne committed
40
Q_DECLARE_LOGGING_CATEGORY(LinkManagerVerboseLog)
Don Gagne's avatar
Don Gagne committed
41

42
class QGCApplication;
43 44
class UDPConfiguration;
class AutoConnectSettings;
45
class LogReplayLink;
46

47
/// @brief Manage communication links
48 49 50 51 52
///
/// The Link Manager organizes the physical Links. It can manage arbitrary
/// links and takes care of connecting them as well assigning the correct
/// protocol instance to transport the link data into the application.

53
class LinkManager : public QGCTool
54
{
pixhawk's avatar
pixhawk committed
55
    Q_OBJECT
56

57
    // Unit Test has access to private constructor/destructor
Don Gagne's avatar
Don Gagne committed
58
    friend class LinkManagerTest;
59

Don Gagne's avatar
Don Gagne committed
60
public:
61
    LinkManager(QGCApplication* app, QGCToolbox* toolbox);
62
    ~LinkManager();
63

64 65 66 67
    Q_PROPERTY(bool isBluetoothAvailable                READ isBluetoothAvailable                                               CONSTANT)
    Q_PROPERTY(QmlObjectListModel*  linkConfigurations  READ _qmlLinkConfigurations                                             NOTIFY linkConfigurationsChanged)
    Q_PROPERTY(QStringList          linkTypeStrings     READ linkTypeStrings                                                    CONSTANT)
    Q_PROPERTY(QStringList          serialBaudRates     READ serialBaudRates                                                    CONSTANT)
68 69 70
    Q_PROPERTY(QStringList          serialPortStrings   READ serialPortStrings                                                  NOTIFY commPortStringsChanged)
    Q_PROPERTY(QStringList          serialPorts         READ serialPorts                                                        NOTIFY commPortsChanged)

71
    /// Create/Edit Link Configuration
72 73 74 75 76 77
    Q_INVOKABLE LinkConfiguration*  createConfiguration         (int type, const QString& name);
    Q_INVOKABLE LinkConfiguration*  startConfigurationEditing   (LinkConfiguration* config);
    Q_INVOKABLE void                cancelConfigurationEditing  (LinkConfiguration* config) { delete config; }
    Q_INVOKABLE bool                endConfigurationEditing     (LinkConfiguration* config, LinkConfiguration* editedConfig);
    Q_INVOKABLE bool                endCreateConfiguration      (LinkConfiguration* config);
    Q_INVOKABLE void                removeConfiguration         (LinkConfiguration* config);
Don Gagne's avatar
Don Gagne committed
78 79 80

    // Property accessors

dogmaphobic's avatar
dogmaphobic committed
81
    bool isBluetoothAvailable       (void);
Don Gagne's avatar
Don Gagne committed
82

83 84 85 86 87
    QList<LinkInterface*> links                 (void);
    QStringList         linkTypeStrings         (void) const;
    QStringList         serialBaudRates         (void);
    QStringList         serialPortStrings       (void);
    QStringList         serialPorts             (void);
88 89 90 91 92 93 94 95 96 97

    /// Load list of link configurations from disk
    void loadLinkConfigurationList();

    /// Save list of link configurations from disk
    void saveLinkConfigurationList();

    /// Suspend automatic confguration updates (during link maintenance for instance)
    void suspendConfigurationUpdates(bool suspend);

98
    /// Sets the flag to suspend the all new connections
99 100
    ///     @param reason User visible reason to suspend connections
    void setConnectionsSuspended(QString reason);
101

102
    /// Sets the flag to allow new connections to be made
103
    void setConnectionsAllowed(void) { _connectionsSuspended = false; }
104

105
    /// Creates, connects (and adds) a link  based on the given configuration instance.
Don Gagne's avatar
Don Gagne committed
106
    /// Link takes ownership of config.
107
    LinkInterface* createConnectedLink(SharedLinkConfigurationPointer& config, bool isPX4Flow = false);
Don Gagne's avatar
Don Gagne committed
108 109 110

    // This should only be used by Qml code
    Q_INVOKABLE void createConnectedLink(LinkConfiguration* config);
111

112
    /// Creates, connects (and adds) a link  based on the given configuration name.
Don Gagne's avatar
Don Gagne committed
113
    LinkInterface* createConnectedLink(const QString& name);
114

115 116 117
    /// Returns pointer to the mavlink forwarding link, or nullptr if it does not exist
    SharedLinkInterfacePointer mavlinkForwardingLink();

Don Gagne's avatar
Don Gagne committed
118 119
    /// Disconnects all existing links
    void disconnectAll(void);
120

121 122
    /// Connect the specified link
    bool connectLink(LinkInterface* link);
123

Don Gagne's avatar
Don Gagne committed
124 125
    /// Disconnect the specified link
    Q_INVOKABLE void disconnectLink(LinkInterface* link);
126

127 128 129 130
    // The following APIs are public but should not be called in normal use. The are mainly exposed
    // here for unit test code.
    void _deleteLink(LinkInterface* link);
    void _addLink(LinkInterface* link);
131

Don Gagne's avatar
Don Gagne committed
132
    // Called to signal app shutdown. Disconnects all links while turning off auto-connect.
Don Gagne's avatar
Don Gagne committed
133
    Q_INVOKABLE void shutdown(void);
Don Gagne's avatar
Don Gagne committed
134

135 136
    Q_INVOKABLE LogReplayLink* startLogReplay(const QString& logFile);

Don Gagne's avatar
Don Gagne committed
137 138 139 140 141
#ifdef QT_DEBUG
    // Only used by unit test tp restart after a shutdown
    void restart(void) { setConnectionsAllowed(); }
#endif

142 143 144
    /// @return true: specified link is an autoconnect link
    bool isAutoconnectLink(LinkInterface* link);

145 146 147
    // Override from QGCTool
    virtual void setToolbox(QGCToolbox *toolbox);

148 149 150 151 152 153 154 155 156 157 158
    /// @return This mavlink channel is never assigned to a vehicle.
    uint8_t reservedMavlinkChannel(void) { return 0; }

    /// If you are going to hold a reference to a LinkInterface* in your object you must reference count it
    /// by using this method to get access to the shared pointer.
    SharedLinkInterfacePointer sharedLinkInterfacePointerForLink(LinkInterface* link);

    bool containsLink(LinkInterface* link);

    SharedLinkConfigurationPointer addConfiguration(LinkConfiguration* config);

159 160
    void startAutoConnectedLinks(void);

161 162 163 164 165 166 167
    /// Reserves a mavlink channel for use
    /// @return Mavlink channel index, 0 for no channels available
    int _reserveMavlinkChannel(void);

    /// Free the specified mavlink channel for re-use
    void _freeMavlinkChannel(int channel);

168
    static const char*  settingsGroup;
Don Gagne's avatar
Don Gagne committed
169

170
signals:
pixhawk's avatar
pixhawk committed
171
    void newLink(LinkInterface* link);
Don Gagne's avatar
Don Gagne committed
172 173

    // Link has been deleted. You may not necessarily get a linkInactive before the link is deleted.
174
    void linkDeleted(LinkInterface* link);
Don Gagne's avatar
Don Gagne committed
175 176

    // Link has been connected, but no Vehicle seen on link yet.
177
    void linkConnected(LinkInterface* link);
Don Gagne's avatar
Don Gagne committed
178 179

    // Link disconnected, all vehicles on link should be gone as well.
180
    void linkDisconnected(LinkInterface* link);
Don Gagne's avatar
Don Gagne committed
181 182 183 184 185 186 187

    // New vehicle has been seen on the link.
    void linkActive(LinkInterface* link, int vehicleId, int vehicleFirmwareType, int vehicleType);

    // No longer hearing from any vehicles on this link.
    void linkInactive(LinkInterface* link);

188
    void commPortStringsChanged();
189 190
    void commPortsChanged();
    void linkConfigurationsChanged();
191

192 193 194
private slots:
    void _linkConnected(void);
    void _linkDisconnected(void);
195
    void _linkConnectionRemoved(LinkInterface* link);
Gus Grubba's avatar
Gus Grubba committed
196
#ifndef NO_SERIAL_LINK
Don Gagne's avatar
Don Gagne committed
197
    void _activeLinkCheck(void);
Don Gagne's avatar
Don Gagne committed
198
#endif
199

200
private:
201
    QmlObjectListModel* _qmlLinkConfigurations  (void) { return &_qmlConfigurations; }
202
    bool _connectionsSuspendedMsg(void);
Don Gagne's avatar
Don Gagne committed
203
    void _updateAutoConnectLinks(void);
204 205
    void _updateSerialPorts();
    void _fixUnnamed(LinkConfiguration* config);
206
    void _removeConfiguration(LinkConfiguration* config);
Don Gagne's avatar
Don Gagne committed
207

Gus Grubba's avatar
Gus Grubba committed
208
#ifndef NO_SERIAL_LINK
Don Gagne's avatar
Don Gagne committed
209
    SerialConfiguration* _autoconnectConfigurationsContainsPort(const QString& portName);
dogmaphobic's avatar
dogmaphobic committed
210
#endif
211

212
    void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message);
213

214 215 216 217 218
    bool    _configUpdateSuspended;                     ///< true: stop updating configuration list
    bool    _configurationsLoaded;                      ///< true: Link configurations have been loaded
    bool    _connectionsSuspended;                      ///< true: all new connections should not be allowed
    QString _connectionsSuspendedReason;                ///< User visible reason for suspension
    QTimer  _portListTimer;
219
    uint32_t _mavlinkChannelsUsedBitMask;
220

221 222
    AutoConnectSettings*    _autoConnectSettings;
    MAVLinkProtocol*        _mavlinkProtocol;
223 224 225 226

    QList<SharedLinkInterfacePointer>       _sharedLinks;
    QList<SharedLinkConfigurationPointer>   _sharedConfigurations;
    QList<SharedLinkConfigurationPointer>   _sharedAutoconnectConfigurations;
227
    QString                                 _autoConnectRTKPort;
228
    QmlObjectListModel                      _qmlConfigurations;
Don Gagne's avatar
Don Gagne committed
229

230
    QMap<QString, int>  _autoconnectWaitList;   ///< key: QGCSerialPortInfo.systemLocation, value: wait count
231
    QStringList _commPortList;
232
    QStringList _commPortDisplayList;
233

Gus Grubba's avatar
Gus Grubba committed
234
#ifndef NO_SERIAL_LINK
235 236 237
    QTimer              _activeLinkCheckTimer;                  ///< Timer which checks for a vehicle showing up on a usb direct link
    QList<SerialLink*>  _activeLinkCheckList;                   ///< List of links we are waiting for a vehicle to show up on
    static const int    _activeLinkCheckTimeoutMSecs = 15000;   ///< Amount of time to wait for a heatbeat. Keep in mind ArduPilot stack heartbeat is slow to come.
Don Gagne's avatar
Don Gagne committed
238
#endif
Don Gagne's avatar
Don Gagne committed
239

240
    static const char*  _defaultUDPLinkName;
241
    static const char*  _mavlinkForwardingLinkName;
242 243
    static const int    _autoconnectUpdateTimerMSecs;
    static const int    _autoconnectConnectDelayMSecs;
244 245

    // NMEA GPS device for GCS position
246
#ifndef __mobile__
247
#ifndef NO_SERIAL_LINK
248 249 250
    QString      _nmeaDeviceName;
    QSerialPort* _nmeaPort;
    uint32_t     _nmeaBaud;
251
    UdpIODevice  _nmeaSocket;
252
#endif
253
#endif
pixhawk's avatar
pixhawk committed
254 255
};