Skip to content

Commit

Permalink
Add two new external libraries. SimpleCrypt is used to encrypt passwo…
Browse files Browse the repository at this point in the history
…rds, QMQTT is an MQTT

library that I was able to integrate into the codebase so there aren't any external
dependencies. Both external projects have their own open source licenses. Those licenses
are included. Also in this commit is some preliminary work to start adding MQTT support to SavvyCAN.
  • Loading branch information
collin80 committed Aug 6, 2020
1 parent 7d1893a commit c1661fd
Show file tree
Hide file tree
Showing 47 changed files with 5,481 additions and 19 deletions.
36 changes: 35 additions & 1 deletion SavvyCAN.pro
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,35 @@
#
#-------------------------------------------------

QT = core gui printsupport qml serialbus serialport widgets help
QT = core gui printsupport qml serialbus serialport widgets help network

CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT

CONFIG += c++11
CONFIG += NO_UNIT_TESTS

DEFINES += QCUSTOMPLOT_USE_OPENGL

TARGET = SavvyCAN
TEMPLATE = app

SOURCES += main.cpp\
mqtt/qmqtt_client.cpp \
mqtt/qmqtt_client_p.cpp \
mqtt/qmqtt_frame.cpp \
mqtt/qmqtt_message.cpp \
mqtt/qmqtt_network.cpp \
mqtt/qmqtt_router.cpp \
mqtt/qmqtt_routesubscription.cpp \
mqtt/qmqtt_socket.cpp \
mqtt/qmqtt_ssl_socket.cpp \
mqtt/qmqtt_timer.cpp \
mqtt/qmqtt_websocket.cpp \
mqtt/qmqtt_websocketiodevice.cpp \
re/dbccomparatorwindow.cpp \
mainwindow.cpp \
canframemodel.cpp \
simplecrypt.cpp \
utility.cpp \
qcustomplot.cpp \
frameplaybackwindow.cpp \
Expand Down Expand Up @@ -77,7 +91,27 @@ SOURCES += main.cpp\
HEADERS += mainwindow.h \
can_structs.h \
canframemodel.h \ \
mqtt/qmqtt.h \
mqtt/qmqtt_client.h \
mqtt/qmqtt_client_p.h \
mqtt/qmqtt_frame.h \
mqtt/qmqtt_global.h \
mqtt/qmqtt_message.h \
mqtt/qmqtt_message_p.h \
mqtt/qmqtt_network_p.h \
mqtt/qmqtt_networkinterface.h \
mqtt/qmqtt_routedmessage.h \
mqtt/qmqtt_router.h \
mqtt/qmqtt_routesubscription.h \
mqtt/qmqtt_socket_p.h \
mqtt/qmqtt_socketinterface.h \
mqtt/qmqtt_ssl_socket_p.h \
mqtt/qmqtt_timer_p.h \
mqtt/qmqtt_timerinterface.h \
mqtt/qmqtt_websocket_p.h \
mqtt/qmqtt_websocketiodevice_p.h \
re/dbccomparatorwindow.h \
simplecrypt.h \
utility.h \
qcustomplot.h \
frameplaybackwindow.h \
Expand Down
1 change: 1 addition & 0 deletions connections/canconconst.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace CANCon {
KVASER,
SERIALBUS,
REMOTE,
MQTT,
NONE
};
}
Expand Down
13 changes: 13 additions & 0 deletions connections/newconnectiondialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ 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->rbMQTT, &QAbstractButton::clicked, this, &NewConnectionDialog::handleConnTypeChanged);

connect(ui->cbDeviceType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &NewConnectionDialog::handleDeviceTypeChanged);
connect(ui->btnOK, &QPushButton::clicked, this, &NewConnectionDialog::handleCreateButton);

Expand All @@ -50,6 +52,7 @@ void NewConnectionDialog::handleConnTypeChanged()
if (ui->rbGVRET->isChecked()) selectSerial();
if (ui->rbSocketCAN->isChecked()) selectSocketCan();
if (ui->rbRemote->isChecked()) selectRemote();

}

void NewConnectionDialog::handleDeviceTypeChanged()
Expand Down Expand Up @@ -102,6 +105,14 @@ void NewConnectionDialog::selectRemote()
}
}

void NewConnectionDialog::selectMQTT()
{
ui->lPort->setText("Topic Name:");
ui->lblDeviceType->setHidden(true);
ui->cbDeviceType->setHidden(true);
ui->cbPort->clear();
}

