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: ...@@ -54,7 +54,7 @@ public:
errModeNoSecondResponse, ///< No response to subsequent request to initial command errModeNoSecondResponse, ///< No response to subsequent request to initial command
errModeNakSecondResponse, ///< Nak subsequent request to initial command errModeNakSecondResponse, ///< Nak subsequent request to initial command
errModeBadCRC, ///< Return response with bad CRC 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; } ErrorMode_t;
/// @brief Sets the error mode for command responses. This allows you to simulate various server errors. /// @brief Sets the error mode for command responses. This allows you to simulate various server errors.
...@@ -89,13 +89,14 @@ signals: ...@@ -89,13 +89,14 @@ signals:
void terminateCommandReceived(void); void terminateCommandReceived(void);
private: private:
void _sendAck(void); void _sendAck(uint16_t seqNumber);
void _sendNak(QGCUASFileManager::ErrorCode error); void _sendNak(QGCUASFileManager::ErrorCode error, uint16_t seqNumber);
void _emitResponse(QGCUASFileManager::Request* request); void _emitResponse(QGCUASFileManager::Request* request, uint16_t seqNumber);
void _listCommand(QGCUASFileManager::Request* request); void _listCommand(QGCUASFileManager::Request* request, uint16_t seqNumber);
void _openCommand(QGCUASFileManager::Request* request); void _openCommand(QGCUASFileManager::Request* request, uint16_t seqNumber);
void _readCommand(QGCUASFileManager::Request* request); void _readCommand(QGCUASFileManager::Request* request, uint16_t seqNumber);
void _terminateCommand(QGCUASFileManager::Request* request); void _terminateCommand(QGCUASFileManager::Request* request, uint16_t seqNumber);
uint16_t _nextSeqNumber(uint16_t seqNumber);
QStringList _fileList; ///< List of files returned by List command QStringList _fileList; ///< List of files returned by List command
......
This diff is collapsed.
...@@ -56,7 +56,7 @@ private slots: ...@@ -56,7 +56,7 @@ private slots:
void _noAckTest(void); void _noAckTest(void);
void _resetTest(void); void _resetTest(void);
void _listTest(void); void _listTest(void);
void _openTest(void); void _downloadTest(void);
// Connected to QGCUASFileManager statusMessage signal // Connected to QGCUASFileManager statusMessage signal
void statusMessage(const QString&); void statusMessage(const QString&);
...@@ -68,7 +68,8 @@ private: ...@@ -68,7 +68,8 @@ private:
statusMessageSignalIndex = 0, statusMessageSignalIndex = 0,
errorMessageSignalIndex, errorMessageSignalIndex,
resetStatusMessagesSignalIndex, resetStatusMessagesSignalIndex,
listCompleteSignalIndex,
openFileLengthSignalIndex,
maxSignalIndex maxSignalIndex
}; };
...@@ -76,6 +77,8 @@ private: ...@@ -76,6 +77,8 @@ private:
statusMessageSignalMask = 1 << statusMessageSignalIndex, statusMessageSignalMask = 1 << statusMessageSignalIndex,
errorMessageSignalMask = 1 << errorMessageSignalIndex, errorMessageSignalMask = 1 << errorMessageSignalIndex,
resetStatusMessagesSignalMask = 1 << resetStatusMessagesSignalIndex, resetStatusMessagesSignalMask = 1 << resetStatusMessagesSignalIndex,
listCompleteSignalMask = 1 << listCompleteSignalIndex,
openFileLengthSignalMask = 1 << openFileLengthSignalIndex,
}; };
MockUAS _mockUAS; MockUAS _mockUAS;
......
...@@ -70,7 +70,7 @@ QGCUASFileManager::QGCUASFileManager(QObject* parent, UASInterface* uas) : ...@@ -70,7 +70,7 @@ QGCUASFileManager::QGCUASFileManager(QObject* parent, UASInterface* uas) :
QObject(parent), QObject(parent),
_currentOperation(kCOIdle), _currentOperation(kCOIdle),
_mav(uas), _mav(uas),
_encdata_seq(0), _lastOutgoingSeqNumber(0),
_activeSession(0) _activeSession(0)
{ {
bool connected = connect(&_ackTimer, SIGNAL(timeout()), this, SLOT(_ackTimeout())); bool connected = connect(&_ackTimer, SIGNAL(timeout()), this, SLOT(_ackTimeout()));
...@@ -104,12 +104,16 @@ void QGCUASFileManager::_openAckResponse(Request* openAck) ...@@ -104,12 +104,16 @@ void QGCUASFileManager::_openAckResponse(Request* openAck)
{ {
_currentOperation = kCORead; _currentOperation = kCORead;
_activeSession = openAck->hdr.session; _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 _readOffset = 0; // Start reading at beginning of file
_readFileAccumulator.clear(); // Start with an empty file _readFileAccumulator.clear(); // Start with an empty file
Request request; Request request;
request.hdr.magic = 'f';
request.hdr.session = _activeSession; request.hdr.session = _activeSession;
request.hdr.opcode = kCmdRead; request.hdr.opcode = kCmdRead;
request.hdr.offset = _readOffset; request.hdr.offset = _readOffset;
...@@ -173,7 +177,6 @@ void QGCUASFileManager::_readAckResponse(Request* readAck) ...@@ -173,7 +177,6 @@ void QGCUASFileManager::_readAckResponse(Request* readAck)
_readOffset += readAck->hdr.size; _readOffset += readAck->hdr.size;
Request request; Request request;
request.hdr.magic = 'f';
request.hdr.session = _activeSession; request.hdr.session = _activeSession;
request.hdr.opcode = kCmdRead; request.hdr.opcode = kCmdRead;
request.hdr.offset = _readOffset; request.hdr.offset = _readOffset;
...@@ -251,23 +254,42 @@ void QGCUASFileManager::receiveMessage(LinkInterface* link, mavlink_message_t me ...@@ -251,23 +254,42 @@ void QGCUASFileManager::receiveMessage(LinkInterface* link, mavlink_message_t me
} }
// XXX: hack to prevent files from videostream to interfere // XXX: hack to prevent files from videostream to interfere
if (message.compid != MAV_COMP_ID_IMU) { // FIXME: magic number
if (message.compid != 50) {
return; return;
} }
_clearAckTimeout();
mavlink_encapsulated_data_t data; mavlink_encapsulated_data_t data;
mavlink_msg_encapsulated_data_decode(&message, &data); mavlink_msg_encapsulated_data_decode(&message, &data);
Request* request = (Request*)&data.data[0]; 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 // 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; _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; 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) { if (request->hdr.opcode == kRspAck) {
...@@ -474,8 +496,6 @@ void QGCUASFileManager::_setupAckTimeout(void) ...@@ -474,8 +496,6 @@ void QGCUASFileManager::_setupAckTimeout(void)
/// @brief Clears the ack timeout timer /// @brief Clears the ack timeout timer
void QGCUASFileManager::_clearAckTimeout(void) void QGCUASFileManager::_clearAckTimeout(void)
{ {
Q_ASSERT(_ackTimer.isActive());
_ackTimer.stop(); _ackTimer.stop();
} }
...@@ -502,7 +522,6 @@ void QGCUASFileManager::_ackTimeout(void) ...@@ -502,7 +522,6 @@ void QGCUASFileManager::_ackTimeout(void)
void QGCUASFileManager::_sendTerminateCommand(void) void QGCUASFileManager::_sendTerminateCommand(void)
{ {
Request request; Request request;
request.hdr.magic = 'f';
request.hdr.session = _activeSession; request.hdr.session = _activeSession;
request.hdr.opcode = kCmdTerminate; request.hdr.opcode = kCmdTerminate;
_sendRequest(&request); _sendRequest(&request);
...@@ -526,9 +545,13 @@ void QGCUASFileManager::_sendRequest(Request* request) ...@@ -526,9 +545,13 @@ void QGCUASFileManager::_sendRequest(Request* request)
mavlink_message_t message; mavlink_message_t message;
_setupAckTimeout(); _setupAckTimeout();
_lastOutgoingSeqNumber++;
request->hdr.magic = kProtocolMagic;
request->hdr.crc32 = crc32(request); request->hdr.crc32 = crc32(request);
// FIXME: Send correct system id instead of harcoded 250 // 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); _mav->sendMessage(message);
} }
...@@ -49,6 +49,7 @@ signals: ...@@ -49,6 +49,7 @@ signals:
void resetStatusMessages(); void resetStatusMessages();
void errorMessage(const QString& msg); void errorMessage(const QString& msg);
void listComplete(void); void listComplete(void);
void openFileLength(unsigned int length);
public slots: public slots:
void receiveMessage(LinkInterface* link, mavlink_message_t message); void receiveMessage(LinkInterface* link, mavlink_message_t message);
...@@ -56,6 +57,7 @@ public slots: ...@@ -56,6 +57,7 @@ public slots:
void downloadPath(const QString& from, const QDir& downloadDir); void downloadPath(const QString& from, const QDir& downloadDir);
protected: protected:
static const uint8_t kProtocolMagic = 'f';
struct RequestHeader struct RequestHeader
{ {
uint8_t magic; ///> Magic byte 'f' to idenitfy FTP protocol uint8_t magic; ///> Magic byte 'f' to idenitfy FTP protocol
...@@ -148,7 +150,8 @@ protected: ...@@ -148,7 +150,8 @@ protected:
QTimer _ackTimer; ///> Used to signal a timeout waiting for an ack QTimer _ackTimer; ///> Used to signal a timeout waiting for an ack
UASInterface* _mav; UASInterface* _mav;
quint16 _encdata_seq;
uint16_t _lastOutgoingSeqNumber; ///< Sequence number sent in last outgoing packet
unsigned _listOffset; ///> offset for the current List operation unsigned _listOffset; ///> offset for the current List operation
QString _listPath; ///> path 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