Commit 82446241 authored by Gus Grubba's avatar Gus Grubba

Objectify log processor.

parent 95f0259e
...@@ -106,14 +106,189 @@ MavlinkLogFiles::setUploaded(bool uploaded) ...@@ -106,14 +106,189 @@ MavlinkLogFiles::setUploaded(bool uploaded)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CurrentRunningLog::close() MavlinkLogProcessor::MavlinkLogProcessor()
: _fd(NULL)
, _written(0)
, _sequence(-1)
, _numDrops(0)
, _gotHeader(false)
, _error(false)
, _record(NULL)
{ {
if(fd) { }
fclose(fd);
fd = NULL; //-----------------------------------------------------------------------------
MavlinkLogProcessor::~MavlinkLogProcessor()
{
close();
}
//-----------------------------------------------------------------------------
void
MavlinkLogProcessor::close()
{
if(_fd) {
fclose(_fd);
_fd = NULL;
} }
} }
//-----------------------------------------------------------------------------
bool
MavlinkLogProcessor::valid()
{
return (_fd != NULL) && (_record != NULL);
}
//-----------------------------------------------------------------------------
bool
MavlinkLogProcessor::create(MavlinkLogManager* manager, const QString path, uint8_t id)
{
_fileName.sprintf("%s/%03d-%s%s",
path.toLatin1().data(),
id,
QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz").toLatin1().data(),
kUlogExtension);
_fd = fopen(_fileName.toLatin1().data(), "wb");
if(_fd) {
_record = new MavlinkLogFiles(manager, _fileName, true);
_record->setWriting(true);
_sequence = -1;
return true;
}
return false;
}
//-----------------------------------------------------------------------------
bool
MavlinkLogProcessor::_checkSequence(uint16_t seq, int& num_drops)
{
num_drops = 0;
//-- Check if a sequence is newer than the one previously received and if
// there were dropped messages between the last one and this.
if(_sequence == -1) {
_sequence = seq;
return true;
}
if((uint16_t)_sequence == seq) {
return false;
}
if(seq > (uint16_t)_sequence) {
// Account for wrap-arounds, sequence is 2 bytes
if((seq - _sequence) > (1 << 15)) { // Assume reordered
return false;
}
num_drops = seq - _sequence - 1;
_numDrops += num_drops;
_sequence = seq;
return true;
} else {
if((_sequence - seq) > (1 << 15)) {
num_drops = (1 << 16) - _sequence - 1 + seq;
_numDrops += num_drops;
_sequence = seq;
return true;
}
return false;
}
}
//-----------------------------------------------------------------------------
void
MavlinkLogProcessor::_writeData(void* data, int len)
{
if(!_error) {
_error = fwrite(data, 1, len, _fd) != (size_t)len;
if(!_error) {
_written += len;
if(_record) {
_record->setSize(_written);
}
} else {
qCDebug(MavlinkLogManagerLog) << "File IO error:" << len << "bytes into" << _fileName;
}
}
}
//-----------------------------------------------------------------------------
QByteArray
MavlinkLogProcessor::_writeUlogMessage(QByteArray& data)
{
//-- Write ulog data w/o integrity checking, assuming data starts with a
// valid ulog message. returns the remaining data at the end.
while(data.length() > 2) {
uint8_t* ptr = (uint8_t*)data.data();
int message_length = ptr[0] + (ptr[1] * 256) + 3; // 3 = ULog msg header
if(message_length > data.length())
break;
_writeData(data.data(), message_length);
data.remove(0, message_length);
return data;
}
return data;
}
//-----------------------------------------------------------------------------
bool
MavlinkLogProcessor::processStreamData(uint16_t sequence, uint8_t first_message, QByteArray data)
{
int num_drops = 0;
_error = false;
while(_checkSequence(sequence, num_drops)) {
//-- The first 16 bytes need special treatment (this sounds awfully brittle)
if(!_gotHeader) {
if(data.size() < 16) {
//-- Shouldn't happen but if it does, we might as well close shop.
qCCritical(MavlinkLogManagerLog) << "Corrupt log header. Canceling log download.";
return false;
}
//-- Write header
_writeData(data.data(), 16);
data.remove(0, 16);
_gotHeader = true;
// What about data start offset now that we removed 16 bytes off the start?
}
if(_gotHeader && num_drops > 0) {
if(num_drops > 25) num_drops = 25;
//-- Hocus Pocus
// Write a dropout message. We don't really know the actual duration,
// so just use the number of drops * 10 ms
uint8_t bogus[] = {2, 0, 79, 0, 0};
bogus[3] = num_drops * 10;
_writeData(bogus, sizeof(bogus));
}
if(num_drops > 0) {
_writeUlogMessage(_ulogMessage);
_ulogMessage.clear();
//-- If no usefull information in this message. Drop it.
if(first_message == 255) {
break;
}
if(first_message > 0) {
data.remove(0, first_message);
first_message = 0;
}
}
if(first_message == 255 && _ulogMessage.length() > 0) {
_ulogMessage.append(data);
break;
}
if(_ulogMessage.length()) {
_writeData(_ulogMessage.data(), _ulogMessage.length());
if(first_message) {
_writeData(data.left(first_message).data(), first_message);
}
_ulogMessage.clear();
}
if(first_message) {
data.remove(0, first_message);
}
_ulogMessage = _writeUlogMessage(data);
break;
}
return !_error;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
MavlinkLogManager::MavlinkLogManager(QGCApplication* app) MavlinkLogManager::MavlinkLogManager(QGCApplication* app)
...@@ -125,8 +300,7 @@ MavlinkLogManager::MavlinkLogManager(QGCApplication* app) ...@@ -125,8 +300,7 @@ MavlinkLogManager::MavlinkLogManager(QGCApplication* app)
, _vehicle(NULL) , _vehicle(NULL)
, _logRunning(false) , _logRunning(false)
, _loggingDisabled(false) , _loggingDisabled(false)
, _currentSavingFile(NULL) , _logProcessor(NULL)
, _sequence(0)
, _deleteAfterUpload(false) , _deleteAfterUpload(false)
, _loggingCmdTryCount(0) , _loggingCmdTryCount(0)
{ {
...@@ -382,20 +556,20 @@ MavlinkLogManager::stopLogging() ...@@ -382,20 +556,20 @@ MavlinkLogManager::stopLogging()
//-- Tell vehicle to stop sending logs //-- Tell vehicle to stop sending logs
_vehicle->stopMavlinkLog(); _vehicle->stopMavlinkLog();
} }
if(_currentSavingFile) { if(_logProcessor) {
_currentSavingFile->close(); _logProcessor->close();
if(_currentSavingFile->record) { if(_logProcessor->record()) {
_currentSavingFile->record->setWriting(false); _logProcessor->record()->setWriting(false);
if(_enableAutoUpload) { if(_enableAutoUpload) {
//-- Queue log for auto upload (set selected flag) //-- Queue log for auto upload (set selected flag)
_currentSavingFile->record->setSelected(true); _logProcessor->record()->setSelected(true);
if(!uploading()) { if(!uploading()) {
uploadLog(); uploadLog();
} }
} }
} }
delete _currentSavingFile; delete _logProcessor;
_currentSavingFile = NULL; _logProcessor = NULL;
_logRunning = false; _logRunning = false;
if(_vehicle) { if(_vehicle) {
//-- Setup a timer to make sure vehicle received the command //-- Setup a timer to make sure vehicle received the command
...@@ -619,42 +793,24 @@ MavlinkLogManager::_processCmdAck() ...@@ -619,42 +793,24 @@ MavlinkLogManager::_processCmdAck()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
MavlinkLogManager::_mavlinkLogData(Vehicle* /*vehicle*/, uint8_t /*target_system*/, uint8_t /*target_component*/, uint16_t sequence, uint8_t length, uint8_t first_message, const uint8_t* data, bool /*acked*/) MavlinkLogManager::_mavlinkLogData(Vehicle* /*vehicle*/, uint8_t /*target_system*/, uint8_t /*target_component*/, uint16_t sequence, uint8_t first_message, QByteArray data, bool /*acked*/)
{ {
//-- Disable timer if we got a message before an ACK for the start command //-- Disable timer if we got a message before an ACK for the start command
if(_logRunning) { if(_logRunning) {
_ackTimer.stop(); _ackTimer.stop();
} }
if(_currentSavingFile && _currentSavingFile->fd) { if(_logProcessor && _logProcessor->valid()) {
if(sequence != _sequence) { if(!_logProcessor->processStreamData(sequence, first_message, data)) {
qCWarning(MavlinkLogManagerLog) << "Dropped Mavlink log data"; qCCritical(MavlinkLogManagerLog) << "Error writing Mavlink log file:" << _logProcessor->fileName();
if(first_message < 255) { delete _logProcessor;
data += first_message; _logProcessor = NULL;
length -= first_message;
} else {
return;
}
}
if(fwrite(data, 1, length, _currentSavingFile->fd) != (size_t)length) {
qCCritical(MavlinkLogManagerLog) << "Error writing Mavlink log file:" << _currentSavingFile->fileName;
delete _currentSavingFile;
_currentSavingFile = NULL;
_logRunning = false; _logRunning = false;
_vehicle->stopMavlinkLog(); _vehicle->stopMavlinkLog();
emit logRunningChanged(); emit logRunningChanged();
} }
} else { } else {
length = 0;
qCWarning(MavlinkLogManagerLog) << "Mavlink log data received when not expected."; qCWarning(MavlinkLogManagerLog) << "Mavlink log data received when not expected.";
} }
//-- Update file size
if(_currentSavingFile) {
if(_currentSavingFile->record) {
quint32 size = _currentSavingFile->record->size() + length;
_currentSavingFile->record->setSize(size);
}
}
_sequence = sequence + 1;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -682,13 +838,13 @@ void ...@@ -682,13 +838,13 @@ void
MavlinkLogManager::_discardLog() MavlinkLogManager::_discardLog()
{ {
//-- Delete (empty) log file (and record) //-- Delete (empty) log file (and record)
if(_currentSavingFile) { if(_logProcessor) {
_currentSavingFile->close(); _logProcessor->close();
if(_currentSavingFile->record) { if(_logProcessor->record()) {
_deleteLog(_currentSavingFile->record); _deleteLog(_logProcessor->record());
} }
delete _currentSavingFile; delete _logProcessor;
_currentSavingFile = NULL; _logProcessor = NULL;
} }
_logRunning = false; _logRunning = false;
emit logRunningChanged(); emit logRunningChanged();
...@@ -698,30 +854,20 @@ MavlinkLogManager::_discardLog() ...@@ -698,30 +854,20 @@ MavlinkLogManager::_discardLog()
bool bool
MavlinkLogManager::_createNewLog() MavlinkLogManager::_createNewLog()
{ {
if(_currentSavingFile) { if(_logProcessor) {
delete _currentSavingFile; delete _logProcessor;
_currentSavingFile = NULL; _logProcessor = NULL;
} }
_currentSavingFile = new CurrentRunningLog; _logProcessor = new MavlinkLogProcessor;
_currentSavingFile->fileName.sprintf("%s/%03d-%s%s", if(_logProcessor->create(this, _logPath, _vehicle->id())) {
_logPath.toLatin1().data(), _insertNewLog(_logProcessor->record());
_vehicle->id(),
QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz").toLatin1().data(),
kUlogExtension);
_currentSavingFile->fd = fopen(_currentSavingFile->fileName.toLatin1().data(), "wb");
if(_currentSavingFile->fd) {
MavlinkLogFiles* newLog = new MavlinkLogFiles(this, _currentSavingFile->fileName, true);
newLog->setWriting(true);
_insertNewLog(newLog);
_currentSavingFile->record = newLog;
emit logFilesChanged(); emit logFilesChanged();
} else { } else {
qCCritical(MavlinkLogManagerLog) << "Could not create Mavlink log file:" << _currentSavingFile->fileName; qCCritical(MavlinkLogManagerLog) << "Could not create Mavlink log file:" << _logProcessor->fileName();
delete _currentSavingFile; delete _logProcessor;
_currentSavingFile = NULL; _logProcessor = NULL;
} }
_sequence = 0; return _logProcessor != NULL;
return _currentSavingFile != NULL;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
......
...@@ -73,24 +73,31 @@ private: ...@@ -73,24 +73,31 @@ private:
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class CurrentRunningLog class MavlinkLogProcessor
{ {
public: public:
CurrentRunningLog() MavlinkLogProcessor();
: fd(NULL) ~MavlinkLogProcessor();
, record(NULL) void close ();
, written(0) bool valid ();
{ bool create (MavlinkLogManager *manager, const QString path, uint8_t id);
} MavlinkLogFiles* record () { return _record; }
~CurrentRunningLog() QString fileName () { return _fileName; }
{ bool processStreamData(uint16_t _sequence, uint8_t first_message, QByteArray data);
close(); private:
} bool _checkSequence(uint16_t seq, int &num_drops);
void close(); QByteArray _writeUlogMessage(QByteArray &data);
FILE* fd; void _writeData(void* data, int len);
QString fileName; private:
MavlinkLogFiles* record; FILE* _fd;
quint32 written; quint32 _written;
int _sequence;
int _numDrops;
bool _gotHeader;
bool _error;
QByteArray _ulogMessage;
QString _fileName;
MavlinkLogFiles* _record;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -163,7 +170,7 @@ private slots: ...@@ -163,7 +170,7 @@ private slots:
void _dataAvailable (); void _dataAvailable ();
void _uploadProgress (qint64 bytesSent, qint64 bytesTotal); void _uploadProgress (qint64 bytesSent, qint64 bytesTotal);
void _activeVehicleChanged (Vehicle* vehicle); void _activeVehicleChanged (Vehicle* vehicle);
void _mavlinkLogData (Vehicle* vehicle, uint8_t target_system, uint8_t target_component, uint16_t sequence, uint8_t length, uint8_t first_message, const uint8_t* data, bool acked); void _mavlinkLogData (Vehicle* vehicle, uint8_t target_system, uint8_t target_component, uint16_t sequence, uint8_t first_message, QByteArray data, bool acked);
void _armedChanged (bool armed); void _armedChanged (bool armed);
void _commandLongAck (uint8_t compID, uint16_t command, uint8_t result); void _commandLongAck (uint8_t compID, uint16_t command, uint8_t result);
void _processCmdAck (); void _processCmdAck ();
...@@ -191,8 +198,7 @@ private: ...@@ -191,8 +198,7 @@ private:
Vehicle* _vehicle; Vehicle* _vehicle;
bool _logRunning; bool _logRunning;
bool _loggingDisabled; bool _loggingDisabled;
CurrentRunningLog* _currentSavingFile; MavlinkLogProcessor* _logProcessor;
uint16_t _sequence;
bool _deleteAfterUpload; bool _deleteAfterUpload;
int _loggingCmdTryCount; int _loggingCmdTryCount;
QTimer _ackTimer; QTimer _ackTimer;
......
...@@ -2015,7 +2015,8 @@ Vehicle::_handleMavlinkLoggingData(mavlink_message_t& message) ...@@ -2015,7 +2015,8 @@ Vehicle::_handleMavlinkLoggingData(mavlink_message_t& message)
{ {
mavlink_logging_data_t log; mavlink_logging_data_t log;
mavlink_msg_logging_data_decode(&message, &log); mavlink_msg_logging_data_decode(&message, &log);
emit mavlinkLogData(this, log.target_system, log.target_component, log.sequence, log.length, log.first_message_offset, log.data, false); emit mavlinkLogData(this, log.target_system, log.target_component, log.sequence,
log.first_message_offset, QByteArray((const char*)log.data, log.length), false);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -2025,7 +2026,8 @@ Vehicle::_handleMavlinkLoggingDataAcked(mavlink_message_t& message) ...@@ -2025,7 +2026,8 @@ Vehicle::_handleMavlinkLoggingDataAcked(mavlink_message_t& message)
mavlink_logging_data_t log; mavlink_logging_data_t log;
mavlink_msg_logging_data_decode(&message, &log); mavlink_msg_logging_data_decode(&message, &log);
_ackMavlinkLogData(log.sequence); _ackMavlinkLogData(log.sequence);
emit mavlinkLogData(this, log.target_system, log.target_component, log.sequence, log.length, log.first_message_offset, log.data, true); emit mavlinkLogData(this, log.target_system, log.target_component, log.sequence,
log.first_message_offset, QByteArray((const char*)log.data, log.length), true);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
......
...@@ -643,7 +643,7 @@ signals: ...@@ -643,7 +643,7 @@ signals:
void mavlinkScaledImu3(mavlink_message_t message); void mavlinkScaledImu3(mavlink_message_t message);
// Mavlink Log Download // Mavlink Log Download
void mavlinkLogData (Vehicle* vehicle, uint8_t target_system, uint8_t target_component, uint16_t sequence, uint8_t length, uint8_t first_message, const uint8_t* data, bool acked); void mavlinkLogData (Vehicle* vehicle, uint8_t target_system, uint8_t target_component, uint16_t sequence, uint8_t first_message, QByteArray data, bool acked);
private slots: private slots:
void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message); void _mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message);
......
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