First implementation

This commit is contained in:
Yury Shuvakin
2024-07-03 19:08:19 +09:00
parent a953095a5c
commit 6f85ac3b13
126 changed files with 21667 additions and 0 deletions

300
core/Backend.cpp Normal file
View File

@@ -0,0 +1,300 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Backend.h"
#include "LogModel.h"
#include <QDateTime>
#include <QDebug>
#include <QFile>
#include <core/CanTrace.h>
#include <core/MeasurementSetup.h>
#include <core/MeasurementNetwork.h>
#include <core/MeasurementInterface.h>
#include <driver/CanDriver.h>
#include <driver/CanInterface.h>
#include <driver/CanListener.h>
#include <parser/dbc/DbcParser.h>
Backend *Backend::_instance = 0;
Backend::Backend()
: QObject(0),
_measurementRunning(false),
_measurementStartTime(0),
_setup(this)
{
_logModel = new LogModel(*this);
setDefaultSetup();
_trace = new CanTrace(*this, this, 100);
connect(&_setup, SIGNAL(onSetupChanged()), this, SIGNAL(onSetupChanged()));
}
Backend &Backend::instance()
{
if (!_instance) {
_instance = new Backend;
}
return *_instance;
}
Backend::~Backend()
{
delete _trace;
}
void Backend::addCanDriver(CanDriver &driver)
{
driver.init(_drivers.size());
_drivers.append(&driver);
}
bool Backend::startMeasurement()
{
log_info("Starting measurement");
_measurementStartTime = QDateTime::currentMSecsSinceEpoch();
_timerSinceStart.start();
int i=0;
foreach (MeasurementNetwork *network, _setup.getNetworks()) {
i++;
foreach (MeasurementInterface *mi, network->interfaces()) {
CanInterface *intf = getInterfaceById(mi->canInterface());
if (intf) {
intf->applyConfig(*mi);
log_info(QString("Listening on interface: %1").arg(intf->getName()));
CanListener *listener = new CanListener(0, *this, *intf);
listener->startThread();
_listeners.append(listener);
}
}
}
_measurementRunning = true;
emit beginMeasurement();
return true;
}
bool Backend::stopMeasurement()
{
if (_measurementRunning) {
foreach (CanListener *listener, _listeners) {
listener->requestStop();
}
foreach (CanListener *listener, _listeners) {
log_info(QString("Closing interface: %1").arg(getInterfaceName(listener->getInterfaceId())));
listener->waitFinish();
}
qDeleteAll(_listeners);
_listeners.clear();
log_info("Measurement stopped");
_measurementRunning = false;
emit endMeasurement();
}
return true;
}
bool Backend::isMeasurementRunning() const
{
return _measurementRunning;
}
void Backend::loadDefaultSetup(MeasurementSetup &setup)
{
setup.clear();
int i = 1;
foreach (CanDriver *driver, _drivers) {
driver->update();
foreach (CanInterfaceId intf, driver->getInterfaceIds()) {
MeasurementNetwork *network = setup.createNetwork();
network->setName(QString().sprintf("Network %d", i++));
MeasurementInterface *mi = new MeasurementInterface();
mi->setCanInterface(intf);
mi->setBitrate(500000);
network->addInterface(mi);
}
}
}
void Backend::setDefaultSetup()
{
loadDefaultSetup(_setup);
}
MeasurementSetup &Backend::getSetup()
{
return _setup;
}
void Backend::setSetup(MeasurementSetup &new_setup)
{
_setup.cloneFrom(new_setup);
}
double Backend::currentTimeStamp() const
{
return ((double)QDateTime::currentMSecsSinceEpoch()) / 1000;
}
CanTrace *Backend::getTrace()
{
return _trace;
}
void Backend::clearTrace()
{
_trace->clear();
}
CanDbMessage *Backend::findDbMessage(const CanMessage &msg) const
{
return _setup.findDbMessage(msg);
}
CanInterfaceIdList Backend::getInterfaceList()
{
CanInterfaceIdList result;
foreach (CanDriver *driver, _drivers) {
foreach (CanInterfaceId id, driver->getInterfaceIds()) {
result.append(id);
}
}
return result;
}
CanDriver *Backend::getDriverById(CanInterfaceId id)
{
CanDriver *driver = _drivers.value((id>>8) & 0xFF);
if (!driver) {
log_critical(QString("Unable to get driver for interface id: %1. This should never happen.").arg(QString().number(id)));
}
return driver;
}
CanInterface *Backend::getInterfaceById(CanInterfaceId id)
{
CanDriver *driver = getDriverById(id);
return driver ? driver->getInterfaceById(id) : 0;
}
QString Backend::getInterfaceName(CanInterfaceId id)
{
CanInterface *intf = getInterfaceById(id);
if (intf) {
return intf->getName();
} else {
log_critical(QString("Trying to get name from unknown interface id: %1. This should never happen.").arg(QString().number(id)));
return "";
}
}
QString Backend::getDriverName(CanInterfaceId id)
{
CanDriver *driver = getDriverById(id);
return driver ? driver->getName() : "";
}
CanDriver *Backend::getDriverByName(QString driverName)
{
foreach (CanDriver *driver, _drivers) {
if (driver->getName()==driverName) {
return driver;
}
}
return 0;
}
CanInterface *Backend::getInterfaceByDriverAndName(QString driverName, QString deviceName)
{
CanDriver *driver = getDriverByName(driverName);
if (driver) {
return driver->getInterfaceByName(deviceName);
} else {
return 0;
}
}
pCanDb Backend::loadDbc(QString filename)
{
DbcParser parser;
QFile *dbc = new QFile(filename);
pCanDb candb(new CanDb());
parser.parseFile(dbc, *candb);
delete dbc;
return candb;
}
void Backend::clearLog()
{
_logModel->clear();
}
LogModel &Backend::getLogModel() const
{
return *_logModel;
}
double Backend::getTimestampAtMeasurementStart() const
{
return (double)_measurementStartTime / 1000.0;
}
uint64_t Backend::getUsecsAtMeasurementStart() const
{
return _measurementStartTime * 1000;
}
uint64_t Backend::getNsecsSinceMeasurementStart() const
{
return _timerSinceStart.nsecsElapsed();
}
uint64_t Backend::getUsecsSinceMeasurementStart() const
{
return getNsecsSinceMeasurementStart() / 1000;
}
void Backend::logMessage(const QDateTime dt, const log_level_t level, const QString msg)
{
// QFile logfile("tkr.log");
// logfile.open(QIODevice::WriteOnly | QIODevice::Append);
// logfile.write(QString("%1 %2 %3\n").arg(dt.toString("yyyy-MM-dd hh:mm:ss.zzz")).arg(level).arg(msg).toUtf8());
// logfile.close();
qDebug() << "logMessage" << dt << level << msg;
emit onLogMessage(dt, level, msg);
}

114
core/Backend.h Normal file
View File

