diff --git a/SavvyCAN.pro b/SavvyCAN.pro index 64cbc553..bfdb7099 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -21,6 +21,7 @@ ICON = icons/SavvyIcon.icns SOURCES += main.cpp\ canbridgewindow.cpp \ + connections/canlogserver.cpp \ connections/canserver.cpp \ connections/lawicel_serial.cpp \ connections/mqtt_bus.cpp \ @@ -104,6 +105,7 @@ HEADERS += mainwindow.h \ can_structs.h \ canbridgewindow.h \ canframemodel.h \ + connections/canlogserver.h \ connections/canserver.h \ connections/lawicel_serial.h \ connections/socketcand.h \ diff --git a/connections/canconconst.h b/connections/canconconst.h index 88fa31ea..0f7ba9c0 100644 --- a/connections/canconconst.h +++ b/connections/canconconst.h @@ -22,6 +22,7 @@ namespace CANCon { MQTT, LAWICEL, CANSERVER, + CANLOGSERVER, NONE }; } diff --git a/connections/canconfactory.cpp b/connections/canconfactory.cpp index 2b4be1f4..db93da25 100644 --- a/connections/canconfactory.cpp +++ b/connections/canconfactory.cpp @@ -6,6 +6,7 @@ #include "socketcand.h" #include "lawicel_serial.h" #include "canserver.h" +#include "canlogserver.h" using namespace CANCon; @@ -29,6 +30,8 @@ CANConnection* CanConFactory::create(type pType, QString pPortName, QString pDri return new MQTT_BUS(pPortName); case CANSERVER: return new CANserver(pPortName); + case CANLOGSERVER: + return new CanLogServer(pPortName); default: {} } diff --git a/connections/canconnectionmodel.cpp b/connections/canconnectionmodel.cpp index b3a5e095..c014f558 100644 --- a/connections/canconnectionmodel.cpp +++ b/connections/canconnectionmodel.cpp @@ -88,6 +88,7 @@ QVariant CANConnectionModel::data(const QModelIndex &index, int role) const case CANCon::KAYAK: return "socketcand"; case CANCon::LAWICEL: return "LAWICEL"; case CANCon::CANSERVER: return "CANserver"; + case CANCon::CANLOGSERVER: return "CanLogServer"; default: {} } else qDebug() << "Tried to show connection type but connection was nullptr"; diff --git a/connections/canlogserver.cpp b/connections/canlogserver.cpp new file mode 100644 index 00000000..8ddc5b0c --- /dev/null +++ b/connections/canlogserver.cpp @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include + +#include "utility.h" +#include "canlogserver.h" + +CanLogServer::CanLogServer(QString serverAddressString) : + CANConnection(serverAddressString, "CanLogserver", CANCon::CANLOGSERVER, 0, 0, 1, 4000, true), + m_ptcpSocket(new QTcpSocket(this)) +{ + + qDebug() << "Canlogserver: " << "Constructing new Connection..."; + + CANBus bus_info; + bus_info.setActive(true); + bus_info.setListenOnly(true); + bus_info.setSpeed(500000); + + setBusConfig(0, bus_info); + + // Connect data ready signal + connect(m_ptcpSocket, SIGNAL(readyRead()), this, SLOT(readNetworkData())); + // Connect network connected signal + connect(m_ptcpSocket, SIGNAL(connected()),this, SLOT(networkConnected())); + // Connect network disconnected signal + connect(m_ptcpSocket, SIGNAL(disconnected()),this, SLOT(networkDisconnected())); + // Save address + this->m_qsAddress = serverAddressString; +} + + +CanLogServer::~CanLogServer() +{ + qDebug() << "Canlogserver: " << "Deconstructing Connection..."; + + stop(); + + m_ptcpSocket->close(); + delete m_ptcpSocket; + m_ptcpSocket = NULL; +} + +void CanLogServer::readNetworkData() +{ + // If capture is suspended bail out after reading the bytes from the network. No need to parse them + if(isCapSuspended()) + return; + + while (m_ptcpSocket->canReadLine()) { + // Get a complete line and remove whitespace at the start and at the end of the string + QString data = QString(m_ptcpSocket->readLine()).trimmed(); + // Split to space (obtain "<(time)> ") + QStringList lstData = data.split(" "); + // Expect 3 item in list + if(lstData.size() == 3){ + // Obtain the timestamp. Remove '(', ')' and '.' (logserver send as "(time.fraction)"). + QString qstrTs = lstData[0].remove(QChar('(')).remove(QChar('.')).remove(QChar(')')); + // One bus only. TODO: Use another parameter in connection conf for spcify can bus id to capture. + QString qstrCanId = "0"; + // Split frame + QStringList lstMsg = lstData[2].split("#"); + // Expect 2 item (#) + if(lstMsg.size() == 2){ + // Extract id + QString qstrId = lstMsg[0]; + // Extract payload + QString qstrPayload = lstMsg[1]; + // Support only normal can message. Extended CAN not supported. + if(qstrId.size() <= 4){ + // Prepare the frame + CANFrame* frame_p = getQueue().get(); + // Check for frame existence + if(frame_p){ + // Set frame ID + frame_p->setFrameId(qstrId.toInt(nullptr, 16)); + // Extended frame NOT SUPPORTED + frame_p->setExtendedFrameFormat(0); + // Set bus id + frame_p->bus = qstrCanId.toInt(); + // Set frame type + frame_p->setFrameType(QCanBusFrame::DataFrame); + // Frame is recived + frame_p->isReceived = true; + // Set timestamp + frame_p->setTimeStamp(QCanBusFrame::TimeStamp(0, qstrTs.toULongLong())); + // Set payload + frame_p->setPayload(QByteArray::fromHex(qstrPayload.toUtf8())); + // Elaborate frame + checkTargettedFrame(*frame_p); + /* enqueue frame */ + getQueue().queue(); + } + qDebug() << data << "---" << qstrTs << " - " << qstrId << " + " << qstrPayload; + } + } + } + } +} + +void CanLogServer::networkConnected() +{ + CANConStatus stats; + qDebug() << "networkConnected"; + + setStatus(CANCon::CONNECTED); + stats.conStatus = getStatus(); + stats.numHardwareBuses = 1; + emit status(stats); +} + +void CanLogServer::networkDisconnected() +{ + qDebug() << "networkDisconnected"; +} + +void CanLogServer::piStarted() +{ + this->connectToDevice(); +} + +void CanLogServer::piSuspend(bool pSuspend) +{ + /* update capSuspended */ + setCapSuspended(pSuspend); + + /* flush queue if we are suspended */ + if(isCapSuspended()) + getQueue().flush(); +} + + +void CanLogServer::piStop() +{ + this->disconnectFromDevice(); +} + + +bool CanLogServer::piGetBusSettings(int pBusIdx, CANBus& pBus) +{ + return getBusConfig(pBusIdx, pBus); +} + + +void CanLogServer::piSetBusSettings(int pBusIdx, CANBus bus) +{ + /* sanity checks */ + if( (pBusIdx < 0) || pBusIdx >= getNumBuses()) + return; + + /* copy bus config */ + setBusConfig(pBusIdx, bus); +} + + +bool CanLogServer::piSendFrame(const CANFrame& ) +{ + //We don't support sending frames right now + return true; +} + +void CanLogServer::connectToDevice() +{ + qDebug() << "Canlogserver: " << "Establishing connection to a Canlogserver device..."; + + QUrl url("http://" + m_qsAddress); + qDebug() << "address:" << m_qsAddress; + qDebug() << "Host:" << url.host(); + qDebug() << "Port:" << url.port(); + // Set status at not connected + setStatus(CANCon::NOT_CONNECTED); + // No proxy for connection + m_ptcpSocket->setProxy(QNetworkProxy::NoProxy); + // Connect to log server + m_ptcpSocket->connectToHost(url.host(), url.port()); +} + +void CanLogServer::disconnectFromDevice() +{ + qDebug() << "Canlogserver: " << "Disconnecting..."; + // Close socket + m_ptcpSocket->close(); +} diff --git a/connections/canlogserver.h b/connections/canlogserver.h new file mode 100644 index 00000000..ee7cab54 --- /dev/null +++ b/connections/canlogserver.h @@ -0,0 +1,57 @@ +#ifndef CANLOGSERVER_H +#define CANLOGSERVER_H + +#include + +#include +#include +#include +#include + +/*************/ +#include +/*************/ + +#include "canframemodel.h" +#include "canconnection.h" +#include "canconmanager.h" + +class CanLogServer : public CANConnection +{ + Q_OBJECT + +public: + CanLogServer(QString serverAddress); + virtual ~CanLogServer(); + +// Interface +protected: + virtual void piStarted(); + virtual void piStop(); + virtual void piSetBusSettings(int pBusIdx, CANBus pBus); + virtual bool piGetBusSettings(int pBusIdx, CANBus& pBus); + virtual void piSuspend(bool pSuspend); + virtual bool piSendFrame(const CANFrame&); + +private slots: + void readNetworkData(); + void networkConnected(); + void networkDisconnected(); + +// Utility +private: + void readSettings(); + void connectToDevice(); + void disconnectFromDevice(); + void heartbeat(); + +// Attributes +protected: + QTcpSocket *m_ptcpSocket = nullptr; + QString m_qsAddress; + +// QUdpSocket *_udpClient; + +// QTimer *_heartbeatTimer; +}; +#endif // CANLOGSERVER_H diff --git a/connections/newconnectiondialog.cpp b/connections/newconnectiondialog.cpp index 95338481..a1a1916e 100644 --- a/connections/newconnectiondialog.cpp +++ b/connections/newconnectiondialog.cpp @@ -29,6 +29,7 @@ NewConnectionDialog::NewConnectionDialog(QVector* gvretips, QVectorrbMQTT, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->rbLawicel, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->rbCANserver, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); + connect(ui->rbCanlogserver, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->cbDeviceType, QOverload::of(&QComboBox::currentIndexChanged), this, &NewConnectionDialog::handleDeviceTypeChanged); connect(ui->btnOK, &QPushButton::clicked, this, &NewConnectionDialog::handleCreateButton); @@ -64,6 +65,7 @@ void NewConnectionDialog::handleConnTypeChanged() if (ui->rbKayak->isChecked()) selectKayak(); if (ui->rbMQTT->isChecked()) selectMQTT(); if (ui->rbCANserver->isChecked()) selectCANserver(); + if (ui->rbCanlogserver->isChecked()) selectCANlogserver(); } void NewConnectionDialog::handleDeviceTypeChanged() @@ -218,6 +220,20 @@ void NewConnectionDialog::selectCANserver() ui->cbPort->clear(); } +void NewConnectionDialog::selectCANlogserver() +{ + ui->lPort->setText("CANlogserver IP Address:"); + + ui->lblDeviceType->setHidden(true); + ui->cbDeviceType->setHidden(true); + ui->cbCANSpeed->setHidden(true); + ui->cbSerialSpeed->setHidden(true); + ui->lblCANSpeed->setHidden(true); + ui->lblSerialSpeed->setHidden(true); + + ui->cbPort->clear(); +} + void NewConnectionDialog::setPortName(CANCon::type pType, QString pPortName, QString pDriver) { @@ -244,6 +260,9 @@ void NewConnectionDialog::setPortName(CANCon::type pType, QString pPortName, QSt case CANCon::CANSERVER: ui->rbCANserver->setChecked(true); break; + case CANCon::CANLOGSERVER: + ui->rbCanlogserver->setChecked(true); + break; default: {} } @@ -288,6 +307,7 @@ void NewConnectionDialog::setPortName(CANCon::type pType, QString pPortName, QSt ui->cbPort->setCurrentText(pPortName); break; case CANCon::CANSERVER: + case CANCon::CANLOGSERVER: { ui->cbPort->setCurrentText(pPortName); break; @@ -308,6 +328,7 @@ QString NewConnectionDialog::getPortName() case CANCon::KAYAK: return ui->cbPort->currentText(); case CANCon::CANSERVER: + case CANCon::CANLOGSERVER: return ui->cbPort->currentText(); default: @@ -353,6 +374,7 @@ CANCon::type NewConnectionDialog::getConnectionType() if (ui->rbMQTT->isChecked()) return CANCon::MQTT; if (ui->rbLawicel->isChecked()) return CANCon::LAWICEL; if (ui->rbCANserver->isChecked()) return CANCon::CANSERVER; + if (ui->rbCanlogserver->isChecked()) return CANCon::CANLOGSERVER; qDebug() << "getConnectionType: error"; return CANCon::NONE; diff --git a/connections/newconnectiondialog.h b/connections/newconnectiondialog.h index 9901b834..95dd2b8a 100644 --- a/connections/newconnectiondialog.h +++ b/connections/newconnectiondialog.h @@ -47,6 +47,7 @@ public slots: void selectMQTT(); void selectLawicel(); void selectCANserver(); + void selectCANlogserver(); bool isSerialBusAvailable(); void setPortName(CANCon::type pType, QString pPortName, QString pDriver); }; diff --git a/ui/newconnectiondialog.ui b/ui/newconnectiondialog.ui index 990467e9..46d9123c 100644 --- a/ui/newconnectiondialog.ui +++ b/ui/newconnectiondialog.ui @@ -78,6 +78,13 @@ + + + + CANlogserver + + +