cabana: DBCManager only expose methods/signals through MessageId (#27540)

old-commit-hash: 0afd3bab34
This commit is contained in:
Willem Melching 2023-03-14 19:31:04 +01:00 committed by GitHub
parent da54ce208f
commit 918bad4847
13 changed files with 84 additions and 35 deletions

View File

@ -421,8 +421,8 @@ void ChartView::signalUpdated(const cabana::Signal *sig) {
}
}
void ChartView::msgUpdated(uint32_t address) {
if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id.address == address; }))
void ChartView::msgUpdated(MessageId id) {
if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id == id; }))
updateTitle();
}

View File

@ -57,11 +57,11 @@ signals:
void axisYLabelWidthChanged(int w);
private slots:
void msgUpdated(uint32_t address);
void signalUpdated(const cabana::Signal *sig);
void manageSeries();
void handleMarkerClicked();
void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.msg_id.address == address; }); }
void msgUpdated(MessageId id);
void msgRemoved(MessageId id) { removeIf([=](auto &s) { return s.msg_id == id; }); }
void signalRemoved(const cabana::Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); }
private:

View File

@ -144,19 +144,31 @@ void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t si
auto &m = msgs[id.address];
m.name = name;
m.size = size;
emit msgUpdated(id.address);
// This DBC applies to all active sources, emit for every source
for (uint8_t source : sources) {
emit msgUpdated({.source = source, .address = id.address});
}
}
void DBCManager::removeMsg(const MessageId &id) {
msgs.erase(id.address);
emit msgRemoved(id.address);
// This DBC applies to all active sources, emit for every source
for (uint8_t source : sources) {
emit msgRemoved({.source = source, .address = id.address});
}
}
void DBCManager::addSignal(const MessageId &id, const cabana::Signal &sig) {
if (auto m = const_cast<cabana::Msg *>(msg(id.address))) {
m->sigs.push_back(sig);
auto s = &m->sigs.last();
emit signalAdded(id.address, s);
// This DBC applies to all active sources, emit for every source
for (uint8_t source : sources) {
emit signalAdded({.source = source, .address = id.address}, s);
}
}
}
@ -192,6 +204,10 @@ QStringList DBCManager::signalNames() {
return ret;
}
void DBCManager::updateSources(const QSet<uint8_t> &s) {
sources = s;
}
DBCManager *dbc() {
static DBCManager dbc_manager(nullptr);
return &dbc_manager;

View File

@ -5,6 +5,8 @@
#include <QMetaType>
#include <QObject>
#include <QString>
#include <QSet>
#include <QDebug>
#include "tools/cabana/dbc.h"
@ -20,30 +22,52 @@ public:
void addSignal(const MessageId &id, const cabana::Signal &sig);
void updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig);
void removeSignal(const MessageId &id, const QString &sig_name);
inline int msgCount() const { return msgs.size(); }
inline QString name() const { return name_; }
void updateMsg(const MessageId &id, const QString &name, uint32_t size);
void removeMsg(const MessageId &id);
inline const std::map<uint32_t, cabana::Msg> &messages() const { return msgs; }
inline std::map<MessageId, cabana::Msg> getMessages(uint8_t source) {
std::map<MessageId, cabana::Msg> ret;
for (auto &[address, msg] : msgs) {
MessageId id = {.source = source, .address = address};
ret[id] = msg;
}
return ret;
}
inline const cabana::Msg *msg(const MessageId &id) const { return msg(id.address); }
inline const cabana::Msg *msg(uint32_t address) const {
auto it = msgs.find(address);
return it != msgs.end() ? &it->second : nullptr;
inline const cabana::Msg* msg(uint8_t source, const QString &name) {
for (auto &[_, msg] : msgs) {
if (msg.name == name) {
return &msg;
}
}
return nullptr;
}
QStringList signalNames();
public slots:
void updateSources(const QSet<uint8_t> &s);
signals:
void signalAdded(uint32_t address, const cabana::Signal *sig);
void signalAdded(MessageId id, const cabana::Signal *sig);
void signalRemoved(const cabana::Signal *sig);
void signalUpdated(const cabana::Signal *sig);
void msgUpdated(uint32_t address);
void msgRemoved(uint32_t address);
void msgUpdated(MessageId id);
void msgRemoved(MessageId id);
void DBCFileChanged();
private:
void parseExtraInfo(const QString &content);
std::map<uint32_t, cabana::Msg> msgs;
QString name_;
QSet<uint8_t> sources;
inline const cabana::Msg *msg(uint32_t address) const {
auto it = msgs.find(address);
return it != msgs.end() ? &it->second : nullptr;
}
};
DBCManager *dbc();