@@ -0,0 +1,114 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <QObject>
#include <QList>
#include <QMutex>
#include <QDateTime>
#include <QElapsedTimer>
#include <driver/CanDriver.h>
#include <core/CanDb.h>
#include <core/MeasurementSetup.h>
#include <core/Log.h>
class MeasurementNetwork;
class CanTrace;
class CanListener;
class CanDbMessage;
class SetupDialog;
class LogModel;
class Backend : public QObject
{
Q_OBJECT
public:
static Backend &instance();
explicit Backend();
virtual ~Backend();
void addCanDriver(CanDriver &driver);
bool startMeasurement();
bool stopMeasurement();
bool isMeasurementRunning() const;
double getTimestampAtMeasurementStart() const;
uint64_t getUsecsAtMeasurementStart() const;
uint64_t getNsecsSinceMeasurementStart() const;
uint64_t getUsecsSinceMeasurementStart() const;
void logMessage(const QDateTime dt, const log_level_t level, const QString msg);
MeasurementSetup &getSetup();
void loadDefaultSetup(MeasurementSetup &setup);
void setDefaultSetup();
void setSetup(MeasurementSetup &new_setup);
double currentTimeStamp() const;
CanTrace *getTrace();
void clearTrace();
CanDbMessage *findDbMessage(const CanMessage &msg) const;
CanInterfaceIdList getInterfaceList();
CanDriver *getDriverById(CanInterfaceId id);
CanInterface *getInterfaceById(CanInterfaceId id);
QString getInterfaceName(CanInterfaceId id);
QString getDriverName(CanInterfaceId id);
CanDriver *getDriverByName(QString driverName);
CanInterface *getInterfaceByDriverAndName(QString driverName, QString deviceName);
pCanDb loadDbc(QString filename);
void clearLog();
LogModel &getLogModel() const;
signals:
void beginMeasurement();
void endMeasurement();
void onSetupChanged();
void onLogMessage(const QDateTime dt, const log_level_t level, const QString msg);
void onSetupDialogCreated(SetupDialog &dlg);
public slots:
private:
static Backend *_instance;
bool _measurementRunning;
uint64_t _measurementStartTime;
QElapsedTimer _timerSinceStart;
QList<CanDriver*> _drivers;
MeasurementSetup _setup;
CanTrace *_trace;
QList<CanListener*> _listeners;
LogModel *_logModel;
};

89
core/CanDb.cpp Normal file
View File

@@ -0,0 +1,89 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanDb.h"
#include <QFileInfo>
#include <QDomDocument>
#include <core/Backend.h>
CanDb::CanDb()
{
}
QString CanDb::getFileName()
{
QFileInfo fi(getPath());
return fi.fileName();
}
QString CanDb::getDirectory()
{
QFileInfo fi(getPath());
return fi.absolutePath();
}
CanDbNode *CanDb::getOrCreateNode(QString node_name)
{
if (!_nodes.contains(node_name)) {
CanDbNode *node = new CanDbNode(this);
node->setName(node_name);
_nodes[node_name] = node;
return node;
} else {
return _nodes[node_name];
}
}
CanDbMessage *CanDb::getMessageById(uint32_t raw_id)
{
if (_messages.contains(raw_id)) {
return _messages[raw_id];
} else {
return 0;
}
}
void CanDb::addMessage(CanDbMessage *msg)
{
_messages[msg->getRaw_id()] = msg;
}
QString CanDb::getComment() const
{
return _comment;
}
void CanDb::setComment(const QString &comment)
{
_comment = comment;
}
bool CanDb::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
(void) backend;
(void) xml;
root.setAttribute("type", "dbc");
root.setAttribute("filename", _path);
return true;
}

73
core/CanDb.h Normal file
View File

@@ -0,0 +1,73 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
#include <QList>
#include <QMap>
#include <QSharedPointer>
#include "CanDbNode.h"
#include "CanDbMessage.h"
class QDomDocument;
class QDomElement;
class Backend;
class CanDb;
class CanDbMessage;
typedef QMap<QString,CanDbNode*> CanDbNodeMap;
typedef QMap<uint32_t, CanDbMessage*> CanDbMessageList;
typedef QSharedPointer<CanDb> pCanDb;
class CanDb
{
public:
CanDb();
void setPath(QString path) { _path = path; }
QString getPath() { return _path; }
QString getFileName();
QString getDirectory();
void setVersion(QString version) { _version = version; }
QString getVersion() { return _version; }
CanDbNode *getOrCreateNode(QString node_name);
CanDbMessage *getMessageById(uint32_t raw_id);
void addMessage(CanDbMessage *msg);
QString getComment() const;
void setComment(const QString &comment);
bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
private:
QString _path;
QString _version;
QString _comment;
CanDbNodeMap _nodes;
CanDbMessageList _messages;
};

112
core/CanDbMessage.cpp Normal file
View File

@@ -0,0 +1,112 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanDbMessage.h"
CanDbMessage::CanDbMessage(CanDb *parent)
: _parent(parent), _raw_id(0), _dlc(0), _sender(0), _muxer(0)
{
}
QString CanDbMessage::getName() const
{
return _name;
}
void CanDbMessage::setName(const QString &name)
{
_name = name;
}
uint32_t CanDbMessage::getRaw_id() const
{
return _raw_id;
}
void CanDbMessage::setRaw_id(const uint32_t &raw_id)
{
_raw_id = raw_id;
}
uint8_t CanDbMessage::getDlc() const
{
return _dlc;
}
void CanDbMessage::setDlc(const uint8_t &dlc)
{
_dlc = dlc;
}
CanDbNode *CanDbMessage::getSender() const
{
return _sender;
}
void CanDbMessage::setSender(CanDbNode *sender)
{
_sender = sender;
}
void CanDbMessage::addSignal(CanDbSignal *signal)
{
_signals.append(signal);
}
CanDbSignal *CanDbMessage::getSignal(int num)
{
if (_signals.size()>num) {
return _signals[num];
} else {
return 0;
}
}
CanDbSignal *CanDbMessage::getSignalByName(QString signal_name)
{
CanDbSignal *signal;
foreach (signal, _signals) {
if (signal->name() == signal_name) {
return signal;
}
}
return 0;
}
QString CanDbMessage::getComment() const
{
return _comment;
}
void CanDbMessage::setComment(const QString &comment)
{
_comment = comment;
}
CanDbSignal *CanDbMessage::getMuxer() const
{
return _muxer;
}
void CanDbMessage::setMuxer(CanDbSignal *muxer)
{
_muxer = muxer;
}

73
core/CanDbMessage.h Normal file
View File

@@ -0,0 +1,73 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <QString>
#include "CanDb.h"
#include "CanDbSignal.h"
class CanDbNode;
class CanDbSignal;
typedef QList<CanDbSignal*> CanDbSignalList;
class CanDbMessage
{
public:
CanDbMessage(CanDb *parent);
QString getName() const;
void setName(const QString &name);
uint32_t getRaw_id() const;
void setRaw_id(const uint32_t &raw_id);
uint8_t getDlc() const;
void setDlc(const uint8_t &dlc);
CanDbNode *getSender() const;
void setSender(CanDbNode *sender);
void addSignal(CanDbSignal *signal);
CanDbSignal *getSignal(int num);
CanDbSignal *getSignalByName(QString signal_name);
CanDbSignalList getSignals() { return _signals; }
QString getComment() const;
void setComment(const QString &comment);
CanDbSignal *getMuxer() const;
void setMuxer(CanDbSignal *muxer);
private:
CanDb *_parent;
QString _name;
uint32_t _raw_id;
uint8_t _dlc;
CanDbNode *_sender;
CanDbSignalList _signals;
QString _comment;
CanDbSignal *_muxer;
};

49
core/CanDbNode.cpp Normal file
View File

@@ -0,0 +1,49 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanDbNode.h"
CanDbNode::CanDbNode(CanDb *parent)
: _parent(parent)
{
}
QString CanDbNode::name() const
{
return _name;
}
void CanDbNode::setName(const QString &name)
{
_name = name;
}
QString CanDbNode::comment() const
{
return _comment;
}
void CanDbNode::setComment(const QString &comment)
{
_comment = comment;
}

43
core/CanDbNode.h Normal file
View File

@@ -0,0 +1,43 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
class CanDb;
class CanDbNode
{
public:
CanDbNode(CanDb *parent);
QString name() const;
void setName(const QString &name);
QString comment() const;
void setComment(const QString &comment);
private:
CanDb *_parent;
QString _name;
QString _comment;
};

229
core/CanDbSignal.cpp Normal file
View File

@@ -0,0 +1,229 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanDbSignal.h"
CanDbSignal::CanDbSignal(CanDbMessage *parent)
: _parent(parent),
_isUnsigned(false),
_isBigEndian(false),
_factor(1),
_offset(0),
_min(0),
_max(0),
_isMuxer(false),
_isMuxed(false),
_muxValue(0)
{
}
QString CanDbSignal::name() const
{
return _name;
}
void CanDbSignal::setName(const QString &name)
{
_name = name;
}
uint8_t CanDbSignal::startBit() const
{
return _startBit;
}
void CanDbSignal::setStartBit(uint8_t startBit)
{
_startBit = startBit;
}
uint8_t CanDbSignal::length() const
{
return _length;
}
void CanDbSignal::setLength(uint8_t length)
{
_length = length;
}
QString CanDbSignal::comment() const
{
return _comment;
}
void CanDbSignal::setComment(const QString &comment)
{
_comment = comment;
}
QString CanDbSignal::getValueName(const uint64_t value) const
{
if (_valueTable.contains(value)) {
return _valueTable[value];
} else {
return QString();
}
}
void CanDbSignal::setValueName(const uint64_t value, const QString &name)
{
_valueTable[value] = name;
}
double CanDbSignal::convertRawValueToPhysical(const uint64_t rawValue)
{
if (isUnsigned()) {
uint64_t v = rawValue;
return v * _factor + _offset;
} else {
// TODO check with DBC that actually contains signed values?!
int64_t v = (int64_t)(rawValue<<(64-_length));
v>>=(64-_length);
return v * _factor + _offset;
}
}
double CanDbSignal::extractPhysicalFromMessage(const CanMessage &msg)
{
return convertRawValueToPhysical(extractRawDataFromMessage(msg));
}
double CanDbSignal::getFactor() const
{
return _factor;
}
void CanDbSignal::setFactor(double factor)
{
_factor = factor;
}
double CanDbSignal::getOffset() const
{
return _offset;
}
void CanDbSignal::setOffset(double offset)
{
_offset = offset;
}
double CanDbSignal::getMinimumValue() const
{
return _min;
}
void CanDbSignal::setMinimumValue(double min)
{
_min = min;
}
double CanDbSignal::getMaximumValue() const
{
return _max;
}
void CanDbSignal::setMaximumValue(double max)
{
_max = max;
}
QString CanDbSignal::getUnit() const
{
return _unit;
}
void CanDbSignal::setUnit(const QString &unit)
{
_unit = unit;
}
bool CanDbSignal::isUnsigned() const
{
return _isUnsigned;
}
void CanDbSignal::setUnsigned(bool isUnsigned)
{
_isUnsigned = isUnsigned;
}
bool CanDbSignal::isBigEndian() const
{
return _isBigEndian;
}
void CanDbSignal::setIsBigEndian(bool isBigEndian)
{
_isBigEndian = isBigEndian;
}
bool CanDbSignal::isMuxer() const
{
return _isMuxer;
}
void CanDbSignal::setIsMuxer(bool isMuxer)
{
_isMuxer = isMuxer;
}
bool CanDbSignal::isMuxed() const
{
return _isMuxed;
}
void CanDbSignal::setIsMuxed(bool isMuxed)
{
_isMuxed = isMuxed;
}
uint32_t CanDbSignal::getMuxValue() const
{
return _muxValue;
}
void CanDbSignal::setMuxValue(const uint32_t &muxValue)
{
_muxValue = muxValue;
}
bool CanDbSignal::isPresentInMessage(const CanMessage &msg)
{
if ((_startBit + _length)>(8*msg.getLength())) {
return false;
}
if (!_isMuxed) { return true; }
CanDbSignal *muxer = _parent->getMuxer();
if (!muxer) { return false; }
return _muxValue == muxer->extractRawDataFromMessage(msg);
}
uint64_t CanDbSignal::extractRawDataFromMessage(const CanMessage &msg)
{
return msg.extractRawSignal(startBit(), length(), isBigEndian());
}

106
core/CanDbSignal.h Normal file
View File

@@ -0,0 +1,106 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "CanMessage.h"
#include "CanDbMessage.h"
#include <QString>
#include <QMap>
class CanDbMessage;
typedef QMap<uint64_t,QString> CanDbValueTable;
class CanDbSignal
{
public:
CanDbSignal(CanDbMessage *parent);
QString name() const;
void setName(const QString &name);
uint8_t startBit() const;
void setStartBit(uint8_t startBit);
uint8_t length() const;
void setLength(uint8_t length);
QString comment() const;
void setComment(const QString &comment);
QString getValueName(const uint64_t value) const;
void setValueName(const uint64_t value, const QString &name);
double getFactor() const;
void setFactor(double factor);
double getOffset() const;
void setOffset(double offset);
double getMinimumValue() const;
void setMinimumValue(double min);
double getMaximumValue() const;
void setMaximumValue(double max);
QString getUnit() const;
void setUnit(const QString &unit);
bool isUnsigned() const;
void setUnsigned(bool isUnsigned);
bool isBigEndian() const;
void setIsBigEndian(bool isBigEndian);
bool isMuxer() const;
void setIsMuxer(bool isMuxer);
bool isMuxed() const;
void setIsMuxed(bool isMuxed);
uint32_t getMuxValue() const;
void setMuxValue(const uint32_t &muxValue);
bool isPresentInMessage(const CanMessage &msg);
uint64_t extractRawDataFromMessage(const CanMessage &msg);
double convertRawValueToPhysical(const uint64_t rawValue);
double extractPhysicalFromMessage(const CanMessage &msg);
private:
CanDbMessage *_parent;
QString _name;
uint8_t _startBit;
uint8_t _length;
bool _isUnsigned;
bool _isBigEndian;
double _factor;
double _offset;
double _min;
double _max;
QString _unit;
bool _isMuxer;
bool _isMuxed;
uint32_t _muxValue;
QString _comment;
CanDbValueTable _valueTable;
};

346
core/CanMessage.cpp Normal file
View File

