diff --git a/selfdrive/assets/offroad/icon_wifi_uploading.svg b/selfdrive/assets/offroad/icon_wifi_uploading.svg new file mode 100644 index 0000000000..95cb0e283e --- /dev/null +++ b/selfdrive/assets/offroad/icon_wifi_uploading.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 793530b964..12a3ef48ac 100755 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -18,6 +18,7 @@ from common.basedir import BASEDIR from common.timeout import Timeout from common.params import Params from selfdrive.controls.lib.events import EVENTS, ET +from system.hardware import HARDWARE from system.loggerd.config import ROOT from selfdrive.test.helpers import set_params_enabled, release_only from tools.lib.logreader import LogReader @@ -35,7 +36,6 @@ PROCS = { "./_sensord": 12.0, "selfdrive.controls.radard": 4.5, "./_modeld": 4.48, - "./boardd": 3.63, "./_dmonitoringmodeld": 5.0, "selfdrive.thermald.thermald": 3.87, "selfdrive.locationd.calibrationd": 2.0, @@ -45,12 +45,10 @@ PROCS = { "./proclogd": 1.54, "system.logmessaged": 0.2, "./clocksd": 0.02, - "./ubloxd": 0.02, "selfdrive.tombstoned": 0, "./logcatd": 0, "system.micd": 10.0, "system.timezoned": 0, - "system.sensord.pigeond": 6.0, "selfdrive.boardd.pandad": 0, "selfdrive.statsd": 0.4, "selfdrive.navd.navd": 0.4, @@ -59,6 +57,18 @@ PROCS = { "selfdrive.locationd.laikad": None, # TODO: laikad cpu usage is sporadic } +PROCS.update({ + "tici": { + "./boardd": 4.0, + "./ubloxd": 0.02, + "system.sensord.pigeond": 6.0, + }, + "tizi": { + "./boardd": 19.0, + "system.sensord.rawgps.rawgpsd": 1.0, + } +}[HARDWARE.get_device_type()]) + TIMINGS = { # rtols: max/min, rsd "can": [2.5, 0.35], @@ -96,7 +106,9 @@ class TestOnroad(unittest.TestCase): # setup env params = Params() - params.clear_all() + if "CI" in os.environ: + params.clear_all() + params.remove("CurrentRoute") set_params_enabled() os.environ['TESTING_CLOSET'] = '1' if os.path.exists(ROOT): @@ -156,11 +168,11 @@ class TestOnroad(unittest.TestCase): for s, msgs in self.service_msgs.items(): if s in ('initData', 'sentinel'): continue - + # skip gps services for now - if s in ('ubloxGnss', 'ubloxRaw', 'gnssMeasurements', 'gpsLocationExternal'): + if s in ('ubloxGnss', 'ubloxRaw', 'gnssMeasurements', 'gpsLocation', 'gpsLocationExternal', 'qcomGnss'): continue - + with self.subTest(service=s): assert len(msgs) >= math.floor(service_list[s].frequency*55) @@ -258,6 +270,23 @@ class TestOnroad(unittest.TestCase): result += "------------------------------------------------\n" print(result) + @unittest.skip("TODO: enable once timings are fixed") + def test_camera_frame_timings(self): + result = "\n" + result += "------------------------------------------------\n" + result += "----------------- SoF Timing ------------------\n" + result += "------------------------------------------------\n" + for name in ['roadCameraState', 'wideRoadCameraState', 'driverCameraState']: + ts = [getattr(getattr(m, m.which()), "timestampSof") for m in self.lr if name in m.which()] + d_ms = np.diff(ts) / 1e6 + d50 = np.abs(d_ms-50) + self.assertLess(max(d50), 1.0, f"high sof delta vs 50ms: {max(d50)}") + result += f"{name} sof delta vs 50ms: min {min(d50):.5f}s\n" + result += f"{name} sof delta vs 50ms: max {max(d50):.5f}s\n" + result += f"{name} sof delta vs 50ms: mean {d50.mean():.5f}s\n" + result += "------------------------------------------------\n" + print(result) + def test_mpc_execution_timings(self): result = "\n" result += "------------------------------------------------\n" diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index f54d72ae31..f46e3d5873 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -20,7 +20,7 @@ if arch == "Darwin": qt_env['FRAMEWORKS'] += ['OpenCL'] qt_util = qt_env.Library("qt_util", ["#selfdrive/ui/qt/api.cc", "#selfdrive/ui/qt/util.cc"], LIBS=base_libs) -widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", +widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", "qt/widgets/wifi.cc", "qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc", "qt/widgets/offroad_alerts.cc", "qt/widgets/prime.cc", "qt/widgets/keyboard.cc", "qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#third_party/qrcode/QrCode.cc", diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index 2b8974f73a..587e2f445e 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include "selfdrive/ui/qt/offroad/experimental_mode.h" @@ -136,21 +137,34 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { home_layout->setContentsMargins(0, 0, 0, 0); home_layout->setSpacing(30); - // left: ExperimentalModeButton, DriveStats - QWidget* left_widget = new QWidget(this); - QVBoxLayout* left_column = new QVBoxLayout(left_widget); - left_column->setContentsMargins(0, 0, 0, 0); - left_column->setSpacing(30); + // left: DriveStats/PrimeAdWidget + QStackedWidget *left_widget = new QStackedWidget(this); + left_widget->addWidget(new DriveStats); + left_widget->addWidget(new PrimeAdWidget); + + left_widget->setCurrentIndex(uiState()->primeType() ? 0 : 1); + connect(uiState(), &UIState::primeTypeChanged, [=](int prime_type) { + left_widget->setCurrentIndex(prime_type ? 0 : 1); + }); + + home_layout->addWidget(left_widget, 1); + + // right: ExperimentalModeButton, SetupWidget + QWidget* right_widget = new QWidget(this); + QVBoxLayout* right_column = new QVBoxLayout(right_widget); + right_column->setContentsMargins(0, 0, 0, 0); + right_widget->setFixedWidth(750); + right_column->setSpacing(30); ExperimentalModeButton *experimental_mode = new ExperimentalModeButton(this); QObject::connect(experimental_mode, &ExperimentalModeButton::openSettings, this, &OffroadHome::openSettings); - left_column->addWidget(experimental_mode, 1); - left_column->addWidget(new DriveStats, 1); + right_column->addWidget(experimental_mode, 1); - home_layout->addWidget(left_widget, 1); + SetupWidget *setup_widget = new SetupWidget; + QObject::connect(setup_widget, &SetupWidget::openSettings, this, &OffroadHome::openSettings); + right_column->addWidget(setup_widget, 1); - // right: SetupWidget - home_layout->addWidget(new SetupWidget); + home_layout->addWidget(right_widget, 1); } center_layout->addWidget(home_widget); @@ -170,7 +184,7 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { setStyleSheet(R"( * { - color: white; + color: white; } OffroadHome { background-color: black; diff --git a/selfdrive/ui/qt/widgets/prime.cc b/selfdrive/ui/qt/widgets/prime.cc index fb4aea2b1c..86bd918e0c 100644 --- a/selfdrive/ui/qt/widgets/prime.cc +++ b/selfdrive/ui/qt/widgets/prime.cc @@ -14,6 +14,7 @@ #include "selfdrive/ui/qt/request_repeater.h" #include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/qt_window.h" +#include "selfdrive/ui/qt/widgets/wifi.h" using qrcodegen::QrCode; @@ -123,26 +124,18 @@ PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QFrame(parent) { QWidget *primeWidget = new QWidget; primeWidget->setObjectName("primeWidget"); QVBoxLayout *primeLayout = new QVBoxLayout(primeWidget); - primeLayout->setContentsMargins(60, 50, 60, 50); + primeLayout->setContentsMargins(56, 40, 56, 40); + primeLayout->setSpacing(20); QLabel *subscribed = new QLabel(tr("✓ SUBSCRIBED")); subscribed->setStyleSheet("font-size: 41px; font-weight: bold; color: #86FF4E;"); - primeLayout->addWidget(subscribed, 0, Qt::AlignTop); - - primeLayout->addSpacing(60); + primeLayout->addWidget(subscribed); QLabel *commaPrime = new QLabel(tr("comma prime")); commaPrime->setStyleSheet("font-size: 75px; font-weight: bold;"); - primeLayout->addWidget(commaPrime, 0, Qt::AlignTop); - - primeLayout->addSpacing(20); - - QLabel *connectUrl = new QLabel(tr("CONNECT.COMMA.AI")); - connectUrl->setStyleSheet("font-size: 41px; font-family: Inter SemiBold; color: #A0A0A0;"); - primeLayout->addWidget(connectUrl, 0, Qt::AlignTop); + primeLayout->addWidget(commaPrime); mainLayout->addWidget(primeWidget); - mainLayout->addStretch(); } @@ -195,8 +188,8 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { QFrame* finishRegistration = new QFrame; finishRegistration->setObjectName("primeWidget"); QVBoxLayout* finishRegistationLayout = new QVBoxLayout(finishRegistration); - finishRegistationLayout->setSpacing(40); - finishRegistationLayout->setContentsMargins(64, 64, 64, 64); + finishRegistationLayout->setSpacing(38); + finishRegistationLayout->setContentsMargins(64, 48, 64, 48); QLabel* registrationTitle = new QLabel(tr("Finish Setup")); registrationTitle->setStyleSheet("font-size: 75px; font-weight: bold;"); @@ -204,7 +197,7 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { QLabel* registrationDescription = new QLabel(tr("Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer.")); registrationDescription->setWordWrap(true); - registrationDescription->setStyleSheet("font-size: 55px; font-weight: light;"); + registrationDescription->setStyleSheet("font-size: 50px; font-weight: light;"); finishRegistationLayout->addWidget(registrationDescription); finishRegistationLayout->addStretch(); @@ -234,15 +227,24 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { outer_layout->setContentsMargins(0, 0, 0, 0); outer_layout->addWidget(mainLayout); - primeAd = new PrimeAdWidget; - mainLayout->addWidget(primeAd); + QWidget *content = new QWidget; + QVBoxLayout *content_layout = new QVBoxLayout(content); + content_layout->setContentsMargins(0, 0, 0, 0); + content_layout->setSpacing(30); primeUser = new PrimeUserWidget; - mainLayout->addWidget(primeUser); + content_layout->addWidget(primeUser); - mainLayout->setCurrentWidget(uiState()->primeType() ? (QWidget*)primeUser : (QWidget*)primeAd); + WiFiPromptWidget *wifi_prompt = new WiFiPromptWidget; + QObject::connect(wifi_prompt, &WiFiPromptWidget::openSettings, this, &SetupWidget::openSettings); + content_layout->addWidget(wifi_prompt); + content_layout->addStretch(); + + mainLayout->addWidget(content); + + primeUser->setVisible(uiState()->primeType()); + mainLayout->setCurrentIndex(1); - setFixedWidth(750); setStyleSheet(R"( #primeWidget { border-radius: 10px; @@ -282,10 +284,7 @@ void SetupWidget::replyFinished(const QString &response, bool success) { } else { popup->reject(); - if (prime_type) { - mainLayout->setCurrentWidget(primeUser); - } else { - mainLayout->setCurrentWidget(primeAd); - } + primeUser->setVisible(prime_type); + mainLayout->setCurrentIndex(1); } } diff --git a/selfdrive/ui/qt/widgets/prime.h b/selfdrive/ui/qt/widgets/prime.h index 9c7b4460fc..b41bab1695 100644 --- a/selfdrive/ui/qt/widgets/prime.h +++ b/selfdrive/ui/qt/widgets/prime.h @@ -69,10 +69,12 @@ class SetupWidget : public QFrame { public: explicit SetupWidget(QWidget* parent = 0); +signals: + void openSettings(int index = 0, const QString ¶m = ""); + private: PairingPopup *popup; QStackedWidget *mainLayout; - PrimeAdWidget *primeAd; PrimeUserWidget *primeUser; private slots: diff --git a/selfdrive/ui/qt/widgets/wifi.cc b/selfdrive/ui/qt/widgets/wifi.cc new file mode 100644 index 0000000000..b717a00d98 --- /dev/null +++ b/selfdrive/ui/qt/widgets/wifi.cc @@ -0,0 +1,103 @@ +#include "selfdrive/ui/qt/widgets/wifi.h" + +#include +#include +#include +#include + +WiFiPromptWidget::WiFiPromptWidget(QWidget *parent) : QFrame(parent) { + stack = new QStackedLayout(this); + + // Setup Wi-Fi + QFrame *setup = new QFrame; + QVBoxLayout *setup_layout = new QVBoxLayout(setup); + setup_layout->setContentsMargins(56, 40, 56, 40); + setup_layout->setSpacing(20); + { + QHBoxLayout *title_layout = new QHBoxLayout; + title_layout->setSpacing(32); + { + QLabel *icon = new QLabel; + QPixmap *pixmap = new QPixmap("../assets/offroad/icon_wifi_strength_full.svg"); + icon->setPixmap(pixmap->scaledToWidth(80, Qt::SmoothTransformation)); + title_layout->addWidget(icon); + + QLabel *title = new QLabel(tr("Setup Wi-Fi")); + title->setStyleSheet("font-size: 64px; font-weight: 600;"); + title_layout->addWidget(title); + title_layout->addStretch(); + } + setup_layout->addLayout(title_layout); + + QLabel *desc = new QLabel(tr("Connect to Wi-Fi to upload driving data and help improve openpilot")); + desc->setStyleSheet("font-size: 40px; font-weight: 400;"); + desc->setWordWrap(true); + setup_layout->addWidget(desc); + + QPushButton *settings_btn = new QPushButton(tr("Open Settings")); + connect(settings_btn, &QPushButton::clicked, [=]() { emit openSettings(1); }); + settings_btn->setStyleSheet(R"( + QPushButton { + font-size: 48px; + font-weight: 500; + border-radius: 10px; + background-color: #465BEA; + padding: 32px; + } + QPushButton:pressed { + background-color: #3049F4; + } + )"); + setup_layout->addWidget(settings_btn); + } + stack->addWidget(setup); + + // Uploading data + QWidget *uploading = new QWidget; + QVBoxLayout *uploading_layout = new QVBoxLayout(uploading); + uploading_layout->setContentsMargins(64, 56, 64, 56); + uploading_layout->setSpacing(36); + { + QHBoxLayout *title_layout = new QHBoxLayout; + { + QLabel *title = new QLabel(tr("Uploading training data")); + title->setStyleSheet("font-size: 64px; font-weight: 600;"); + title->setWordWrap(true); + title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + title_layout->addWidget(title); + title_layout->addStretch(); + + QLabel *icon = new QLabel; + QPixmap *pixmap = new QPixmap("../assets/offroad/icon_wifi_uploading.svg"); + icon->setPixmap(pixmap->scaledToWidth(120, Qt::SmoothTransformation)); + title_layout->addWidget(icon); + } + uploading_layout->addLayout(title_layout); + + QLabel *desc = new QLabel(tr("Your data is used to train driving models and help improve openpilot")); + desc->setStyleSheet("font-size: 48px; font-weight: 400;"); + desc->setWordWrap(true); + uploading_layout->addWidget(desc); + } + stack->addWidget(uploading); + + setStyleSheet(R"( + WiFiPromptWidget { + background-color: #333333; + border-radius: 10px; + } + )"); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &WiFiPromptWidget::updateState); +} + +void WiFiPromptWidget::updateState(const UIState &s) { + if (!isVisible()) return; + + auto &sm = *(s.sm); + + auto network_type = sm["deviceState"].getDeviceState().getNetworkType(); + auto uploading = network_type == cereal::DeviceState::NetworkType::WIFI || + network_type == cereal::DeviceState::NetworkType::ETHERNET; + stack->setCurrentIndex(uploading ? 1 : 0); +} diff --git a/selfdrive/ui/qt/widgets/wifi.h b/selfdrive/ui/qt/widgets/wifi.h new file mode 100644 index 0000000000..60c865f2b8 --- /dev/null +++ b/selfdrive/ui/qt/widgets/wifi.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +#include "selfdrive/ui/ui.h" + +class WiFiPromptWidget : public QFrame { + Q_OBJECT + +public: + explicit WiFiPromptWidget(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString ¶m = ""); + +public slots: + void updateState(const UIState &s); + +protected: + QStackedLayout *stack; +}; diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 5bec3f674a..71f3df7597 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -517,10 +517,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1076,6 +1072,29 @@ This may take up to a minute. Aktualisierung fehlgeschlagen + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 43e4974784..019eb1b71b 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -518,10 +518,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1070,6 +1066,29 @@ This may take up to a minute. 更新失敗 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index c985fae0e9..cab5e2ada6 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -518,10 +518,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1071,6 +1067,29 @@ This may take up to a minute. 업데이트 실패 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 9eeedea29c..70f06670a9 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -519,10 +519,6 @@ trabalho definido comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1075,6 +1071,29 @@ Isso pode levar até um minuto. Falha na atualização + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 9302047ab0..f6924b3c57 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -516,10 +516,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1068,6 +1064,29 @@ This may take up to a minute. 更新失败 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 5d17a7b86a..243a91ebd1 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -518,10 +518,6 @@ location set comma prime comma 高級會員 - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1070,6 +1066,29 @@ This may take up to a minute. 更新失敗 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/system/sensord/rawgps/rawgpsd.py b/system/sensord/rawgps/rawgpsd.py index 539a6308a7..a5eafb268d 100755 --- a/system/sensord/rawgps/rawgpsd.py +++ b/system/sensord/rawgps/rawgpsd.py @@ -110,36 +110,52 @@ def gps_enabled() -> bool: raise Exception("failed to execute QGPS mmcli command") from exc def download_and_inject_assistance(): - assist_data_file = '/tmp/xtra3grc.bin' + assist_data_file = '/tmp/xtra3grc.bin' assistance_url = 'http://xtrapath3.izatcloud.net/xtra3grc.bin' + try: - c = pycurl.Curl() - c.setopt(c.URL, assistance_url) - c.setopt(c.NOBODY, 1) - c.setopt(pycurl.CONNECTTIMEOUT, 2) - c.perform() - c.close() - bytes_n = c.getinfo(c.CONTENT_LENGTH_DOWNLOAD) - if bytes_n > 1e5: - cloudlog.exception("Qcom assistance data larger than expected") - return - with open(assist_data_file, "wb") as fp: + # download assistance + try: c = pycurl.Curl() - c.setopt(pycurl.URL, assistance_url) - c.setopt(pycurl.CONNECTTIMEOUT, 5) - - c.setopt(pycurl.WRITEDATA, fp) + c.setopt(c.URL, assistance_url) + c.setopt(c.NOBODY, 1) + c.setopt(pycurl.CONNECTTIMEOUT, 2) c.perform() + bytes_n = c.getinfo(c.CONTENT_LENGTH_DOWNLOAD) c.close() - except pycurl.error as e: - cloudlog.exception(f'Failed to download assistance file with error: {e}') - if os.path.isfile(assist_data_file): + if bytes_n > 1e5: + cloudlog.error("Qcom assistance data larger than expected") + return + + with open(assist_data_file, 'wb') as fp: + c = pycurl.Curl() + c.setopt(pycurl.URL, assistance_url) + c.setopt(pycurl.CONNECTTIMEOUT, 5) + + c.setopt(pycurl.WRITEDATA, fp) + c.perform() + c.close() + except pycurl.error: + cloudlog.exception("Failed to download assistance file") + return + + # inject into module try: - subprocess.check_call(f"mmcli -m any --timeout 30 --location-inject-assistance-data={assist_data_file}", shell=True) - except subprocess.CalledProcessError: - cloudlog.exception("rawgps.mmcli_command_failed") - if os.path.isfile(assist_data_file): - os.remove(assist_data_file) + cmd = f"mmcli -m any --timeout 30 --location-inject-assistance-data={assist_data_file}" + subprocess.check_output(cmd, stderr=subprocess.PIPE, shell=True) + cloudlog.info("successfully loaded assistance data") + except subprocess.CalledProcessError as e: + cloudlog.event( + "rawgps.assistance_loading_failed", + error=True, + cmd=e.cmd, + output=e.output, + returncode=e.returncode + ) + finally: + if os.path.exists(assist_data_file): + os.remove(assist_data_file) + def setup_quectel(diag: ModemDiag): # enable OEMDRE in the NV diff --git a/tools/cabana/dbc/dbcfile.cc b/tools/cabana/dbc/dbcfile.cc index d9938b0fbc..2a8d3d2d54 100644 --- a/tools/cabana/dbc/dbcfile.cc +++ b/tools/cabana/dbc/dbcfile.cc @@ -212,7 +212,7 @@ void DBCFile::parseExtraInfo(const QString &content) { uint32_t address = 0; while (!stream.atEnd()) { ++line_num; - line = stream.readLine(); + line = stream.readLine().trimmed(); if (line.startsWith("BO_ ")) { auto match = bo_regexp.match(line); dbc_assert(match.hasMatch()); diff --git a/tools/cabana/tests/test_cabana.cc b/tools/cabana/tests/test_cabana.cc index a3921d727b..abbb3dbf13 100644 --- a/tools/cabana/tests/test_cabana.cc +++ b/tools/cabana/tests/test_cabana.cc @@ -69,3 +69,44 @@ TEST_CASE("Parse can messages") { } } } + +TEST_CASE("Parse dbc") { + QString content = R"( +BO_ 160 message_1: 8 XXX + SG_ signal_1 : 0|12@1+ (1,0) [0|4095] "unit" XXX + SG_ signal_2 : 12|1@1+ (1.0,0.0) [0.0|1] "" XXX + +VAL_ 160 signal_1 0 "disabled" 1.2 "initializing" 2 "fault"; + +CM_ BO_ 160 "message comment"; +CM_ SG_ 160 signal_1 "signal comment"; +CM_ SG_ 160 signal_2 "multiple line comment +1 +2 +";)"; + + DBCFile file("", content); + auto msg = file.msg(160); + REQUIRE(msg != nullptr); + REQUIRE(msg->name == "message_1"); + REQUIRE(msg->size == 8); + REQUIRE(msg->comment == "message comment"); + REQUIRE(msg->sigs.size() == 2); + REQUIRE(file.msg("message_1") != nullptr); + + auto &sig_1 = msg->sigs[0]; + REQUIRE(sig_1.name == "signal_1"); + REQUIRE(sig_1.start_bit == 0); + REQUIRE(sig_1.size == 12); + REQUIRE(sig_1.min == 0); + REQUIRE(sig_1.max == 4095); + REQUIRE(sig_1.unit == "unit"); + REQUIRE(sig_1.comment == "signal comment"); + REQUIRE(sig_1.val_desc.size() == 3); + REQUIRE(sig_1.val_desc[0] == std::pair{0, "disabled"}); + REQUIRE(sig_1.val_desc[1] == std::pair{1.2, "initializing"}); + REQUIRE(sig_1.val_desc[2] == std::pair{2, "fault"}); + + auto &sig_2 = msg->sigs[1]; + REQUIRE(sig_2.comment == "multiple line comment\n1\n2"); +}