mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 23:33:58 +08:00
Cabana: add tool to find similar bits (#26834)
* find similar bits
* set window title
old-commit-hash: 65509669b6
This commit is contained in:
@@ -18,7 +18,7 @@ cabana_env = qt_env.Clone()
|
||||
prev_moc_path = cabana_env['QT_MOCHPREFIX']
|
||||
cabana_env['QT_MOCHPREFIX'] = os.path.dirname(prev_moc_path) + '/cabana/moc_'
|
||||
cabana_lib = cabana_env.Library("cabana_lib", ['mainwin.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc', 'dbcmanager.cc',
|
||||
'canmessages.cc', 'commands.cc', 'messageswidget.cc', 'settings.cc', 'detailwidget.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
'canmessages.cc', 'commands.cc', 'messageswidget.cc', 'settings.cc', 'detailwidget.cc', 'tools/findsimilarbits.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
cabana_env.Program('_cabana', ['cabana.cc', cabana_lib], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
|
||||
if GetOption('test'):
|
||||
|
||||
@@ -133,6 +133,9 @@ void MainWindow::createActions() {
|
||||
commands_act->setDefaultWidget(undo_view);
|
||||
commands_menu->addAction(commands_act);
|
||||
|
||||
QMenu *tools_menu = menuBar()->addMenu(tr("&Tools"));
|
||||
tools_menu->addAction(tr("Find &Similar Bits"), this, &MainWindow::findSimilarBits);
|
||||
|
||||
QMenu *help_menu = menuBar()->addMenu(tr("&Help"));
|
||||
help_menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
|
||||
}
|
||||
@@ -283,3 +286,8 @@ void MainWindow::setOption() {
|
||||
SettingsDlg dlg(this);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void MainWindow::findSimilarBits() {
|
||||
FindSimilarBitsDlg dlg(this);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "tools/cabana/detailwidget.h"
|
||||
#include "tools/cabana/messageswidget.h"
|
||||
#include "tools/cabana/videowidget.h"
|
||||
#include "tools/cabana/tools/findsimilarbits.h"
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
@@ -41,6 +42,7 @@ protected:
|
||||
void DBCFileChanged();
|
||||
void updateDownloadProgress(uint64_t cur, uint64_t total, bool success);
|
||||
void setOption();
|
||||
void findSimilarBits();
|
||||
|
||||
VideoWidget *video_widget;
|
||||
MessagesWidget *messages_widget;
|
||||
|
||||
115
tools/cabana/tools/findsimilarbits.cc
Normal file
115
tools/cabana/tools/findsimilarbits.cc
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "tools/cabana/tools/findsimilarbits.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QHBoxLayout>
|
||||
#include <QIntValidator>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
|
||||
#include "tools/cabana/canmessages.h"
|
||||
#include "tools/cabana/dbcmanager.h"
|
||||
|
||||
FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent) {
|
||||
setWindowTitle(tr("Find similar bits"));
|
||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||
|
||||
QHBoxLayout *form_layout = new QHBoxLayout();
|
||||
bus_combo = new QComboBox(this);
|
||||
QSet<uint8_t> bus_set;
|
||||
for (auto it = can->can_msgs.begin(); it != can->can_msgs.end(); ++it) {
|
||||
bus_set << DBCManager::parseId(it.key()).first;
|
||||
}
|
||||
for (uint8_t bus : bus_set) {
|
||||
bus_combo->addItem(QString::number(bus));
|
||||
}
|
||||
bus_combo->model()->sort(0);
|
||||
bus_combo->setCurrentIndex(0);
|
||||
form_layout->addWidget(new QLabel("Bus"));
|
||||
form_layout->addWidget(bus_combo);
|
||||
|
||||
bit_combo = new QComboBox(this);
|
||||
bit_combo->addItems({"0", "1"});
|
||||
bit_combo->setCurrentIndex(1);
|
||||
form_layout->addWidget(new QLabel("Bit"));
|
||||
form_layout->addWidget(bit_combo);
|
||||
|
||||
min_msgs = new QLineEdit(this);
|
||||
min_msgs->setValidator(new QIntValidator(this));
|
||||
min_msgs->setText("100");
|
||||
form_layout->addWidget(new QLabel("Min msg count"));
|
||||
form_layout->addWidget(min_msgs);
|
||||
search_btn = new QPushButton(tr("&Find"), this);
|
||||
form_layout->addWidget(search_btn);
|
||||
form_layout->addStretch(1);
|
||||
main_layout->addLayout(form_layout);
|
||||
|
||||
table = new QTableWidget(this);
|
||||
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
table->horizontalHeader()->setStretchLastSection(true);
|
||||
main_layout->addWidget(table);
|
||||
|
||||
setMinimumSize({700, 500});
|
||||
QObject::connect(search_btn, &QPushButton::clicked, this, &FindSimilarBitsDlg::find);
|
||||
}
|
||||
|
||||
void FindSimilarBitsDlg::find() {
|
||||
search_btn->setEnabled(false);
|
||||
table->clear();
|
||||
auto msg_mismatched = calcBits(bus_combo->currentText().toUInt(), bit_combo->currentIndex(), min_msgs->text().toInt());
|
||||
table->setRowCount(msg_mismatched.size());
|
||||
table->setColumnCount(6);
|
||||
table->setHorizontalHeaderLabels({"address", "byte idx", "bit idx", "mismatches", "total", "perc%"});
|
||||
for (int i = 0; i < msg_mismatched.size(); ++i) {
|
||||
auto &m = msg_mismatched[i];
|
||||
table->setItem(i, 0, new QTableWidgetItem(QString("%1").arg(m.address, 1, 16)));
|
||||
table->setItem(i, 1, new QTableWidgetItem(QString::number(m.byte_idx)));
|
||||
table->setItem(i, 2, new QTableWidgetItem(QString::number(m.bit_idx)));
|
||||
table->setItem(i, 3, new QTableWidgetItem(QString::number(m.mismatches)));
|
||||
table->setItem(i, 4, new QTableWidgetItem(QString::number(m.total)));
|
||||
table->setItem(i, 5, new QTableWidgetItem(QString::number(m.perc)));
|
||||
}
|
||||
search_btn->setEnabled(true);
|
||||
}
|
||||
|
||||
QList<FindSimilarBitsDlg::mismatched_struct> FindSimilarBitsDlg::calcBits(uint8_t bus, int bit_to_find, int min_msgs_cnt) {
|
||||
QHash<uint32_t, QVector<uint32_t>> mismatches;
|
||||
QHash<uint32_t, uint32_t> msg_count;
|
||||
auto events = can->events();
|
||||
for (auto e : *events) {
|
||||
if (e->which == cereal::Event::Which::CAN) {
|
||||
for (const auto &c : e->event.getCan()) {
|
||||
if (c.getSrc() == bus) {
|
||||
uint32_t address = c.getAddress();
|
||||
++msg_count[address];
|
||||
auto &mismatched = mismatches[address];
|
||||
const auto dat = c.getDat();
|
||||
if (mismatched.size() < dat.size() * 8) {
|
||||
mismatched.resize(dat.size() * 8);
|
||||
}
|
||||
for (int i = 0; i < dat.size(); ++i) {
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
int bit = ((dat[i] >> (7 - j)) & 1) != 0;
|
||||
mismatched[i * 8 + j] += (bit != bit_to_find);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<mismatched_struct> result;
|
||||
result.reserve(mismatches.size());
|
||||
for (auto it = mismatches.begin(); it != mismatches.end(); ++it) {
|
||||
if (auto cnt = msg_count[it.key()]; cnt > min_msgs_cnt) {
|
||||
auto &mismatched = it.value();
|
||||
for (int i = 0; i < mismatched.size(); ++i) {
|
||||
if (uint32_t perc = (mismatched[i] / (double)cnt) * 100; perc < 50) {
|
||||
result.push_back({it.key(), (uint32_t)i / 8, (uint32_t)i % 8, mismatched[i], cnt, perc});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::sort(result.begin(), result.end(), [](auto &l, auto &r) { return l.perc > r.perc; });
|
||||
return result;
|
||||
}
|
||||
23
tools/cabana/tools/findsimilarbits.h
Normal file
23
tools/cabana/tools/findsimilarbits.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QTableWidget>
|
||||
|
||||
class FindSimilarBitsDlg : public QDialog {
|
||||
public:
|
||||
FindSimilarBitsDlg(QWidget *parent);
|
||||
|
||||
private:
|
||||
struct mismatched_struct {
|
||||
uint32_t address, byte_idx, bit_idx, mismatches, total, perc;
|
||||
};
|
||||
QList<mismatched_struct> calcBits(uint8_t bus, int bit_to_find, int min_msgs_cnt);
|
||||
void find();
|
||||
|
||||
QTableWidget *table;
|
||||
QComboBox *bus_combo, *bit_combo;
|
||||
QPushButton *search_btn;
|
||||
QLineEdit *min_msgs;
|
||||
};
|
||||
Reference in New Issue
Block a user