From dd1c6b8a6ee132cc0043ad946639c848562a0f32 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Mon, 22 Oct 2018 22:29:21 -0400 Subject: [PATCH] Updated Sniffer help, added a lot of functionality to Sniffer Window Sniffer can now keep all ids without expiring Fade out bytes that aren't changing --- docs/source/sniffer.rst | 7 +++-- re/sniffer/snifferitem.cpp | 52 ++++++++++++++++++++++++----------- re/sniffer/snifferitem.h | 11 +++++--- re/sniffer/sniffermodel.cpp | 53 +++++++++++++++++++++++++++++++++--- re/sniffer/sniffermodel.h | 11 ++++++++ re/sniffer/snifferwindow.cpp | 3 ++ ui/snifferwindow.ui | 23 +++++++++++++++- 7 files changed, 132 insertions(+), 28 deletions(-) diff --git a/docs/source/sniffer.rst b/docs/source/sniffer.rst index a5668e1..6dae98c 100644 --- a/docs/source/sniffer.rst +++ b/docs/source/sniffer.rst @@ -8,11 +8,12 @@ Sniffer Window Using the Sniffer Window ========================= -This window is essentially a graphical version of the linux can_utils. The general idea here is to display a list of frames such that you only see frames that are actively updating. If a given ID has not been seen in 4 seconds the ID portion will turn RED and then disappear from the list. In this way only frames that are updating are in the list. They are ordered by last update time. Bytes that have deincremented will be red and bytes that have incremented will be green. You can use the "Filters" area to mask away some IDs so that they never show up. This can help to declutter the list. +This window is essentially a graphical version of the linux can_utils program "cansniffer". The general idea here is to display a list of frames such that you only see frames that are actively updating. If a given ID has not been seen in 5 seconds the ID portion will turn RED and then disappear from the list. In this way only frames that are updating are in the list. They are ordered by ID. Bytes that have deincremented will be red and bytes that have incremented will be green. You can use the "Filters" area to mask away some IDs so that they never show up. This can help to declutter the list. + +This window updates with a 200ms interval. Notching and Unnotching ======================== -Honestly, I don't know. It seems that notching means to store the current value of the data bytes for each frame and then use that notch data for the comparison for increment / deincrement to color the bytes. Unnotching would then be clearing that out so that it uses the previous value from the last time the frame ID was seen. But, don't quote me on that. This should be figured out definitively and corrected. - +While the window is running it keeps a running list each 200ms cycle of all the bits that changed in that timespan. Each 200ms this list is backed up and reset. If you push the notch button the system will remember all the bits that were set in the last 200ms window and will not color the output if those bits are toggled in the future. They will thus somewhat be ignored except that you can visually still see them updating. If you click the Notch button repeatedly it will add any new changed bits to the old changed bits. In this way you can build up a set of bits to ignore. Un-notching causes all notched (ignored) bits to be reset and thus all changes will be colored once again. diff --git a/re/sniffer/snifferitem.cpp b/re/sniffer/snifferitem.cpp index 98f0bad..e6e45e8 100644 --- a/re/sniffer/snifferitem.cpp +++ b/re/sniffer/snifferitem.cpp @@ -4,14 +4,17 @@ SnifferItem::SnifferItem(const CANFrame& pFrame): - mNotch(0), mID(pFrame.ID) { - mMarker = {0,0}; - mLastMarker = {0,0}; + for (int i = 0; i < 8; i++) { + mNotch[i] =0; + mMarker.data[i] = 0; + mMarker.dataTimestamp[i] = 0; + } + mLastMarker = mMarker; /* that's dirty */ - update(pFrame); - update(pFrame); + update(pFrame, 0); + update(pFrame, 0); } @@ -33,7 +36,12 @@ float SnifferItem::getDelta() const //Get a data byte by index 0-7 (but not more than the length of the actual frame) int SnifferItem::getData(uchar i) const { - return (i >= mCurrent.len) ? -1 : ((uchar*) &mCurrent.data)[i]; + return (i >= mCurrent.len) ? -1 : mCurrent.data[i]; +} + +quint32 SnifferItem::getDataTimestamp(uchar i) const +{ + return (i >= mCurrent.len) ? 0 : mCurrent.dataTimestamp[i]; } //Return whether a given data byte (by index 0-7) has incremented, deincremented, or stayed the same @@ -45,10 +53,10 @@ dc SnifferItem::dataChange(uchar i) const { if (i >= mCurrent.len) return dc::NO; - uchar notch = ((uchar*) &mNotch)[i]; - uchar byt = ((uchar*) &mCurrent.data)[i]; - uchar last = ((uchar*) &mLast.data)[i]; - uchar lastMark = ((uchar*) &mLastMarker.data)[i]; + uchar notch = mNotch[i]; + uchar byt = mCurrent.data[i]; + uchar last = mLast.data[i]; + uchar lastMark = mLastMarker.data[i]; if( lastMark ) { if (!notch) //if no notching is set @@ -66,27 +74,36 @@ dc SnifferItem::dataChange(uchar i) const return dc::NO; } + + int SnifferItem::elapsed() const { return mTime.elapsed(); } //called when a new frame comes in that matches our same ID -void SnifferItem::update(const CANFrame& pFrame) +void SnifferItem::update(const CANFrame& pFrame, quint32 timeSeq) { /* copy current to last */ mLast = mCurrent; mLastTime = mCurrentTime; /* copy new value */ - memcpy(&mCurrent.data, pFrame.data, 8); + for (int i = 0; i < 8; i++) + { + if (mCurrent.data[i] != pFrame.data[i]) + { + mCurrent.data[i] = pFrame.data[i]; + mCurrent.dataTimestamp[i] = timeSeq; + } + } mCurrent.len = pFrame.len; mCurrentTime = pFrame.timestamp; /* update marker */ //We "OR" our stored marker with the changed bits. //this accumulates changed bits into the marker - mMarker.data |= mLast.data ^ mCurrent.data; //XOR causes only changed bits to be 1's + for (int i = 0 ; i < 8; i++) mMarker.data[i] |= mLast.data[i] ^ mCurrent.data[i]; //XOR causes only changed bits to be 1's mMarker.len |= mLast.len ^ mCurrent.len; /* restart timeout */ @@ -98,14 +115,17 @@ void SnifferItem::update(const CANFrame& pFrame) void SnifferItem::updateMarker() { mLastMarker = mMarker; - mMarker = {0, 0}; + for (int i = 0; i < 8; i++) mMarker.data[i] = 0; } //Notch or un-notch this snifferitem / frame void SnifferItem::notch(bool pNotch) { if(pNotch) - mNotch |= mLastMarker.data; //add changed bits to notch value + { + for (int i = 0; i < 8; i++) mNotch[i] |= mLastMarker.data[i]; //add changed bits to notch value + } + else - mNotch = 0; + for (int i = 0; i < 8; i++) mNotch[i] = 0; } diff --git a/re/sniffer/snifferitem.h b/re/sniffer/snifferitem.h index 18d836e..5f85880 100644 --- a/re/sniffer/snifferitem.h +++ b/re/sniffer/snifferitem.h @@ -7,7 +7,8 @@ struct fstCan { - quint64 data; + quint8 data[8]; + quint32 dataTimestamp[8]; int len; }; @@ -28,18 +29,20 @@ public: quint64 getId() const; float getDelta() const; int getData(uchar i) const; + quint32 getDataTimestamp(uchar i) const; dc dataChange(uchar) const; int elapsed() const; - void update(const CANFrame& pFrame); + void update(const CANFrame& pFrame, quint32 timeSeq); void updateMarker(); void notch(bool); + private: - quint64 mID; + quint32 mID; struct fstCan mLast; struct fstCan mCurrent; struct fstCan mLastMarker; struct fstCan mMarker; - quint64 mNotch; + quint8 mNotch[8]; quint64 mLastTime; quint64 mCurrentTime; diff --git a/re/sniffer/sniffermodel.cpp b/re/sniffer/sniffermodel.cpp index 6815f21..d8dfdb5 100644 --- a/re/sniffer/sniffermodel.cpp +++ b/re/sniffer/sniffermodel.cpp @@ -5,7 +5,11 @@ SnifferModel::SnifferModel(QObject *parent) : QAbstractItemModel(parent), - mFilter(false) + mFilter(false), + mNeverExpire(false), + mFadeInactive(false), + mMuteNotched(false), + mTimeSequence(0) { } @@ -61,11 +65,20 @@ QVariant SnifferModel::data(const QModelIndex &index, int role) const } break; } + case Qt::ForegroundRole: + { + if (!mFadeInactive || col < 2) return QBrush(Qt::black); + int v = (mTimeSequence - item->getDataTimestamp(col - 2)) * 20; + if (v > 215) v = 215; + return QBrush(QColor(v,v,v,255)); + break; + } + case Qt::BackgroundRole: { if(tc::ID==col) { - if(item->elapsed()>4000) + if(item->elapsed() > 4000) return QBrush(Qt::red); } else if(tc::DATA_0<=col && col<=tc::DATA_7) @@ -143,6 +156,35 @@ QModelIndex SnifferModel::parent(const QModelIndex &) const return QModelIndex(); } +bool SnifferModel::getNeverExpire() +{ + return mNeverExpire; +} + +bool SnifferModel::getFadeInactive() +{ + return mFadeInactive; +} + +bool SnifferModel::getMuteNotched() +{ + return mMuteNotched; +} + +void SnifferModel::setNeverExpire(bool val) +{ + mNeverExpire = val; +} + +void SnifferModel::setFadeInactive(bool val) +{ + mFadeInactive = val; +} + +void SnifferModel::setMuteNotched(bool val) +{ + mMuteNotched = val; +} void SnifferModel::clear() { @@ -161,13 +203,15 @@ void SnifferModel::refresh() QVector toRemove; SnifferItem* item; + mTimeSequence++; + /* update markers */ for (i = mMap.begin(); i != mMap.end(); ++i) { i.value()->updateMarker(); - if(i.value()->elapsed()>5000) + if(i.value()->elapsed()>5000 && !mNeverExpire) toRemove.append(i.key()); } @@ -238,13 +282,14 @@ void SnifferModel::update(CANConnection*, QVector& pFrames) /* add the frame */ beginInsertRows(QModelIndex(), index, index); mMap[frame.ID] = new SnifferItem(frame); + mMap[frame.ID]->update(frame, mTimeSequence); endInsertRows(); emit idChange(frame.ID, true); } else //updateData - mMap[frame.ID]->update(frame); + mMap[frame.ID]->update(frame, mTimeSequence); } } diff --git a/re/sniffer/sniffermodel.h b/re/sniffer/sniffermodel.h index 7c3fc19..4945cd2 100644 --- a/re/sniffer/sniffermodel.h +++ b/re/sniffer/sniffermodel.h @@ -40,6 +40,13 @@ public: void refresh(); void clear(); void filter(fltType pType, int pId=0); + bool getNeverExpire(); + bool getFadeInactive(); + bool getMuteNotched(); + void setNeverExpire(bool val); + void setFadeInactive(bool val); + void setMuteNotched(bool val); + public slots: void update(CANConnection*, QVector&); @@ -53,6 +60,10 @@ private: QMap mMap; QMap mFilters; bool mFilter; + bool mNeverExpire; + bool mFadeInactive; + bool mMuteNotched; + quint32 mTimeSequence; }; #endif // SNIFFERMODEL_H diff --git a/re/sniffer/snifferwindow.cpp b/re/sniffer/snifferwindow.cpp index 685a850..df4b154 100644 --- a/re/sniffer/snifferwindow.cpp +++ b/re/sniffer/snifferwindow.cpp @@ -37,6 +37,9 @@ SnifferWindow::SnifferWindow(QWidget *parent) : connect(&mModel, &SnifferModel::idChange, this, &SnifferWindow::idChange); connect(ui->listWidget, &QListWidget::itemChanged, this, &SnifferWindow::itemChanged); + connect(ui->cbFadeInactive, &QCheckBox::stateChanged, this, [this](int val){mModel.setFadeInactive(val);}); + connect(ui->cbMuteNotched, &QCheckBox::stateChanged, this, [this](int val){mModel.setMuteNotched(val);}); + connect(ui->cbNoExpire, &QCheckBox::stateChanged, this, [this](int val){mModel.setNeverExpire(val);}); } SnifferWindow::~SnifferWindow() diff --git a/ui/snifferwindow.ui b/ui/snifferwindow.ui index 44d36a0..e705513 100644 --- a/ui/snifferwindow.ui +++ b/ui/snifferwindow.ui @@ -6,7 +6,7 @@ 0 0 - 602 + 710 752 @@ -82,6 +82,27 @@ + + + + Never Expire IDs + + + + + + + Mute notched bits + + + + + + + Fade inactive bytes + + +