pull/27829/head
Justin Newberry 2 years ago
parent fcb584e110
commit f93746487e
  1. 2
      tools/cabana/SConscript
  2. 1
      tools/cabana/dbc/dbcmanager.h
  3. 6
      tools/cabana/mainwin.cc
  4. 2
      tools/cabana/mainwin.h
  5. 254
      tools/cabana/tools/search.cc
  6. 194
      tools/cabana/tools/search.h
  7. 25
      tools/cabana/videowidget.cc

@ -30,7 +30,7 @@ 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', 'streams/livestream.cc', 'streams/abstractstream.cc', 'streams/replaystream.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc',
'dbc/dbc.cc', 'dbc/dbcfile.cc', 'dbc/dbcmanager.cc',
'commands.cc', 'messageswidget.cc', 'route.cc', 'settings.cc', 'util.cc', 'detailwidget.cc', 'tools/findsimilarbits.cc', 'tools/search.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
'commands.cc', 'messageswidget.cc', 'route.cc', 'settings.cc', 'util.cc', 'detailwidget.cc', 'tools/findsimilarbits.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
cabana_env.Program('_cabana', ['cabana.cc', cabana_lib, assets], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
if arch == "Darwin":

@ -1,7 +1,6 @@
#pragma once
#include <map>
#include <optional>
#include <QList>
#include <QMetaType>
#include <QObject>

@ -149,7 +149,6 @@ void MainWindow::createActions() {
if (!can->liveStreaming()) {
QMenu *tools_menu = menuBar()->addMenu(tr("&Tools"));
tools_menu->addAction(tr("Find &Similar Bits"), this, &MainWindow::findSimilarBits);
tools_menu->addAction(tr("Search"), this, &MainWindow::searchDlg);
}
QMenu *help_menu = menuBar()->addMenu(tr("&Help"));
@ -591,11 +590,6 @@ void MainWindow::findSimilarBits() {
dlg->show();
}
void MainWindow::searchDlg() {
SearchDlg *dlg = new SearchDlg(this);
dlg->show();
}
void MainWindow::onlineHelp() {
if (auto help = findChild<HelpOverlay*>()) {
help->close();

@ -13,7 +13,6 @@
#include "tools/cabana/messageswidget.h"
#include "tools/cabana/videowidget.h"
#include "tools/cabana/tools/findsimilarbits.h"
#include "tools/cabana/tools/search.h"
class MainWindow : public QMainWindow {
Q_OBJECT
@ -59,7 +58,6 @@ protected:
void updateDownloadProgress(uint64_t cur, uint64_t total, bool success);
void setOption();
void findSimilarBits();
void searchDlg();
void undoStackCleanChanged(bool clean);
void undoStackIndexChanged(int index);
void onlineHelp();

@ -1,254 +0,0 @@
#include "tools/cabana/tools/search.h"
#include <iostream>
std::map<ScanType, std::string> scanTypeToDisplayName {
{ExactValue, "Exact value"},
{BiggerThan, "Bigger than..."},
{SmallerThan, "Smaller than..."},
{BiggerThan, "Bigger than..."},
{ValueBetween, "Value between..."},
{IncreasedValue, "Increased value"},
{IncreaseValueBy, "Increased value by..."},
{DecreasedValue, "Decreased value"},
{DecreasedValueBy, "Decreased value by..."},
{ChangedValue, "Changed value"},
{UnchangedValue, "Unchanged value"},
{UnknownInitialValue, "Unknown initial value"},
};
uint64_t getBitValue(uint64_t val, int offset, int size){
return (((1 << size) - 1) & (val >> (offset - 1)));
}
SearchDlg::SearchDlg(QWidget *parent) : QDialog(parent) {
setWindowTitle(tr("Search"));
setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout *main_layout = new QVBoxLayout(this);
QHBoxLayout *scan_button_layout = new QHBoxLayout();
first_scan_button = new QPushButton(QString("..."), this);
next_scan_button = new QPushButton(QString("Next Scan"), this);
undo_scan_button = new QPushButton(QString("Undo Scan"), this);
undo_scan_button->setEnabled(false);
next_scan_button->setEnabled(false);
QObject::connect(first_scan_button, &QPushButton::clicked, [=]() { firstScan(); });
QObject::connect(next_scan_button, &QPushButton::clicked, [=]() { nextScan(); });
QObject::connect(undo_scan_button, &QPushButton::clicked, [=]() { undoScan(); });
scan_button_layout->addWidget(first_scan_button);
scan_button_layout->addWidget(next_scan_button);
scan_button_layout->addWidget(undo_scan_button);
QVBoxLayout *search_parameters_layout = new QVBoxLayout();
QLineEdit *value_box1 = new QLineEdit();
value_box1->setValidator( new QIntValidator(this) );
QObject::connect(value_box1, &QLineEdit::textChanged, [=](QString value) { scan_value1 = value.toInt(); });
scan_type = new QComboBox();
QObject::connect(scan_type, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) { selectedScanType = (ScanType)(scan_type->itemData(index).toInt()); });
QHBoxLayout *bits_min_max_layout = new QHBoxLayout();
QSpinBox *bits_min = new QSpinBox();
bits_min->setRange(1,32);
bits_min->setValue(scan_bits_range_min);
QSpinBox *bits_max = new QSpinBox();
bits_max->setRange(1,32);
bits_max->setValue(scan_bits_range_max);
QObject::connect(bits_min, qOverload<int>(&QSpinBox::valueChanged), [=](int value) { scan_bits_range_min=value; });
QObject::connect(bits_max, qOverload<int>(&QSpinBox::valueChanged), [=](int value) { scan_bits_range_max=value; });
bits_min_max_layout->addWidget(bits_min);
bits_min_max_layout->addWidget(bits_max);
search_parameters_layout->addWidget(value_box1);
search_parameters_layout->addWidget(scan_type);
search_parameters_layout->addLayout(bits_min_max_layout);
QVBoxLayout *search_results_layout = new QVBoxLayout();
numberOfSigsLabel = new QLabel(QString("Found: 0"));
search_results_layout->addWidget(numberOfSigsLabel);
data_table = new QTableWidget();
data_table->setRowCount(1);
data_table->setColumnCount(6);
search_results_layout->addWidget(data_table);
main_layout->addLayout(scan_button_layout);
main_layout->addLayout(search_parameters_layout);
main_layout->addLayout(search_results_layout);
update();
QObject::connect(can, &AbstractStream::received, this, &SearchDlg::updateRowData);
QObject::connect(can, &AbstractStream::seekedTo, this, &SearchDlg::updateRowData);
}
void SearchDlg::setRowData(int row, QString msgID, QString bitRange, QString currentValue, QString previousValue){
QTableWidgetItem *msg_id = new QTableWidgetItem(msgID);
data_table->setItem(row, 0, msg_id);
QTableWidgetItem *bit_range = new QTableWidgetItem(bitRange);
data_table->setItem(row, 1, bit_range);
QTableWidgetItem *current_value = new QTableWidgetItem(currentValue);
data_table->setItem(row, 2, current_value);
QTableWidgetItem *previous_value = new QTableWidgetItem(previousValue);
data_table->setItem(row, 3, previous_value);
}
void SearchDlg::updateRowData(){
data_table->clear();
data_table->setRowCount(0);
if(filteredSignals.size() < 1000){
data_table->setRowCount(filteredSignals.size() + 1);
setRowData(0, QString("Message ID"), QString("Bit Range"), QString("Current Value"), QString("Previous Value"));
int row=1;
for(auto &sig : filteredSignals){
setRowData(row, sig.messageID.toString(), QString("%1:%2").arg(sig.offset).arg(sig.offset+sig.size), QString::number(sig.getValue()), QString::number(sig.previousValue));
row++;
}
}
}
void SearchDlg::update(){
first_scan_button->setText(scanningStarted ? "New Scan" : "First Scan");
numberOfSigsLabel->setText(QString("Found: ") + QString::number(filteredSignals.size()));
ScanType selectedValue = (ScanType)(scan_type->currentData().toInt());
next_scan_button->setEnabled(scanningStarted);
undo_scan_button->setEnabled(false);
scan_type->clear();
int selectedIndex = -1;
int i = 0;
for(auto scanType : enabledScanTypes()){
if(scanType == selectedValue) selectedIndex = i;
scan_type->addItem(QString::fromStdString(scanTypeToDisplayName[scanType]), QVariant(scanType));
i++;
}
if(selectedIndex != -1){
scan_type->setCurrentIndex(selectedIndex);
}
updateRowData();
for(auto &sig : filteredSignals){
sig.previousValue = sig.getValue();
}
}
std::vector<Sig> getAllPossibleSignals(int bits_min, int bits_max){
std::vector<Sig> ret;
for(auto msg_id : can->last_msgs.keys()) {
for(int i = bits_min; i < bits_max+1; i++) {
for(int j = 0; j < 64 - i; j++) {
ret.push_back(Sig(msg_id, j, i));
}
}
}
return ret;
}
std::vector<ScanType> SearchDlg::enabledScanTypes(){
if(!scanningStarted){
return std::vector<ScanType> {
ExactValue,
BiggerThan,
SmallerThan,
ValueBetween,
UnknownInitialValue
};
}
else{
return std::vector<ScanType> {
ExactValue,
BiggerThan,
SmallerThan,
ValueBetween,
IncreasedValue,
IncreaseValueBy,
DecreasedValue,
DecreasedValueBy,
ChangedValue,
UnchangedValue
};
}
}
void SearchDlg::firstScan(){
if(scanningStarted){
filteredSignals.clear();
scanningStarted = false;
}
else{
filteredSignals = getAllPossibleSignals(scan_bits_range_min, scan_bits_range_max);
scanningStarted = true;
nextScan();
}
update();
}
SignalFilterer* SearchDlg::getCurrentFilterer() {
if(selectedScanType == ExactValue){
return new ExactValueSignalFilterer(scan_value1);
}
if(selectedScanType == BiggerThan){
return new BiggerThanSignalFilterer(scan_value1);
}
if(selectedScanType == SmallerThan){
return new SmallerThanSignalFilterer(scan_value1);
}
if(selectedScanType == UnknownInitialValue){
return new UnknownInitialValueSignalFilter();
}
if(selectedScanType == UnchangedValue){
return new UnchangedValueSignalFilter();
}
if(selectedScanType == ChangedValue){
return new ChangedValueSignalFilter();
}
if(selectedScanType == IncreasedValue){
return new IncreasedValueSignalFilter();
}
if(selectedScanType == DecreasedValue){
return new DecreasedValueSignalFilter();
}
return nullptr;
}
void SearchDlg::nextScan(){
auto filterer = getCurrentFilterer();
filteredSignals = filterer->filter(filteredSignals);
update();
}
void SearchDlg::undoScan(){
}

@ -1,194 +0,0 @@
#pragma once
#include <QDialog>
#include <QPushButton>
#include <QButtonGroup>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QDoubleValidator>
#include <QComboBox>
#include <QSpinBox>
#include <QLabel>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <iostream>
#include "tools/cabana/dbc/dbcmanager.h"
#include "tools/cabana/streams/abstractstream.h"
uint64_t getBitValue(uint64_t val, int offset, int size);
enum ScanType {
ExactValue,
BiggerThan,
SmallerThan,
ValueBetween,
IncreasedValue,
IncreaseValueBy,
DecreasedValue,
DecreasedValueBy,
ChangedValue,
UnchangedValue,
UnknownInitialValue
};
class Sig {
public:
Sig(MessageId _messageID, int _offset, int _size) : messageID(_messageID), offset(_offset), size(_size) {}
MessageId messageID;
size_t offset;
size_t size;
uint64_t previousValue;
uint64_t getValue(){
auto msg = can->last_msgs[messageID];
uint64_t* data = (uint64_t*)(msg.dat.data());
return getBitValue(*data, offset, size);
}
};
class SignalFilterer {
public:
virtual bool signalMatches(Sig sig) = 0;
std::vector<Sig> filter(std::vector<Sig> in) {
std::vector<Sig> ret;
std::copy_if(in.begin(), in.end(), std::back_inserter(ret), [=] (Sig sig) { return signalMatches(sig); });
return ret;
}
};
class ZeroInputSignalFilterer : public SignalFilterer {
public:
ZeroInputSignalFilterer(){
}
};
class SingleInputSignalFilterer : public SignalFilterer {
public:
SingleInputSignalFilterer(uint64_t _value) : value(_value){
}
protected:
uint64_t value;
};
class DoubleInputSignalFilterer : public SignalFilterer {
public:
DoubleInputSignalFilterer(uint64_t _value1, uint64_t _value2) : value1(_value1), value2(_value2){
}
protected:
uint64_t value1;
uint64_t value2;
};
class ExactValueSignalFilterer : public SingleInputSignalFilterer {
using SingleInputSignalFilterer::SingleInputSignalFilterer;
bool signalMatches(Sig sig) {
return sig.getValue() == value;
}
};
class BiggerThanSignalFilterer : public SingleInputSignalFilterer {
using SingleInputSignalFilterer::SingleInputSignalFilterer;
bool signalMatches(Sig sig) {
return sig.getValue() > value;
}
};
class SmallerThanSignalFilterer : public SingleInputSignalFilterer {
using SingleInputSignalFilterer::SingleInputSignalFilterer;
bool signalMatches(Sig sig) {
return sig.getValue() < value;
}
};
class UnknownInitialValueSignalFilter : public ZeroInputSignalFilterer {
using ZeroInputSignalFilterer::ZeroInputSignalFilterer;
bool signalMatches(Sig sig) {
return true;
}
};
class IncreasedValueSignalFilter : public ZeroInputSignalFilterer {
using ZeroInputSignalFilterer::ZeroInputSignalFilterer;
bool signalMatches(Sig sig) {
return sig.getValue() > sig.previousValue;
}
};
class DecreasedValueSignalFilter : public ZeroInputSignalFilterer {
using ZeroInputSignalFilterer::ZeroInputSignalFilterer;
bool signalMatches(Sig sig) {
return sig.getValue() < sig.previousValue;
}
};
class ChangedValueSignalFilter : public ZeroInputSignalFilterer {
using ZeroInputSignalFilterer::ZeroInputSignalFilterer;
bool signalMatches(Sig sig) {
return sig.getValue() != sig.previousValue;
}
};
class UnchangedValueSignalFilter : public ZeroInputSignalFilterer {
using ZeroInputSignalFilterer::ZeroInputSignalFilterer;
bool signalMatches(Sig sig) {
return sig.getValue() == sig.previousValue;
}
};
class SearchDlg : public QDialog {
Q_OBJECT
public:
SearchDlg(QWidget *parent);
private:
void firstScan();
void nextScan();
void undoScan();
void update();
void updateRowData();
void setRowData(int row, QString msgID, QString bitRange, QString currentValue, QString previousValue);
std::vector<ScanType> enabledScanTypes();
SignalFilterer* getCurrentFilterer();
bool scanningStarted = false;
uint32_t scan_bits_range_min = 1;
uint32_t scan_bits_range_max = 32;
uint64_t scan_value1 = 0;
uint64_t scan_value2 = 0;
std::vector<Sig> filteredSignals;
ScanType selectedScanType;
QLabel* numberOfSigsLabel;
QComboBox *scan_type;
QPushButton *first_scan_button;
QPushButton *next_scan_button;
QPushButton *undo_scan_button;
QTableWidget *data_table;
};

@ -188,36 +188,15 @@ void Slider::sliderChange(QAbstractSlider::SliderChange change) {
}
}
bool sortTimelineBasedOnEventPriority(std::tuple<int, int, TimelineType> left, std::tuple<int, int, TimelineType> right){
std::map<TimelineType, int> timelinePriority = {
{ TimelineType::None, 0 },
{ TimelineType::Engaged, 10 },
{ TimelineType::AlertInfo, 20 },
{ TimelineType::AlertWarning, 30 },
{ TimelineType::AlertCritical, 40 },
{ TimelineType::UserFlag, 35 }
};
return timelinePriority[std::get<2>(left)] < timelinePriority[std::get<2>(right)];
}
void Slider::paintEvent(QPaintEvent *ev) {
QPainter p(this);
QRect r = rect().adjusted(0, 4, 0, -4);
p.fillRect(r, timeline_colors[(int)TimelineType::None]);
double min = minimum() / 1000.0;
double max = maximum() / 1000.0;
std::vector<std::tuple<int, int, TimelineType>> sortedTimeline;
std::copy(timeline.begin(), timeline.end(), std::back_inserter(sortedTimeline));
std::sort(sortedTimeline.begin(), sortedTimeline.end(), sortTimelineBasedOnEventPriority);
for (auto [begin, end, type] : sortedTimeline) {
if (begin > max || end < min)
for (auto [begin, end, type] : timeline) {
if (begin > max || end < min)
continue;
r.setLeft(((std::max(min, (double)begin) - min) / (max - min)) * width());
r.setRight(((std::min(max, (double)end) - min) / (max - min)) * width());
p.fillRect(r, timeline_colors[(int)type]);

Loading…
Cancel
Save