/**************************************************************************** * * (c) 2009-2020 QGROUNDCONTROL PROJECT * * QGroundControl is licensed according to the terms in the file * COPYING.md in the root of the source code directory. * ****************************************************************************/ #pragma once #include #include #include #include #include "UASInterface.h" #include "QGCLoggingCategory.h" #include "QGCMAVLink.h" Q_DECLARE_LOGGING_CATEGORY(FTPManagerLog) class Vehicle; class FTPManager : public QObject { Q_OBJECT friend class Vehicle; public: FTPManager(Vehicle* vehicle); /// Downloads the specified file. /// @param from File to download from vehicle, fully qualified path. May be in the format mavlinkftp://... /// @param toDir Local directory to download file to /// @return true: download has started, false: error, no download /// Signals downloadComplete, commandError, commandProgress bool download(const QString& from, const QString& toDir); signals: void downloadComplete(const QString& file, const QString& errorMsg); // Signals associated with all commands /// Signalled after a command has completed void commandComplete(void); void commandError(const QString& msg); /// Signalled during a lengthy command to show progress /// @param value Amount of progress: 0.0 = none, 1.0 = complete void commandProgress(int value); private slots: void _ackOrNakTimeout(void); private: typedef void (FTPManager::*StateBeginFn) (void); typedef void (FTPManager::*StateAckNakFn) (const MavlinkFTP::Request* ackOrNak); typedef void (FTPManager::*StateTimeoutFn) (void); typedef struct { StateBeginFn beginFn; StateAckNakFn ackNakFn; StateTimeoutFn timeoutFn; } StateFunctions_t; typedef struct { uint32_t offset; uint32_t cBytesMissing; } MissingData_t; typedef struct { uint8_t sessionId; uint32_t expectedOffset; ///< offset which should be coming next uint32_t bytesWritten; QList rgMissingData; QString fullPathOnVehicle; ///< Fully qualified path to file on vehicle QDir toDir; ///< Directory to download file to QString fileName; ///< Filename (no path) for download file uint32_t fileSize; ///< Size of file being downloaded QFile file; int retryCount; void reset() { sessionId = 0; expectedOffset = 0; bytesWritten = 0; retryCount = 0; fileSize = 0; fullPathOnVehicle.clear(); fileName.clear(); rgMissingData.clear(); file.close(); } } DownloadState_t; void _mavlinkMessageReceived (const mavlink_message_t& message); void _startStateMachine (void); void _advanceStateMachine (void); void _openFileROBegin (void); void _openFileROAckOrNak (const MavlinkFTP::Request* ackOrNak); void _openFileROTimeout (void); void _burstReadFileBegin (void); void _burstReadFileAckOrNak (const MavlinkFTP::Request* ackOrNak); void _burstReadFileTimeout (void); void _fillMissingBlocksBegin (void); void _fillMissingBlocksAckOrNak (const MavlinkFTP::Request* ackOrNak); void _fillMissingBlocksTimeout (void); void _resetSessionsBegin (void); void _resetSessionsAckOrNak (const MavlinkFTP::Request* ackOrNak); void _resetSessionsTimeout (void); QString _errorMsgFromNak (const MavlinkFTP::Request* nak); void _sendRequestExpectAck (MavlinkFTP::Request* request); void _downloadCompleteNoError (void) { _downloadComplete(QString()); } void _downloadComplete (const QString& errorMsg); void _emitErrorMessage (const QString& msg); void _fillRequestDataWithString(MavlinkFTP::Request* request, const QString& str); void _fillMissingBlocksWorker (bool firstRequest); void _burstReadFileWorker (bool firstRequest); Vehicle* _vehicle; QList _rgStateMachine; DownloadState_t _downloadState; QTimer _ackOrNakTimeoutTimer; int _currentStateMachineIndex = -1; uint16_t _expectedIncomingSeqNumber = 0; static const int _ackOrNakTimeoutMsecs = 1000; static const int _maxRetry = 3; };