167 lines
4.0 KiB
C++
167 lines
4.0 KiB
C++
|
#include "apism_tcp_client.h"
|
||
|
|
||
|
#include <QHostAddress>
|
||
|
#include <QTimer>
|
||
|
|
||
|
ApismTcpClient::ApismTcpClient(const QString & hostname,
|
||
|
const QString & port,
|
||
|
QObject *parent)
|
||
|
: QObject(parent)
|
||
|
, hostname(hostname)
|
||
|
, port(port)
|
||
|
, responseTimerTimeoutCounter(0)
|
||
|
{
|
||
|
this->responseTimeoutTimer = new QTimer(this);
|
||
|
this->responseTimeoutTimer->setInterval(10000);
|
||
|
this->responseTimeoutTimer->setSingleShot(true);
|
||
|
|
||
|
connect(this->responseTimeoutTimer, SIGNAL(timeout()), this, SLOT(onResponseTimeoutTimerTimeout()));
|
||
|
|
||
|
socket = new QTcpSocket(this);
|
||
|
connect(socket, SIGNAL(connected()), this, SLOT(onSocketConnected()));
|
||
|
connect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
|
||
|
connect(socket, SIGNAL(readyRead()), this, SLOT(onSocketReadyRead()));
|
||
|
connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(onSocketBytesWritten(qint64)));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void ApismTcpClient::connectToHost()
|
||
|
{
|
||
|
int portNumber = this->port.toInt();
|
||
|
this->socket->connectToHost(QHostAddress(this->hostname), portNumber);
|
||
|
}
|
||
|
|
||
|
void ApismTcpClient::connectToHost(const QString & hostname, const QString & port)
|
||
|
{
|
||
|
qCritical() << "ApismTcpClient::connectToHost(" << hostname << ", " << port << ")";
|
||
|
|
||
|
int portNumber = port.toInt();
|
||
|
socket->connectToHost(hostname, portNumber);
|
||
|
}
|
||
|
|
||
|
void ApismTcpClient::closeConnection()
|
||
|
{
|
||
|
socket->close();
|
||
|
}
|
||
|
|
||
|
bool ApismTcpClient::isConnected()
|
||
|
{
|
||
|
bool result = false;
|
||
|
QAbstractSocket::SocketState socketState = socket->state();
|
||
|
|
||
|
switch (socketState) {
|
||
|
case QAbstractSocket::UnconnectedState:
|
||
|
/* FALLTHRU */
|
||
|
case QAbstractSocket::HostLookupState:
|
||
|
/* FALLTHRU */
|
||
|
case QAbstractSocket::ConnectingState:
|
||
|
result = false;
|
||
|
break;
|
||
|
case QAbstractSocket::ConnectedState:
|
||
|
/* FALLTHRU */
|
||
|
case QAbstractSocket::BoundState:
|
||
|
result = true;
|
||
|
break;
|
||
|
case QAbstractSocket::ClosingState:
|
||
|
/* FALLTHRU */
|
||
|
case QAbstractSocket::ListeningState:
|
||
|
result = false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void ApismTcpClient::sendData(const QByteArray & message)
|
||
|
{
|
||
|
//qCritical() << "ApismTcpClient::send: " << message;
|
||
|
|
||
|
this->sendQueue.enqueue(message);
|
||
|
|
||
|
if (this->isConnected()) {
|
||
|
this->private_sendData();
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
this->connectToHost();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief ApismTcpClient::private_sendData
|
||
|
*
|
||
|
* Precondition is that queue is not empty.
|
||
|
*/
|
||
|
void ApismTcpClient::private_sendData()
|
||
|
{
|
||
|
// take message from queue
|
||
|
QByteArray ba = this->sendQueue.dequeue();
|
||
|
|
||
|
qCritical() << "ApismTcpClient::send: " << QString(ba);
|
||
|
|
||
|
socket->write(ba);
|
||
|
socket->flush();
|
||
|
|
||
|
// start timeoutTimer
|
||
|
this->responseTimeoutTimer->start();
|
||
|
}
|
||
|
|
||
|
void ApismTcpClient::onSocketConnected()
|
||
|
{
|
||
|
qCritical() << "ApismTcpClient: Connected!";
|
||
|
|
||
|
if (this->sendQueue.size() > 0) {
|
||
|
this->private_sendData();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ApismTcpClient::onSocketDisconnected()
|
||
|
{
|
||
|
qCritical() << "ApismTcpClient: Disconnected!";
|
||
|
qCritical() << " -> SocketErrorString: " << socket->errorString();
|
||
|
|
||
|
if (this->sendQueue.size() > 0) {
|
||
|
this->connectToHost();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ApismTcpClient::onSocketBytesWritten(qint64 bytes)
|
||
|
{
|
||
|
Q_UNUSED(bytes)
|
||
|
}
|
||
|
|
||
|
void ApismTcpClient::onSocketReadyRead()
|
||
|
{
|
||
|
QByteArray readData;
|
||
|
|
||
|
// stop timeoutTimer
|
||
|
this->responseTimeoutTimer->stop();
|
||
|
|
||
|
readData = socket->readAll();
|
||
|
|
||
|
qCritical() << "ISMAS received: " << QString(readData);
|
||
|
|
||
|
emit this->receivedData(readData);
|
||
|
|
||
|
this->socket->close();
|
||
|
}
|
||
|
|
||
|
|
||
|
void ApismTcpClient::onResponseTimeoutTimerTimeout()
|
||
|
{
|
||
|
if (this->sendQueue.size() == 0) {
|
||
|
return;
|
||
|
}
|
||
|
emit this->responseTimeout();
|
||
|
|
||
|
qCritical() << "ApismTcpClient::onResponseTimeoutTimerTimeout() --> skip this message, send next command, if available.";
|
||
|
|
||
|
// Try next command
|
||
|
this->sendQueue.removeFirst();
|
||
|
if (this->sendQueue.size() > 0) this->private_sendData();
|
||
|
}
|