Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
bf9553bb
Commit
bf9553bb
authored
May 03, 2015
by
Don Gagne
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New burst download for file transfer
parent
3520241e
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
520 additions
and
293 deletions
+520
-293
QGCApplication.pro
QGCApplication.pro
+2
-2
FileManagerTest.cc
src/qgcunittest/FileManagerTest.cc
+161
-40
FileManagerTest.h
src/qgcunittest/FileManagerTest.h
+14
-11
MockMavlinkFileServer.cc
src/qgcunittest/MockMavlinkFileServer.cc
+105
-46
MockMavlinkFileServer.h
src/qgcunittest/MockMavlinkFileServer.h
+11
-9
FileManager.cc
src/uas/FileManager.cc
+150
-129
FileManager.h
src/uas/FileManager.h
+62
-39
UAS.h
src/uas/UAS.h
+4
-4
UASInterface.h
src/uas/UASInterface.h
+2
-2
QGCUASFileView.cc
src/ui/QGCUASFileView.cc
+6
-8
QGCUASFileView.h
src/ui/QGCUASFileView.h
+3
-3
No files found.
QGCApplication.pro
View file @
bf9553bb
...
...
@@ -267,7 +267,7 @@ HEADERS += \
src
/
QmlControls
/
ParameterEditorController
.
h
\
src
/
QmlControls
/
ScreenTools
.
h
\
src
/
uas
/
QGCMAVLinkUASFactory
.
h
\
src
/
uas
/
QGCUAS
FileManager
.
h
\
src
/
uas
/
FileManager
.
h
\
src
/
uas
/
UAS
.
h
\
src
/
uas
/
UASInterface
.
h
\
src
/
uas
/
UASManager
.
h
\
...
...
@@ -399,7 +399,7 @@ SOURCES += \
src
/
QmlControls
/
ParameterEditorController
.
cc
\
src
/
QmlControls
/
ScreenTools
.
cc
\
src
/
uas
/
QGCMAVLinkUASFactory
.
cc
\
src
/
uas
/
QGCUAS
FileManager
.
cc
\
src
/
uas
/
FileManager
.
cc
\
src
/
uas
/
UAS
.
cc
\
src
/
uas
/
UASManager
.
cc
\
src
/
uas
/
UASMessageHandler
.
cc
\
...
...
src/qgcunittest/
QGCUAS
FileManagerTest.cc
→
src/qgcunittest/FileManagerTest.cc
View file @
bf9553bb
This diff is collapsed.
Click to expand it.
src/qgcunittest/
QGCUAS
FileManagerTest.h
→
src/qgcunittest/FileManagerTest.h
View file @
bf9553bb
...
...
@@ -21,8 +21,8 @@
======================================================================*/
#ifndef
QGCUASFILEMANAGER
TEST_H
#define
QGCUASFILEMANAGER
TEST_H
#ifndef
FileManager
TEST_H
#define
FileManager
TEST_H
#include <QObject>
#include <QtTest/QtTest>
...
...
@@ -30,20 +30,20 @@
#include "UnitTest.h"
#include "MockUAS.h"
#include "MockMavlinkFileServer.h"
#include "
QGCUAS
FileManager.h"
#include "FileManager.h"
#include "MultiSignalSpy.h"
/// @file
/// @brief
QGCUAS
FileManager unit test
/// @brief FileManager unit test
///
/// @author Don Gagne <don@thegagnes.com>
class
QGCUASFileManagerUnit
Test
:
public
UnitTest
class
FileManager
Test
:
public
UnitTest
{
Q_OBJECT
public:
QGCUASFileManagerUnit
Test
(
void
);
FileManager
Test
(
void
);
private
slots
:
// Test case initialization
...
...
@@ -53,13 +53,16 @@ private slots:
void
cleanup
(
void
);
// Test cases
#if 0
void _ackTest(void);
void _noAckTest(void);
void _resetTest(void);
void _listTest(void);
void
_downloadTest
(
void
);
// Connected to QGCUASFileManager listEntry signal
void _readDownloadTest(void);
#endif
void
_streamDownloadTest
(
void
);
// Connected to FileManager listEntry signal
void
listEntry
(
const
QString
&
entry
);
private:
...
...
@@ -88,7 +91,7 @@ private:
MockUAS
*
_mockUAS
;
MockMavlinkFileServer
_mockFileServer
;
QGCUAS
FileManager
*
_fileManager
;
FileManager
*
_fileManager
;
MultiSignalSpy
*
_multiSpy
;
static
const
size_t
_cSignals
=
maxSignalIndex
;
...
...
@@ -96,7 +99,7 @@ private:
/// @brief This is the amount of time to wait to allow the FileManager enough time to timeout waiting for an Ack.
/// As such it must be larger than the Ack Timeout used by the FileManager.
static
const
int
_ackTimerTimeoutMsecs
=
QGCUAS
FileManager
::
ackTimerTimeoutMsecs
*
2
;
static
const
int
_ackTimerTimeoutMsecs
=
FileManager
::
ackTimerTimeoutMsecs
*
2
;
QStringList
_fileListReceived
;
};
...
...
src/qgcunittest/MockMavlinkFileServer.cc
View file @
bf9553bb
This diff is collapsed.
Click to expand it.
src/qgcunittest/MockMavlinkFileServer.h
View file @
bf9553bb
...
...
@@ -25,7 +25,7 @@
#define MOCKMAVLINKFILESERVER_H
#include "MockMavlinkInterface.h"
#include "
QGCUAS
FileManager.h"
#include "FileManager.h"
/// @file
/// @brief Mock implementation of Mavlink FTP server. Used as mavlink plugin to MockUAS.
...
...
@@ -77,7 +77,8 @@ public:
struct
FileTestCase
{
const
char
*
filename
;
///< Filename to download
uint8_t
length
;
///< Length of file in bytes
bool
fMultiPacketResponse
;
///< true: multiple acks required to download, false: single ack contains entire download
int
packetCount
;
///< Number of packets required for data
bool
exactFit
;
///< true: last packet is exact fit, false: last packet is partially filled
};
/// @brief The numbers of test cases in the rgFileTestCases array.
...
...
@@ -91,13 +92,14 @@ signals:
void
terminateCommandReceived
(
void
);
private:
void
_sendAck
(
uint16_t
seqNumber
);
void
_sendNak
(
QGCUASFileManager
::
ErrorCode
error
,
uint16_t
seqNumber
);
void
_emitResponse
(
QGCUASFileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_listCommand
(
QGCUASFileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_openCommand
(
QGCUASFileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_readCommand
(
QGCUASFileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_terminateCommand
(
QGCUASFileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_sendAck
(
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
);
void
_sendNak
(
FileManager
::
ErrorCode
error
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
);
void
_emitResponse
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_listCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_openCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_readCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_streamCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
void
_terminateCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
);
uint16_t
_nextSeqNumber
(
uint16_t
seqNumber
);
QStringList
_fileList
;
///< List of files returned by List command
...
...
src/uas/
QGCUAS
FileManager.cc
→
src/uas/FileManager.cc
View file @
bf9553bb
This diff is collapsed.
Click to expand it.
src/uas/
QGCUAS
FileManager.h
→
src/uas/FileManager.h
View file @
bf9553bb
...
...
@@ -21,29 +21,46 @@
======================================================================*/
#ifndef
QGCUAS
FILEMANAGER_H
#define
QGCUAS
FILEMANAGER_H
#ifndef FILEMANAGER_H
#define FILEMANAGER_H
#include <QObject>
#include <QDir>
#include "UASInterface.h"
#include "QGCLoggingCategory.h"
class
QGCUASFileManager
:
public
QObject
Q_DECLARE_LOGGING_CATEGORY
(
FileManagerLog
)
class
FileManager
:
public
QObject
{
Q_OBJECT
public:
QGCUAS
FileManager
(
QObject
*
parent
,
UASInterface
*
uas
,
uint8_t
unitTestSystemIdQGC
=
0
);
FileManager
(
QObject
*
parent
,
UASInterface
*
uas
,
uint8_t
unitTestSystemIdQGC
=
0
);
/// These methods are only used for testing purposes.
bool
_sendCmdTestAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdNone
,
kCOAck
);
};
bool
_sendCmdTestNoAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdTestNoAck
,
kCOAck
);
};
bool
_sendCmdReset
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdResetSessions
,
kCOAck
);
};
///
@brief
Timeout in msecs to wait for an Ack time come back. This is public so we can write unit tests which wait long enough
/// Timeout in msecs to wait for an Ack time come back. This is public so we can write unit tests which wait long enough
/// for the FileManager to timeout.
static
const
int
ackTimerTimeoutMsecs
=
1000
;
static
const
int
ackTimerTimeoutMsecs
=
1000
0
;
/// Downloads the specified file.
/// @param from File to download from UAS, fully qualified path
/// @param downloadDir Local directory to download file to
void
downloadPath
(
const
QString
&
from
,
const
QDir
&
downloadDir
);
/// Stream downloads the specified file.
/// @param from File to download from UAS, fully qualified path
/// @param downloadDir Local directory to download file to
void
streamPath
(
const
QString
&
from
,
const
QDir
&
downloadDir
);
/// Lists the specified directory. Emits listEntry signal for each entry, followed by listComplete signal.
/// @param dirPath Fully qualified path to list
void
listDirectory
(
const
QString
&
dirPath
);
signals:
/// @brief Signalled whenever an error occurs during the listDirectory or downloadPath methods.
void
errorMessage
(
const
QString
&
msg
);
...
...
@@ -83,20 +100,23 @@ public slots:
void
listDirectory
(
const
QString
&
dirPath
);
void
downloadPath
(
const
QString
&
from
,
const
QDir
&
downloadDir
);
void
uploadPath
(
const
QString
&
toPath
,
const
QFileInfo
&
uploadFile
);
private
slots
:
void
_ackTimeout
(
void
);
protected:
private:
/// @brief This is the fixed length portion of the protocol data. Trying to pack structures across differing compilers is
/// questionable, so we pad the structure ourselves to 32 bit alignment which should get us what we want.
struct
RequestHeader
{
uint16_t
seqNumber
;
///< sequence number for message
uint8_t
session
;
///< Session id for read and write commands
uint8_t
opcode
;
///< Command opcode
uint8_t
size
;
///< Size of data
uint8_t
req_opcode
;
///< Request opcode returned in kRspAck, kRspNak message
uint8_t
padding
[
2
];
///< 32 bit aligment padding
uint32_t
offset
;
///< Offsets for List and Read commands
uint16_t
seqNumber
;
///< sequence number for message
uint8_t
session
;
///< Session id for read and write commands
uint8_t
opcode
;
///< Command opcode
uint8_t
size
;
///< Size of data
uint8_t
req_opcode
;
///< Request opcode returned in kRspAck, kRspNak message
uint8_t
burstComplete
;
///< Only used if req_opcode=kCmdBurstReadFile - 1: set of burst packets complete, 0: More burst packets coming.
uint8_t
padding
;
///< 32 bit aligment padding
uint32_t
offset
;
///< Offsets for List and Read commands
};
struct
Request
...
...
@@ -108,7 +128,7 @@ protected:
// The entire Request must fit into the payload member of the mavlink_file_transfer_protocol_t structure. We use as many leftover bytes
// after we use up space for the RequestHeader for the data portion of the Request.
uint8_t
data
[
sizeof
(((
mavlink_file_transfer_protocol_t
*
)
0
)
->
payload
)
-
sizeof
(
RequestHeader
)];
// File length returned by Open command
uint32_t
openFileLength
;
...
...
@@ -119,17 +139,22 @@ protected:
enum
Opcode
{
kCmdNone
,
///< ignored, always acked
kCmdNone
,
///< ignored, always acked
kCmdTerminateSession
,
///< Terminates open Read session
kCmdResetSessions
,
///< Terminates all open Read sessions
kCmdListDirectory
,
///< List files in <path> from <offset>
kCmdOpenFile
,
///< Opens file at <path> for reading, returns <session>
kCmdReadFile
,
///< Reads <size> bytes from <offset> in <session>
kCmdCreateFile
,
///< Creates file at <path> for writing, returns <session>
kCmdWriteFile
,
///< Appends <size> bytes to file
in <session>
kCmdRemoveFile
,
///< Remove file at <path>
kCmdResetSessions
,
///< Terminates all open Read sessions
kCmdListDirectory
,
///< List files in <path> from <offset>
kCmdOpenFile
RO
,
///< Opens file at <path> for reading, returns <session>
kCmdReadFile
,
///< Reads <size> bytes from <offset> in <session>
kCmdCreateFile
,
///< Creates file at <path> for writing, returns <session>
kCmdWriteFile
,
///< Writes <size> bytes to <offset>
in <session>
kCmdRemoveFile
,
///< Remove file at <path>
kCmdCreateDirectory
,
///< Creates directory at <path>
kCmdRemoveDirectory
,
///< Removes Directory at <path>, must be empty
kCmdOpenFileWO
,
///< Opens file at <path> for writing, returns <session>
kCmdTruncateFile
,
///< Truncate file at <path> to <offset> length
kCmdRename
,
///< Rename <path1> to <path2>
kCmdCalcFileCRC32
,
///< Calculate CRC32 for file at <path>
kCmdBurstReadFile
,
///< Burst download session file
kRspAck
=
128
,
///< Ack response
kRspNak
,
///< Nak response
...
...
@@ -155,20 +180,16 @@ protected:
enum
OperationState
{
kCOIdle
,
// not doing anything
kCOAck
,
// waiting for an Ack
kCOList
,
// waiting for List response
kCOOpen
,
// waiting for Open response
kCORead
,
// waiting for Read response
kCOCreate
,
// waiting for Create response
kCOWrite
,
// waiting for Write response
kCOIdle
,
// not doing anything
kCOAck
,
// waiting for an Ack
kCOList
,
// waiting for List response
kCOOpenRead
,
// waiting for Open response followed by Read download
kCOOpenStream
,
// waiting for Open response, followed by Stream download
kCORead
,
// waiting for Read response
kCOBurst
,
// waiting for Burst response
kCOWrite
,
// waiting for Write response
};
protected
slots
:
void
_ackTimeout
(
void
);
protected:
bool
_sendOpcodeOnlyCmd
(
uint8_t
opcode
,
OperationState
newOpState
);
void
_setupAckTimeout
(
void
);
void
_clearAckTimeout
(
void
);
...
...
@@ -177,14 +198,15 @@ protected:
void
_sendRequest
(
Request
*
request
);
void
_fillRequestWithString
(
Request
*
request
,
const
QString
&
str
);
void
_openAckResponse
(
Request
*
openAck
);
void
_
readAckResponse
(
Request
*
readAck
);
void
_
downloadAckResponse
(
Request
*
readAck
,
bool
readFile
);
void
_listAckResponse
(
Request
*
listAck
);
void
_createAckResponse
(
Request
*
createAck
);
void
_writeAckResponse
(
Request
*
writeAck
);
void
_writeFileDatablock
(
void
);
void
_sendListCommand
(
void
);
void
_sendTerminateCommand
(
void
);
void
_closeReadSession
(
bool
success
);
void
_closeDownloadSession
(
bool
success
);
void
_downloadWorker
(
const
QString
&
from
,
const
QDir
&
downloadDir
,
bool
readFile
);
static
QString
errorString
(
uint8_t
errorCode
);
...
...
@@ -203,6 +225,7 @@ protected:
uint32_t
_writeOffset
;
///< current write offset
uint32_t
_writeSize
;
///< current write data size
uint32_t
_writeFileSize
;
///< current write file size
uint32_t
_downloadOffset
;
///< current download offset
QByteArray
_readFileAccumulator
;
///< Holds file being downloaded
QByteArray
_writeFileAccumulator
;
///< Holds file being uploaded
QDir
_readFileDownloadDir
;
///< Directory to download file to
...
...
@@ -216,4 +239,4 @@ protected:
friend
class
MockMavlinkFileServer
;
};
#endif //
QGCUASFILEMANAGER
_H
#endif //
FileManager
_H
src/uas/UAS.h
View file @
bf9553bb
...
...
@@ -40,7 +40,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCFlightGearLink.h"
#include "QGCJSBSimLink.h"
#include "QGCXPlaneLink.h"
#include "
QGCUAS
FileManager.h"
#include "FileManager.h"
Q_DECLARE_LOGGING_CATEGORY
(
UASLog
)
...
...
@@ -332,7 +332,7 @@ public:
bool
isFixedWing
();
friend
class
UASWaypointManager
;
friend
class
QGCUAS
FileManager
;
friend
class
FileManager
;
protected:
//COMMENTS FOR TEST UNIT
/// LINK ID AND STATUS
...
...
@@ -435,7 +435,7 @@ protected: //COMMENTS FOR TEST UNIT
double
groundSpeed
;
///< Groundspeed
double
bearingToWaypoint
;
///< Bearing to next waypoint
UASWaypointManager
waypointManager
;
QGCUAS
FileManager
fileManager
;
FileManager
fileManager
;
/// ATTITUDE
bool
attitudeKnown
;
///< True if attitude was received, false else
...
...
@@ -487,7 +487,7 @@ public:
return
&
waypointManager
;
}
virtual
QGCUAS
FileManager
*
getFileManager
()
{
virtual
FileManager
*
getFileManager
()
{
return
&
fileManager
;
}
...
...
src/uas/UASInterface.h
View file @
bf9553bb
...
...
@@ -42,7 +42,7 @@ This file is part of the QGROUNDCONTROL project
#include "ProtocolInterface.h"
#include "UASWaypointManager.h"
class
QGCUAS
FileManager
;
class
FileManager
;
enum
BatteryType
{
...
...
@@ -132,7 +132,7 @@ public:
/** @brief Get reference to the waypoint manager **/
virtual
UASWaypointManager
*
getWaypointManager
(
void
)
=
0
;
virtual
QGCUAS
FileManager
*
getFileManager
()
=
0
;
virtual
FileManager
*
getFileManager
()
=
0
;
/** @brief Send a message over this link (to this or to all UAS on this link) */
virtual
void
sendMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
)
=
0
;
...
...
src/ui/QGCUASFileView.cc
View file @
bf9553bb
...
...
@@ -22,14 +22,14 @@
======================================================================*/
#include "QGCUASFileView.h"
#include "uas/
QGCUAS
FileManager.h"
#include "uas/FileManager.h"
#include "QGCFileDialog.h"
#include <QFileDialog>
#include <QDir>
#include <QDebug>
QGCUASFileView
::
QGCUASFileView
(
QWidget
*
parent
,
QGCUAS
FileManager
*
manager
)
:
QGCUASFileView
::
QGCUASFileView
(
QWidget
*
parent
,
FileManager
*
manager
)
:
QWidget
(
parent
),
_manager
(
manager
),
_listInProgress
(
false
),
...
...
@@ -83,13 +83,12 @@ void QGCUASFileView::_downloadFile(void)
path
.
prepend
(
"/"
+
name
);
item
=
item
->
parent
();
}
while
(
item
);
qDebug
()
<<
"Download: "
<<
path
;
_ui
.
downloadButton
->
setEnabled
(
false
);
_downloadInProgress
=
true
;
_connectDownloadSignals
();
_manager
->
download
Path
(
path
,
QDir
(
downloadToHere
));
_manager
->
stream
Path
(
path
,
QDir
(
downloadToHere
));
}
}
...
...
@@ -163,7 +162,7 @@ void QGCUASFileView::_downloadProgress(unsigned int bytesReceived)
}
}
/// @brief Called when the download associated with the
QGCUAS
FileManager::downloadPath command completes.
/// @brief Called when the download associated with the FileManager::downloadPath command completes.
void
QGCUASFileView
::
_downloadComplete
(
void
)
{
Q_ASSERT
(
_downloadInProgress
);
...
...
@@ -305,11 +304,10 @@ void QGCUASFileView::_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetIt
void
QGCUASFileView
::
_requestDirectoryList
(
const
QString
&
dir
)
{
qDebug
()
<<
"List:"
<<
dir
;
_manager
->
listDirectory
(
dir
);
}
/// @brief Connects to the signals associated with the
QGCUAS
FileManager::downloadPath method. We only leave these signals connected
/// @brief Connects to the signals associated with the FileManager::downloadPath method. We only leave these signals connected
/// while a download because there may be multiple UAS, which in turn means multiple QGCUASFileView instances. We only want the signals
/// connected to the active FileView which is doing the current download.
void
QGCUASFileView
::
_connectDownloadSignals
(
void
)
...
...
@@ -335,7 +333,7 @@ void QGCUASFileView::_disconnectDownloadSignals(void)
disconnect
(
_manager
,
SIGNAL
(
errorMessage
(
const
QString
&
)),
this
,
SLOT
(
_downloadErrorMessage
(
const
QString
&
)));
}
/// @brief Connects to the signals associated with the
QGCUAS
FileManager::listDirectory method. We only leave these signals connected
/// @brief Connects to the signals associated with the FileManager::listDirectory method. We only leave these signals connected
/// while a download because there may be multiple UAS, which in turn means multiple QGCUASFileView instances. We only want the signals
/// connected to the active FileView which is doing the current download.
void
QGCUASFileView
::
_connectListSignals
(
void
)
...
...
src/ui/QGCUASFileView.h
View file @
bf9553bb
...
...
@@ -27,7 +27,7 @@
#include <QWidget>
#include <QTreeWidgetItem>
#include "uas/
QGCUAS
FileManager.h"
#include "uas/FileManager.h"
#include "ui_QGCUASFileView.h"
class
QGCUASFileView
:
public
QWidget
...
...
@@ -35,10 +35,10 @@ class QGCUASFileView : public QWidget
Q_OBJECT
public:
explicit
QGCUASFileView
(
QWidget
*
parent
,
QGCUAS
FileManager
*
manager
);
explicit
QGCUASFileView
(
QWidget
*
parent
,
FileManager
*
manager
);
protected:
QGCUAS
FileManager
*
_manager
;
FileManager
*
_manager
;
private
slots
:
void
_refreshTree
(
void
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment