/*! * * Copyright (c) 2019-2019 Diality Inc. - All Rights Reserved. * \copyright \n * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, \n * IN PART OR IN WHOLE, \n * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n * * \file caninterface.cpp * \date 2019/09/30 * \author Behrouz NematiPour * */ #include "caninterface.h" // Qt #include // Project #include "messagehandler.h" // namespace using namespace Can; // Singleton SINGLETON_INIT(CanInterface) /*! * \brief Caninterface Constructor * \param parent object */ CanInterface::CanInterface(QObject *parent) : QObject(parent) { } /*! * \brief CanInterface Initialization * \details Initializes the CANBUS and checks if can be connected * \return true if connected, false otherwise */ bool CanInterface::init() { QString mError; _canDevice = QCanBus::instance()->createDevice(_canType, _canInterface, &mError); if (!_canDevice) { status(tr("Error: Device Creation"),mError); return false; } _numberFramesWritten = 0; initConnections(); if (!_canDevice->connectDevice()) { status(tr("Error: Connection")); delete _canDevice; _canDevice = nullptr; return false; } status(tr("Connected")); return true; } /*! * \brief CanInterface status * \details CanInterface status description * \return The current stores status */ QString CanInterface::status() const { return _canStatus; } /*! * \brief CanInterface connections definition * \details Initializes the required signal/slot connection between this class and other objects * to be able to communicate. */ void CanInterface::initConnections() { if (_canDevice) { connect(_canDevice, SIGNAL( framesReceived()), this , SLOT (onFrameReceive ())); connect(_canDevice, SIGNAL( errorOccurred(QCanBusDevice::CanBusError)), this , SLOT (onFrameError (QCanBusDevice::CanBusError))); connect(_canDevice, SIGNAL( framesWritten(qint64)), this , SLOT (onFrameWrittern(qint64))); } connect(_MessageHandler, SIGNAL(didFrameTransmit(QCanBusFrame)), this , SLOT( onFrameTransmit(QCanBusFrame))); } /*! * \brief CanInterface status * \details Sets the Can interface status description * \param vDescription - Description about the CANBUS Interface errors * \param vError - Qt CANBUS Interface Error */ void CanInterface::status(const QString &vDescription, QString vError) { QString mError=""; if (_canDevice) { mError = _canDevice->errorString() + vError; } else { mError = vError; } _canStatus = tr("%1 '%2[%3]', %4") .arg(vDescription) .arg(_canType) .arg(_canInterface) .arg(mError) ; qDebug() << _canStatus; } /*! * \brief CanInterface send * \details send a frame over the CANBUS * \param vFrame - CANBUS message frame */ bool CanInterface::transmit(const QCanBusFrame &vFrame) { if( !_canDevice ) return false; return _canDevice->writeFrame(vFrame); } /*! * \brief CanInterface console Output messaging * \details Sends out formatted CANBUS message to the console * for debugging purposes. * \param vFrame - The CANBUS frame to be sent out */ void CanInterface::consoleOut(const QCanBusFrame &vFrame) { if ( ! _enableConsoleOut ) return; const QString time = QString::fromLatin1("%1.%2 ") .arg(vFrame.timeStamp().seconds(), 10, 10, QLatin1Char(' ')) .arg(vFrame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0')); const QString flags = frameFlags(vFrame); QString view; if (vFrame.frameType() == QCanBusFrame::ErrorFrame) { view = _canDevice->interpretErrorFrame(vFrame); } else { view = vFrame.payload().toHex('.').replace(QByteArray("a5"),QByteArray("\033[1;33mA5\033[0m")); } fprintf(stderr, "%s %s %i %s\n", time.toLatin1().constData(), flags.toLatin1().constData(), vFrame.frameId(), view.toLatin1().constData()); } /*! * \brief CanInterface quit * \details Quit the CANBUS Interface by disconnecting the bus and device. */ void CanInterface::quit() { if (!_canDevice) return; _canDevice->disconnectDevice(); delete _canDevice; _canDevice = nullptr; status(tr("Disconnected")); } /*! * \brief frameFlags * \details CANBUS message frame type as flags * \param vFrame - CANBUS message frame * \return Frame flag as QString */ QString CanInterface::frameFlags(const QCanBusFrame &vFrame) { QString result = QLatin1String(" --- "); if (vFrame.hasBitrateSwitch()) result[1] = QLatin1Char('B'); if (vFrame.hasErrorStateIndicator()) result[2] = QLatin1Char('E'); if (vFrame.hasLocalEcho()) result[3] = QLatin1Char('L'); return result; } /*! * \brief CanInterface onError * \details Can Bus error handler which sets the can status description * \param vError - CANBUS error */ void CanInterface::onFrameError(QCanBusDevice::CanBusError vError) { switch (vError) { case QCanBusDevice::ReadError: case QCanBusDevice::WriteError: case QCanBusDevice::ConnectionError: case QCanBusDevice::ConfigurationError: case QCanBusDevice::UnknownError: _canStatus = _canDevice->errorString(); break; default: break; } emit didFrameError(_canStatus); } /*! * \brief CanInterface::onFrameWrittern * \details This is the slot connected to the signal * which is emitted every time a payload of frames * has been written to the CANBUS bus. * \param vFramesCount - The framesCount argument is set to the number of frames * that were written in this payload. */ void CanInterface::onFrameWrittern(qint64 /*vFramesCount*/) { //_numberFramesWritten = vFramesCount; //qDebug() << "onFrameWrittern::FramesCount : " << vFramesCount; } /*! * \brief CanInterface onFrameReceived * \details CANBUS message read handler */ void CanInterface::onFrameReceive () { if (!_canDevice) return; while (_canDevice->framesAvailable()) { const QCanBusFrame frame = _canDevice->readFrame(); consoleOut(frame); emit didFrameReceive(frame); } } /*! * \brief CanInterface onActionPerform * \details sends a CANBUS message frame of the CANBUS message of the performed action * This is a response from application UI to HD device * \param vFrame - CANBUS message frame */ void CanInterface::onFrameTransmit(const QCanBusFrame &vFrame) { bool ok = transmit(vFrame); emit didFrameTransmit(ok); }