From c49783a55b9ee8300da86b6cb8c2d26b74b735e3 Mon Sep 17 00:00:00 2001 From: Bertrand Date: Tue, 23 Feb 2021 09:38:19 +0100 Subject: [PATCH 1/2] adding socketcand support --- SavvyCAN.pro | 4 +- connections/canconconst.h | 1 + connections/canconfactory.cpp | 3 + connections/canconmanager.cpp | 2 + connections/canconnectionmodel.cpp | 1 + connections/connectionwindow.cpp | 67 ++++- connections/connectionwindow.h | 6 +- connections/newconnectiondialog.cpp | 38 ++- connections/newconnectiondialog.h | 6 +- connections/socketcand.cpp | 393 ++++++++++++++++++++++++++++ connections/socketcand.h | 82 ++++++ ui/newconnectiondialog.ui | 23 +- 12 files changed, 599 insertions(+), 27 deletions(-) create mode 100644 connections/socketcand.cpp create mode 100644 connections/socketcand.h diff --git a/SavvyCAN.pro b/SavvyCAN.pro index abe5b55..c559faf 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -51,6 +51,7 @@ SOURCES += main.cpp\ connections/serialbusconnection.cpp \ connections/canconfactory.cpp \ connections/gvretserial.cpp \ + connections/socketcand.cpp \ connections/canconmanager.cpp \ re/sniffer/snifferitem.cpp \ re/sniffer/sniffermodel.cpp \ @@ -91,7 +92,8 @@ SOURCES += main.cpp\ HEADERS += mainwindow.h \ can_structs.h \ - canframemodel.h \ \ + canframemodel.h \ + connections/socketcand.h \ connections/mqtt_bus.h \ mqtt/qmqtt.h \ mqtt/qmqtt_client.h \ diff --git a/connections/canconconst.h b/connections/canconconst.h index 71dc3fd..7f479c1 100644 --- a/connections/canconconst.h +++ b/connections/canconconst.h @@ -18,6 +18,7 @@ namespace CANCon { KVASER, SERIALBUS, REMOTE, + KAYAK, MQTT, NONE }; diff --git a/connections/canconfactory.cpp b/connections/canconfactory.cpp index 345b0ef..1fc461c 100644 --- a/connections/canconfactory.cpp +++ b/connections/canconfactory.cpp @@ -3,6 +3,7 @@ #include "serialbusconnection.h" #include "gvretserial.h" #include "mqtt_bus.h" +#include "socketcand.h" using namespace CANCon; @@ -15,6 +16,8 @@ CANConnection* CanConFactory::create(type pType, QString pPortName, QString pDri return new GVRetSerial(pPortName, false); case REMOTE: return new GVRetSerial(pPortName, true); //it's a special case of GVRET connected over TCP/IP so it uses the same class + case KAYAK: + return new SocketCANd(pPortName); case MQTT: return new MQTT_BUS(pPortName); default: {} diff --git a/connections/canconmanager.cpp b/connections/canconmanager.cpp index a1e0cab..fe97759 100644 --- a/connections/canconmanager.cpp +++ b/connections/canconmanager.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "canconmanager.h" #include "canconfactory.h" @@ -228,6 +229,7 @@ bool CANConManager::sendFrame(const CANFrame& pFrame) //workingFrame.timestamp -= mTimestampBasis; } txFrame = conn->getQueue().get(); + QCoreApplication::processEvents(); *txFrame = workingFrame; conn->getQueue().queue(); return conn->sendFrame(workingFrame); diff --git a/connections/canconnectionmodel.cpp b/connections/canconnectionmodel.cpp index 35a0c1e..aba9c7c 100644 --- a/connections/canconnectionmodel.cpp +++ b/connections/canconnectionmodel.cpp @@ -85,6 +85,7 @@ QVariant CANConnectionModel::data(const QModelIndex &index, int role) const case CANCon::KVASER: return "KVASER"; case CANCon::SERIALBUS: return "SerialBus"; case CANCon::GVRET_SERIAL: return "GVRET"; + case CANCon::KAYAK: return "socketcand"; default: {} } else qDebug() << "Tried to show connection type but connection was nullptr"; diff --git a/connections/connectionwindow.cpp b/connections/connectionwindow.cpp index a3b4cb4..e6f7dae 100644 --- a/connections/connectionwindow.cpp +++ b/connections/connectionwindow.cpp @@ -69,12 +69,17 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) : ui->cbBusSpeed->addItem("500000"); ui->cbBusSpeed->addItem("1000000"); - rxBroadcast = new QUdpSocket(this); + rxBroadcastGVRET = new QUdpSocket(this); //Need to make sure it tries to share the address in case there are //multiple instances of SavvyCAN running. - rxBroadcast->bind(QHostAddress::Any, 17222, QAbstractSocket::ShareAddress); + rxBroadcastGVRET->bind(QHostAddress::AnyIPv4, 17222, QAbstractSocket::ShareAddress); - connect(rxBroadcast, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); + connect(rxBroadcastGVRET, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); + + //Doing the same for socketcand/kayak hosts: + rxBroadcastKayak = new QUdpSocket(this); + rxBroadcastKayak->bind(QHostAddress::AnyIPv4, 42000, QAbstractSocket::ShareAddress); + connect(rxBroadcastKayak, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); } @@ -82,12 +87,56 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) : void ConnectionWindow::readPendingDatagrams() { //qDebug() << "Got a UDP frame!"; - while (rxBroadcast->hasPendingDatagrams()) { - QNetworkDatagram datagram = rxBroadcast->receiveDatagram(); - if (!remoteDeviceIP.contains(datagram.senderAddress().toString())) + while (rxBroadcastGVRET->hasPendingDatagrams()) { + QNetworkDatagram datagram = rxBroadcastGVRET->receiveDatagram(); + if (!remoteDeviceIPGVRET.contains(datagram.senderAddress().toString())) { - remoteDeviceIP.append(datagram.senderAddress().toString()); - qDebug() << "Add new remote IP " << datagram.senderAddress().toString(); + remoteDeviceIPGVRET.append(datagram.senderAddress().toString()); + //qDebug() << "Add new remote IP " << datagram.senderAddress().toString(); + } + } + while (rxBroadcastKayak->hasPendingDatagrams()) { + QNetworkDatagram datagram = rxBroadcastKayak->receiveDatagram(); + //qDebug() << "Broadcast Datagram: " << QString::fromUtf8(datagram.data()); + QXmlStreamReader CANBeaconXml(QString::fromUtf8(datagram.data())); + QString KayakHost; + QString KayakBus; + while(!CANBeaconXml.atEnd() && !CANBeaconXml.hasError()) + { + CANBeaconXml.readNext(); + if(CANBeaconXml.name() == "CANBeacon" && !CANBeaconXml.isEndElement()) + KayakHost.append(CANBeaconXml.attributes().value("name")); + + if(CANBeaconXml.name() == "URL") + KayakHost.append(" (" + CANBeaconXml.readElementText() + ')'); + + //Kayak can theoretically send multiple busses over one ports + //TODO: implement this case in socketcand.cpp + if(CANBeaconXml.name() == "Bus" && !CANBeaconXml.isEndElement()) + KayakBus.append(CANBeaconXml.attributes().value("name") + ","); + + } + KayakHost = KayakBus.left(KayakBus.length() - 1) + "@" + KayakHost; + + QVector connectedPorts; + if (connModel->rowCount() > 0) + { + for (int i = 0; i < connModel->rowCount(); i++) + { + CANConnection *var_conn = connModel->getAtIdx(i); + connectedPorts.append(var_conn->getPort()); + } + } + + if (connectedPorts.contains(KayakHost)) + { + remoteDeviceKayak.removeOne(KayakHost); + } + + if (!remoteDeviceKayak.contains(KayakHost) && !connectedPorts.contains(KayakHost)) + { + remoteDeviceKayak.append(KayakHost); + //qDebug() << "Add new remote IP " << datagram.senderAddress().toString(); } } } @@ -193,7 +242,7 @@ void ConnectionWindow::consoleEnableChanged(bool checked) { void ConnectionWindow::handleNewConn() { - NewConnectionDialog *thisDialog = new NewConnectionDialog(&remoteDeviceIP); + NewConnectionDialog *thisDialog = new NewConnectionDialog(&remoteDeviceIPGVRET, &remoteDeviceKayak); CANCon::type newType; QString newPort; QString newDriver; diff --git a/connections/connectionwindow.h b/connections/connectionwindow.h index dc081b3..b13f31f 100644 --- a/connections/connectionwindow.h +++ b/connections/connectionwindow.h @@ -60,8 +60,10 @@ private: Ui::ConnectionWindow *ui; QSettings *settings; CANConnectionModel *connModel; - QUdpSocket *rxBroadcast; - QVector remoteDeviceIP; + QUdpSocket *rxBroadcastGVRET; + QUdpSocket *rxBroadcastKayak; + QVector remoteDeviceIPGVRET; + QVector remoteDeviceKayak; CANConnection* create(CANCon::type pTye, QString pPortName, QString pDriver); void populateBusDetails(int offset); diff --git a/connections/newconnectiondialog.cpp b/connections/newconnectiondialog.cpp index 25fa899..db4a721 100644 --- a/connections/newconnectiondialog.cpp +++ b/connections/newconnectiondialog.cpp @@ -2,13 +2,13 @@ #include "newconnectiondialog.h" #include "ui_newconnectiondialog.h" -NewConnectionDialog::NewConnectionDialog(QVector* ips, QWidget *parent) : +NewConnectionDialog::NewConnectionDialog(QVector* gvretips, QVector* kayakhosts, QWidget *parent) : QDialog(parent), ui(new Ui::NewConnectionDialog), - remoteDeviceIP(ips) + remoteDeviceIPGVRET(gvretips), + remoteBusKayak(kayakhosts) { ui->setupUi(this); - if (isSerialBusAvailable()) { ui->rbSocketCAN->setEnabled(true); @@ -25,6 +25,7 @@ NewConnectionDialog::NewConnectionDialog(QVector* ips, QWidget *parent) connect(ui->rbGVRET, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->rbRemote, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); + connect(ui->rbKayak, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->rbMQTT, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged); connect(ui->cbDeviceType, QOverload::of(&QComboBox::currentIndexChanged), this, &NewConnectionDialog::handleDeviceTypeChanged); @@ -34,7 +35,8 @@ NewConnectionDialog::NewConnectionDialog(QVector* ips, QWidget *parent) ui->cbDeviceType->setHidden(true); selectSerial(); - qDebug() << "Was passed " << remoteDeviceIP->count() << " remote IPs"; + qDebug() << "Was passed " << remoteDeviceIPGVRET->count() << " remote GVRET IPs"; + qDebug() << "Was passed " << remoteBusKayak->count() << " remote Kayak Busses"; } NewConnectionDialog::~NewConnectionDialog() @@ -52,6 +54,7 @@ void NewConnectionDialog::handleConnTypeChanged() if (ui->rbGVRET->isChecked()) selectSerial(); if (ui->rbSocketCAN->isChecked()) selectSocketCan(); if (ui->rbRemote->isChecked()) selectRemote(); + if (ui->rbKayak->isChecked()) selectKayak(); if (ui->rbMQTT->isChecked()) selectMQTT(); } @@ -99,7 +102,19 @@ void NewConnectionDialog::selectRemote() ui->lblDeviceType->setHidden(true); ui->cbDeviceType->setHidden(true); ui->cbPort->clear(); - foreach(QString pName, *remoteDeviceIP) + foreach(QString pName, *remoteDeviceIPGVRET) + { + ui->cbPort->addItem(pName); + } +} + +void NewConnectionDialog::selectKayak() +{ + ui->lPort->setText("Available Bus(ses):"); + ui->lblDeviceType->setHidden(true); + ui->cbDeviceType->setHidden(true); + ui->cbPort->clear(); + foreach(QString pName, *remoteBusKayak) { ui->cbPort->addItem(pName); } @@ -127,6 +142,9 @@ void NewConnectionDialog::setPortName(CANCon::type pType, QString pPortName, QSt case CANCon::REMOTE: ui->rbRemote->setChecked(true); break; + case CANCon::KAYAK: + ui->rbKayak->setChecked(true); + break; case CANCon::MQTT: ui->rbMQTT->setChecked(true); break; @@ -162,6 +180,13 @@ void NewConnectionDialog::setPortName(CANCon::type pType, QString pPortName, QSt else ui->cbPort->addItem(pPortName); break; } + case CANCon::KAYAK: + { + int idx = ui->cbPort->findText(pPortName); + if (idx > -1) ui->cbPort->setCurrentIndex(idx); + else ui->cbPort->addItem(pPortName); + break; + } case CANCon::MQTT: ui->cbPort->setCurrentText(pPortName); break; @@ -177,6 +202,8 @@ QString NewConnectionDialog::getPortName() case CANCon::REMOTE: case CANCon::MQTT: return ui->cbPort->currentText(); + case CANCon::KAYAK: + return ui->cbPort->currentText(); default: qDebug() << "getPortName: can't get port"; } @@ -198,6 +225,7 @@ CANCon::type NewConnectionDialog::getConnectionType() if (ui->rbGVRET->isChecked()) return CANCon::GVRET_SERIAL; if (ui->rbSocketCAN->isChecked()) return CANCon::SERIALBUS; if (ui->rbRemote->isChecked()) return CANCon::REMOTE; + if (ui->rbKayak->isChecked()) return CANCon::KAYAK; if (ui->rbMQTT->isChecked()) return CANCon::MQTT; qDebug() << "getConnectionType: error"; diff --git a/connections/newconnectiondialog.h b/connections/newconnectiondialog.h index 52b43e5..1410b42 100644 --- a/connections/newconnectiondialog.h +++ b/connections/newconnectiondialog.h @@ -18,7 +18,7 @@ class NewConnectionDialog : public QDialog Q_OBJECT public: - explicit NewConnectionDialog(QVector* ips, QWidget *parent = nullptr); + explicit NewConnectionDialog(QVector* gvretips, QVector* kayakips, QWidget *parent = nullptr); ~NewConnectionDialog(); CANCon::type getConnectionType(); @@ -34,12 +34,14 @@ private: Ui::NewConnectionDialog *ui; QList ports; QList canDevices; - QVector* remoteDeviceIP; + QVector* remoteDeviceIPGVRET; + QVector* remoteBusKayak; void selectSerial(); void selectKvaser(); void selectSocketCan(); void selectRemote(); + void selectKayak(); void selectMQTT(); bool isSerialBusAvailable(); void setPortName(CANCon::type pType, QString pPortName, QString pDriver); diff --git a/connections/socketcand.cpp b/connections/socketcand.cpp new file mode 100644 index 0000000..9bbddbb --- /dev/null +++ b/connections/socketcand.cpp @@ -0,0 +1,393 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socketcand.h" + +SocketCANd::SocketCANd(QString portName) : + CANConnection(portName, "kayak", CANCon::KAYAK, 1, 4000, true), + mTimer(this) /*NB: set this as parent of timer to manage it from working thread */ +{ + + mTimer.setInterval(10000); //tick every 10 seconds + mTimer.setSingleShot(false); //keep ticking + connect(&mTimer, SIGNAL(timeout()), this, SLOT(checkConnection())); + + sendDebug("SocketCANd()"); + //tcpClient = nullptr; + hostCanIDs = portName.left(portName.indexOf("@")).split(','); + QString hostIPandPort = portName.mid(portName.indexOf("can://")+6, portName.length() - portName.indexOf("can://") - 7); //7 is lenght of 'can://' and ')' + hostIP = QHostAddress(hostIPandPort.left(hostIPandPort.indexOf(":"))); + hostPort = (hostIPandPort.right(hostIPandPort.length() - hostIPandPort.lastIndexOf(":") -1)).toInt(); + QVarLengthArray tcpClient(0); + mNumBuses = hostCanIDs.length(); + mBusData.resize(mNumBuses); + reconnecting = false; + + for (int i = 0; i < mNumBuses; i++) + { + rx_state.append(IDLE); + } + +} + + +SocketCANd::~SocketCANd() +{ + stop(); + sendDebug("~SocketCANd()"); +} + +void SocketCANd::sendDebug(const QString debugText) +{ + qDebug() << debugText; + debugOutput(debugText); +} + +void SocketCANd::sendBytesToTCP(const QByteArray &bytes, int busNum) +{ + if (tcpClient[busNum] && !tcpClient[busNum]->isOpen()) + { + sendDebug("Attempt to write to TCP/IP port when it is not open!"); + return; + } + + QString buildDebug; + buildDebug = "Send data to " + hostIP.toString() + ":" + QString::number(hostPort) + " -> "; + foreach (int byt, bytes) { + byt = (unsigned char)byt; + buildDebug = buildDebug % QString::number(byt, 16) % " "; + } + sendDebug(buildDebug); + + if (tcpClient[busNum]) tcpClient[busNum]->write(bytes); +} + +void SocketCANd::sendStringToTCP(const char* data, int busNum) +{ + if (tcpClient[busNum] && !tcpClient[busNum]->isOpen()) + { + sendDebug("Attempt to write to TCP/IP port when it is not open!"); + return; + } + + QString buildDebug; + buildDebug = "Send data to " + hostIP.toString() + ":" + QString::number(hostPort) + " -> " + data; + sendDebug(buildDebug); + //qInfo() << buildDebug; + + if (tcpClient[busNum]) tcpClient[busNum]->write(data); +} + +void SocketCANd::piStarted() +{ + connectDevice(); +} + + +void SocketCANd::piSuspend(bool pSuspend) +{ + /* update capSuspended */ + setCapSuspended(pSuspend); + + /* flush queue if we are suspended */ + if(isCapSuspended()) + getQueue().flush(); +} + + +void SocketCANd::piStop() +{ + mTimer.stop(); + disconnectDevice(); +} + + +bool SocketCANd::piGetBusSettings(int pBusIdx, CANBus& pBus) +{ + return getBusConfig(pBusIdx, pBus); +} + + +void SocketCANd::piSetBusSettings(int pBusIdx, CANBus bus) +{ + setBusConfig(pBusIdx, bus); + bus.setSpeed(250000); +} + + +bool SocketCANd::piSendFrame(const CANFrame& frame) +{ + QByteArray buffer; + int c; + int ID; + +// //calculate bus number offset (in case of multiple connections) +// //useless since SavvyCAN already delivers the right index in frame.bus +// QList connList = CANConManager::getInstance()->getConnections(); +// int currentConnPos = connList.indexOf(this); +// int busOffset = 0; +// for (int i = 0; i < currentConnPos; i++) +// { +// busOffset += connList[i]->getNumBuses(); +// } +// int busNum = frame.bus - busOffset; + + int busNum = frame.bus; + + framesRapid++; + + if (tcpClient[busNum] && !tcpClient[busNum]->isOpen()) return false; + //if (!isConnected) return false; + + // Doesn't make sense to send an error frame + // to an adapter + if (frame.frameId() & 0x20000000) { + return true; + } + ID = frame.frameId(); + if (frame.hasExtendedFrameFormat()) ID |= 1 << 31; + + QString sendStr = "< send " + QString::number(ID, 16) + " " + QString::number(frame.payload().length()) + " "; + for (c = 0; c < frame.payload().length(); c++) + { + sendStr.append(QString::number(frame.payload()[c], 16) + " "); + } + sendStr.append(">"); + std::string str = sendStr.toStdString(); + const char* sendCmd = str.c_str(); + sendStringToTCP(sendCmd, busNum); + + return true; +} + + + +/****************************************************************/ + +void SocketCANd::connectDevice() +{ + QSettings settings; + + /* disconnect device */ + /* avoiding this solution since it removes connection selection in case of connection check */ + //if(tcpClient) + // disconnectDevice(); + + // only resetting tcpClient + for (int i = 0; i < tcpClient.length(); i++) + { + if (tcpClient[i]) + { + if (tcpClient[i]->isOpen()) + { + tcpClient[i]->close(); + } + tcpClient[i]->disconnect(); + delete tcpClient[i]; + tcpClient[i] = nullptr; + } + } + tcpClient.clear(); + + mTimer.start(); + + //sendDebug("TCP Connection to a Kayak device"); + for (int i = 0; i < mNumBuses; i++) + { + rx_state[i] = IDLE; + tcpClient.append(new QTcpSocket()); + tcpClient[i]->connectToHost(hostIP, hostPort); + //connect(tcpClient[i], SIGNAL(readyRead()), this, SLOT(readTCPData())); + connect(tcpClient[i], SIGNAL(readyRead()), this, SLOT(invokeReadTCPData())); + sendDebug("Created TCP Socket to Kayak device " + hostCanIDs.at(i)); + } + setStatus(CANCon::CONNECTED); + CANConStatus stats; + stats.conStatus = getStatus(); + stats.numHardwareBuses = mNumBuses; + //signalSender = qobject_cast(QObject::sender()); + if (!reconnecting) emit status(stats); +} + +void SocketCANd::deviceConnected(int busNum) +{ + sendDebug("Opening CAN on Kayak Device!"); + const char* openCanCmd = ("< open " + hostCanIDs[busNum] + " >").toStdString().c_str(); + sendStringToTCP(openCanCmd, busNum); + + QCoreApplication::processEvents(); +} + +void SocketCANd::checkConnection() +{ + int bufSize = 0; + for (int i = 0; i < tcpClient.length(); i++) + { + bufSize += tcpClient[i]->readBufferSize(); + //sendDebug("Buffer size: " + QString::number(bufSize)); + } + + if (bufSize == 0) + { + reconnecting = true; + connectDevice(); + sendDebug("Reconnecting to TCP Host " + hostIP.toString()); + } +} + +void SocketCANd::switchToRawMode(int busNum) +{ + sendDebug("Switching to rawmode..."); + const char* rawmodeCmd = "< rawmode >"; + sendStringToTCP(rawmodeCmd, busNum); + QCoreApplication::processEvents(); +} + +void SocketCANd::decodeFrames(QString data, int busNum) +{ + if (data.indexOf("< frame ") == -1) + { + qDebug() << "Received datagramm doesn't contain any frame: " << data; + return; + } + else + { + QString framePart = data.mid(data.indexOf("< frame "), data.length()); //remove starting beginning of payload if not < frame > + const QString frameStrConst = framePart.left(framePart.indexOf(">")+1); + QString frameStr = frameStrConst; + QStringList frameParsed = (frameStr.remove(QRegExp("^<")).remove(QRegExp(">$"))).simplified().split(' '); + + buildFrame.setFrameId(frameParsed[1].toUInt(nullptr, 16)); + buildFrame.bus = busNum; + + if (buildFrame.frameId() > 0x7FF) buildFrame.setExtendedFrameFormat(true); + else buildFrame.setExtendedFrameFormat(false); + + buildFrame.setTimeStamp(QCanBusFrame::TimeStamp(0, frameParsed[2].toDouble() * 1000000l)); + //buildFrame.len = frameParsed[3].length() * 0.5; + int framelength = frameParsed[3].length() * 0.5; + + buildData.resize(framelength); + + int c; + for (c = 0; c < framelength; c++) + { + bool ok; + unsigned char byteVal = frameParsed[3].mid(c*2, 2).toUInt(&ok, 16); + buildData[c] = byteVal; + } + buildFrame.setPayload(buildData); +// buildFrame.isReceived = true; + + if (!isCapSuspended()) + { + /* get frame from queue */ + CANFrame* frame_p = getQueue().get(); + if(frame_p) { + /* copy frame */ + *frame_p = buildFrame; + //frame_p->remote = false; + frame_p->setFrameType(QCanBusFrame::DataFrame); + checkTargettedFrame(buildFrame); + /* enqueue frame */ + getQueue().queue(); + } + } + else + qDebug() << "can't get a frame, capture suspended"; + + if (framePart.length() > frameStrConst.length()) + decodeFrames(framePart.right(framePart.length() - frameStrConst.length()), busNum); + } +} + +void SocketCANd::disconnectDevice() { + for (int i = 0; i < tcpClient.length(); i++) + { + if (tcpClient[i]) + { + if (tcpClient[i]->isOpen()) + { + tcpClient[i]->close(); + } + tcpClient[i]->disconnect(); + delete tcpClient[i]; + tcpClient[i] = nullptr; + } + } + tcpClient.clear(); + + setStatus(CANCon::NOT_CONNECTED); + CANConStatus stats; + stats.conStatus = getStatus(); + stats.numHardwareBuses = mNumBuses; + emit status(stats); +} + +void SocketCANd::invokeReadTCPData() +{ + QTcpSocket* signalSender = qobject_cast(QObject::sender()); + int busNum = tcpClient.indexOf(signalSender); + QMetaObject::invokeMethod(this, "readTCPData", Qt::QueuedConnection, Q_ARG(int, busNum)); +} + +void SocketCANd::readTCPData(int busNum) +{ + QByteArray data; + + if (tcpClient[busNum]) data = tcpClient[busNum]->readAll(); + //sendDebug("Got data from TCP. Len = " % QString::number(data.length())); + //qDebug() << "Received datagramm: " << data; + procRXData(data, busNum); +} + + +void SocketCANd::procRXData(QString data, int busNum) +{ + if (data != "") + { + mTimer.stop(); + mTimer.start(); + } + QByteArray output; + + switch (rx_state.at(busNum)) + { + case IDLE: + qDebug() << "Received datagramm: " << data; + if (data == "< hi >") + { + deviceConnected(busNum); + rx_state[busNum] = BCM; + } + else qInfo() << hostCanIDs[busNum] << ": Could not open bus. Host did not greet with ""< hi >"": " << data; + break; + case BCM: + qDebug() << "Received datagramm: " << data; + if (data == "< ok >") + { + switchToRawMode(busNum); + rx_state[busNum] = SWITCHING2RAW; + } + else qInfo() << hostCanIDs[busNum] << ": Could not open bus. Host did not respond with ""< ok >"": " << data; + break; + case SWITCHING2RAW: + qDebug() << "Received datagramm: " << data; + if (data == "< ok >") + { + rx_state[busNum] = RAWMODE; + } + break; + case RAWMODE: + decodeFrames(data, busNum); + break; + case ISOTP: + break; + } +} diff --git a/connections/socketcand.h b/connections/socketcand.h new file mode 100644 index 0000000..b5c9376 --- /dev/null +++ b/connections/socketcand.h @@ -0,0 +1,82 @@ +#ifndef SOCKETCAND_H +#define SOCKETCAND_H + +//#include +//#include +#include +#include +#include +//#include + +/*************/ +#include +/*************/ + +#include "canframemodel.h" +#include "canconnection.h" +#include "canconmanager.h" + + +namespace KAYAKSTATE { + +enum MODE +{ + IDLE, //NO_BUS in socketcand doc + BCM, + SWITCHING2RAW, + RAWMODE, + ISOTP +}; + +} + +using namespace KAYAKSTATE; +class SocketCANd : public CANConnection +{ + Q_OBJECT + +public: + SocketCANd(QString portName); + virtual ~SocketCANd(); + +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&); + + void disconnectDevice(); + +private slots: + void connectDevice(); + void checkConnection(); + void readTCPData(int busNum); + void invokeReadTCPData(); + void deviceConnected(int busNum); + void switchToRawMode(int busNum); + void decodeFrames(QString, int busNum); + +private: + void procRXData(QString, int busNum); + void sendBytesToTCP(const QByteArray &bytes, int busNum); + void sendStringToTCP(const char* data, int busNum); + void sendDebug(const QString debugText); + +protected: + QTimer mTimer; + bool reconnecting; + QVarLengthArray tcpClient; + QHostAddress hostIP; + int hostPort; + QList hostCanIDs; + int framesRapid; + QByteArray buildData; + QVarLengthArray rx_state; + CANFrame buildFrame; +}; + + +#endif // SOCKETCAND_H diff --git a/ui/newconnectiondialog.ui b/ui/newconnectiondialog.ui index 26eeb74..faa847a 100644 --- a/ui/newconnectiondialog.ui +++ b/ui/newconnectiondialog.ui @@ -6,8 +6,8 @@ 0 0 - 359 - 291 + 356 + 282 @@ -26,14 +26,21 @@ - Serial Connection + Serial Connection (GVRET) true - + + + + Network connection (GVRET) + + + + false @@ -43,14 +50,14 @@ - - + + - Network Connection + socketcand (SocketCAN over Ethernet) - + MQTT Connection From 52c18f23ba31485db9ca35b721af8adc9a3923a9 Mon Sep 17 00:00:00 2001 From: Bertrand Date: Tue, 23 Feb 2021 11:48:58 +0100 Subject: [PATCH 2/2] changing back to opengl32.lib for appveyor --- SavvyCAN.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SavvyCAN.pro b/SavvyCAN.pro index c559faf..8aa53cc 100644 --- a/SavvyCAN.pro +++ b/SavvyCAN.pro @@ -212,7 +212,7 @@ RESOURCES += \ images.qrc win32 { - LIBS += libopengl32 + LIBS += opengl32.lib } unix {