View File

@ -177,7 +177,7 @@ void DetailWidget::removeMsg() {
// EditMessageDialog
EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent)
: original_name(title), QDialog(parent) {
: original_name(title), msg_id(msg_id), QDialog(parent) {
setWindowTitle(tr("Edit message: %1").arg(msg_id.toString()));
QFormLayout *form_layout = new QFormLayout(this);
@ -207,8 +207,7 @@ void EditMessageDialog::validateName(const QString &text) {
bool valid = text.compare(UNTITLED, Qt::CaseInsensitive) != 0;
error_label->setVisible(false);
if (!text.isEmpty() && valid && text != original_name) {
valid = std::none_of(dbc()->messages().begin(), dbc()->messages().end(),
[&text](auto &m) { return m.second.name == text; });
valid = dbc()->msg(msg_id.source, text) == nullptr;
if (!valid) {
error_label->setText(tr("Name already exists"));
error_label->setVisible(true);

View File

@ -15,6 +15,7 @@ public:
EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent);
void validateName(const QString &text);
MessageId msg_id;
QString original_name;
QDialogButtonBox *btn_box;
QLineEdit *name_edit;

View File

@ -42,6 +42,7 @@ MainWindow::MainWindow() : QMainWindow() {
messages_widget->restoreHeaderState(settings.message_header_state);
qRegisterMetaType<uint64_t>("uint64_t");
qRegisterMetaType<QSet<uint8_t>>("QSet<uint8_t>");
qRegisterMetaType<ReplyMsgType>("ReplyMsgType");
installMessageHandler([this](ReplyMsgType type, const std::string msg) {
// use queued connection to recv the log messages from replay.
@ -70,6 +71,7 @@ MainWindow::MainWindow() : QMainWindow() {
QObject::connect(can, &AbstractStream::streamStarted, this, &MainWindow::loadDBCFromFingerprint);
QObject::connect(can, &AbstractStream::eventsMerged, this, &MainWindow::updateStatus);
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &MainWindow::DBCFileChanged);
QObject::connect(can, &AbstractStream::sourcesUpdated, dbc(), &DBCManager::updateSources);
QObject::connect(UndoStack::instance(), &QUndoStack::cleanChanged, this, &MainWindow::undoStackCleanChanged);
QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &MainWindow::undoStackIndexChanged);
QObject::connect(&settings, &Settings::changed, this, &MainWindow::updateStatus);
@ -310,7 +312,7 @@ void MainWindow::loadDBCFromClipboard() {
QString dbc_str = QGuiApplication::clipboard()->text();
QString error;
bool ret = dbc()->open("clipboard", dbc_str, &error);
if (ret && dbc()->messages().size() > 0) {
if (ret && dbc()->msgCount() > 0) {
QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!"));
} else {
QMessageBox msg_box(QMessageBox::Warning, tr("Failed to load DBC from clipboard"), tr("Make sure that you paste the text with correct format."));

View File

@ -239,8 +239,7 @@ void SignalModel::addSignal(int start_bit, int size, bool little_endian) {
auto msg = dbc()->msg(msg_id);
for (int i = 0; !msg; ++i) {
QString name = QString("NEW_MSG_") + QString::number(msg_id.address, 16).toUpper();
if (i > 0) name += QString("_%1").arg(i);
if (std::none_of(dbc()->messages().begin(), dbc()->messages().end(), [&](auto &m) { return m.second.name == name; })) {
if (!dbc()->msg(msg_id.source, name)) {
UndoStack::push(new EditMsgCommand(msg_id, name, can->lastMessage(msg_id).dat.size()));
msg = dbc()->msg(msg_id);
}
@ -265,14 +264,14 @@ void SignalModel::removeSignal(const cabana::Signal *sig) {
UndoStack::push(new RemoveSigCommand(msg_id, sig));
}
void SignalModel::handleMsgChanged(uint32_t address) {
if (address == msg_id.address) {
void SignalModel::handleMsgChanged(MessageId id) {
if (id == msg_id) {
refresh();
}
}
void SignalModel::handleSignalAdded(uint32_t address, const cabana::Signal *sig) {
if (address == msg_id.address) {
void SignalModel::handleSignalAdded(MessageId id, const cabana::Signal *sig) {
if (id == msg_id) {
int i = 0;
for (; i < root->children.size(); ++i) {
if (sig->start_bit < root->children[i]->sig->start_bit) break;
@ -442,7 +441,7 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts),
QObject::connect(model, &QAbstractItemModel::modelReset, this, &SignalView::rowsChanged);
QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &SignalView::rowsChanged);
QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &SignalView::rowsChanged);
QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const cabana::Signal *sig) { selectSignal(sig); });
QObject::connect(dbc(), &DBCManager::signalAdded, [this](MessageId id, const cabana::Signal *sig) { selectSignal(sig); });
setWhatsThis(tr(R"(
<b>Signal view</b><br />

View File

@ -48,10 +48,10 @@ public:
private:
void insertItem(SignalModel::Item *parent_item, int pos, const cabana::Signal *sig);
void handleSignalAdded(uint32_t address, const cabana::Signal *sig);
void handleSignalAdded(MessageId id, const cabana::Signal *sig);
void handleSignalUpdated(const cabana::Signal *sig);
void handleSignalRemoved(const cabana::Signal *sig);
void handleMsgChanged(uint32_t address);
void handleMsgChanged(MessageId id);
void refresh();
void updateState(const QHash<MessageId, CanData> *msgs);

View File

@ -39,6 +39,11 @@ bool AbstractStream::updateEvent(const Event *event) {
data.colors = tracker.colors;
data.last_change_t = tracker.last_change_t;
data.bit_change_counts = tracker.bit_change_counts;
if (!sources.contains(id.source)) {
sources.insert(id.source);
emit sourcesUpdated(sources);
}
}
double ts = millis_since_boot();

View File

@ -52,9 +52,11 @@ signals:
void updated();
void msgsReceived(const QHash<MessageId, CanData> *);
void received(QHash<MessageId, CanData> *);
void sourcesUpdated(const QSet<uint8_t> &s);
public:
QHash<MessageId, CanData> can_msgs;
QSet<uint8_t> sources;
protected:
void process(QHash<MessageId, CanData> *);

View File

@ -15,11 +15,11 @@ TEST_CASE("DBCManager::generateDBC") {
DBCManager dbc_from_generated(nullptr);
dbc_from_generated.open("", dbc_origin.generateDBC());
auto &msgs = dbc_origin.messages();
auto &new_msgs = dbc_from_generated.messages();
REQUIRE(msgs.size() == new_msgs.size());
for (auto &[address, m] : msgs) {
auto &new_m = new_msgs.at(address);
REQUIRE(dbc_origin.msgCount() == dbc_from_generated.msgCount());
auto msgs = dbc_origin.getMessages(0);
auto new_msgs = dbc_from_generated.getMessages(0);
for (auto &[id, m] : msgs) {
auto &new_m = new_msgs.at(id);
REQUIRE(m.name == new_m.name);
REQUIRE(m.size == new_m.size);
REQUIRE(m.getSignals().size() == new_m.getSignals().size());
@ -43,7 +43,7 @@ TEST_CASE("Parse can messages") {
if (e->which == cereal::Event::Which::CAN) {
std::map<std::pair<uint32_t, QString>, std::vector<double>> values_1;
for (const auto &c : e->event.getCan()) {
const auto msg = dbc.msg(c.getAddress());
const auto msg = dbc.msg({.source = c.getSrc(), .address = c.getAddress()});
if (c.getSrc() == 0 && msg) {
for (auto sig : msg->getSignals()) {
double val = get_raw_value((uint8_t *)c.getDat().begin(), c.getDat().size(), *sig);

View File

@ -29,8 +29,9 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi
bus_combo->setCurrentIndex(0);
msg_cb = new QComboBox(this);
for (auto &[address, msg] : dbc()->messages()) {
msg_cb->addItem(msg.name, address);
// TODO: update when bus_combo changes
for (auto &[id, msg] : dbc()->getMessages(0)) {
msg_cb->addItem(msg.name, id.address);
}
msg_cb->model()->sort(0);
msg_cb->setCurrentIndex(0);