Add macOS USB UART support
This commit is contained in:
+16
-1
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(location_plotter VERSION 0.1.0 LANGUAGES CXX)
|
||||
project(location_plotter VERSION 0.2.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
@@ -31,6 +31,16 @@ add_executable(location_plotter
|
||||
|
||||
target_link_libraries(location_plotter PRIVATE Qt6::Core Qt6::Widgets Qt6::Network ZLIB::ZLIB)
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(location_plotter PROPERTIES
|
||||
MACOSX_BUNDLE TRUE
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "Location Plotter"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "com.ankasys.location-plotter"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}"
|
||||
)
|
||||
endif()
|
||||
|
||||
qt_add_resources(location_plotter "app_resources"
|
||||
PREFIX "/"
|
||||
FILES resources/ankasys-logo.png resources/land-110m.json
|
||||
@@ -82,3 +92,8 @@ endif()
|
||||
add_test(NAME location_main_window_tests COMMAND location_main_window_tests)
|
||||
set_tests_properties(location_main_window_tests PROPERTIES
|
||||
ENVIRONMENT "QT_QPA_PLATFORM=offscreen;XDG_CACHE_HOME=/tmp/location-plotter-test-cache")
|
||||
|
||||
install(TARGETS location_plotter
|
||||
BUNDLE DESTINATION .
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Location Plotter
|
||||
|
||||
Qt6/C++ GUI that listens to `/dev/ttyUSB2`, parses normal debug lines, and plots live
|
||||
locations on a map.
|
||||
Qt6/C++ GUI that listens to a USB UART on Linux or macOS, parses normal debug lines,
|
||||
and plots live locations on a map.
|
||||
|
||||
The application also includes an interactive 3D Earth/orbit view. It downloads the current
|
||||
stream-derived RINEX 3 navigation file from the BKG/IGS archive at startup and every 15
|
||||
@@ -95,6 +95,50 @@ make platform_scenario_matrix_test
|
||||
Desteklenen senaryolar `stationary`, `pedestrian`, `car`, `aircraft`; GNSS
|
||||
periyotları 200/500/1000 ms, IMU periyotları 19/20/200/300 ms'dir.
|
||||
|
||||
## macOS'ta kurulum (MacBook Air, Apple Silicon veya Intel)
|
||||
|
||||
Guncel macOS surumunde once [Homebrew](https://brew.sh) kurulu olmalidir. Ardindan:
|
||||
|
||||
```bash
|
||||
cd location_plotter
|
||||
chmod +x setup-macos.sh run.sh
|
||||
./setup-macos.sh
|
||||
./run.sh
|
||||
```
|
||||
|
||||
Betik Homebrew ile guncel `cmake` ve `qt` paketlerini kurar, yerel mimari icin
|
||||
`location_plotter.app` paketini derler, gerekli Qt kutuphanelerini uygulama paketine
|
||||
ekler ve testleri calistirir.
|
||||
|
||||
macOS USB UART aygitlarini genellikle iki adla gosterir:
|
||||
|
||||
```text
|
||||
/dev/cu.usbserial-XXXXXXXX
|
||||
/dev/tty.usbserial-XXXXXXXX
|
||||
```
|
||||
|
||||
veya bir CDC aygitinda:
|
||||
|
||||
```text
|
||||
/dev/cu.usbmodemXXXX
|
||||
/dev/tty.usbmodemXXXX
|
||||
```
|
||||
|
||||
Uygulama her iki bicimi de algilar. Mümkünse `cu.usb...` yolunu secin; macOS'ta
|
||||
disariya baglanti baslatan uygulamalar icin uygun olan aygit budur. UART uygulama
|
||||
acikken takildiysa port alaninin yanindaki `Yenile` dugmesine basin. Otomatik
|
||||
algilanmayan bir yol port alanina elle de yazilabilir.
|
||||
|
||||
Istenen port baslatmadan once ortam degiskeniyle de secilebilir:
|
||||
|
||||
```bash
|
||||
LOCATION_PLOTTER_PORT=/dev/cu.usbserial-XXXXXXXX ./run.sh
|
||||
```
|
||||
|
||||
Port hic gorunmuyorsa `ls /dev/cu.usb* /dev/tty.usb*` ile macOS'un aygiti olusturup
|
||||
olusturmadigini kontrol edin. Hic sonuc yoksa kabloyu/veri baglantisini ve UART
|
||||
donaniminizin macOS surucusunu kontrol edin.
|
||||
|
||||
## Ubuntu'da kurulum
|
||||
|
||||
Ubuntu 22.04 ve daha yeni surumlerde gerekli paketleri kurmak, uygulamayi derlemek ve
|
||||
@@ -140,8 +184,10 @@ Uygulama Qt tabanli bir masaustu arayuzudur; grafik oturumu olan bir Ubuntu maki
|
||||
calistirilmalidir. Harita karolari ve guncel RINEX verisi icin internet erisimi gerekir,
|
||||
ancak son gecerli RINEX verisi ve harita onbellegiyle cevrimdisi kullanim da desteklenir.
|
||||
|
||||
The port selector lists only detected `/dev/ttyUSB*` devices. The default selection is
|
||||
`/dev/ttyUSB2` and the default baud rate is `115200`.
|
||||
Port secici Linux'ta `/dev/ttyUSB*` ve `/dev/ttyACM*`; macOS'ta USB ile ilgili
|
||||
`/dev/cu.*` ve `/dev/tty.*` aygitlarini listeler. Hic aygit algilanmazsa Linux'ta
|
||||
`/dev/ttyUSB2`, macOS'ta `/dev/cu.usbserial` duzenlenebilir bir varsayilan yol olarak
|
||||
gosterilir. Varsayilan baud rate `115200`'dur.
|
||||
|
||||
If the port cannot be opened, make sure the user has serial access:
|
||||
|
||||
|
||||
@@ -5,29 +5,46 @@ cd "$(dirname "$0")"
|
||||
|
||||
print_qt_install_hint() {
|
||||
echo
|
||||
echo "Qt6 bulunamadi. Ubuntu'da gerekli paketleri kurmak icin:"
|
||||
echo " sudo apt update"
|
||||
echo " sudo apt install build-essential cmake qt6-base-dev"
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
echo "Qt6 bulunamadi. macOS'ta gerekli paketleri kurmak icin:"
|
||||
echo " brew install cmake qt"
|
||||
echo "veya doğrudan: ./setup-macos.sh"
|
||||
else
|
||||
echo "Qt6 bulunamadi. Ubuntu'da gerekli paketleri kurmak icin:"
|
||||
echo " sudo apt update"
|
||||
echo " sudo apt install build-essential cmake qt6-base-dev"
|
||||
fi
|
||||
}
|
||||
|
||||
project_dir="$(pwd -P)"
|
||||
|
||||
if [[ -f ./build/CMakeCache.txt ]]; then
|
||||
cached_source="$(sed -n 's/^CMAKE_HOME_DIRECTORY:INTERNAL=//p' ./build/CMakeCache.txt)"
|
||||
if [[ -n "$cached_source" && "$cached_source" != "$project_dir" ]]; then
|
||||
echo "Build klasoru farkli bir proje yoluna ait, yeniden olusturuluyor:"
|
||||
echo " $cached_source"
|
||||
cached_system="$(sed -n 's/^CMAKE_SYSTEM_NAME:INTERNAL=//p' ./build/CMakeCache.txt)"
|
||||
host_system="$(uname -s)"
|
||||
if [[ ( -n "$cached_source" && "$cached_source" != "$project_dir" ) \
|
||||
|| ( -n "$cached_system" && "$cached_system" != "$host_system" ) ]]; then
|
||||
echo "Build klasoru farkli bir proje yolu veya sisteme ait, yeniden olusturuluyor."
|
||||
rm -rf ./build
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! cmake -S . -B build; then
|
||||
cmake_args=(-S . -B build)
|
||||
if [[ "$(uname -s)" == "Darwin" ]] && command -v brew >/dev/null 2>&1; then
|
||||
cmake_args+=("-DCMAKE_PREFIX_PATH=$(brew --prefix qt)")
|
||||
fi
|
||||
|
||||
if ! cmake "${cmake_args[@]}"; then
|
||||
print_qt_install_hint
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cmake --build build
|
||||
|
||||
if [[ "$(uname -s)" == "Darwin" ]]; then
|
||||
exec ./build/location_plotter.app/Contents/MacOS/location_plotter "$@"
|
||||
fi
|
||||
|
||||
missing_libs="$(ldd ./build/location_plotter 2>/dev/null | awk '/not found/ { print $1 }' || true)"
|
||||
if [[ -n "$missing_libs" ]]; then
|
||||
echo "Eksik paylasimli kutuphaneler:"
|
||||
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [[ "$(uname -s)" != "Darwin" ]]; then
|
||||
echo "Bu kurulum betigi macOS icindir." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v brew >/dev/null 2>&1; then
|
||||
echo "Homebrew bulunamadi. Once https://brew.sh adresindeki Homebrew kurulumunu tamamlayin." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Gerekli macOS paketleri kuruluyor..."
|
||||
brew install cmake qt
|
||||
|
||||
qt_prefix="$(brew --prefix qt)"
|
||||
parallel_jobs="$(sysctl -n hw.logicalcpu 2>/dev/null || echo 4)"
|
||||
|
||||
if [[ -f build/CMakeCache.txt ]]; then
|
||||
cached_system="$(sed -n 's/^CMAKE_SYSTEM_NAME:INTERNAL=//p' build/CMakeCache.txt)"
|
||||
if [[ -n "$cached_system" && "$cached_system" != "Darwin" ]]; then
|
||||
echo "Baska bir sisteme ait build klasoru yeniden olusturuluyor."
|
||||
rm -rf build
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Uygulama derleniyor..."
|
||||
cmake -S . -B build \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH="$qt_prefix"
|
||||
cmake --build build --parallel "$parallel_jobs"
|
||||
|
||||
echo "Testler calistiriliyor..."
|
||||
ctest --test-dir build --output-on-failure
|
||||
|
||||
echo "macOS uygulama paketi hazirlaniyor..."
|
||||
"$qt_prefix/bin/macdeployqt" build/location_plotter.app -always-overwrite
|
||||
|
||||
echo
|
||||
echo "Kurulum tamamlandi. Uygulamayi baslatmak icin:"
|
||||
echo " ./run.sh"
|
||||
echo
|
||||
echo "USB UART icin port listesinden /dev/cu.usb... aygitini secin."
|
||||
echo "/dev/tty.usb... gorunuyorsa o yol da desteklenir."
|
||||
+79
-13
@@ -212,6 +212,45 @@ QString optionalDopText(const std::optional<double> &value)
|
||||
return QString::number(*value, 'f', 3);
|
||||
}
|
||||
|
||||
QStringList detectedSerialPorts()
|
||||
{
|
||||
const QDir deviceDirectory(QStringLiteral("/dev"));
|
||||
QStringList patterns;
|
||||
#ifdef Q_OS_MACOS
|
||||
// macOS exposes USB UARTs as paired callout (cu.*) and terminal (tty.*)
|
||||
// devices. Prefer cu.* because it does not wait for carrier detect.
|
||||
patterns = {
|
||||
QStringLiteral("cu.usb*"), QStringLiteral("cu.wchusbserial*"),
|
||||
QStringLiteral("cu.SLAB_USBtoUART*"), QStringLiteral("cu.*USB*"),
|
||||
QStringLiteral("tty.usb*"), QStringLiteral("tty.wchusbserial*"),
|
||||
QStringLiteral("tty.SLAB_USBtoUART*"), QStringLiteral("tty.*USB*")};
|
||||
#else
|
||||
patterns = {QStringLiteral("ttyUSB*"), QStringLiteral("ttyACM*")};
|
||||
#endif
|
||||
|
||||
QStringList ports;
|
||||
for (const QString &pattern : patterns) {
|
||||
const QStringList names = deviceDirectory.entryList(
|
||||
{pattern}, QDir::System | QDir::Files, QDir::Name);
|
||||
for (const QString &name : names) {
|
||||
const QString path = QStringLiteral("/dev/") + name;
|
||||
if (!ports.contains(path)) {
|
||||
ports.push_back(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ports;
|
||||
}
|
||||
|
||||
QString fallbackSerialPort()
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
return QStringLiteral("/dev/cu.usbserial");
|
||||
#else
|
||||
return QStringLiteral("/dev/ttyUSB2");
|
||||
#endif
|
||||
}
|
||||
|
||||
void mergeDopValues(DopValues &target, const DopValues &source)
|
||||
{
|
||||
if (source.gdop.has_value()) {
|
||||
@@ -425,6 +464,34 @@ void MainWindow::openTelemetryLog()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::refreshSerialPorts()
|
||||
{
|
||||
const QString previousPort = m_portCombo->currentText().trimmed();
|
||||
const QString configuredPort = qEnvironmentVariable("LOCATION_PLOTTER_PORT").trimmed();
|
||||
const QStringList detectedPorts = detectedSerialPorts();
|
||||
|
||||
m_portCombo->clear();
|
||||
for (const QString &port : detectedPorts) {
|
||||
m_portCombo->addItem(port);
|
||||
}
|
||||
|
||||
QString selectedPort;
|
||||
if (!configuredPort.isEmpty()) {
|
||||
selectedPort = configuredPort;
|
||||
} else if (!previousPort.isEmpty() && detectedPorts.contains(previousPort)) {
|
||||
selectedPort = previousPort;
|
||||
} else if (!detectedPorts.isEmpty()) {
|
||||
selectedPort = detectedPorts.first();
|
||||
} else {
|
||||
selectedPort = previousPort.isEmpty() ? fallbackSerialPort() : previousPort;
|
||||
}
|
||||
|
||||
if (m_portCombo->findText(selectedPort) < 0) {
|
||||
m_portCombo->addItem(selectedPort);
|
||||
}
|
||||
m_portCombo->setCurrentText(selectedPort);
|
||||
}
|
||||
|
||||
void MainWindow::handleSerialLine(const QString &line)
|
||||
{
|
||||
static const QRegularExpression solveStartRegex(
|
||||
@@ -727,19 +794,16 @@ void MainWindow::buildUi()
|
||||
|
||||
m_portCombo = new QComboBox(this);
|
||||
m_portCombo->setObjectName(QStringLiteral("portSelector"));
|
||||
m_portCombo->setMinimumWidth(165);
|
||||
m_portCombo->setEditable(false);
|
||||
QDir deviceDirectory(QStringLiteral("/dev"));
|
||||
const QStringList deviceNames = deviceDirectory.entryList(
|
||||
{QStringLiteral("ttyUSB*")},
|
||||
QDir::System | QDir::Files | QDir::Readable, QDir::Name);
|
||||
for (const QString &deviceName : deviceNames) {
|
||||
m_portCombo->addItem(QStringLiteral("/dev/") + deviceName);
|
||||
}
|
||||
if (m_portCombo->findText(QStringLiteral("/dev/ttyUSB2")) < 0) {
|
||||
m_portCombo->addItem(QStringLiteral("/dev/ttyUSB2"));
|
||||
}
|
||||
m_portCombo->setCurrentText(QStringLiteral("/dev/ttyUSB2"));
|
||||
m_portCombo->setMinimumWidth(220);
|
||||
m_portCombo->setEditable(true);
|
||||
m_portCombo->setToolTip(QStringLiteral(
|
||||
"USB UART portu. macOS'ta /dev/cu.usb... tercih edilir; /dev/tty.usb... da desteklenir."));
|
||||
refreshSerialPorts();
|
||||
|
||||
auto *refreshPortsButton = new QToolButton(this);
|
||||
refreshPortsButton->setObjectName(QStringLiteral("refreshPortsButton"));
|
||||
refreshPortsButton->setText(QStringLiteral("Yenile"));
|
||||
refreshPortsButton->setToolTip(QStringLiteral("Seri port listesini yenile"));
|
||||
|
||||
m_baudCombo = new QComboBox(this);
|
||||
for (const int baud : {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600}) {
|
||||
@@ -773,6 +837,7 @@ void MainWindow::buildUi()
|
||||
|
||||
toolbarLayout->addWidget(new QLabel(QStringLiteral("Port"), this));
|
||||
toolbarLayout->addWidget(m_portCombo);
|
||||
toolbarLayout->addWidget(refreshPortsButton);
|
||||
toolbarLayout->addWidget(new QLabel(QStringLiteral("Baud"), this));
|
||||
toolbarLayout->addWidget(m_baudCombo);
|
||||
toolbarLayout->addWidget(new QLabel(QStringLiteral("Max"), this));
|
||||
@@ -996,6 +1061,7 @@ void MainWindow::buildUi()
|
||||
connect(m_connectButton, &QPushButton::clicked, this, &MainWindow::toggleSerial);
|
||||
connect(m_clearButton, &QPushButton::clicked, this, &MainWindow::clearPoints);
|
||||
connect(m_openLogButton, &QPushButton::clicked, this, &MainWindow::openTelemetryLog);
|
||||
connect(refreshPortsButton, &QToolButton::clicked, this, &MainWindow::refreshSerialPorts);
|
||||
connect(m_maxPointsSpin, qOverload<int>(&QSpinBox::valueChanged), this,
|
||||
&MainWindow::trimToMaxPoints);
|
||||
connect(m_autoFollowCheck, &QCheckBox::toggled, m_map, &MapWidget::setAutoFollow);
|
||||
|
||||
@@ -43,6 +43,7 @@ private slots:
|
||||
void updateReferenceLocation();
|
||||
void flushUiUpdates();
|
||||
void openTelemetryLog();
|
||||
void refreshSerialPorts();
|
||||
|
||||
private:
|
||||
void buildUi();
|
||||
|
||||
+57
-21
@@ -10,38 +10,70 @@
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
#include <IOKit/serial/ioss.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr qsizetype MaxBytesPerReadCycle = 64 * 1024;
|
||||
|
||||
speed_t baudToSpeed(int baudRate)
|
||||
bool applyBaudRate(termios &options, int baudRate)
|
||||
{
|
||||
speed_t speed = 0;
|
||||
switch (baudRate) {
|
||||
case 1200:
|
||||
return B1200;
|
||||
speed = B1200;
|
||||
break;
|
||||
case 2400:
|
||||
return B2400;
|
||||
speed = B2400;
|
||||
break;
|
||||
case 4800:
|
||||
return B4800;
|
||||
speed = B4800;
|
||||
break;
|
||||
case 9600:
|
||||
return B9600;
|
||||
speed = B9600;
|
||||
break;
|
||||
case 19200:
|
||||
return B19200;
|
||||
speed = B19200;
|
||||
break;
|
||||
case 38400:
|
||||
return B38400;
|
||||
speed = B38400;
|
||||
break;
|
||||
case 57600:
|
||||
return B57600;
|
||||
speed = B57600;
|
||||
break;
|
||||
case 115200:
|
||||
return B115200;
|
||||
speed = B115200;
|
||||
break;
|
||||
#ifdef B230400
|
||||
case 230400:
|
||||
return B230400;
|
||||
speed = B230400;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B460800
|
||||
case 460800:
|
||||
return B460800;
|
||||
speed = B460800;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
case 921600:
|
||||
return B921600;
|
||||
speed = B921600;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
#ifdef Q_OS_MACOS
|
||||
// IOSSIOSPEED below applies the exact requested rate. A valid termios
|
||||
// placeholder is still required before that ioctl can be issued.
|
||||
speed = B9600;
|
||||
break;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ::cfsetispeed(&options, speed) == 0
|
||||
&& ::cfsetospeed(&options, speed) == 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -176,12 +208,6 @@ void SerialReader::flushPartialLine()
|
||||
|
||||
bool SerialReader::configurePort(int baudRate)
|
||||
{
|
||||
const speed_t speed = baudToSpeed(baudRate);
|
||||
if (speed == 0) {
|
||||
emit errorOccurred(QStringLiteral("Desteklenmeyen baud rate: %1").arg(baudRate));
|
||||
return false;
|
||||
}
|
||||
|
||||
termios options {};
|
||||
if (::tcgetattr(m_fd, &options) != 0) {
|
||||
emitSystemError(QStringLiteral("Port ayarlari okunamadi"));
|
||||
@@ -189,8 +215,10 @@ bool SerialReader::configurePort(int baudRate)
|
||||
}
|
||||
|
||||
::cfmakeraw(&options);
|
||||
::cfsetispeed(&options, speed);
|
||||
::cfsetospeed(&options, speed);
|
||||
if (!applyBaudRate(options, baudRate)) {
|
||||
emit errorOccurred(QStringLiteral("Bu sistemde desteklenmeyen baud rate: %1").arg(baudRate));
|
||||
return false;
|
||||
}
|
||||
|
||||
options.c_cflag |= CLOCAL | CREAD;
|
||||
options.c_cflag &= ~HUPCL;
|
||||
@@ -206,6 +234,14 @@ bool SerialReader::configurePort(int baudRate)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
speed_t requestedSpeed = static_cast<speed_t>(baudRate);
|
||||
if (::ioctl(m_fd, IOSSIOSPEED, &requestedSpeed) != 0) {
|
||||
emitSystemError(QStringLiteral("macOS baud rate uygulanamadi"));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
::tcflush(m_fd, TCIFLUSH);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,9 @@ void flushUpdates(MainWindow &window)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
qputenv("LOCATION_PLOTTER_PORT", "/dev/test-usb-uart");
|
||||
MainWindow window;
|
||||
qunsetenv("LOCATION_PLOTTER_PORT");
|
||||
|
||||
auto *table = window.findChild<QTableView *>();
|
||||
auto *referenceLatInput = window.findChild<QLineEdit *>(QStringLiteral("referenceLatInput"));
|
||||
@@ -67,10 +69,11 @@ int main(int argc, char **argv)
|
||||
assert(showRecentPoints != nullptr);
|
||||
assert(showAverage != nullptr);
|
||||
assert(portSelector != nullptr);
|
||||
assert(!portSelector->isEditable());
|
||||
assert(portSelector->isEditable());
|
||||
assert(portSelector->count() >= 1);
|
||||
assert(portSelector->currentText() == QStringLiteral("/dev/test-usb-uart"));
|
||||
for (int i = 0; i < portSelector->count(); ++i) {
|
||||
assert(portSelector->itemText(i).startsWith(QStringLiteral("/dev/ttyUSB")));
|
||||
assert(portSelector->itemText(i).startsWith(QStringLiteral("/dev/")));
|
||||
assert(!portSelector->itemText(i).trimmed().isEmpty());
|
||||
}
|
||||
assert(map != nullptr);
|
||||
|
||||
Reference in New Issue
Block a user