From cdff06ebe31bd1eaf0cf0448b54c089e99007502 Mon Sep 17 00:00:00 2001 From: canpadawan Date: Wed, 15 Jun 2016 18:23:21 +0200 Subject: [PATCH] new socketcan connection --- connections/socketcan.cpp | 221 ++++++++++++++++++++++++++++---------- connections/socketcan.h | 62 +++++++---- 2 files changed, 203 insertions(+), 80 deletions(-) diff --git a/connections/socketcan.cpp b/connections/socketcan.cpp index 94eb4b7..76b6fe3 100644 --- a/connections/socketcan.cpp +++ b/connections/socketcan.cpp @@ -2,33 +2,7 @@ #include #include - -#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; -} +#include "socketcan.h" @@ -36,41 +10,120 @@ void BUSConfig::operator=(CANBus& bus) { /**** 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()"; - qRegisterMetaType("CANFrame"); } + SocketCanConnection::~SocketCanConnection() { + stop(); 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 */ - if(mDev_p) disconnect(); + if(mDev_p) + disconnectDevice(); + + /* copy bus config */ + setBusConfig(0, bus); /* if bus is not active we are done */ - if(!bus.active) return; + if(!bus.active) + return; /* create device */ - mDev_p = QCanBus::instance()->createDevice("socketcan", portName); + mDev_p = QCanBus::instance()->createDevice("socketcan", getPort()); if (!mDev_p) { - qDebug() << "can't create device"; - return; + disconnectDevice(); + qDebug() << "can't create device"; + return; } /* connect slots */ 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::framesReceived, this, &SocketCanConnection::framesReceived); /* set configuration */ /*if (p.useConfigurationEnabled) { @@ -80,19 +133,23 @@ void SocketCanConnection::updateBusSettings(CANBus bus) /* connect device */ if (!mDev_p->connectDevice()) { - disconnect(); + disconnectDevice(); qDebug() << "can't connect device"; } } +void SocketCanConnection::sendFrame(const CANFrame *) {} +void SocketCanConnection::sendFrameBatch(const QList *){} + + /***********************************/ /**** private methods ****/ /***********************************/ -/* connect device */ -void SocketCanConnection::disconnect() { +/* disconnect device */ +void SocketCanConnection::disconnectDevice() { if(mDev_p) { mDev_p->disconnectDevice(); delete mDev_p; @@ -123,35 +180,81 @@ void SocketCanConnection::framesWritten(qint64 count) void SocketCanConnection::framesReceived() { /* sanity checks */ - if(!mDev_p) return; + if(!mDev_p) + return; /* read frame */ while(true) { 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() && recFrame.payload().length()<=8) { - CANFrame frame; - frame.len = recFrame.payload().length(); - frame.bus = 0; - memcpy(frame.data, recFrame.payload().data(), frame.len); - frame.extended = false; - frame.ID = recFrame.frameId(); - frame.isReceived = true; - frame.timestamp = recFrame.timeStamp().microSeconds(); + CANFrame* frame_p = getQueue().get(); + if(frame_p) { + frame_p->len = recFrame.payload().length(); + frame_p->bus = 0; + memcpy(frame_p->data, recFrame.payload().data(), frame_p->len); + frame_p->extended = false; + frame_p->ID = recFrame.frameId(); + frame_p->isReceived = true; + frame_p->timestamp = recFrame.timeStamp().seconds()*1000000 + recFrame.timeStamp().microSeconds(); - /* send frame */ - QMetaObject::invokeMethod(model, "addFrame", - Qt::QueuedConnection, - Q_ARG(CANFrame, frame), - Q_ARG(bool, false)); + /* enqueue frame */ + getQueue().queue(); + } + else + qDebug() << "can't get a frame, ERROR"; } else { 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; +} diff --git a/connections/socketcan.h b/connections/socketcan.h index 1662501..eea37a9 100644 --- a/connections/socketcan.h +++ b/connections/socketcan.h @@ -3,21 +3,11 @@ #include #include +#include +#include #include "canframemodel.h" -#include "canconnection_old.h" - -class BUSConfig { -public: - BUSConfig(); - void reset(); - bool operator ==(CANBus&); - void operator =(CANBus&); - bool isConfigured; - int speed; - bool listenOnly; - bool active; -}; +#include "canconnection.h" class SocketCanConnection : public CANConnection @@ -25,20 +15,50 @@ class SocketCanConnection : public CANConnection Q_OBJECT public: - SocketCanConnection(CANFrameModel *, int); - virtual ~SocketCanConnection() override; + SocketCanConnection(QString portName); + 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: - virtual void updateBusSettings(CANBus) override; -private: - void errorReceived(QCanBusDevice::CanBusError error) const; + virtual void sendFrame(const CANFrame *); + virtual void sendFrameBatch(const QList *); + + 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 framesReceived(); - void disconnect(); + void testConnection(); - QCanBusDevice* mDev_p; - BUSConfig mConf; +protected: + QCanBusDevice* mDev_p; + QTimer mTimer; + QThread mThread; }; + #endif // SOCKETCANCONNECTION_H