A bit more work on MQTT support. It can actually connect to an MQTT broker now.

This commit is contained in:
Collin Kidder
2020-08-05 21:53:21 -04:00
parent ee287eac4b
commit 2da2855bfa
6 changed files with 288 additions and 4 deletions
+205
View File
@@ -0,0 +1,205 @@
#include <QObject>
#include <QDebug>
#include <QCanBusFrame>
#include <QSettings>
#include <QStringBuilder>
#include <QtNetwork>
#include "mqtt_bus.h"
MQTT_BUS::MQTT_BUS(QString topicName) :
CANConnection(topicName, "mqtt_client", CANCon::MQTT, 1, 4000, true),
mTimer(this) /*NB: set this as parent of timer to manage it from working thread */
{
sendDebug("MQTT_BUS()");
crypto = new SimpleCrypt(Q_UINT64_C(0xdeadbeefface6285));
isAutoRestart = false;
this->topicName = topicName;
timeBasis = 0;
lastSystemTimeBasis = 0;
readSettings();
}
MQTT_BUS::~MQTT_BUS()
{
delete crypto;
stop();
sendDebug("~MQTT_BUS");
}
void MQTT_BUS::sendDebug(const QString debugText)
{
qDebug() << debugText;
debugOutput(debugText);
}
void MQTT_BUS::piStarted()
{
QSettings settings;
QString userName = settings.value("Remote/User", "Anonymous").toString();
QString host = settings.value("Remote/Host", "api.savvycan.com").toString();
int port = settings.value("Remote/Port", 8333).toInt();
QByteArray encPass = settings.value("Remote/Pass", "").toByteArray();
QByteArray password = crypto->decryptToByteArray(encPass);
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
mqttClient = new QMQTT::Client(host, port, sslConfig);
connect(mqttClient, &QMQTT::Client::connected, this, &MQTT_BUS::clientConnected);
connect(mqttClient, &QMQTT::Client::error, this, &MQTT_BUS::clientErrored);
//qDebug() << "User: " << userName << " Pass: " << password;
mqttClient->setClientId(genRandomClientID());
mqttClient->setUsername(userName);
mqttClient->setPassword(password);
mqttClient->connectToHost();
}
//MQTT required a client ID and they cannot be the same for any two clients. But, they really aren't super exciting
//or important to be named explicitly. Perhaps it might be nice to be able to see it for debugging though.
QString MQTT_BUS::genRandomClientID()
{
QString output;
output.reserve(12);
QRandomGenerator gen;
for (int i = 0; i < 12; i++)
{
int val = gen.bounded(0, 62);
if (val < 26) output.append(QChar('A'+val));
else if (val < 52) output.append(QChar('a'+val-26));
else output.append(QChar('0'+val-52));
}
qDebug() << "Client ID: " << output;
return output;
}
void MQTT_BUS::clientErrored(const QMQTT::ClientError error)
{
qDebug() << QString::number(error);
}
void MQTT_BUS::piSuspend(bool pSuspend)
{
/* update capSuspended */
setCapSuspended(pSuspend);
/* flush queue if we are suspended */
if(isCapSuspended())
getQueue().flush();
}
void MQTT_BUS::piStop()
{
mTimer.stop();
disconnectDevice();
}
bool MQTT_BUS::piGetBusSettings(int pBusIdx, CANBus& pBus)
{
return getBusConfig(pBusIdx, pBus);
}
void MQTT_BUS::piSetBusSettings(int pBusIdx, CANBus bus)
{
/* sanity checks */
if( (pBusIdx < 0) || pBusIdx >= getNumBuses())
return;
/* copy bus config */
setBusConfig(pBusIdx, bus);
//we don't really update anything. We're just here to listen and perhaps send frames.
}
bool MQTT_BUS::piSendFrame(const CANFrame& frame)
{
QByteArray buffer;
int c;
quint32 ID;
//qDebug() << "Sending out GVRET frame with id " << frame.ID << " on bus " << frame.bus;
framesRapid++;
// 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 |= 1u << 31;
buffer[0] = (char)0xF1; //start of a command over serial
buffer[1] = 0; //command ID for sending a CANBUS frame
buffer[2] = (char)(ID & 0xFF); //four bytes of ID LSB first
buffer[3] = (char)(ID >> 8);
buffer[4] = (char)(ID >> 16);
buffer[5] = (char)(ID >> 24);
buffer[6] = (char)((frame.bus) & 3);
buffer[7] = (char)frame.payload().length();
for (c = 0; c < frame.payload().length(); c++)
{
buffer[8 + c] = frame.payload()[c];
}
buffer[8 + frame.payload().length()] = 0;
return true;
}
/****************************************************************/
void MQTT_BUS::readSettings()
{
QSettings settings;
}
void MQTT_BUS::clientConnected()
{
sendDebug("Connecting to MQTT Broker!");
setStatus(CANCon::CONNECTED);
CANConStatus stats;
stats.conStatus = getStatus();
stats.numHardwareBuses = 1;//mNumBuses;
emit status(stats);
}
void MQTT_BUS::disconnectDevice() {
setStatus(CANCon::NOT_CONNECTED);
CANConStatus stats;
stats.conStatus = getStatus();
stats.numHardwareBuses = mNumBuses;
emit status(stats);
}
void MQTT_BUS::rebuildLocalTimeBasis()
{
//qDebug() << "Rebuilding GVRET time base. GVRET local base = " << buildTimeBasis;
/*
our time basis is the value we have to modulate the main system basis by in order
to sync the GVRET timestamps to the rest of the system.
The rest of the system uses CANConManager::getInstance()->getTimeBasis as the basis.
GVRET returns to us the current time since boot up in microseconds.
timeAtGVRETSync stores the "system" timestamp when the GVRET timestamp was retrieved.
*/
/*
lastSystemTimeBasis = CANConManager::getInstance()->getTimeBasis();
int64_t systemDelta = timeAtGVRETSync - lastSystemTimeBasis;
int32_t localDelta = buildTimeBasis - systemDelta;
timeBasis = -localDelta;
*/
}