30 #include <QTextStream>
31 #include <QMainWindow>
32 #include <QMessageBox>
39 , timestampBufferIdx(0)
63 if (
file.open(mode) ==
false) {
64 qDebug() <<
"Unable to open " <<
file.fileName() <<
" for logging";
78 if (mode == QIODevice::WriteOnly) {
92 out <<
"dRonin git hash:\n" << gitHash <<
"\n" << uavoHash <<
"\n##\n";
93 }
else if (mode == QIODevice::ReadOnly) {
96 QString logGitHashString =
file.readLine().trimmed();
99 QString logUAVOHashString =
file.readLine().trimmed();
110 if (logUAVOHashString != uavoHash) {
112 msgBox.setText(
"Likely log file incompatibility.");
113 msgBox.setInformativeText(QString(
"The log file was made with branch %1, UAVO hash %2. "
114 "GCS will attempt to play the file.")
115 .arg(logGitHashString)
116 .arg(logUAVOHashString));
118 }
else if (logGitHashString != gitHash) {
120 msgBox.setText(
"Possible log file incompatibility.");
121 msgBox.setInformativeText(
122 QString(
"The log file was made with branch %1. GCS will attempt to play the file.")
123 .arg(logGitHashString));
127 QString tmpLine =
file.readLine();
129 while (tmpLine !=
"##\n" && cnt < 10 && !
file.atEnd()) {
130 tmpLine =
file.readLine().trimmed();
135 if (cnt >= 10 ||
file.atEnd()) {
137 msgBox.setText(
"Corrupted file.");
138 msgBox.setInformativeText(
"GCS cannot find the separation byte. GCS will attempt to "
149 qDebug() <<
"Logging read/write mode incorrectly set.";
155 QIODevice::open(QIODevice::ReadWrite);
164 if (
timer.isActive())
172 if (!
file.isWritable())
175 quint32 timeStamp =
myTime.elapsed();
177 file.write(reinterpret_cast<char *>(&timeStamp),
sizeof(timeStamp));
178 file.write(reinterpret_cast<char *>(&dataSize),
sizeof(dataSize));
180 qint64 written =
file.write(data, dataSize);
182 emit bytesWritten(written);
189 QMutexLocker locker(&
mutex);
190 qint64 toRead = qMin(maxSize, (qint64)
dataBuffer.size());
205 if (
file.bytesAvailable() > 4) {
214 if (
file.bytesAvailable() < 4) {
221 file.read(reinterpret_cast<char *>(&dataSize),
sizeof(dataSize));
223 if (dataSize < 1 || dataSize > (1024 * 1024)) {
224 qDebug() <<
"Error: Logfile corrupted! Unlikely packet size: " << dataSize <<
"\n";
228 if (
file.bytesAvailable() < dataSize) {
238 if (
file.bytesAvailable() < 4) {
243 lastTimeStampPos = timestampPos[timestampBufferIdx];
245 timestampBufferIdx++;
264 timestampBuffer.clear();
265 timestampPos.clear();
266 quint64 logFileStartIdx =
file.pos();
267 timestampBufferIdx = 0;
270 while (!
file.atEnd()) {
274 timestampPos.append(
file.pos());
278 file.read(reinterpret_cast<char *>(&dataSize),
sizeof(dataSize));
283 if ((dataSize & 0xFFFFFFFFFFFF0000) != 0) {
284 qDebug() <<
"Wrong sync byte. At file location 0x"
285 << QString(
"%1").arg(
file.pos(), 0, 16) <<
"Got 0x"
286 << QString(
"%1").arg(dataSize & 0xFFFFFFFFFFFF0000, 0, 16)
287 <<
", but expected 0x"
290 file.seek(timestampPos.last() + 1);
291 timestampPos.pop_back();
296 if (!timestampBuffer.isEmpty() &&
lastTimeStamp < timestampBuffer.last()) {
298 msgBox.setText(
"Corrupted file.");
299 msgBox.setInformativeText(
"Timestamps are not sequential. Playback may have unexpected "
304 qDebug() <<
"Timestamp: " << timestampBuffer.last() <<
" " <<
lastTimeStamp;
309 file.seek(timestampPos.last() +
sizeof(
lastTimeStamp) +
sizeof(dataSize) + dataSize);
313 if (timestampBuffer.size() == 0) {
315 msgBox.setText(
"Empty logfile.");
316 msgBox.setInformativeText(
"No log data can be found.");
325 lastTimeStampPos = timestampPos[0];
327 firstTimestamp = timestampBuffer[0];
328 timestampBufferIdx = 1;
330 timer.setInterval(10);
361 while (timestampBuffer[tmpIdx++] <= val * 1000 && tmpIdx <= timestampBufferIdx) {
364 lastTimeStampPos = timestampPos[tmpIdx];
366 timestampBufferIdx = tmpIdx;
371 qDebug() <<
"Replaying at: " <<
lastTimeStamp <<
", but requestion at" << val * 1000;
qint64 writeData(const char *data, qint64 dataSize)
void setReplayTime(double val)
LogFile::setReplayTime, sets the playback time.
const char *const UAVOSHA1_STR
qint64 bytesAvailable() const
qint64 readData(char *data, qint64 maxlen)
Plugin for generating a logfile.
static ICore * instance()
const char *const GCS_REVISION_STR
LogFile(QObject *parent=nullptr)