Commit 93a24d4b authored by Don Gagne's avatar Don Gagne

More FTP support plus unit testing

Added:
- sequence numbers
- better filtering for image encapsulated data messages versus FTP
- directory list now contains file sizes
- open command now returns file size in data
parent 92af5125
This diff is collapsed.
......@@ -54,7 +54,7 @@ public:
errModeNoSecondResponse, ///< No response to subsequent request to initial command
errModeNakSecondResponse, ///< Nak subsequent request to initial command
errModeBadCRC, ///< Return response with bad CRC
errModeBadSequence ///< Return response with bad sequence number, NYI: Waiting on Firmware sequence # support
errModeBadSequence ///< Return response with bad sequence number
} ErrorMode_t;
/// @brief Sets the error mode for command responses. This allows you to simulate various server errors.
......@@ -89,13 +89,14 @@ signals:
void terminateCommandReceived(void);
private:
void _sendAck(void);
void _sendNak(QGCUASFileManager::ErrorCode error);
void _emitResponse(QGCUASFileManager::Request* request);
void _listCommand(QGCUASFileManager::Request* request);
void _openCommand(QGCUASFileManager::Request* request);
void _readCommand(QGCUASFileManager::Request* request);
void _terminateCommand(QGCUASFileManager::Request* request);
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);
uint16_t _nextSeqNumber(uint16_t seqNumber);
QStringList _fileList; ///< List of files returned by List command
......
This diff is collapsed.
......@@ -56,7 +56,7 @@ private slots:
void _noAckTest(void);
void _resetTest(void);
void _listTest(void);
void _openTest(void);
void _downloadTest(void);
// Connected to QGCUASFileManager statusMessage signal
void statusMessage(const QString&);
......@@ -68,7 +68,8 @@ private:
statusMessageSignalIndex = 0,
errorMessageSignalIndex,
resetStatusMessagesSignalIndex,
listCompleteSignalIndex,
openFileLengthSignalIndex,
maxSignalIndex
};
......@@ -76,6 +77,8 @@ private:
statusMessageSignalMask = 1 << statusMessageSignalIndex,
errorMessageSignalMask = 1 << errorMessageSignalIndex,
resetStatusMessagesSignalMask = 1 << resetStatusMessagesSignalIndex,
listCompleteSignalMask = 1 << listCompleteSignalIndex,
openFileLengthSignalMask = 1 << openFileLengthSignalIndex,
};
MockUAS _mockUAS;
......
......@@ -70,7 +70,7 @@ QGCUASFileManager::QGCUASFileManager(QObject* parent, UASInterface* uas) :
QObject(parent),
_currentOperation(kCOIdle),
_mav(uas),
_encdata_seq(0),
_lastOutgoingSeqNumber(0),
_activeSession(0)
{
bool connected = connect(&_ackTimer, SIGNAL(timeout()), this, SLOT(_ackTimeout()));
......@@ -104,12 +104,16 @@ void QGCUASFileManager::_openAckResponse(Request* openAck)
{
_currentOperation = kCORead;
_activeSession = openAck->hdr.session;
// File length comes back in data
Q_ASSERT(openAck->hdr.size == sizeof(uint32_t));
uint32_t fileLength = *((uint32_t*)openAck->data);
emit openFileLength(fileLength);
_readOffset = 0; // Start reading at beginning of file
_readFileAccumulator.clear(); // Start with an empty file
Request request;
request.hdr.magic = 'f';
request.hdr.session = _activeSession;
request.hdr.opcode = kCmdRead;
request.hdr.offset = _readOffset;
......@@ -173,7 +177,6 @@ void QGCUASFileManager::_readAckResponse(Request* readAck)
_readOffset += readAck->hdr.size;
Request request;
request.hdr.magic = 'f';
request.hdr.session = _activeSession;
request.hdr.opcode = kCmdRead;
request.hdr.offset = _readOffset;
......@@ -251,23 +254,42 @@ void QGCUASFileManager::receiveMessage(LinkInterface* link, mavlink_message_t me
}
// XXX: hack to prevent files from videostream to interfere
if (message.compid != MAV_COMP_ID_IMU) {
// FIXME: magic number
if (message.compid != 50) {
return;
}
_clearAckTimeout();
mavlink_encapsulated_data_t data;
mavlink_msg_encapsulated_data_decode(&message, &data);
Request* request = (Request*)&data.data[0];
if (request->hdr.magic != kProtocolMagic) {
return;
}
_clearAckTimeout();
uint16_t incomingSeqNumber = data.seqnr;
// Make sure we have a good CRC
if (request->hdr.crc32 != crc32(request)) {
quint32 expectedCRC = crc32(request);
quint32 receivedCRC = request->hdr.crc32;
if (receivedCRC != expectedCRC) {
_currentOperation = kCOIdle;
_emitErrorMessage(tr("Bad CRC on received message"));
_emitErrorMessage(tr("Bad CRC on received message: expected(%1) received(%2)").arg(expectedCRC).arg(receivedCRC));
return;
}
// Make sure we have a good sequence number
uint16_t expectedSeqNumber = _lastOutgoingSeqNumber + 1;
if (incomingSeqNumber != expectedSeqNumber) {
_currentOperation = kCOIdle;
_emitErrorMessage(tr("Bad sequence number on received message: expected(%1) received(%2)").arg(expectedSeqNumber).arg(incomingSeqNumber));
return;
}
// Move past the incoming sequence number for next request
_lastOutgoingSeqNumber = incomingSeqNumber;
if (request->hdr.opcode == kRspAck) {
......@@ -474,8 +496,6 @@ void QGCUASFileManager::_setupAckTimeout(void)
/// @brief Clears the ack timeout timer
void QGCUASFileManager::_clearAckTimeout(void)
{
Q_ASSERT(_ackTimer.isActive());
_ackTimer.stop();
}
......@@ -502,7 +522,6 @@ void QGCUASFileManager::_ackTimeout(void)
void QGCUASFileManager::_sendTerminateCommand(void)
{
Request request;
request.hdr.magic = 'f';
request.hdr.session = _activeSession;
request.hdr.opcode = kCmdTerminate;
_sendRequest(&request);
......@@ -526,9 +545,13 @@ void QGCUASFileManager::_sendRequest(Request* request)
mavlink_message_t message;
_setupAckTimeout();
_lastOutgoingSeqNumber++;
request->hdr.magic = kProtocolMagic;
request->hdr.crc32 = crc32(request);
// FIXME: Send correct system id instead of harcoded 250
mavlink_msg_encapsulated_data_pack(250, 0, &message, _encdata_seq, (uint8_t*)request);
// FIXME: What about the component id? Should it be set to something specific.
mavlink_msg_encapsulated_data_pack(250, 0, &message, _lastOutgoingSeqNumber, (uint8_t*)request);
_mav->sendMessage(message);
}
......@@ -49,6 +49,7 @@ signals:
void resetStatusMessages();
void errorMessage(const QString& msg);
void listComplete(void);
void openFileLength(unsigned int length);
public slots:
void receiveMessage(LinkInterface* link, mavlink_message_t message);
......@@ -56,6 +57,7 @@ public slots:
void downloadPath(const QString& from, const QDir& downloadDir);
protected:
static const uint8_t kProtocolMagic = 'f';
struct RequestHeader
{
uint8_t magic; ///> Magic byte 'f' to idenitfy FTP protocol
......@@ -148,7 +150,8 @@ protected:
QTimer _ackTimer; ///> Used to signal a timeout waiting for an ack
UASInterface* _mav;
quint16 _encdata_seq;
uint16_t _lastOutgoingSeqNumber; ///< Sequence number sent in last outgoing packet
unsigned _listOffset; ///> offset for the current List operation
QString _listPath; ///> path for the current List operation
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment