Commit 2c9fc33d authored by Thomas BOUTROUE's avatar Thomas BOUTROUE

Add a software watchdog for auto-close when not recv frames for too long

parent 2c68aa23
......@@ -6,14 +6,16 @@
#define QS QStringLiteral
const QString CanDriver_cobsTcp::PORT = QS ("port");
const QString CanDriver_cobsTcp::HOST = QS ("host");
const QString CanDriver_cobsTcp::SERV = QS ("isServer");
const QString CanDriver_cobsTcp::CACHE_ALL = QS ("cacheAll");
const QString CanDriver_cobsTcp::CACHE_LAST = QS ("cacheLast");
const QString CanDriver_cobsTcp::LOOPBACK = QS ("loopback");
const QString CanDriver_cobsTcp::FORCE_FLUSH = QS ("forceFlush");
const QString CanDriver_cobsTcp::WAIT_DELAY = QS ("waitDelay");
const QString CanDriver_cobsTcp::PORT = QS ("port");
const QString CanDriver_cobsTcp::HOST = QS ("host");
const QString CanDriver_cobsTcp::SERV = QS ("isServer");
const QString CanDriver_cobsTcp::CACHE_ALL = QS ("cacheAll");
const QString CanDriver_cobsTcp::CACHE_LAST = QS ("cacheLast");
const QString CanDriver_cobsTcp::LOOPBACK = QS ("loopback");
const QString CanDriver_cobsTcp::FORCE_FLUSH = QS ("forceFlush");
const QString CanDriver_cobsTcp::WAIT_DELAY = QS ("waitDelay");
const QString CanDriver_cobsTcp::AUTO_CLOSE = QS ("autoClose");
const QString CanDriver_cobsTcp::IDLE_WATCHDOG = QS ("idleWatchdog");
CanDriver_cobsTcp::CobsEncodeStatusFlags CanDriver_cobsTcp::cobsEncode (const qbyte * srcPtr,
const qsize srcLen,
......@@ -131,30 +133,36 @@ CanDriver_cobsTcp::CanPackedFrame::CanPackedFrame (void) {
}
CanDriver_cobsTcp::CanDriver_cobsTcp (QObject * parent)
: CanDriver (parent)
, m_caching (false)
: CanDriver (parent)
, m_caching (false)
, m_loopback (false)
, m_socket (Q_NULLPTR)
, m_server (Q_NULLPTR)
, m_watchdog (Q_NULLPTR)
, m_socket (Q_NULLPTR)
, m_server (Q_NULLPTR)
{
m_socket = new QTcpSocket (this);
m_server = new QTcpServer (this);
m_socket = new QTcpSocket (this);
m_server = new QTcpServer (this);
m_watchdog = new QTimer (this);
m_watchdog->setSingleShot (true);
typedef void (QAbstractSocket::*ErrorSignal) (QAbstractSocket::SocketError);
connect (m_socket, &QTcpSocket::readyRead, this, &CanDriver_cobsTcp::onSocketReadyRead);
connect (m_socket, ErrorSignal (&QTcpSocket::error), this, &CanDriver_cobsTcp::onSocketError);
connect (m_server, &QTcpServer::newConnection, this, &CanDriver_cobsTcp::onClientConnected);
connect (m_watchdog, &QTimer::timeout, this, &CanDriver_cobsTcp::onWatchdogTriggered);
connect (m_socket, &QTcpSocket::readyRead, this, &CanDriver_cobsTcp::onSocketReadyRead);
connect (m_socket, ErrorSignal (&QTcpSocket::error), this, &CanDriver_cobsTcp::onSocketError);
connect (m_server, &QTcpServer::newConnection, this, &CanDriver_cobsTcp::onClientConnected);
}
bool CanDriver_cobsTcp::init (const QVariantMap & options) {
bool ret = false;
const bool serv = options.value (SERV, false).value<bool> ();
const bool loop = options.value (LOOPBACK, false).value<bool> ();
const bool flush = options.value (FORCE_FLUSH, false).value<bool> ();
const int delay = options.value (WAIT_DELAY, 3000).value<int> ();
const quint16 port = options.value (PORT, 0).value<quint16> ();
const QString host = options.value (HOST, "localhost").value<QString> ();
const QVariantList cacheAll = options.value (CACHE_ALL).value<QVariantList> ();
const QVariantList cacheLast = options.value (CACHE_LAST).value<QVariantList> ();
const bool serv = options.value (SERV, false).toBool ();
const bool loop = options.value (LOOPBACK, false).toBool ();
const bool flush = options.value (FORCE_FLUSH, false).toBool ();
const bool autoClose = options.value (AUTO_CLOSE, false).toBool ();
const int watchdog = options.value (IDLE_WATCHDOG, 60000).toInt ();
const int delay = options.value (WAIT_DELAY, 3000).toInt ();
const quint16 port = options.value (PORT, 0).toUInt ();
const QString host = options.value (HOST, "localhost").toString ();
const QVariantList cacheAll = options.value (CACHE_ALL).toList ();
const QVariantList cacheLast = options.value (CACHE_LAST).toList ();
m_loopback = loop;
m_forceFlush = flush;
foreach (const QVariant & id, cacheAll) {
......@@ -182,6 +190,10 @@ bool CanDriver_cobsTcp::init (const QVariantMap & options) {
if (m_socket->waitForConnected (delay)) {
ret = true;
diag (Information, QS ("COBS socket driver connected."));
if (!serv && autoClose) {
m_watchdog->setInterval (watchdog);
m_watchdog->start ();
}
}
else {
diag (Error, QS ("COBS socket couldn't connect ! %1").arg (m_socket->errorString ()));
......@@ -206,6 +218,7 @@ QVariantMap CanDriver_cobsTcp::info (void) {
}
bool CanDriver_cobsTcp::stop (void) {
m_watchdog->stop ();
m_socket->close ();
m_server->close ();
m_cacheById.clear ();
......@@ -265,6 +278,8 @@ bool CanDriver_cobsTcp::send (CanMessage * message) {
}
void CanDriver_cobsTcp::onSocketReadyRead (void) {
const bool restart = m_watchdog->isActive ();
m_watchdog->stop ();
while (m_socket->bytesAvailable () > CobsTcpHelper::FRAME_PAYLOAD) {
m_socket->read (reinterpret_cast<char *> (m_rx.buffer), CobsTcpHelper::FRAME_PAYLOAD);
m_socket->read (&m_rx.sep, 1);
......@@ -281,21 +296,25 @@ void CanDriver_cobsTcp::onSocketReadyRead (void) {
}
}
}
if (restart) {
m_watchdog->start ();
}
}
void CanDriver_cobsTcp::onClientConnected (void) {
while (m_server->hasPendingConnections ()) {
QTcpSocket * client = m_server->nextPendingConnection ();
connect (client, &QTcpSocket::readyRead, this, &CanDriver_cobsTcp::onClientSentData);
connect (client, &QTcpSocket::disconnected, this, &CanDriver_cobsTcp::onClientDisconnected);
m_clients.append (client);
for (QHash<quint32, QByteArray *>::const_iterator it = m_cacheById.constBegin (); it != m_cacheById.constEnd (); ++it) {
if (!it.value ()->isEmpty ()) {
client->write (* it.value ());
if (QTcpSocket * client = m_server->nextPendingConnection ()) {
connect (client, &QTcpSocket::readyRead, this, &CanDriver_cobsTcp::onClientSentData);
connect (client, &QTcpSocket::disconnected, this, &CanDriver_cobsTcp::onClientDisconnected);
m_clients.append (client);
for (QHash<quint32, QByteArray *>::const_iterator it = m_cacheById.constBegin (); it != m_cacheById.constEnd (); ++it) {
if (!it.value ()->isEmpty ()) {
client->write (* it.value ());
}
}
if (m_forceFlush) {
client->flush ();
}
}
if (m_forceFlush) {
client->flush ();
}
}
}
......@@ -308,6 +327,11 @@ void CanDriver_cobsTcp::onClientDisconnected (void) {
}
}
void CanDriver_cobsTcp::onWatchdogTriggered (void) {
emit lost ();
stop ();
}
void CanDriver_cobsTcp::onSocketError (void) {
emit lost ();
}
......
......@@ -10,6 +10,7 @@
#include <QTcpServer>
#include <QVector>
#include <QtGlobal>
#include <QTimer>
class QTCAN_DRIVER_EXPORT CanDriver_cobsTcp : public CanDriver {
Q_OBJECT
......@@ -60,6 +61,8 @@ public:
static const QString LOOPBACK;
static const QString FORCE_FLUSH;
static const QString WAIT_DELAY;
static const QString AUTO_CLOSE;
static const QString IDLE_WATCHDOG;
enum CobsEncodeStatusFlag {
COBS_ENCODE_OK = 0x00,
......@@ -88,10 +91,10 @@ public:
const qsize dstLen);
public slots: // CanDriver interface
bool init (const QVariantMap & options);
bool send (CanMessage * message);
bool stop (void);
QVariantMap info (void);
bool init (const QVariantMap & options) Q_DECL_FINAL;
bool send (CanMessage * message) Q_DECL_FINAL;
bool stop (void) Q_DECL_FINAL;
QVariantMap info (void) Q_DECL_FINAL;
private slots:
void onSocketReadyRead (void);
......@@ -99,6 +102,7 @@ private slots:
void onClientConnected (void);
void onClientSentData (void);
void onClientDisconnected (void);
void onWatchdogTriggered (void);
private:
bool m_caching;
......@@ -106,6 +110,7 @@ private:
bool m_forceFlush;
CobsTcpHelper m_rx;
CobsTcpHelper m_tx;
QTimer * m_watchdog;
QTcpSocket * m_socket;
QTcpServer * m_server;
QVector<QTcpSocket *> m_clients;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment