Add source-aware UART log replay
Ubuntu build / build-and-test (ubuntu-22.04) (push) Has been cancelled
Ubuntu build / build-and-test (ubuntu-24.04) (push) Has been cancelled

This commit is contained in:
Onur Cayan
2026-08-12 13:54:11 +03:00
parent 9ced0da0b2
commit 498757b502
11 changed files with 712 additions and 3 deletions
+30
View File
@@ -6,15 +6,19 @@
#include <QCheckBox>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QDir>
#include <QFile>
#include <QLabel>
#include <QLineEdit>
#include <QMetaObject>
#include <QSpinBox>
#include <QPushButton>
#include <QRegularExpression>
#include <QTableView>
#include <QTabWidget>
#include <QSplitter>
#include <QTemporaryFile>
#include <QTemporaryDir>
#include <cassert>
@@ -43,6 +47,32 @@ int main(int argc, char **argv)
MainWindow window;
qunsetenv("LOCATION_PLOTTER_PORT");
{
QTemporaryDir uartLogDirectory;
assert(uartLogDirectory.isValid());
qputenv("LOCATION_PLOTTER_UART_LOG_DIR", uartLogDirectory.path().toUtf8());
bool loggingStarted = false;
assert(QMetaObject::invokeMethod(
&window, "startUartLogging", Qt::DirectConnection,
Q_RETURN_ARG(bool, loggingStarted),
Q_ARG(QString, QStringLiteral("/dev/test-uart")), Q_ARG(int, 460800)));
assert(loggingStarted);
sendLine(window, QStringLiteral("raw uart test line"));
assert(QMetaObject::invokeMethod(&window, "stopUartLogging", Qt::DirectConnection));
qunsetenv("LOCATION_PLOTTER_UART_LOG_DIR");
const QStringList logFiles = QDir(uartLogDirectory.path()).entryList(
{QStringLiteral("uart_*.log")}, QDir::Files);
assert(logFiles.size() == 1);
QFile logFile(QDir(uartLogDirectory.path()).filePath(logFiles.constFirst()));
assert(logFile.open(QIODevice::ReadOnly | QIODevice::Text));
const QString contents = QString::fromUtf8(logFile.readAll());
assert(contents.contains(QStringLiteral("[SESSION START] port=/dev/test-uart baud=460800")));
assert(contents.contains(QRegularExpression(
QStringLiteral(R"(\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\] raw uart test line)"))));
assert(contents.contains(QStringLiteral("[SESSION END]")));
}
auto *table = window.findChild<QTableView *>();
auto *referenceLatInput = window.findChild<QLineEdit *>(QStringLiteral("referenceLatInput"));
auto *referenceLonInput = window.findChild<QLineEdit *>(QStringLiteral("referenceLonInput"));
+8
View File
@@ -250,6 +250,14 @@ int main(int argc, char **argv)
assert(parsed->satellites == 5);
}
{
const auto parsed = LocationParser::parseLine(QStringLiteral(
"[FUSION] state=moving lat=40.7357 lon=31.5986 height=811"));
assert(parsed.has_value());
assert(parsed->hasLocation());
assert(parsed->source == LocationSource::ImuCorrected);
}
{
const auto parsed = LocationParser::parseLine(QStringLiteral(
"[LOCATION] source=trajectory lat=40.7358 lon=31.5987 height=810 tracked=4 used=4"));
+70
View File
@@ -0,0 +1,70 @@
#include "../src/UartReplay.h"
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QEventLoop>
#include <QTemporaryFile>
#include <QTimer>
#include <cassert>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
QTemporaryFile log;
assert(log.open());
log.write(
"[2026-08-12 10:00:00.000] [SESSION START] port=/dev/test baud=460800\n"
"[2026-08-12 10:00:00.001] [LOCATION] source=gps lat=40.0 lon=29.0\n"
"diagnostic line without timestamp\n"
"[LOCATION] source=imu_corrected lat=40.1 lon=29.1\n"
"[FUSION] lat=40.2 lon=29.2 height=10\n"
"[LOCATION] source=gps lat=40.3 lon=29.3\n"
"[2026-08-12 10:00:00.999] [SESSION END]\n");
log.flush();
UartReplay replay;
QStringList received;
QVector<qint64> receivedAt;
QElapsedTimer elapsed;
QEventLoop loop;
QObject::connect(&replay, &UartReplay::lineReady, &loop, [&](const QString &line) {
received.push_back(line);
receivedAt.push_back(elapsed.elapsed());
});
QObject::connect(&replay, &UartReplay::replayFinished, &loop, &QEventLoop::quit);
QTimer::singleShot(2000, &loop, &QEventLoop::quit);
elapsed.start();
assert(replay.start(log.fileName(), 20, 10));
assert(replay.locationCount() == 4);
loop.exec();
assert(!replay.isRunning());
assert(received.size() == 5);
assert(received.first().startsWith(QStringLiteral("[LOCATION] source=gps")));
assert(received.at(1) == QStringLiteral("diagnostic line without timestamp"));
assert(received.at(3).startsWith(QStringLiteral("[FUSION]")));
assert(receivedAt.last() >= 15);
QTemporaryFile splitLog;
assert(splitLog.open());
splitLog.write("latitude: 40.25\nlongitude: 29.50\n");
splitLog.flush();
received.clear();
receivedAt.clear();
elapsed.restart();
assert(replay.start(splitLog.fileName(), 1, 1));
assert(replay.locationCount() == 1);
loop.exec();
assert(received.size() == 2);
QTemporaryFile invalidLog;
assert(invalidLog.open());
invalidLog.write("only diagnostics\n");
invalidLog.flush();
assert(!replay.start(invalidLog.fileName(), 200, 50));
return 0;
}