@@ -0,0 +1,346 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanMessage.h"
#include <core/portable_endian.h>
enum {
id_flag_extended = 0x80000000,
id_flag_rtr = 0x40000000,
id_flag_error = 0x20000000,
id_mask_extended = 0x1FFFFFFF,
id_mask_standard = 0x7FF
};
CanMessage::CanMessage()
: _raw_id(0), _dlc(0), _isFD(false), _interface(0), _u8()
{
_timestamp.tv_sec = 0;
_timestamp.tv_usec = 0;
}
CanMessage::CanMessage(uint32_t can_id)
: _dlc(0), _interface(0), _u8()
{
_timestamp.tv_sec = 0;
_timestamp.tv_usec = 0;
setId(can_id);
}
CanMessage::CanMessage(const CanMessage &msg)
{
cloneFrom(msg);
}
void CanMessage::cloneFrom(const CanMessage &msg)
{
_raw_id = msg._raw_id;
_dlc = msg._dlc;
// Copy data
for(int i=0; i<64; i++)
{
_u8[i] = msg._u8[i];
}
_interface = msg._interface;
_timestamp = msg._timestamp;
}
uint32_t CanMessage::getRawId() const {
return _raw_id;
}
void CanMessage::setRawId(const uint32_t raw_id) {
_raw_id = raw_id;
}
uint32_t CanMessage::getId() const {
if (isExtended()) {
return _raw_id & id_mask_extended;
} else {
return _raw_id & id_mask_standard;
}
}
void CanMessage::setId(const uint32_t id) {
_raw_id &= ~ id_mask_extended;
_raw_id = id;
if (id>0x7FF) {
setExtended(true);
}
}
bool CanMessage::isExtended() const {
return (_raw_id & id_flag_extended) != 0;
}
void CanMessage::setExtended(const bool isExtended) {
if (isExtended) {
_raw_id |= id_flag_extended;
} else {
_raw_id &= ~id_flag_extended;
}
}
bool CanMessage::isRTR() const {
return (_raw_id & id_flag_rtr) != 0;
}
void CanMessage::setRTR(const bool isRTR) {
if (isRTR) {
_raw_id |= id_flag_rtr;
} else {
_raw_id &= ~id_flag_rtr;
}
}
bool CanMessage::isFD() const {
return _isFD;
}
void CanMessage::setFD(const bool isFD) {
_isFD = isFD;
}
bool CanMessage::isBRS() const {
return _isBRS;
}
void CanMessage::setBRS(const bool isBRS) {
_isBRS = isBRS;
}
bool CanMessage::isErrorFrame() const {
return (_raw_id & id_flag_error) != 0;
}
void CanMessage::setErrorFrame(const bool isErrorFrame) {
if (isErrorFrame) {
_raw_id |= id_flag_error;
} else {
_raw_id &= ~id_flag_error;
}
}
CanInterfaceId CanMessage::getInterfaceId() const
{
return _interface;
}
void CanMessage::setInterfaceId(CanInterfaceId interface)
{
_interface = interface;
}
uint8_t CanMessage::getLength() const {
return _dlc;
}
void CanMessage::setLength(const uint8_t dlc) {
// Limit to CANFD max length
if (dlc<=64) {
_dlc = dlc;
} else {
_dlc = 8;
}
}
uint8_t CanMessage::getByte(const uint8_t index) const {
if (index<sizeof(_u8)) {
return _u8[index];
} else {
return 0;
}
}
void CanMessage::setByte(const uint8_t index, const uint8_t value) {
if (index<sizeof(_u8)) {
_u8[index] = value;
}
}
uint64_t CanMessage::extractRawSignal(uint8_t start_bit, const uint8_t length, const bool isBigEndian) const
{
// if ((start_bit+length) > (getLength()*8)) {
// return 0;
// }
// FIXME: This only gives access to data bytes 0-8. Need to rework for CANFD.
uint64_t data = le64toh(_u64[0]);
data >>= start_bit;
uint64_t mask = 0xFFFFFFFFFFFFFFFF;
mask <<= length;
mask = ~mask;
data &= mask;
// If the length is greater than 8, we need to byteswap to preserve endianness
if (isBigEndian && (length > 8))
{
// Swap bytes
data = __builtin_bswap64(data);
// Shift out unused bits
data >>= 64 - length;
}
return data;
}
void CanMessage::setDataAt(uint8_t position, uint8_t data)
{
if(position < 64)
_u8[position] = data;
else
return;
}
void CanMessage::setData(const uint8_t d0) {
_dlc = 1;
_u8[0] = d0;
}
void CanMessage::setData(const uint8_t d0, const uint8_t d1) {
_dlc = 2;
_u8[0] = d0;
_u8[1] = d1;
}
void CanMessage::setData(const uint8_t d0, const uint8_t d1, const uint8_t d2) {
_dlc = 3;
_u8[0] = d0;
_u8[1] = d1;
_u8[2] = d2;
}
void CanMessage::setData(const uint8_t d0, const uint8_t d1, const uint8_t d2,
const uint8_t d3) {
_dlc = 4;
_u8[0] = d0;
_u8[1] = d1;
_u8[2] = d2;
_u8[3] = d3;
}
void CanMessage::setData(const uint8_t d0, const uint8_t d1, const uint8_t d2,
const uint8_t d3, const uint8_t d4) {
_dlc = 5;
_u8[0] = d0;
_u8[1] = d1;
_u8[2] = d2;
_u8[3] = d3;
_u8[4] = d4;
}
void CanMessage::setData(const uint8_t d0, const uint8_t d1, const uint8_t d2,
const uint8_t d3, const uint8_t d4, const uint8_t d5) {
_dlc = 6;
_u8[0] = d0;
_u8[1] = d1;
_u8[2] = d2;
_u8[3] = d3;
_u8[4] = d4;
_u8[5] = d5;
}
void CanMessage::setData(const uint8_t d0, const uint8_t d1, const uint8_t d2,
const uint8_t d3, const uint8_t d4, const uint8_t d5,
const uint8_t d6) {
_dlc = 7;
_u8[0] = d0;
_u8[1] = d1;
_u8[2] = d2;
_u8[3] = d3;
_u8[4] = d4;
_u8[5] = d5;
_u8[6] = d6;
}
void CanMessage::setData(const uint8_t d0, const uint8_t d1, const uint8_t d2,
const uint8_t d3, const uint8_t d4, const uint8_t d5, const uint8_t d6,
const uint8_t d7) {
_dlc = 8;
_u8[0] = d0;
_u8[1] = d1;
_u8[2] = d2;
_u8[3] = d3;
_u8[4] = d4;
_u8[5] = d5;
_u8[6] = d6;
_u8[7] = d7;
}
timeval CanMessage::getTimestamp() const
{
return _timestamp;
}
void CanMessage::setTimestamp(const timeval timestamp)
{
_timestamp = timestamp;
}
void CanMessage::setTimestamp(const uint64_t seconds, const uint32_t micro_seconds)
{
_timestamp.tv_sec = seconds;
_timestamp.tv_usec = micro_seconds;
}
double CanMessage::getFloatTimestamp() const
{
return (double)_timestamp.tv_sec + ((double)_timestamp.tv_usec/1000000);
}
QDateTime CanMessage::getDateTime() const
{
return QDateTime::fromMSecsSinceEpoch((qint64)(1000*getFloatTimestamp()));
}
QString CanMessage::getIdString() const
{
if (isExtended()) {
return QString().sprintf("0x%08X", getId());
} else {
return QString().sprintf("0x%03X", getId());
}
}
QString CanMessage::getDataHexString() const
{
if(getLength() == 0)
return "";
QString outstr = "";
for(int i=0; i<getLength(); i++)
{
outstr += QString().sprintf("%02X ", getByte(i));
}
return outstr;
}

104
core/CanMessage.h Normal file
View File

@@ -0,0 +1,104 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <sys/time.h>
#include <QString>
#include <QDateTime>
#include <driver/CanDriver.h>
class CanMessage {
public:
CanMessage();
CanMessage(uint32_t can_id);
CanMessage(const CanMessage &msg);
void cloneFrom(const CanMessage &msg);
uint32_t getRawId() const;
void setRawId(const uint32_t raw_id);
uint32_t getId() const;
void setId(const uint32_t id);
bool isExtended() const;
void setExtended(const bool isExtended);
bool isRTR() const;
void setRTR(const bool isRTR);
bool isFD() const;
void setFD(const bool isFD);
bool isBRS() const;
void setBRS(const bool isFD);
bool isErrorFrame() const;
void setErrorFrame(const bool isErrorFrame);
CanInterfaceId getInterfaceId() const;
void setInterfaceId(CanInterfaceId interface);
uint8_t getLength() const;
void setLength(const uint8_t dlc);
uint8_t getByte(const uint8_t index) const;
void setByte(const uint8_t index, const uint8_t value);
uint64_t extractRawSignal(uint8_t start_bit, const uint8_t length, const bool isBigEndian) const;
void setDataAt(uint8_t position, uint8_t data);
void setData(const uint8_t d0);
void setData(const uint8_t d0, const uint8_t d1);
void setData(const uint8_t d0, const uint8_t d1, const uint8_t d2);
void setData(const uint8_t d0, const uint8_t d1, const uint8_t d2, const uint8_t d3);
void setData(const uint8_t d0, const uint8_t d1, const uint8_t d2, const uint8_t d3, const uint8_t d4);
void setData(const uint8_t d0, const uint8_t d1, const uint8_t d2, const uint8_t d3, const uint8_t d4, const uint8_t d5);
void setData(const uint8_t d0, const uint8_t d1, const uint8_t d2, const uint8_t d3, const uint8_t d4, const uint8_t d5, const uint8_t d6);
void setData(const uint8_t d0, const uint8_t d1, const uint8_t d2, const uint8_t d3, const uint8_t d4, const uint8_t d5, const uint8_t d6, const uint8_t d7);
struct timeval getTimestamp() const;
void setTimestamp(const struct timeval timestamp);
void setTimestamp(const uint64_t seconds, const uint32_t micro_seconds);
double getFloatTimestamp() const;
QDateTime getDateTime() const;
QString getIdString() const;
QString getDataHexString() const;
private:
uint32_t _raw_id;
uint8_t _dlc;
bool _isFD;
bool _isBRS;
CanInterfaceId _interface;
union {
uint8_t _u8[8*8];
uint16_t _u16[4*8];
uint32_t _u32[2*8];
uint64_t _u64[8];
};
struct timeval _timestamp;
};

