adding socketcand support
This commit is contained in:
+3
-1
@@ -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 \
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace CANCon {
|
||||
KVASER,
|
||||
SERIALBUS,
|
||||
REMOTE,
|
||||
KAYAK,
|
||||
MQTT,
|
||||
NONE
|
||||
};
|
||||
|
||||
@@ -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: {}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <QDateTime>
|
||||
#include <QSettings>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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<QString> 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;
|
||||
|
||||
@@ -60,8 +60,10 @@ private:
|
||||
Ui::ConnectionWindow *ui;
|
||||
QSettings *settings;
|
||||
CANConnectionModel *connModel;
|
||||
QUdpSocket *rxBroadcast;
|
||||
QVector<QString> remoteDeviceIP;
|
||||
QUdpSocket *rxBroadcastGVRET;
|
||||
QUdpSocket *rxBroadcastKayak;
|
||||
QVector<QString> remoteDeviceIPGVRET;
|
||||
QVector<QString> remoteDeviceKayak;
|
||||
|
||||
CANConnection* create(CANCon::type pTye, QString pPortName, QString pDriver);
|
||||
void populateBusDetails(int offset);
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
#include "newconnectiondialog.h"
|
||||
#include "ui_newconnectiondialog.h"
|
||||
|
||||
NewConnectionDialog::NewConnectionDialog(QVector<QString>* ips, QWidget *parent) :
|
||||
NewConnectionDialog::NewConnectionDialog(QVector<QString>* gvretips, QVector<QString>* 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<QString>* 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<int>::of(&QComboBox::currentIndexChanged), this, &NewConnectionDialog::handleDeviceTypeChanged);
|
||||
@@ -34,7 +35,8 @@ NewConnectionDialog::NewConnectionDialog(QVector<QString>* 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";
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class NewConnectionDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewConnectionDialog(QVector<QString>* ips, QWidget *parent = nullptr);
|
||||
explicit NewConnectionDialog(QVector<QString>* gvretips, QVector<QString>* kayakips, QWidget *parent = nullptr);
|
||||
~NewConnectionDialog();
|
||||
|
||||
CANCon::type getConnectionType();
|
||||
@@ -34,12 +34,14 @@ private:
|
||||
Ui::NewConnectionDialog *ui;
|
||||
QList<QSerialPortInfo> ports;
|
||||
QList<QCanBusDeviceInfo> canDevices;
|
||||
QVector<QString>* remoteDeviceIP;
|
||||
QVector<QString>* remoteDeviceIPGVRET;
|
||||
QVector<QString>* remoteBusKayak;
|
||||
|
||||
void selectSerial();
|
||||
void selectKvaser();
|
||||
void selectSocketCan();
|
||||
void selectRemote();
|
||||
void selectKayak();
|
||||
void selectMQTT();
|
||||
bool isSerialBusAvailable();
|
||||
void setPortName(CANCon::type pType, QString pPortName, QString pDriver);
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QCanBusFrame>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QSettings>
|
||||
#include <QStringBuilder>
|
||||
#include <QtNetwork>
|
||||
#include <QMetaObject>
|
||||
|
||||
#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<QTcpSocket*> 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<CANConnection*> 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<QTcpSocket*>(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<QTcpSocket*>(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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#ifndef SOCKETCAND_H
|
||||
#define SOCKETCAND_H
|
||||
|
||||
//#include <QSerialPort>
|
||||
//#include <QCanBusDevice>
|
||||
#include <QTimer>
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
//#include <QUdpSocket>
|
||||
|
||||
/*************/
|
||||
#include <QDateTime>
|
||||
/*************/
|
||||
|
||||
#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<QTcpSocket*> tcpClient;
|
||||
QHostAddress hostIP;
|
||||
int hostPort;
|
||||
QList<QString> hostCanIDs;
|
||||
int framesRapid;
|
||||
QByteArray buildData;
|
||||
QVarLengthArray<MODE> rx_state;
|
||||
CANFrame buildFrame;
|
||||
};
|
||||
|
||||
|
||||
#endif // SOCKETCAND_H
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>359</width>
|
||||
<height>291</height>
|
||||
<width>356</width>
|
||||
<height>282</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -26,14 +26,21 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="rbGVRET">
|
||||
<property name="text">
|
||||
<string>Serial Connection</string>
|
||||
<string>Serial Connection (GVRET)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="rbRemote">
|
||||
<property name="text">
|
||||
<string>Network connection (GVRET)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="rbSocketCAN">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@@ -43,14 +50,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="rbRemote">
|
||||
<item row="3" column="0">
|
||||
<widget class="QRadioButton" name="rbKayak">
|
||||
<property name="text">
|
||||
<string>Network Connection</string>
|
||||
<string>socketcand (SocketCAN over Ethernet)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QRadioButton" name="rbMQTT">
|
||||
<property name="text">
|
||||
<string>MQTT Connection</string>
|
||||
|
||||
Reference in New Issue
Block a user