new socketcan connection

This commit is contained in:
canpadawan
2016-06-15 18:23:21 +02:00
parent 4553dd59ee
commit cdff06ebe3
2 changed files with 203 additions and 80 deletions
+160 -57
View File
@@ -2,33 +2,7 @@
#include <QDebug> #include <QDebug>
#include <QCanBusFrame> #include <QCanBusFrame>
#include "socketcan.h"
#include "canframemodel.h"
#include "canconnection_old.h"
#include "socketcanconnection.h"
/***********************************/
/**** nested class ****/
/***********************************/
BUSConfig::BUSConfig():isConfigured(false){}
void BUSConfig::reset() {
isConfigured = false;
}
bool BUSConfig::operator==(CANBus& bus) {
return isConfigured && speed == bus.speed &&
listenOnly == bus.listenOnly && active == bus.active;
}
void BUSConfig::operator=(CANBus& bus) {
isConfigured = true;
speed = bus.speed;
listenOnly = bus.listenOnly;
active = bus.active;
}
@@ -36,41 +10,120 @@ void BUSConfig::operator=(CANBus& bus) {
/**** class definition ****/ /**** class definition ****/
/***********************************/ /***********************************/
SocketCanConnection::SocketCanConnection(CANFrameModel *model, int base) : CANConnection(model, base), mDev_p(NULL) SocketCanConnection::SocketCanConnection(QString portName) :
CANConnection(portName, CANCon::SOCKETCAN, 1),
mDev_p(NULL),
mThread(NULL)
{ {
getQueue().setSize(2000); /*TODO add check on returned value */
/* move ourself to the thread */
moveToThread(&mThread);
qDebug() << "SocketCanConnection()"; qDebug() << "SocketCanConnection()";
qRegisterMetaType<CANFrame>("CANFrame");
} }
SocketCanConnection::~SocketCanConnection() SocketCanConnection::~SocketCanConnection()
{ {
stop();
qDebug() << "~SocketCanConnection()"; qDebug() << "~SocketCanConnection()";
/* stop device */
} }
void SocketCanConnection::updateBusSettings(CANBus bus)
{
qDebug()<<"updateBusSettings";
if(mConf == bus) return; void SocketCanConnection::start() {
qDebug() << "enter thread";
mThread.start(QThread::HighPriority);
connect(&mTimer, SIGNAL(timeout()), this, SLOT(testConnection()));
mTimer.setInterval(1000);
mTimer.setSingleShot(false); //keep ticking
mTimer.start();
}
void SocketCanConnection::suspend(bool pSuspend) {
/* make sure we execute in mThread context */
if(QThread::currentThread() != &mThread) {
QMetaObject::invokeMethod(this, "suspend",
Qt::BlockingQueuedConnection,
Q_ARG(bool, pSuspend));
return;
}
/* update capSuspended */
setCapSuspended(pSuspend);
/* flush queue if we are suspended */
if(isCapSuspended())
getQueue().flush();
}
void SocketCanConnection::stop() {
mTimer.stop();
mThread.quit();
if(!mThread.wait()) {
qDebug() << "can't stop thread";
}
disconnectDevice();
}
bool SocketCanConnection::getBusSettings(int pBusIdx, CANBus& pBus) {
/* make sure we execute in mThread context */
if(QThread::currentThread() != &mThread) {
bool ret;
QMetaObject::invokeMethod(this, "getBusSettings",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, ret),
Q_ARG(int , pBusIdx),
Q_ARG(CANBus& , pBus));
return ret;
}
return getBusConfig(pBusIdx, pBus);
}
void SocketCanConnection::setBusSettings(int pBusIdx, CANBus bus)
{
/* make sure we execute in mThread context */
if(QThread::currentThread() != &mThread) {
QMetaObject::invokeMethod(this, "setBusSettings",
Qt::BlockingQueuedConnection,
Q_ARG(int, pBusIdx),
Q_ARG(CANBus, bus));
return;
}
/* sanity checks */
if(0 != pBusIdx)
return;
/* disconnect device if we have one connected */ /* disconnect device if we have one connected */
if(mDev_p) disconnect(); if(mDev_p)
disconnectDevice();
/* copy bus config */
setBusConfig(0, bus);
/* if bus is not active we are done */ /* if bus is not active we are done */
if(!bus.active) return; if(!bus.active)
return;
/* create device */ /* create device */
mDev_p = QCanBus::instance()->createDevice("socketcan", portName); mDev_p = QCanBus::instance()->createDevice("socketcan", getPort());
if (!mDev_p) { if (!mDev_p) {
disconnectDevice();
qDebug() << "can't create device"; qDebug() << "can't create device";
return; return;
} }
/* connect slots */ /* connect slots */
connect(mDev_p, &QCanBusDevice::errorOccurred, this, &SocketCanConnection::errorReceived); connect(mDev_p, &QCanBusDevice::errorOccurred, this, &SocketCanConnection::errorReceived);
connect(mDev_p, &QCanBusDevice::framesReceived, this, &SocketCanConnection::framesReceived);
connect(mDev_p, &QCanBusDevice::framesWritten, this, &SocketCanConnection::framesWritten); connect(mDev_p, &QCanBusDevice::framesWritten, this, &SocketCanConnection::framesWritten);
connect(mDev_p, &QCanBusDevice::framesReceived, this, &SocketCanConnection::framesReceived);
/* set configuration */ /* set configuration */
/*if (p.useConfigurationEnabled) { /*if (p.useConfigurationEnabled) {
@@ -80,19 +133,23 @@ void SocketCanConnection::updateBusSettings(CANBus bus)
/* connect device */ /* connect device */
if (!mDev_p->connectDevice()) { if (!mDev_p->connectDevice()) {
disconnect(); disconnectDevice();
qDebug() << "can't connect device"; qDebug() << "can't connect device";
} }
} }
void SocketCanConnection::sendFrame(const CANFrame *) {}
void SocketCanConnection::sendFrameBatch(const QList<CANFrame> *){}
/***********************************/ /***********************************/
/**** private methods ****/ /**** private methods ****/
/***********************************/ /***********************************/
/* connect device */ /* disconnect device */
void SocketCanConnection::disconnect() { void SocketCanConnection::disconnectDevice() {
if(mDev_p) { if(mDev_p) {
mDev_p->disconnectDevice(); mDev_p->disconnectDevice();
delete mDev_p; delete mDev_p;
@@ -123,35 +180,81 @@ void SocketCanConnection::framesWritten(qint64 count)
void SocketCanConnection::framesReceived() void SocketCanConnection::framesReceived()
{ {
/* sanity checks */ /* sanity checks */
if(!mDev_p) return; if(!mDev_p)
return;
/* read frame */ /* read frame */
while(true) while(true)
{ {
const QCanBusFrame recFrame = mDev_p->readFrame(); const QCanBusFrame recFrame = mDev_p->readFrame();
/* exit case */
if(!recFrame.isValid()) return;
/* exit case */
if(!recFrame.isValid())
return;
/* drop frame if capture is suspended */
if(isCapSuspended())
continue;
/* check frame */
if(!recFrame.payload().isEmpty() && if(!recFrame.payload().isEmpty() &&
recFrame.payload().length()<=8) recFrame.payload().length()<=8)
{ {
CANFrame frame; CANFrame* frame_p = getQueue().get();
frame.len = recFrame.payload().length(); if(frame_p) {
frame.bus = 0; frame_p->len = recFrame.payload().length();
memcpy(frame.data, recFrame.payload().data(), frame.len); frame_p->bus = 0;
frame.extended = false; memcpy(frame_p->data, recFrame.payload().data(), frame_p->len);
frame.ID = recFrame.frameId(); frame_p->extended = false;
frame.isReceived = true; frame_p->ID = recFrame.frameId();
frame.timestamp = recFrame.timeStamp().microSeconds(); frame_p->isReceived = true;
frame_p->timestamp = recFrame.timeStamp().seconds()*1000000 + recFrame.timeStamp().microSeconds();
/* send frame */ /* enqueue frame */
QMetaObject::invokeMethod(model, "addFrame", getQueue().queue();
Qt::QueuedConnection, }
Q_ARG(CANFrame, frame), else
Q_ARG(bool, false)); qDebug() << "can't get a frame, ERROR";
} }
else { else {
qDebug() << "invalid frame"; qDebug() << "invalid frame";
} }
} }
} }
void SocketCanConnection::testConnection() {
QCanBusDevice* dev_p = QCanBus::instance()->createDevice("socketcan", getPort());
switch(getStatus())
{
case CANCon::CONNECTED:
if (!dev_p || !dev_p->connectDevice()) {
/* we have lost connectivity */
disconnectDevice();
setStatus(CANCon::NOT_CONNECTED);
emit status(getStatus());
}
break;
case CANCon::NOT_CONNECTED:
if (dev_p && dev_p->connectDevice()) {
/* try to reconnect */
CANBus bus;
if(getBusConfig(0, bus))
setBusSettings(0, bus);
/* disconnect test instance */
dev_p->disconnectDevice();
setStatus(CANCon::CONNECTED);
emit status(getStatus());
}
break;
default: {}
}
if(dev_p)
delete dev_p;
}
+40 -20
View File
@@ -3,21 +3,11 @@
#include <QObject> #include <QObject>
#include <QCanBus> #include <QCanBus>
#include <QTimer>
#include <qthread.h>
#include "canframemodel.h" #include "canframemodel.h"
#include "canconnection_old.h" #include "canconnection.h"
class BUSConfig {
public:
BUSConfig();
void reset();
bool operator ==(CANBus&);
void operator =(CANBus&);
bool isConfigured;
int speed;
bool listenOnly;
bool active;
};
class SocketCanConnection : public CANConnection class SocketCanConnection : public CANConnection
@@ -25,20 +15,50 @@ class SocketCanConnection : public CANConnection
Q_OBJECT Q_OBJECT
public: public:
SocketCanConnection(CANFrameModel *, int); SocketCanConnection(QString portName);
virtual ~SocketCanConnection() override; virtual ~SocketCanConnection();
virtual void start();
virtual void stop();
signals:
void error(const QString &);
void status(CANCon::status);
void deviceInfo(int, int); //First param = driver version (or version of whatever you want), second param a status byte
//bus number, bus speed, status (bit 0 = enabled, 1 = single wire, 2 = listen only)
//3 = Use value stored for enabled, 4 = use value passed for single wire, 5 = use value passed for listen only
//6 = use value passed for speed. This allows bus status to be updated but set that some things aren't really
//being passed. Just set for things that really are being updated.
void busStatus(int, int, int);
public slots: public slots:
virtual void updateBusSettings(CANBus) override;
private: virtual void sendFrame(const CANFrame *);
void errorReceived(QCanBusDevice::CanBusError error) const; virtual void sendFrameBatch(const QList<CANFrame> *);
virtual void setBusSettings(int, CANBus);
virtual bool getBusSettings(int pBusIdx, CANBus& pBus);
virtual void suspend(bool);
protected:
void disconnectDevice();
private slots:
void errorReceived(QCanBusDevice::CanBusError) const;
void framesWritten(qint64 count); void framesWritten(qint64 count);
void framesReceived(); void framesReceived();
void disconnect(); void testConnection();
protected:
QCanBusDevice* mDev_p; QCanBusDevice* mDev_p;
BUSConfig mConf; QTimer mTimer;
QThread mThread;
}; };
#endif // SOCKETCANCONNECTION_H #endif // SOCKETCANCONNECTION_H