215
core/CanTrace.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CanTrace.h"
#include <QMutexLocker>
#include <QFile>
#include <QTextStream>
#include <core/Backend.h>
#include <core/CanMessage.h>
#include <core/CanDbMessage.h>
#include <core/CanDbSignal.h>
#include <driver/CanInterface.h>
CanTrace::CanTrace(Backend &backend, QObject *parent, int flushInterval)
: QObject(parent),
_backend(backend),
_isTimerRunning(false),
_mutex(QMutex::Recursive),
_timerMutex(),
_flushTimer(this)
{
clear();
_flushTimer.setSingleShot(true);
_flushTimer.setInterval(flushInterval);
connect(&_flushTimer, SIGNAL(timeout()), this, SLOT(flushQueue()));
}
unsigned long CanTrace::size()
{
QMutexLocker locker(&_mutex);
return _dataRowsUsed;
}
void CanTrace::clear()
{
QMutexLocker locker(&_mutex);
emit beforeClear();
_data.resize(pool_chunk_size);
_dataRowsUsed = 0;
_newRows = 0;
emit afterClear();
}
const CanMessage *CanTrace::getMessage(int idx)
{
QMutexLocker locker(&_mutex);
if (idx >= (_dataRowsUsed + _newRows)) {
return 0;
} else {
return &_data[idx];
}
}
void CanTrace::enqueueMessage(const CanMessage &msg, bool more_to_follow)
{
QMutexLocker locker(&_mutex);
int idx = size() + _newRows;
if (idx>=_data.size()) {
_data.resize(_data.size() + pool_chunk_size);
}
_data[idx].cloneFrom(msg);
_newRows++;
if (!more_to_follow) {
startTimer();
}
emit messageEnqueued(idx);
}
void CanTrace::flushQueue()
{
{
QMutexLocker locker(&_timerMutex);
_isTimerRunning = false;
}
QMutexLocker locker(&_mutex);
if (_newRows) {
emit beforeAppend(_newRows);
// see if we have muxed messages. cache muxed values, if any.
MeasurementSetup &setup = _backend.getSetup();
for (int i=_dataRowsUsed; i<_dataRowsUsed + _newRows; i++) {
CanMessage &msg = _data[i];
CanDbMessage *dbmsg = setup.findDbMessage(msg);
if (dbmsg && dbmsg->getMuxer()) {
foreach (CanDbSignal *signal, dbmsg->getSignals()) {
if (signal->isMuxed() && signal->isPresentInMessage(msg)) {
_muxCache[signal] = signal->extractRawDataFromMessage(msg);
}
}
}
}
_dataRowsUsed += _newRows;
_newRows = 0;
emit afterAppend();
}
}
void CanTrace::startTimer()
{
QMutexLocker locker(&_timerMutex);
if (!_isTimerRunning) {
_isTimerRunning = true;
QMetaObject::invokeMethod(&_flushTimer, "start", Qt::QueuedConnection);
}
}
void CanTrace::saveCanDump(QFile &file)
{
QMutexLocker locker(&_mutex);
QTextStream stream(&file);
for (unsigned int i=0; i<size(); i++) {
CanMessage *msg = &_data[i];
QString line;
line.append(QString().sprintf("(%.6f) ", msg->getFloatTimestamp()));
line.append(_backend.getInterfaceName(msg->getInterfaceId()));
if (msg->isExtended()) {
line.append(QString().sprintf(" %08X#", msg->getId()));
} else {
line.append(QString().sprintf(" %03X#", msg->getId()));
}
for (int i=0; i<msg->getLength(); i++) {
line.append(QString().sprintf("%02X", msg->getByte(i)));
}
stream << line << endl;
}
}
void CanTrace::saveVectorAsc(QFile &file)
{
QMutexLocker locker(&_mutex);
QTextStream stream(&file);
if (_data.length()<1) {
return;
}
auto firstMessage = _data.first();
double t_start = firstMessage.getFloatTimestamp();
QLocale locale_c(QLocale::C);
QString dt_start = locale_c.toString(firstMessage.getDateTime(), "ddd MMM dd hh:mm:ss.zzz ap yyyy");
stream << "date " << dt_start << endl;
stream << "base hex timestamps absolute" << endl;
stream << "internal events logged" << endl;
stream << "// version 8.5.0" << endl;
stream << "Begin Triggerblock " << dt_start << endl;
stream << " 0.000000 Start of measurement" << endl;
for (unsigned int i=0; i<size(); i++) {
CanMessage &msg = _data[i];
double t_current = msg.getFloatTimestamp();
QString id_hex_str = QString().sprintf("%x", msg.getId());
QString id_dec_str = QString().sprintf("%d", msg.getId());
if (msg.isExtended()) {
id_hex_str.append("x");
id_dec_str.append("x");
}
// TODO how to handle RTR flag?
QString line = QString().sprintf(
"%11.6lf 1 %-15s %s d %d %s Length = %d BitCount = %d ID = %s",
t_current-t_start,
id_hex_str.toStdString().c_str(),
"Rx", // TODO handle Rx/Tx
msg.getLength(),
msg.getDataHexString().toStdString().c_str(),
0, // TODO Length (transfer time in ns)
0, // TODO BitCount (overall frame length, including stuff bits)
id_dec_str.toStdString().c_str()
);
stream << line << endl;
}
stream << "End TriggerBlock" << endl;
}
bool CanTrace::getMuxedSignalFromCache(const CanDbSignal *signal, uint64_t *raw_value)
{
if (_muxCache.contains(signal)) {
*raw_value = _muxCache[signal];
return true;
} else {
return false;
}
}

87
core/CanTrace.h Normal file
View File

@@ -0,0 +1,87 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QObject>
#include <QMutex>
#include <QTimer>
#include <QVector>
#include <QMap>
#include <QFile>
#include "CanMessage.h"
class CanInterface;
class CanDbMessage;
class CanDbSignal;
class MeasurementSetup;
class Backend;
class CanTrace : public QObject
{
Q_OBJECT
public:
explicit CanTrace(Backend &backend, QObject *parent, int flushInterval);
unsigned long size();
void clear();
const CanMessage *getMessage(int idx);
void enqueueMessage(const CanMessage &msg, bool more_to_follow=false);
void saveCanDump(QFile &file);
void saveVectorAsc(QFile &file);
bool getMuxedSignalFromCache(const CanDbSignal *signal, uint64_t *raw_value);
signals:
void messageEnqueued(int idx);
void beforeAppend(int num_messages);
void afterAppend();
void beforeClear();
void afterClear();
private slots:
void flushQueue();
private:
enum {
pool_chunk_size = 1024
};
Backend &_backend;
QVector<CanMessage> _data;
int _dataRowsUsed;
int _newRows;
bool _isTimerRunning;
QMap<const CanDbSignal*,uint64_t> _muxCache;
QMutex _mutex;
QMutex _timerMutex;
QTimer _flushTimer;
void startTimer();
};

View File

@@ -0,0 +1,44 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ConfigurableWidget.h"
#include <QDomDocument>
#include <core/Backend.h>
ConfigurableWidget::ConfigurableWidget(QWidget *parent) : QWidget(parent)
{
}
bool ConfigurableWidget::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
(void) backend;
(void) xml;
(void) root;
return true;
}
bool ConfigurableWidget::loadXML(Backend &backend, QDomElement &el)
{
(void) backend;
(void) el;
return true;
}

43
core/ConfigurableWidget.h Normal file
View File

@@ -0,0 +1,43 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QObject>
#include <QWidget>
class Backend;
class QDomDocument;
class QDomElement;
class ConfigurableWidget : public QWidget
{
Q_OBJECT
public:
explicit ConfigurableWidget(QWidget *parent = 0);
virtual bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
virtual bool loadXML(Backend &backend, QDomElement &el);
signals:
void settingsChanged(ConfigurableWidget *sender);
public slots:
};

