diff --git a/tools/cabana/.gitignore b/tools/cabana/.gitignore index 88ffab2717..d7a552eabb 100644 --- a/tools/cabana/.gitignore +++ b/tools/cabana/.gitignore @@ -3,3 +3,5 @@ moc_* _cabana settings +car_fingerprint_to_dbc.json + diff --git a/tools/cabana/SConscript b/tools/cabana/SConscript index fd44ecd138..d791466ce7 100644 --- a/tools/cabana/SConscript +++ b/tools/cabana/SConscript @@ -12,5 +12,6 @@ else: qt_libs = ['qt_util', 'Qt5Charts'] + base_libs cabana_libs = [widgets, cereal, messaging, visionipc, replay_lib, opendbc,'avutil', 'avcodec', 'avformat', 'bz2', 'curl', 'yuv'] + qt_libs +qt_env.Execute('./generate_dbc_json.py --out car_fingerprint_to_dbc.json') qt_env.Program('_cabana', ['cabana.cc', 'mainwin.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc', 'dbcmanager.cc', 'canmessages.cc', 'messageswidget.cc', 'detailwidget.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks) diff --git a/tools/cabana/generate_dbc_json.py b/tools/cabana/generate_dbc_json.py new file mode 100755 index 0000000000..cb122e2eb2 --- /dev/null +++ b/tools/cabana/generate_dbc_json.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +import argparse +import json + +from selfdrive.car.car_helpers import get_interface_attr + + +def generate_dbc_json() -> str: + all_cars_by_brand = get_interface_attr("CAR_INFO") + all_dbcs_by_brand = get_interface_attr("DBC") + dbc_map = {car: all_dbcs_by_brand[brand][car]['pt'] for brand, cars in all_cars_by_brand.items() for car in cars if car != 'mock'} + return json.dumps(dict(sorted(dbc_map.items())), indent=2) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate mapping for all car fingerprints to DBC names and outputs json file", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument("--out", required=True, help="Generated json filepath") + args = parser.parse_args() + + with open(args.out, 'w') as f: + f.write(generate_dbc_json()) + print(f"Generated and written to {args.out}") diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index f39ce97684..dfe665d750 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -68,9 +68,10 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { // signals/slots QObject::connect(filter, &QLineEdit::textChanged, proxy_model, &QSortFilterProxyModel::setFilterFixedString); + QObject::connect(can, &CANMessages::eventsMerged, this, &MessagesWidget::loadDBCFromFingerprint); QObject::connect(can, &CANMessages::updated, model, &MessageListModel::updateState); - QObject::connect(dbc_combo, SIGNAL(activated(const QString &)), SLOT(dbcSelectionChanged(const QString &))); - QObject::connect(load_from_paste, &QPushButton::clicked, this, &MessagesWidget::loadFromPaste); + QObject::connect(dbc_combo, SIGNAL(activated(const QString &)), SLOT(loadDBCFromName(const QString &))); + QObject::connect(load_from_paste, &QPushButton::clicked, this, &MessagesWidget::loadDBCFromPaste); QObject::connect(save_btn, &QPushButton::clicked, [=]() { // TODO: save DBC to file }); @@ -80,17 +81,20 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { } }); - // For test purpose - dbc_combo->setCurrentText("toyota_nodsu_pt_generated"); + QFile json_file("./car_fingerprint_to_dbc.json"); + if(json_file.open(QIODevice::ReadOnly)) { + fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); + } } -void MessagesWidget::dbcSelectionChanged(const QString &dbc_file) { - dbc()->open(dbc_file); - // TODO: reset model? - table_widget->sortByColumn(0, Qt::AscendingOrder); +void MessagesWidget::loadDBCFromName(const QString &name) { + dbc()->open(name); + dbc_combo->setCurrentText(name); + // refresh model + model->updateState(); } -void MessagesWidget::loadFromPaste() { +void MessagesWidget::loadDBCFromPaste() { LoadDBCDialog dlg(this); if (dlg.exec()) { dbc()->open("from paste", dlg.dbc_edit->toPlainText()); @@ -98,6 +102,16 @@ void MessagesWidget::loadFromPaste() { } } +void MessagesWidget::loadDBCFromFingerprint() { + auto fingerprint = can->carFingerprint(); + if (!fingerprint.isEmpty() && dbc()->name().isEmpty()) { + auto dbc_name = fingerprint_to_dbc[fingerprint]; + if (dbc_name != QJsonValue::Undefined) { + loadDBCFromName(dbc_name.toString()); + } + } +} + // MessageListModel QVariant MessageListModel::headerData(int section, Qt::Orientation orientation, int role) const { diff --git a/tools/cabana/messageswidget.h b/tools/cabana/messageswidget.h index 1184772f3b..bef15c2cf7 100644 --- a/tools/cabana/messageswidget.h +++ b/tools/cabana/messageswidget.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -38,8 +39,9 @@ public: MessagesWidget(QWidget *parent); public slots: - void dbcSelectionChanged(const QString &dbc_file); - void loadFromPaste(); + void loadDBCFromName(const QString &name); + void loadDBCFromFingerprint(); + void loadDBCFromPaste(); signals: void msgSelectionChanged(const QString &message_id); @@ -48,4 +50,5 @@ protected: QTableView *table_widget; QComboBox *dbc_combo; MessageListModel *model; + QJsonDocument fingerprint_to_dbc; };