void NewConnectionDialog::setPortName(CANCon::type pType, QString pPortName, QString pDriver)
{

Expand Down Expand Up @@ -156,6 +167,7 @@ QString NewConnectionDialog::getPortName()
case CANCon::GVRET_SERIAL:
case CANCon::SERIALBUS:
case CANCon::REMOTE:
case CANCon::MQTT:
return ui->cbPort->currentText();
default:
qDebug() << "getPortName: can't get port";
Expand All @@ -178,6 +190,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->rbMQTT->isChecked()) return CANCon::MQTT;
qDebug() << "getConnectionType: error";

return CANCon::NONE;
Expand Down
1 change: 1 addition & 0 deletions connections/newconnectiondialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public slots:
void selectKvaser();
void selectSocketCan();
void selectRemote();
void selectMQTT();
bool isSerialBusAvailable();
void setPortName(CANCon::type pType, QString pPortName, QString pDriver);
};
Expand Down
23 changes: 18 additions & 5 deletions mainsettingsdialog.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#include "mainsettingsdialog.h"
#include "ui_mainsettingsdialog.h"
#include "helpwindow.h"

#include <qevent.h>
#include "simplecrypt.h"

//using this simple encryption library to obfuscate stored password a bit. It's not super secure but better than
//storing a password in straight plaintext. You have the source to this application anyway, whatever algorithm used,
//whatever key, you'd see it. Just behave yourselves
SimpleCrypt crypto(Q_UINT64_C(0xdeadbeefface6285));

MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
QDialog(parent),
Expand All @@ -11,6 +16,7 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
QSettings settings;
ui->setupUi(this);

//TODO: This is still hard coded to support only two buses. Sometimes there is none, sometimes 1, sometimes much more than 2. Fix this.
ui->comboSendingBus->addItem(tr("None"));
ui->comboSendingBus->addItem(tr("0"));
ui->comboSendingBus->addItem(tr("1"));
Expand All @@ -30,8 +36,12 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
ui->spinPlaybackSpeed->setValue(settings.value("Playback/DefSpeed", 5).toInt());
ui->lineClockFormat->setText(settings.value("Main/TimeFormat", "MMM-dd HH:mm:ss.zzz").toString());
ui->lineRemoteHost->setText(settings.value("Remote/Host", "api.savvycan.com").toString());
ui->lineRemotePort->setText(settings.value("Remote/Port", "21315").toString()); // = 0x5343 = SC. Yep, really creative port number
ui->cbAutoStartRemote->setChecked(settings.value("Remote/AutoStart", false).toBool());
ui->lineRemotePort->setText(settings.value("Remote/Port", "8883").toString()); //default port for SSL enabled MQTT
ui->lineRemoteUser->setText(settings.value("Remote/User", "Anonymous").toString());
QByteArray encPass = settings.value("Remote/Pass", "").toByteArray();
QString decPass = crypto.decryptToString(encPass);
ui->lineRemotePassword->setText(decPass);

ui->cbLoadConnections->setChecked(settings.value("Main/SaveRestoreConnections", false).toBool());

ui->spinFontSize->setValue(settings.value("Main/FontSize", ui->cbDisplayHex->font().pointSize()).toUInt());
Expand Down Expand Up @@ -82,9 +92,10 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
connect(ui->cbUseFiltered, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
connect(ui->lineClockFormat, SIGNAL(editingFinished()), this, SLOT(updateSettings()));
connect(ui->cbUseOpenGL, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
connect(ui->cbAutoStartRemote, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
connect(ui->lineRemoteHost, SIGNAL(editingFinished()), this, SLOT(updateSettings()));
connect(ui->lineRemotePort, SIGNAL(editingFinished()), this, SLOT(updateSettings()));
connect(ui->lineRemoteUser, SIGNAL(editingFinished()), this, SLOT(updateSettings()));
connect(ui->lineRemotePassword, SIGNAL(editingFinished()), this, SLOT(updateSettings()));
connect(ui->cbLoadConnections, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
connect(ui->cbFilterLabeling, SIGNAL(toggled(bool)), this, SLOT(updateSettings()));
installEventFilter(this);
Expand Down Expand Up @@ -144,7 +155,9 @@ void MainSettingsDialog::updateSettings()
settings.setValue("Main/FontSize", ui->spinFontSize->value());
settings.setValue("Remote/Host", ui->lineRemoteHost->text());
settings.setValue("Remote/Port", ui->lineRemotePort->text());
settings.setValue("Remote/AutoStart", ui->cbAutoStartRemote->isChecked());
settings.setValue("Remote/User", ui->lineRemoteUser->text());
QByteArray encPass = crypto.encryptToByteArray(ui->lineRemotePassword->text());
settings.setValue("Remote/Pass", encPass);
settings.setValue("Main/FilterLabeling", ui->cbFilterLabeling->isChecked());

settings.sync();
Expand Down
2 changes: 2 additions & 0 deletions mqtt/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This project is dual licensed under the Eclipse Public License 1.0 and the
Eclipse Distribution License 1.0 as described in the epl-v10 and edl-v10 files.
139 changes: 139 additions & 0 deletions mqtt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
QMQTT
=====

mqtt client for Qt

**Please compile the library with Qt >= 5.3 version. On Windows you need to specify `CONFIG += NO_UNIT_TESTS`, since gtest is not supported.**

SSL is enabled by default, if the version of OpenSSL < 1.0.2, SSL may not be supported.

Disable the SSL in CMakeLists.txt (cmake):

option( ${PROJECT_NAME}_SSL "Enable SSL support for MQTT" OFF )

Disable the SSL with src/mqtt/qmqtt.pro (qmake):

CONFIG+=QMQTT_NO_SSL

To add websocket support, compile the library with Qt >= 5.7, and specify 'CONFIG += QMQTT_WEBSOCKETS'.
This also works when compiling qmqtt for WebAssembly.

Usage
=====

In your QMake project, add:

QT += qmqtt

Connect using TCP:

#include "qmqtt.h"

QMQTT::Client *client = new QMQTT::Client(QHostAddress::LocalHost, 1883);
client->setClientId("clientId");
client->setUsername("user");
client->setPassword("password");
client->connectToHost();

Connect using SSL:

QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
// Add custom SSL options here (for example extra certificates)
QMQTT::Client *client = new QMQTT::Client("example.com", 8883, sslConfig);
client->setClientId("clientId");
client->setUsername("user");
client->setPassword("password");
// Optionally, set ssl errors you want to ignore. Be careful, because this may weaken security.
// See QSslSocket::ignoreSslErrors(const QList<QSslError> &) for more information.
client->ignoreSslErrors(<list of expected ssl errors>)
client->connectToHost();
// Here's another option to suppress SSL errors (again, be careful)
QObject::connect(client, &QMQTT::Client::sslErrors, [&](const QList<QSslError> &errors) {
// Investigate the errors here, if you find no serious problems, call ignoreSslErrors()
// to continue connecting.
client->ignoreSslErrors();
});

Connect using WebSockets:

QMQTT::Client *client = new QMQTT::Client("ws://www.example.com/mqtt", "<origin>", QWebSocketProtocol::VersionLatest);
client->setClientId("clientId");
client->setUsername("user");
client->setPassword("password");
client->connectToHost();

Slots
=====

void setHost(const QHostAddress& host);
void setPort(const quint16 port);
void setClientId(const QString& clientId);
void setUsername(const QString& username);
void setPassword(const QString& password);
void setKeepAlive(const int keepAlive);
void setCleanSession(const bool cleansess);
void setAutoReconnect(const bool value);
void setAutoReconnectInterval(const int autoReconnectInterval);
void setWillTopic(const QString& willTopic);
void setWillQos(const quint8 willQos);
void setWillRetain(const bool willRetain);
void setWillMessage(const QString& willMessage);

void connectToHost();
void disconnectFromHost();

quint16 subscribe(const QString& topic, const quint8 qos);
void unsubscribe(const QString& topic);

quint16 publish(const Message& message);

Signals
=======

void connected();
void disconnected();
void error(const QMQTT::ClientError error);

void subscribed(const QString& topic, const quint8 qos);
void unsubscribed(const QString& topic);
void published(const quint16 msgid, const quint8 qos);
void pingresp();
void received(const QMQTT::Message& message);


License
=======

New BSD License


Contributors
=============

[@Kampfgnom](https://github.com/Kampfgnom)

[@rafaeldelucena](https://github.com/rafaeldelucena)

[@Vortex375](https://github.com/Vortex375)

[@mwallnoefer](https://github.com/mwallnoefer)

[@KonstantinRitt](https://github.com/KonstantinRitt)

[@cncap](https://github.com/cncap)

[@Psy-Kai](https://github.com/Psy-Kai)

[@ejvr](https://github.com/ejvr)

[@keytee](https://github.com/keytee)


Authors
=======

[@emqplus](https://github.com/emqplus) Feng Lee <[email protected]>

[@wguynes](https://github.com/wguynes) William Guynes <[email protected]>

[@wuming123057](https://github.com/wuming123057) Xuan <[email protected]>
30 changes: 30 additions & 0 deletions mqtt/edl-v10
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Eclipse Distribution License - v 1.0

Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

Neither the name of the Eclipse Foundation, Inc. nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Loading

0 comments on commit c1661fd

Please sign in to comment.