63
core/Log.cpp Normal file
View File

@@ -0,0 +1,63 @@
/*
Copyright (c) 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Log.h"
#include <core/Backend.h>
void log_msg(const QDateTime dt, const log_level_t level, const QString msg)
{
Backend::instance().logMessage(dt, level, msg);
}
void log_msg(const log_level_t level, const QString msg)
{
Backend::instance().logMessage(QDateTime::currentDateTime(), level, msg);
}
void log_debug(const QString msg)
{
log_msg(log_level_debug, msg);
}
void log_info(const QString msg)
{
log_msg(log_level_info, msg);
}
void log_warning(const QString msg)
{
log_msg(log_level_warning, msg);
}
void log_error(const QString msg)
{
log_msg(log_level_error, msg);
}
void log_critical(const QString msg)
{
log_msg(log_level_critical, msg);
}
void log_fatal(const QString msg)
{
log_msg(log_level_fatal, msg);
}

43
core/Log.h Normal file
View File

@@ -0,0 +1,43 @@
/*
Copyright (c) 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QDateTime>
typedef enum log_level {
log_level_debug,
log_level_info,
log_level_warning,
log_level_error,
log_level_critical,
log_level_fatal
} log_level_t;
void log_msg(const QDateTime dt, const log_level_t level, const QString msg);
void log_msg(const log_level_t level, const QString msg);
void log_debug(const QString msg);
void log_info(const QString msg);
void log_warning(const QString msg);
void log_error(const QString msg);
void log_critical(const QString msg);
void log_fatal(const QString msg);

160
core/LogModel.cpp Normal file
View File

@@ -0,0 +1,160 @@
/*
Copyright (c) 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LogModel.h"
LogModel::LogModel(Backend &backend)
{
connect(&backend, SIGNAL(onLogMessage(QDateTime,log_level_t,QString)), this, SLOT(onLogMessage(QDateTime,log_level_t,QString)));
}
LogModel::~LogModel()
{
qDeleteAll(_items);
_items.clear();
}
void LogModel::clear()
{
beginResetModel();
_items.clear();
endResetModel();
}
QModelIndex LogModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid()) {
return QModelIndex();
} else {
return createIndex(row, column, (quintptr)0);
}
}
QModelIndex LogModel::parent(const QModelIndex &child) const
{
(void) child;
return QModelIndex();
}
int LogModel::rowCount(const QModelIndex &parent) const
{
(void) parent;
return _items.size();
}
int LogModel::columnCount(const QModelIndex &parent) const
{
(void) parent;
return column_count;
}
bool LogModel::hasChildren(const QModelIndex &parent) const
{
return !parent.isValid();
}
QVariant LogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal) {
switch (section) {
case column_time:
return QString("Time");
case column_level:
return QString("Level");
case column_text:
return QString("Message");
}
}
}
return QVariant();
}
QVariant LogModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::TextAlignmentRole) {
switch (index.column()) {
case column_time:
return Qt::AlignRight + Qt::AlignVCenter;
case column_level:
return Qt::AlignCenter + Qt::AlignVCenter;
case column_text:
return Qt::AlignLeft + Qt::AlignVCenter;
default:
return QVariant();
}
}
if (role != Qt::DisplayRole) {
return QVariant();
}
if (!index.isValid()) {
return QVariant();
}
LogItem *item = _items.value(index.row(), 0);
if (item) {
switch (index.column()) {
case column_time:
return item->dt.toString("hh:mm:ss");
case column_level:
return logLevelText(item->level);
case column_text:
return item->text;
default:
return QVariant();
}
}
return QVariant();
}
void LogModel::onLogMessage(const QDateTime dt, const log_level_t level, const QString msg)
{
LogItem *item = new LogItem();
item->dt = dt;
item->level = level;
item->text = msg;
beginInsertRows(QModelIndex(), _items.size(), _items.size());
_items.append(item);
endInsertRows();
}
QString LogModel::logLevelText(log_level_t level)
{
switch (level) {
case log_level_debug: return "debug";
case log_level_info: return "info";
case log_level_warning: return "warning";
case log_level_error: return "error";
case log_level_critical: return "critical";
case log_level_fatal: return "fatal";
default: return "";
}
}

71
core/LogModel.h Normal file
View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QAbstractItemModel>
#include <QDateTime>
#include <QList>
#include <core/Backend.h>
class LogItem {
public:
QDateTime dt;
log_level_t level;
QString text;
};
class LogModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum {
column_time,
column_level,
column_text,
column_count
};
public:
LogModel(Backend &backend);
virtual ~LogModel();
void clear();
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const;
virtual QModelIndex parent(const QModelIndex &child) const;
virtual int rowCount(const QModelIndex &parent) const;
virtual int columnCount(const QModelIndex &parent) const;
virtual bool hasChildren(const QModelIndex &parent) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
virtual QVariant data(const QModelIndex &index, int role) const;
public slots:
void onLogMessage(const QDateTime dt, const log_level_t level, const QString msg);
private:
QList<LogItem*> _items;
static QString logLevelText(log_level_t level);
};

View File

@@ -0,0 +1,215 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MeasurementInterface.h"
#include <core/Backend.h>
#include <driver/CanDriver.h>
#include <driver/CanInterface.h>
MeasurementInterface::MeasurementInterface()
: _doConfigure(true),
_bitrate(500000),
_samplePoint(875),
_isCanFD(false),
_fdBitrate(4000000),
_fdSamplePoint(875),
_isListenOnlyMode(false),
_isOneShotMode(false),
_isTripleSampling(false),
_doAutoRestart(false),
_autoRestartMs(100)
{
}
bool MeasurementInterface::loadXML(Backend &backend, QDomElement &el)
{
(void) backend;
_doConfigure = el.attribute("configure", "0").toInt() != 0;
_bitrate = el.attribute("bitrate", "500000").toInt();
_samplePoint = el.attribute("sample-point", "875").toInt();
_isCanFD = el.attribute("can-fd", "0").toInt() != 0;
_fdBitrate = el.attribute("bitrate-fd", "500000").toInt();
_fdSamplePoint = el.attribute("sample-point-fd", "875").toInt();
_isListenOnlyMode = el.attribute("listen-only", "0").toInt() != 0;
_isOneShotMode = el.attribute("one-shot", "0").toInt() != 0;
_isTripleSampling = el.attribute("triple-sampling", "0").toInt() != 0;
_doAutoRestart = el.attribute("auto-restart", "0").toInt() != 0;
_autoRestartMs = el.attribute("auto-restart-time", "100").toInt();
return true;
}
bool MeasurementInterface::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
(void) xml;
root.setAttribute("type", "can");
root.setAttribute("driver", backend.getDriverName(_canif));
root.setAttribute("name", backend.getInterfaceName(_canif));
root.setAttribute("configure", _doConfigure ? 1 : 0);
root.setAttribute("bitrate", _bitrate);
root.setAttribute("sample-point", _samplePoint);
root.setAttribute("can-fd", _isCanFD ? 1 : 0);
root.setAttribute("bitrate-fd", _fdBitrate);
root.setAttribute("sample-point-fd", _fdSamplePoint);
root.setAttribute("listen-only", _isListenOnlyMode ? 1 : 0);
root.setAttribute("one-shot", _isOneShotMode ? 1 : 0);
root.setAttribute("triple-sampling", _isTripleSampling ? 1 : 0);
root.setAttribute("auto-restart", _doAutoRestart ? 1 : 0);
root.setAttribute("auto-restart-time", _autoRestartMs);
return true;
}
unsigned MeasurementInterface::bitrate() const
{
return _bitrate;
}
void MeasurementInterface::setBitrate(unsigned bitrate)
{
_bitrate = bitrate;
}
CanInterfaceId MeasurementInterface::canInterface() const
{
return _canif;
}
void MeasurementInterface::setCanInterface(CanInterfaceId canif)
{
_canif = canif;
}
void MeasurementInterface::cloneFrom(MeasurementInterface &origin)
{
*this = origin;
}
bool MeasurementInterface::doConfigure() const
{
return _doConfigure;
}
void MeasurementInterface::setDoConfigure(bool doConfigure)
{
_doConfigure = doConfigure;
}
bool MeasurementInterface::isListenOnlyMode() const
{
return _isListenOnlyMode;
}
void MeasurementInterface::setListenOnlyMode(bool isListenOnlyMode)
{
_isListenOnlyMode = isListenOnlyMode;
}
bool MeasurementInterface::isOneShotMode() const
{
return _isOneShotMode;
}
void MeasurementInterface::setOneShotMode(bool isOneShotMode)
{
_isOneShotMode = isOneShotMode;
}
bool MeasurementInterface::isTripleSampling() const
{
return _isTripleSampling;
}
void MeasurementInterface::setTripleSampling(bool isTripleSampling)
{
_isTripleSampling = isTripleSampling;
}
bool MeasurementInterface::isCanFD() const
{
return _isCanFD;
}
void MeasurementInterface::setCanFD(bool isCanFD)
{
_isCanFD = isCanFD;
}
int MeasurementInterface::samplePoint() const
{
return _samplePoint;
}
void MeasurementInterface::setSamplePoint(int samplePoint)
{
_samplePoint = samplePoint;
}
unsigned MeasurementInterface::fdBitrate() const
{
return _fdBitrate;
}
void MeasurementInterface::setFdBitrate(unsigned fdBitrate)
{
_fdBitrate = fdBitrate;
}
unsigned MeasurementInterface::fdSamplePoint() const
{
return _fdSamplePoint;
}
void MeasurementInterface::setFdSamplePoint(unsigned fdSamplePoint)
{
_fdSamplePoint = fdSamplePoint;
}
bool MeasurementInterface::doAutoRestart() const
{
return _doAutoRestart;
}
void MeasurementInterface::setAutoRestart(bool doAutoRestart)
{
_doAutoRestart = doAutoRestart;
}
int MeasurementInterface::autoRestartMs() const
{
return _autoRestartMs;
}
void MeasurementInterface::setAutoRestartMs(int autoRestartMs)
{
_autoRestartMs = autoRestartMs;
}

View File

@@ -0,0 +1,92 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QDomDocument>
#include <driver/CanDriver.h>
#include <driver/CanInterface.h>
class Backend;
class MeasurementInterface
{
public:
MeasurementInterface();
CanInterfaceId canInterface() const;
void setCanInterface(CanInterfaceId canif);
void cloneFrom(MeasurementInterface &origin);
bool loadXML(Backend &backend, QDomElement &el);
bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
bool doConfigure() const;
void setDoConfigure(bool doConfigure);
bool isListenOnlyMode() const;
void setListenOnlyMode(bool isListenOnlyMode);
bool isOneShotMode() const;
void setOneShotMode(bool isOneShotMode);
bool isTripleSampling() const;
void setTripleSampling(bool isTripleSampling);
bool isCanFD() const;
void setCanFD(bool isCanFD);
unsigned bitrate() const;
void setBitrate(unsigned bitrate);
int samplePoint() const;
void setSamplePoint(int samplePoint);
unsigned fdBitrate() const;
void setFdBitrate(unsigned fdBitrate);
unsigned fdSamplePoint() const;
void setFdSamplePoint(unsigned fdSamplePoint);
bool doAutoRestart() const;
void setAutoRestart(bool doAutoRestart);
int autoRestartMs() const;
void setAutoRestartMs(int autoRestartMs);
private:
CanInterfaceId _canif;
bool _doConfigure;
unsigned _bitrate;
unsigned _samplePoint;
bool _isCanFD;
unsigned _fdBitrate;
unsigned _fdSamplePoint;
bool _isListenOnlyMode;
bool _isOneShotMode;
bool _isTripleSampling;
bool _doAutoRestart;
int _autoRestartMs;
};

159
core/MeasurementNetwork.cpp Normal file
View File

@@ -0,0 +1,159 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MeasurementNetwork.h"
#include "MeasurementInterface.h"
#include <core/Backend.h>
MeasurementNetwork::MeasurementNetwork()
{
}
void MeasurementNetwork::cloneFrom(MeasurementNetwork &origin)
{
_name = origin._name;
foreach (MeasurementInterface *omi, origin._interfaces) {
MeasurementInterface *mi = new MeasurementInterface();
mi->cloneFrom(*omi);
_interfaces.append(mi);
}
_canDbs = origin._canDbs;
}
void MeasurementNetwork::addInterface(MeasurementInterface *intf)
{
_interfaces.append(intf);
}
void MeasurementNetwork::removeInterface(MeasurementInterface *intf)
{
_interfaces.removeAll(intf);
}
QList<MeasurementInterface *> MeasurementNetwork::interfaces()
{
return _interfaces;
}
MeasurementInterface *MeasurementNetwork::addCanInterface(CanInterfaceId canif)
{
MeasurementInterface *mi = new MeasurementInterface();
mi->setCanInterface(canif);
addInterface(mi);
return mi;
}
CanInterfaceIdList MeasurementNetwork::getReferencedCanInterfaces()
{
CanInterfaceIdList list;
foreach (MeasurementInterface *mi, _interfaces) {
list << mi->canInterface();
}
return list;
}
void MeasurementNetwork::addCanDb(QSharedPointer<CanDb> candb)
{
_canDbs.append(candb);
}
void MeasurementNetwork::reloadCanDbs(Backend *backend)
{
foreach(pCanDb db, _canDbs)
{
db = backend->loadDbc(db->getPath());
}
}
QString MeasurementNetwork::name() const
{
return _name;
}
void MeasurementNetwork::setName(const QString &name)
{
_name = name;
}
bool MeasurementNetwork::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
root.setAttribute("name", _name);
QDomElement interfacesNode = xml.createElement("interfaces");
foreach (MeasurementInterface *intf, _interfaces) {
QDomElement intfNode = xml.createElement("interface");
if (!intf->saveXML(backend, xml, intfNode)) {
return false;
}
interfacesNode.appendChild(intfNode);
}
root.appendChild(interfacesNode);
QDomElement candbsNode = xml.createElement("databases");
foreach (pCanDb candb, _canDbs) {
QDomElement dbNode = xml.createElement("database");
if (!candb->saveXML(backend, xml, dbNode)) {
return false;
}
candbsNode.appendChild(dbNode);
}
root.appendChild(candbsNode);
return true;
}
bool MeasurementNetwork::loadXML(Backend &backend, QDomElement el)
{
setName(el.attribute("name", "unnamed network"));
QDomNodeList ifList = el.firstChildElement("interfaces").elementsByTagName("interface");
for (int i=0; i<ifList.length(); i++) {
QDomElement elIntf = ifList.item(i).toElement();
QString driverName = elIntf.attribute("driver");
QString deviceName = elIntf.attribute("name");
CanInterface *intf = backend.getInterfaceByDriverAndName(driverName, deviceName);
if (intf) {
MeasurementInterface *mi = addCanInterface(intf->getId());
mi->loadXML(backend, elIntf);
} else {
log_error(QString("Could not find interface %1/%2, which is referenced in the workspace config file.").arg(driverName, deviceName));
}
}
QDomNodeList dbList = el.firstChildElement("databases").elementsByTagName("database");
for (int i=0; i<dbList.length(); i++) {
QDomElement elDb = dbList.item(i).toElement();
QString filename = elDb.attribute("filename", QString());
if (!filename.isEmpty()) {
addCanDb(backend.loadDbc(filename));
} else {
log_error(QString("Unable to load CanDB: %1").arg(filename));
}
}
return true;
}

61
core/MeasurementNetwork.h Normal file
View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
#include <QList>
#include <QDomDocument>
#include <driver/CanDriver.h>
#include <driver/CanInterface.h>
#include <core/CanDb.h>
class Backend;
class MeasurementInterface;
class MeasurementNetwork
{
public:
MeasurementNetwork();
void cloneFrom(MeasurementNetwork &origin);
void addInterface(MeasurementInterface *intf);
void removeInterface(MeasurementInterface *intf);
QList<MeasurementInterface*> interfaces();
MeasurementInterface *addCanInterface(CanInterfaceId canif);
CanInterfaceIdList getReferencedCanInterfaces();
void addCanDb(pCanDb candb);
void reloadCanDbs(Backend *backend);
QList<pCanDb> _canDbs;
QString name() const;
void setName(const QString &name);
bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
bool loadXML(Backend &backend, QDomElement el);
private:
QString _name;
QList<MeasurementInterface*> _interfaces;
};

145
core/MeasurementSetup.cpp Normal file
View File

@@ -0,0 +1,145 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MeasurementSetup.h"
#include <QThread>
#include <QMetaType>
#include <core/CanTrace.h>
#include <core/CanMessage.h>
#include <core/MeasurementNetwork.h>
MeasurementSetup::MeasurementSetup(QObject *parent)
: QObject(parent)
{
}
MeasurementSetup::~MeasurementSetup()
{
qDeleteAll(_networks);
}
void MeasurementSetup::clear()
{
qDeleteAll(_networks);
_networks.clear();
emit onSetupChanged();
}
void MeasurementSetup::cloneFrom(MeasurementSetup &origin)
{
clear();
foreach (MeasurementNetwork *network, origin._networks) {
MeasurementNetwork *network_copy = new MeasurementNetwork();
network_copy->cloneFrom(*network);
_networks.append(network_copy);
}
emit onSetupChanged();
}
bool MeasurementSetup::saveXML(Backend &backend, QDomDocument &xml, QDomElement &root)
{
foreach (MeasurementNetwork *network, _networks) {
QDomElement networkNode = xml.createElement("network");
if (!network->saveXML(backend, xml, networkNode)) {
return false;
}
root.appendChild(networkNode);
}
return true;
}
bool MeasurementSetup::loadXML(Backend &backend, QDomElement &el)
{
clear();
QDomNodeList networks = el.elementsByTagName("network");
for (int i=0; i<networks.length(); i++) {
MeasurementNetwork *network = createNetwork();
if (!network->loadXML(backend, networks.item(i).toElement())) {
return false;
}
}
emit onSetupChanged();
return true;
}
MeasurementNetwork *MeasurementSetup::createNetwork()
{
MeasurementNetwork *network = new MeasurementNetwork();
_networks.append(network);
return network;
}
void MeasurementSetup::removeNetwork(MeasurementNetwork *network)
{
_networks.removeAll(network);
}
CanDbMessage *MeasurementSetup::findDbMessage(const CanMessage &msg) const
{
CanDbMessage *result = 0;
foreach (MeasurementNetwork *network, _networks) {
foreach (pCanDb db, network->_canDbs) {
result = db->getMessageById(msg.getRawId());
if (result != 0) {
return result;
}
}
}
return result;
}
QString MeasurementSetup::getInterfaceName(const CanInterface &interface) const
{
return interface.getName();
}
int MeasurementSetup::countNetworks() const
{
return _networks.length();
}
MeasurementNetwork *MeasurementSetup::getNetwork(int index) const
{
return _networks.value(index);
}
MeasurementNetwork *MeasurementSetup::getNetworkByName(QString name) const
{
foreach (MeasurementNetwork *network, _networks) {
if (network->name() == name) {
return network;
}
}
return 0;
}
QList<MeasurementNetwork *> MeasurementSetup::getNetworks()
{
return _networks;
}

63
core/MeasurementSetup.h Normal file
View File

@@ -0,0 +1,63 @@
/*
Copyright (c) 2015, 2016 Hubert Denkmair <hubert@denkmair.de>
This file is part of cangaroo.
cangaroo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
cangaroo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cangaroo. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QObject>
#include <QList>
#include <QDomDocument>
class Backend;
class MeasurementNetwork;
class CanTrace;
class CanMessage;
class CanInterface;
class CanDbMessage;
class MeasurementSetup : public QObject
{
Q_OBJECT
public:
explicit MeasurementSetup(QObject *parent);
virtual ~MeasurementSetup();
void clear();
CanDbMessage *findDbMessage(const CanMessage &msg) const;
QString getInterfaceName(const CanInterface &interface) const;
int countNetworks() const;
MeasurementNetwork *getNetwork(int index) const;
MeasurementNetwork *getNetworkByName(QString name) const;
QList<MeasurementNetwork*> getNetworks();
MeasurementNetwork *createNetwork();
void removeNetwork(MeasurementNetwork *network);
void cloneFrom(MeasurementSetup &origin);
bool saveXML(Backend &backend, QDomDocument &xml, QDomElement &root);
bool loadXML(Backend &backend, QDomElement &el);
signals:
void onSetupChanged();
private:
QList<MeasurementNetwork*> _networks;
};

30
core/core.pri Normal file
View File

@@ -0,0 +1,30 @@
SOURCES += \
$$PWD/Backend.cpp \
$$PWD/CanMessage.cpp \
$$PWD/CanTrace.cpp \
$$PWD/CanDbMessage.cpp \
$$PWD/CanDb.cpp \
$$PWD/CanDbNode.cpp \
$$PWD/CanDbSignal.cpp \
$$PWD/MeasurementSetup.cpp \
$$PWD/MeasurementNetwork.cpp \
$$PWD/MeasurementInterface.cpp \
$$PWD/LogModel.cpp \
$$PWD/ConfigurableWidget.cpp \
$$PWD/Log.cpp
HEADERS += \
$$PWD/portable_endian.h \
$$PWD/Backend.h \
$$PWD/CanMessage.h \
$$PWD/CanTrace.h \
$$PWD/CanDbMessage.h \
$$PWD/CanDb.h \
$$PWD/CanDbNode.h \
$$PWD/CanDbSignal.h \
$$PWD/MeasurementSetup.h \
$$PWD/MeasurementNetwork.h \
$$PWD/MeasurementInterface.h \
$$PWD/LogModel.h \
$$PWD/ConfigurableWidget.h \
$$PWD/Log.h

73
core/portable_endian.h Normal file
View File

@@ -0,0 +1,73 @@
// "License": Public Domain
// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like.
// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to
// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it
// an example on how to get the endian conversion functions on different platforms.
#pragma once
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
# define __WINDOWS__
#endif
#if defined(__linux__) || defined(__CYGWIN__)
# include <endian.h>
#elif defined(__WINDOWS__)
# include <sys/param.h>
# if BYTE_ORDER == LITTLE_ENDIAN
# define htobe16(x) htons(x)
# define htole16(x) (x)
# define be16toh(x) ntohs(x)
# define le16toh(x) (x)
# define htobe32(x) htonl(x)
# define htole32(x) (x)
# define be32toh(x) ntohl(x)
# define le32toh(x) (x)
# define htobe64(x) htonll(x)
# define htole64(x) (x)
# define be64toh(x) ntohll(x)
# define le64toh(x) (x)
# elif BYTE_ORDER == BIG_ENDIAN
/* that would be xbox 360 */
# define htobe16(x) (x)
# define htole16(x) __builtin_bswap16(x)
# define be16toh(x) (x)
# define le16toh(x) __builtin_bswap16(x)
# define htobe32(x) (x)
# define htole32(x) __builtin_bswap32(x)
# define be32toh(x) (x)
# define le32toh(x) __builtin_bswap32(x)
# define htobe64(x) (x)
# define htole64(x) __builtin_bswap64(x)
# define be64toh(x) (x)
# define le64toh(x) __builtin_bswap64(x)
# else
# error byte order not supported
# endif
# define __BYTE_ORDER BYTE_ORDER
# define __BIG_ENDIAN BIG_ENDIAN
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __PDP_ENDIAN PDP_ENDIAN
#else
# error platform not supported
#endif