Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
2e3088b8
Commit
2e3088b8
authored
May 06, 2015
by
Don Gagne
Browse files
Merge pull request #1532 from DonLakeFlyer/BurstDownload
New burst download for file transfer
parents
1909dfba
3b60ab27
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
QGCApplication.pro
View file @
2e3088b8
...
...
@@ -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 @
2e3088b8
...
...
@@ -21,18 +21,18 @@
======================================================================*/
#include
"
QGCUAS
FileManagerTest.h"
#include
"FileManagerTest.h"
/// @file
/// @brief
QGCUAS
FileManager unit test. Note: All code here assumes all work between
/// @brief FileManager unit test. Note: All code here assumes all work between
/// the unit test, mack mavlink file server and file manager is happening on
/// the same thread.
///
/// @author Don Gagne <don@thegagnes.com>
UT_REGISTER_TEST
(
QGCUAS
FileManager
Unit
Test
)
UT_REGISTER_TEST
(
FileManagerTest
)
QGCUAS
FileManager
Unit
Test
::
QGCUAS
FileManager
Unit
Test
(
void
)
:
FileManagerTest
::
FileManagerTest
(
void
)
:
_mockFileServer
(
_systemIdQGC
,
_systemIdServer
),
_fileManager
(
NULL
),
_multiSpy
(
NULL
)
...
...
@@ -40,7 +40,7 @@ QGCUASFileManagerUnitTest::QGCUASFileManagerUnitTest(void) :
}
// Called once before all test cases are run
void
QGCUAS
FileManager
Unit
Test
::
initTestCase
(
void
)
void
FileManagerTest
::
initTestCase
(
void
)
{
_mockUAS
=
new
MockUAS
();
Q_CHECK_PTR
(
_mockUAS
);
...
...
@@ -49,28 +49,28 @@ void QGCUASFileManagerUnitTest::initTestCase(void)
_mockUAS
->
setMockMavlinkPlugin
(
&
_mockFileServer
);
}
void
QGCUAS
FileManager
Unit
Test
::
cleanupTestCase
(
void
)
void
FileManagerTest
::
cleanupTestCase
(
void
)
{
delete
_mockUAS
;
}
// Called before every test case
void
QGCUAS
FileManager
Unit
Test
::
init
(
void
)
void
FileManagerTest
::
init
(
void
)
{
UnitTest
::
init
();
Q_ASSERT
(
_multiSpy
==
NULL
);
_fileManager
=
new
QGCUAS
FileManager
(
NULL
,
_mockUAS
,
_systemIdQGC
);
_fileManager
=
new
FileManager
(
NULL
,
_mockUAS
,
_systemIdQGC
);
Q_CHECK_PTR
(
_fileManager
);
// Reset any internal state back to normal
_mockFileServer
.
setErrorMode
(
MockMavlinkFileServer
::
errModeNone
);
_fileListReceived
.
clear
();
connect
(
&
_mockFileServer
,
&
MockMavlinkFileServer
::
messageReceived
,
_fileManager
,
&
QGCUAS
FileManager
::
receiveMessage
);
connect
(
&
_mockFileServer
,
&
MockMavlinkFileServer
::
messageReceived
,
_fileManager
,
&
FileManager
::
receiveMessage
);
connect
(
_fileManager
,
&
QGCUAS
FileManager
::
listEntry
,
this
,
&
QGCUAS
FileManager
Unit
Test
::
listEntry
);
connect
(
_fileManager
,
&
FileManager
::
listEntry
,
this
,
&
FileManagerTest
::
listEntry
);
_rgSignals
[
listEntrySignalIndex
]
=
SIGNAL
(
listEntry
(
const
QString
&
));
_rgSignals
[
listCompleteSignalIndex
]
=
SIGNAL
(
listComplete
(
void
));
...
...
@@ -86,7 +86,7 @@ void QGCUASFileManagerUnitTest::init(void)
}
// Called after every test case
void
QGCUAS
FileManager
Unit
Test
::
cleanup
(
void
)
void
FileManagerTest
::
cleanup
(
void
)
{
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_fileManager
);
...
...
@@ -100,15 +100,16 @@ void QGCUASFileManagerUnitTest::cleanup(void)
UnitTest
::
cleanup
();
}
/// @brief Connected to
QGCUAS
FileManager listEntry signal in order to catch list entries
void
QGCUAS
FileManager
Unit
Test
::
listEntry
(
const
QString
&
entry
)
/// @brief Connected to FileManager listEntry signal in order to catch list entries
void
FileManagerTest
::
listEntry
(
const
QString
&
entry
)
{
// Keep a list of all names received so we can test it for correctness
_fileListReceived
+=
entry
;
}
void
QGCUASFileManagerUnitTest
::
_ackTest
(
void
)
#if 0
void FileManagerTest::_ackTest(void)
{
Q_ASSERT(_fileManager);
Q_ASSERT(_multiSpy);
...
...
@@ -134,7 +135,7 @@ void QGCUASFileManagerUnitTest::_ackTest(void)
_multiSpy->clearAllSignals();
}
void
QGCUAS
FileManager
Unit
Test
::
_noAckTest
(
void
)
void FileManagerTest::_noAckTest(void)
{
Q_ASSERT(_fileManager);
Q_ASSERT(_multiSpy);
...
...
@@ -146,7 +147,7 @@ void QGCUASFileManagerUnitTest::_noAckTest(void)
QCOMPARE(_multiSpy->checkOnlySignalByMask(errorMessageSignalMask), true);
}
void
QGCUAS
FileManager
Unit
Test
::
_resetTest
(
void
)
void FileManagerTest::_resetTest(void)
{
Q_ASSERT(_fileManager);
Q_ASSERT(_multiSpy);
...
...
@@ -158,13 +159,13 @@ void QGCUASFileManagerUnitTest::_resetTest(void)
QVERIFY(_multiSpy->checkNoSignals());
}
void
QGCUAS
FileManager
Unit
Test
::
_listTest
(
void
)
void FileManagerTest::_listTest(void)
{
Q_ASSERT(_fileManager);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
//
QGCUAS
FileManager::listDirectory signalling as follows:
// FileManager::listDirectory signalling as follows:
// Emits a listEntry signal for each list entry
// Emits an errorMessage signal if:
// It gets a Nak back
...
...
@@ -225,32 +226,13 @@ void QGCUASFileManagerUnitTest::_listTest(void)
QVERIFY(_fileListReceived == fileList);
}
void
QGCUASFileManagerUnitTest
::
_validateFileContents
(
const
QString
&
filePath
,
uint8_t
length
)
{
QFile
file
(
filePath
);
// Make sure file size is correct
QCOMPARE
(
file
.
size
(),
(
qint64
)
length
);
// Read data
QVERIFY
(
file
.
open
(
QIODevice
::
ReadOnly
));
QByteArray
bytes
=
file
.
readAll
();
file
.
close
();
// Validate file contents:
// Repeating 0x00, 0x01 .. 0xFF until file is full
for
(
uint8_t
i
=
0
;
i
<
bytes
.
length
();
i
++
)
{
QCOMPARE
((
uint8_t
)
bytes
[
i
],
(
uint8_t
)(
i
&
0xFF
));
}
}
void
QGCUASFileManagerUnitTest
::
_downloadTest
(
void
)
void FileManagerTest::_readDownloadTest(void)
{
Q_ASSERT(_fileManager);
Q_ASSERT(_multiSpy);
Q_ASSERT(_multiSpy->checkNoSignals() == true);
//
QGCUAS
FileManager::downloadPath works as follows:
// FileManager::downloadPath works as follows:
// Sends an Open Command to the server
// Expects an Ack Response back from the server with the correct sequence numner
// Emits an errorMessage signal if it gets a Nak back
...
...
@@ -297,7 +279,7 @@ void QGCUASFileManagerUnitTest::_downloadTest(void)
// Run through the various failure modes for this test case
for (size_t j=0; j<MockMavlinkFileServer::cFailureModes; j++) {
MockMavlinkFileServer::ErrorMode_t errMode = MockMavlinkFileServer::rgFailureModes[j];
qDebug() << "Testing failure mode:" << errMode;
_mockFileServer.setErrorMode(errMode);
...
...
@@ -341,6 +323,7 @@ void QGCUASFileManagerUnitTest::_downloadTest(void)
}
// Run what should be a successful file download test case. No servers errors are being simulated.
_mockFileServer.setErrorMode(MockMavlinkFileServer::errModeNone);
_fileManager->downloadPath(testCase->filename, QDir::temp());
// This should be a succesful download
...
...
@@ -360,3 +343,141 @@ void QGCUASFileManagerUnitTest::_downloadTest(void)
_validateFileContents(filePath, MockMavlinkFileServer::rgFileTestCases[i].length);
}
}
#endif
void
FileManagerTest
::
_streamDownloadTest
(
void
)
{
Q_ASSERT
(
_fileManager
);
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_multiSpy
->
checkNoSignals
()
==
true
);
// FileManager::streamPath works as follows:
// Sends an Open Command to the server
// Expects an Ack Response back from the server with the correct sequence numner
// Emits an errorMessage signal if it gets a Nak back
// Emits an downloadFileLength signal with the file length if it gets back a good Ack
// Sends a single Stream command to the server
// Expects continuous Ack responses back with file contents
// Emits a downloadFileProgress for each ack it gets back
// Sends Terminate command to server when download is complete to close Open command
// Mock file server will signal terminateCommandReceived when it gets a Terminate command
// Sends downloadFileComplete signal to indicate the download is complete
// Emits an errorMessage signal if sequence number is incorrrect on any response
// Emits an errorMessage signal if CRC is incorrect on any responses
// Expected signals if the Open command fails for any reason
quint16
signalMaskOpenFailure
=
errorMessageSignalMask
;
// Expected signals if the Read command fails for any reason
quint16
signalMaskReadFailure
=
downloadFileLengthSignalMask
|
errorMessageSignalMask
;
// Expected signals if the downloadPath command succeeds
quint16
signalMaskDownloadSuccess
=
downloadFileLengthSignalMask
|
downloadFileCompleteSignalMask
;
// Send a bogus path
// We should get a single resetStatusMessages signal
// We should get a single errorMessage signal
_fileManager
->
streamPath
(
"bogus"
,
QDir
::
temp
());
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskOpenFailure
),
true
);
_multiSpy
->
clearAllSignals
();
// Clean previous downloads
for
(
size_t
i
=
0
;
i
<
MockMavlinkFileServer
::
cFileTestCases
;
i
++
)
{
QString
filePath
=
QDir
::
temp
().
absoluteFilePath
(
MockMavlinkFileServer
::
rgFileTestCases
[
i
].
filename
);
if
(
QFile
::
exists
(
filePath
))
{
Q_ASSERT
(
QFile
::
remove
(
filePath
));
}
}
// We setup a spy on the Terminate command signal of the mock file server so that we can determine that a
// Terminate command was correctly sent after the Open/Read commands complete.
QSignalSpy
terminateSpy
(
&
_mockFileServer
,
SIGNAL
(
terminateCommandReceived
()));
// Run through the set of file test cases
for
(
size_t
i
=
0
;
i
<
MockMavlinkFileServer
::
cFileTestCases
;
i
++
)
{
const
MockMavlinkFileServer
::
FileTestCase
*
testCase
=
&
MockMavlinkFileServer
::
rgFileTestCases
[
i
];
// Run through the various failure modes for this test case
for
(
size_t
j
=
0
;
j
<
MockMavlinkFileServer
::
cFailureModes
;
j
++
)
{
MockMavlinkFileServer
::
ErrorMode_t
errMode
=
MockMavlinkFileServer
::
rgFailureModes
[
j
];
qDebug
()
<<
"Testing failure mode:"
<<
errMode
;
_mockFileServer
.
setErrorMode
(
errMode
);
_fileManager
->
streamPath
(
testCase
->
filename
,
QDir
::
temp
());
QTest
::
qWait
(
_ackTimerTimeoutMsecs
);
// Let the file manager timeout
if
(
errMode
==
MockMavlinkFileServer
::
errModeNoSecondResponse
||
errMode
==
MockMavlinkFileServer
::
errModeNakSecondResponse
)
{
// For simulated server errors on subsequent Acks, the first Ack will go through. We must handle things differently depending
// on whether the downloaded file requires multiple packets to complete the download.
if
(
testCase
->
packetCount
!=
1
)
{
// The downloaded file requires multiple Acks to complete. Second Ack should have failed.
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskReadFailure
),
true
);
// Open command succeeded, so we should get a Terminate for the open
QCOMPARE
(
terminateSpy
.
count
(),
1
);
}
else
{
// The downloaded file fits within a single Ack response, hence there is no second Read issued.
// This should result in a successful download.
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskDownloadSuccess
),
true
);
// We should get a single Terminate command to close the Open session
QCOMPARE
(
terminateSpy
.
count
(),
1
);
// Validate file contents
QString
filePath
=
QDir
::
temp
().
absoluteFilePath
(
testCase
->
filename
);
_validateFileContents
(
filePath
,
testCase
->
length
);
}
}
else
{
// For all the other simulated server errors the Open command should have failed. Since the Open failed
// there is no session to terminate, hence no Terminate in this case.
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskOpenFailure
),
true
);
QCOMPARE
(
terminateSpy
.
count
(),
0
);
}
// Cleanup for next iteration
_multiSpy
->
clearAllSignals
();
terminateSpy
.
clear
();
_mockFileServer
.
setErrorMode
(
MockMavlinkFileServer
::
errModeNone
);
}
// Run what should be a successful file download test case. No servers errors are being simulated.
_mockFileServer
.
setErrorMode
(
MockMavlinkFileServer
::
errModeNone
);
_fileManager
->
streamPath
(
testCase
->
filename
,
QDir
::
temp
());
// This should be a succesful download
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
signalMaskDownloadSuccess
),
true
);
// Make sure the file length coming back through the openFileLength signal is correct
QVERIFY
(
_multiSpy
->
getSpyByIndex
(
downloadFileLengthSignalIndex
)
->
takeFirst
().
at
(
0
).
toInt
()
==
testCase
->
length
);
_multiSpy
->
clearAllSignals
();
// We should get a single Terminate command to close the session
QCOMPARE
(
terminateSpy
.
count
(),
1
);
terminateSpy
.
clear
();
// Validate file contents
QString
filePath
=
QDir
::
temp
().
absoluteFilePath
(
MockMavlinkFileServer
::
rgFileTestCases
[
i
].
filename
);
_validateFileContents
(
filePath
,
MockMavlinkFileServer
::
rgFileTestCases
[
i
].
length
);
}
}
void
FileManagerTest
::
_validateFileContents
(
const
QString
&
filePath
,
uint8_t
length
)
{
QFile
file
(
filePath
);
// Make sure file size is correct
QCOMPARE
(
file
.
size
(),
(
qint64
)
length
);
// Read data
QVERIFY
(
file
.
open
(
QIODevice
::
ReadOnly
));
QByteArray
bytes
=
file
.
readAll
();
file
.
close
();
// Validate file contents:
// Repeating 0x00, 0x01 .. 0xFF until file is full
for
(
uint8_t
i
=
0
;
i
<
bytes
.
length
();
i
++
)
{
QCOMPARE
((
uint8_t
)
bytes
[
i
],
(
uint8_t
)(
i
&
0xFF
));
}
}
src/qgcunittest/
QGCUAS
FileManagerTest.h
→
src/qgcunittest/FileManagerTest.h
View file @
2e3088b8
...
...
@@ -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
QGCUAS
FileManager
Unit
Test
:
public
UnitTest
class
FileManagerTest
:
public
UnitTest
{
Q_OBJECT
public:
QGCUAS
FileManager
Unit
Test
(
void
);
FileManagerTest
(
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 @
2e3088b8
...
...
@@ -34,11 +34,11 @@ const size_t MockMavlinkFileServer::cFailureModes = sizeof(MockMavlinkFileServer
const
MockMavlinkFileServer
::
FileTestCase
MockMavlinkFileServer
::
rgFileTestCases
[
MockMavlinkFileServer
::
cFileTestCases
]
=
{
// File fits one Read Ack packet, partially filling data
{
"partial.qgc"
,
sizeof
(((
QGCUAS
FileManager
::
Request
*
)
0
)
->
data
)
-
1
,
false
},
{
"partial.qgc"
,
sizeof
(((
FileManager
::
Request
*
)
0
)
->
data
)
-
1
,
1
,
false
},
// File fits one Read Ack packet, exactly filling all data
{
"exact.qgc"
,
sizeof
(((
QGCUAS
FileManager
::
Request
*
)
0
)
->
data
),
true
},
{
"exact.qgc"
,
sizeof
(((
FileManager
::
Request
*
)
0
)
->
data
),
1
,
true
},
// File is larger than a single Read Ack packets, requires multiple Reads
{
"multi.qgc"
,
sizeof
(((
QGCUAS
FileManager
::
Request
*
)
0
)
->
data
)
+
1
,
tru
e
},
{
"multi.qgc"
,
sizeof
(((
FileManager
::
Request
*
)
0
)
->
data
)
+
1
,
2
,
fals
e
},
};
// We only support a single fixed session
...
...
@@ -54,28 +54,28 @@ MockMavlinkFileServer::MockMavlinkFileServer(uint8_t systemIdQGC, uint8_t system
/// @brief Handles List command requests. Only supports root folder paths.
/// File list returned is set using the setFileList method.
void
MockMavlinkFileServer
::
_listCommand
(
QGCUAS
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_listCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
// FIXME: Does not support directories that span multiple packets
QGCUAS
FileManager
::
Request
ackResponse
;
FileManager
::
Request
ackResponse
;
QString
path
;
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
// We only support root path
path
=
(
char
*
)
&
request
->
data
[
0
];
if
(
!
path
.
isEmpty
()
&&
path
!=
"/"
)
{
_sendNak
(
QGCUAS
FileManager
::
kErrFail
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
return
;
}
// Offset requested is past the end of the list
if
(
request
->
hdr
.
offset
>
(
uint32_t
)
_fileList
.
size
())
{
_sendNak
(
QGCUAS
FileManager
::
kErrEOF
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
return
;
}
ackResponse
.
hdr
.
opcode
=
QGCUAS
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
offset
=
request
->
hdr
.
offset
;
ackResponse
.
hdr
.
size
=
0
;
...
...
@@ -95,21 +95,21 @@ void MockMavlinkFileServer::_listCommand(QGCUASFileManager::Request* request, ui
_emitResponse
(
&
ackResponse
,
outgoingSeqNumber
);
}
else
if
(
_errMode
==
errModeNakSecondResponse
)
{
// Nak error all subsequent requests
_sendNak
(
QGCUAS
FileManager
::
kErrFail
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
return
;
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
// No response for all subsequent requests
return
;
}
else
{
// FIXME: Does not support directories that span multiple packets
_sendNak
(
QGCUAS
FileManager
::
kErrEOF
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdListDirectory
);
}
}
/// @brief Handles Open command requests.
void
MockMavlinkFileServer
::
_openCommand
(
QGCUAS
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_openCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
QGCUAS
FileManager
::
Request
response
;
FileManager
::
Request
response
;
QString
path
;
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
...
...
@@ -129,11 +129,12 @@ void MockMavlinkFileServer::_openCommand(QGCUASFileManager::Request* request, ui
}
}
if
(
!
found
)
{
_sendNak
(
QGCUAS
FileManager
::
kErrFail
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdOpenFileRO
);
return
;
}
response
.
hdr
.
opcode
=
QGCUASFileManager
::
kRspAck
;
response
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
response
.
hdr
.
req_opcode
=
FileManager
::
kCmdOpenFileRO
;
response
.
hdr
.
session
=
_sessionId
;
// Data contains file length
...
...
@@ -143,14 +144,13 @@ void MockMavlinkFileServer::_openCommand(QGCUASFileManager::Request* request, ui
_emitResponse
(
&
response
,
outgoingSeqNumber
);
}
/// @brief Handles Read command requests.
void
MockMavlinkFileServer
::
_readCommand
(
QGCUASFileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_readCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
QGCUAS
FileManager
::
Request
response
;
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
FileManager
::
Request
response
;
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
_sendNak
(
QGCUAS
FileManager
::
kErrFail
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
return
;
}
...
...
@@ -161,7 +161,7 @@ void MockMavlinkFileServer::_readCommand(QGCUASFileManager::Request* request, ui
// If we get here it means the client is requesting additional data past the first request
if
(
_errMode
==
errModeNakSecondResponse
)
{
// Nak error all subsequent requests
_sendNak
(
QGCUAS
FileManager
::
kErrFail
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
return
;
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
// No rsponse for all subsequent requests
...
...
@@ -170,7 +170,7 @@ void MockMavlinkFileServer::_readCommand(QGCUASFileManager::Request* request, ui
}
if
(
readOffset
>=
_readFileLength
)
{
_sendNak
(
QGCUAS
FileManager
::
kErrEOF
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdReadFile
);
return
;
}
...
...
@@ -185,23 +185,76 @@ void MockMavlinkFileServer::_readCommand(QGCUASFileManager::Request* request, ui
response
.
hdr
.
session
=
_sessionId
;
response
.
hdr
.
size
=
cDataBytes
;
response
.
hdr
.
offset
=
request
->
hdr
.
offset
;
response
.
hdr
.
opcode
=
QGCUASFileManager
::
kRspAck
;
response
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
response
.
hdr
.
req_opcode
=
FileManager
::
kCmdReadFile
;
_emitResponse
(
&
response
,
outgoingSeqNumber
);
}
void
MockMavlinkFileServer
::
_streamCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
FileManager
::
Request
response
;
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
return
;
}
uint32_t
readOffset
=
0
;
// offset into file for reading
uint32_t
ackOffset
=
0
;
// offset for ack
uint8_t
cDataAck
;
// number of bytes in ack
while
(
readOffset
<
_readFileLength
)
{
cDataAck
=
0
;
if
(
readOffset
!=
0
)
{
// If we get here it means the client is requesting additional data past the first request
if
(
_errMode
==
errModeNakSecondResponse
)
{
// Nak error all subsequent requests
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
return
;
}
else
if
(
_errMode
==
errModeNoSecondResponse
)
{
// No response for all subsequent requests
return
;
}
}
// Write file bytes. Data is a repeating sequence of 0x00, 0x01, .. 0xFF.
for
(;
cDataAck
<
sizeof
(
response
.
data
)
&&
readOffset
<
_readFileLength
;
readOffset
++
,
cDataAck
++
)
{
response
.
data
[
cDataAck
]
=
readOffset
&
0xFF
;
}
// We should always have written something, otherwise there is something wrong with the code above
Q_ASSERT
(
cDataAck
);
response
.
hdr
.
session
=
_sessionId
;
response
.
hdr
.
size
=
cDataAck
;
response
.
hdr
.
offset
=
ackOffset
;
response
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
response
.
hdr
.
req_opcode
=
FileManager
::
kCmdBurstReadFile
;
_emitResponse
(
&
response
,
outgoingSeqNumber
);
outgoingSeqNumber
=
_nextSeqNumber
(
outgoingSeqNumber
);
ackOffset
+=
cDataAck
;
}
_sendNak
(
FileManager
::
kErrEOF
,
outgoingSeqNumber
,
FileManager
::
kCmdBurstReadFile
);
}
/// @brief Handles Terminate commands
void
MockMavlinkFileServer
::
_terminateCommand
(
QGCUAS
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_terminateCommand
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
uint16_t
outgoingSeqNumber
=
_nextSeqNumber
(
seqNumber
);
if
(
request
->
hdr
.
session
!=
_sessionId
)
{
_sendNak
(
QGCUAS
FileManager
::
kErrInvalidSession
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrInvalidSession
,
outgoingSeqNumber
,
FileManager
::
kCmdTerminateSession
);
return
;
}
_sendAck
(
outgoingSeqNumber
);
_sendAck
(
outgoingSeqNumber
,
FileManager
::
kCmdTerminateSession
);
// Let our test harness know that we got a terminate command. This is used to validate the a Terminate is correctly
// sent after an Open.
emit
terminateCommandReceived
();
...
...
@@ -210,13 +263,13 @@ void MockMavlinkFileServer::_terminateCommand(QGCUASFileManager::Request* reques
/// @brief Handles messages sent to the FTP server.
void
MockMavlinkFileServer
::
sendMessage
(
mavlink_message_t
message
)
{
QGCUAS
FileManager
::
Request
ackResponse
;
FileManager
::
Request
ackResponse
;
Q_ASSERT
(
message
.
msgid
==
MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL
);
mavlink_file_transfer_protocol_t
requestFileTransferProtocol
;
mavlink_msg_file_transfer_protocol_decode
(
&
message
,
&
requestFileTransferProtocol
);
QGCUAS
FileManager
::
Request
*
request
=
(
QGCUAS
FileManager
::
Request
*
)
&
requestFileTransferProtocol
.
payload
[
0
];
FileManager
::
Request
*
request
=
(
FileManager
::
Request
*
)
&
requestFileTransferProtocol
.
payload
[
0
];
Q_ASSERT
(
requestFileTransferProtocol
.
target_system
==
_systemIdServer
);
...
...
@@ -228,56 +281,61 @@ void MockMavlinkFileServer::sendMessage(mavlink_message_t message)
return
;
}
else
if
(
_errMode
==
errModeNakResponse
)
{
// Nak all requests, the actual error send back doesn't really matter as long as it's an error
_sendNak
(
QGCUAS
FileManager
::
kErrFail
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrFail
,
outgoingSeqNumber
,
(
FileManager
::
Opcode
)
request
->
hdr
.
opcode
);
return
;
}
switch
(
request
->
hdr
.
opcode
)
{
case
QGCUAS
FileManager
::
kCmdTestNoAck
:
case
FileManager
::
kCmdTestNoAck
:
// ignored, ack not sent back, for testing only
break
;
case
QGCUAS
FileManager
::
kCmdResetSessions
:
case
FileManager
::
kCmdResetSessions
:
// terminates all sessions
// Fall through to send back Ack
case
QGCUAS
FileManager
::
kCmdNone
:
case
FileManager
::
kCmdNone
:
// ignored, always acked
ackResponse
.
hdr
.
opcode
=
QGCUAS
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
size
=
0
;
_emitResponse
(
&
ackResponse
,
outgoingSeqNumber
);
break
;
case
QGCUAS
FileManager
::
kCmdListDirectory
:
case
FileManager
::
kCmdListDirectory
:
_listCommand
(
request
,
incomingSeqNumber
);
break
;
case
QGCUAS
FileManager
::
kCmdOpenFile
:
case
FileManager
::
kCmdOpenFile
RO
:
_openCommand
(
request
,
incomingSeqNumber
);
break
;
case
QGCUAS
FileManager
::
kCmdReadFile
:
case
FileManager
::
kCmdReadFile
:
_readCommand
(
request
,
incomingSeqNumber
);
break
;
case
QGCUASFileManager
::
kCmdTerminateSession
:
case
FileManager
::
kCmdBurstReadFile
:
_streamCommand
(
request
,
incomingSeqNumber
);
break
;
case
FileManager
::
kCmdTerminateSession
:
_terminateCommand
(
request
,
incomingSeqNumber
);
break
;
default:
// nack for all NYI opcodes
_sendNak
(
QGCUAS
FileManager
::
kErrUnknownCommand
,
outgoingSeqNumber
);
_sendNak
(
FileManager
::
kErrUnknownCommand
,
outgoingSeqNumber
,
(
FileManager
::
Opcode
)
request
->
hdr
.
opcode
);
break
;
}
}
/// @brief Sends an Ack
void
MockMavlinkFileServer
::
_sendAck
(
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_sendAck
(
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
)
{
QGCUAS
FileManager
::
Request
ackResponse
;
FileManager
::
Request
ackResponse
;
ackResponse
.
hdr
.
opcode
=
QGCUASFileManager
::
kRspAck
;
ackResponse
.
hdr
.
opcode
=
FileManager
::
kRspAck
;
ackResponse
.
hdr
.
req_opcode
=
reqOpcode
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
size
=
0
;
...
...
@@ -285,11 +343,12 @@ void MockMavlinkFileServer::_sendAck(uint16_t seqNumber)
}
/// @brief Sends a Nak with the specified error code.
void
MockMavlinkFileServer
::
_sendNak
(
QGCUAS
FileManager
::
ErrorCode
error
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_sendNak
(
FileManager
::
ErrorCode
error
,
uint16_t
seqNumber
,
FileManager
::
Opcode
reqOpcode
)
{
QGCUAS
FileManager
::
Request
nakResponse
;
FileManager
::
Request
nakResponse
;
nakResponse
.
hdr
.
opcode
=
QGCUASFileManager
::
kRspNak
;
nakResponse
.
hdr
.
opcode
=
FileManager
::
kRspNak
;
nakResponse
.
hdr
.
req_opcode
=
reqOpcode
;
nakResponse
.
hdr
.
session
=
0
;
nakResponse
.
hdr
.
size
=
1
;
nakResponse
.
data
[
0
]
=
error
;
...
...
@@ -298,7 +357,7 @@ void MockMavlinkFileServer::_sendNak(QGCUASFileManager::ErrorCode error, uint16_
}
/// @brief Emits a Request through the messageReceived signal.
void
MockMavlinkFileServer
::
_emitResponse
(
QGCUAS
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
void
MockMavlinkFileServer
::
_emitResponse
(
FileManager
::
Request
*
request
,
uint16_t
seqNumber
)
{
mavlink_message_t
mavlinkMessage
;
...
...
src/qgcunittest/MockMavlinkFileServer.h
View file @
2e3088b8
...
...
@@ -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 @
2e3088b8
This diff is collapsed.
Click to expand it.
src/uas/
QGCUAS
FileManager.h
→
src/uas/FileManager.h
View file @
2e3088b8
...
...
@@ -21,29 +21,49 @@
======================================================================*/
#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
);
/// Upload the specified file to the specified location
void
uploadPath
(
const
QString
&
toPath
,
const
QFileInfo
&
uploadFile
);
signals:
/// @brief Signalled whenever an error occurs during the listDirectory or downloadPath methods.
void
errorMessage
(
const
QString
&
msg
);
...
...
@@ -80,23 +100,23 @@ signals:
public
slots
:
void
receiveMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
);
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
,
///< Append
s <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
,
///< Write
s <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,17 @@ 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
kCOCreate
,
// waiting for Create response
};
protected
slots
:
void
_ackTimeout
(
void
);
protected:
bool
_sendOpcodeOnlyCmd
(
uint8_t
opcode
,
OperationState
newOpState
);
void
_setupAckTimeout
(
void
);
void
_clearAckTimeout
(
void
);
...
...
@@ -177,14 +199,15 @@ protected:
void
_sendRequest
(
Request
*
request
);
void
_fillRequestWithString
(
Request
*
request
,
const
QString
&
str
);
void
_openAckResponse
(
Request
*
openAck
);
void
_
re
adAckResponse
(
Request
*
readAck
);
void
_
downlo
adAckResponse
(
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 +226,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 +240,4 @@ protected:
friend
class
MockMavlinkFileServer
;
};
#endif //
QGCUASFILEMANAGER
_H
#endif //
FileManager
_H
src/uas/UAS.h
View file @
2e3088b8
...
...
@@ -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 @
2e3088b8
...
...
@@ -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 @
2e3088b8
...
...
@@ -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 @
2e3088b8
...
...
@@ -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
Supports
Markdown
0%
Try again
or
attach a new 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