337 lines
12 KiB
C++
337 lines
12 KiB
C++
|
#include "ApismClient.h"
|
|||
|
|
|||
|
#include <QDebug>
|
|||
|
#include <QByteArray>
|
|||
|
#include <QHostAddress>
|
|||
|
#include <QString>
|
|||
|
#include <QList>
|
|||
|
#include <QListIterator>
|
|||
|
#include <QScopedPointer>
|
|||
|
#include <QProcess>
|
|||
|
#include <QRegularExpression>
|
|||
|
|
|||
|
|
|||
|
ApismClient::ApismClient(QObject *parent)
|
|||
|
: QObject(parent)
|
|||
|
, lastError(0)
|
|||
|
, lastErrorDescription("")
|
|||
|
, currentRequest(ISMAS::REQUEST::NO_REQUEST)
|
|||
|
, retryCounter(0)
|
|||
|
, flagValidParameter(false)
|
|||
|
{
|
|||
|
this->apismTcpSendClient.reset(new ApismTcpClient("127.0.0.1", "7777", ApismTcpClient::ExpectedResponse::STATE, this));
|
|||
|
this->apismTcpRequestResponseClient.reset(new ApismTcpClient("127.0.0.1", "7778", ApismTcpClient::ExpectedResponse::JSON, this));
|
|||
|
|
|||
|
this->apismTcpRequestResponseClient->setResponseTimeout(30000);
|
|||
|
|
|||
|
connect(apismTcpRequestResponseClient.get(), &ApismTcpClient::receivedData,
|
|||
|
this, &ApismClient::onReceivedResponse);
|
|||
|
connect(apismTcpRequestResponseClient.get(), &ApismTcpClient::responseTimeout,
|
|||
|
this, &ApismClient::onRequestResponseClientResponseTimeout);
|
|||
|
connect(apismTcpRequestResponseClient.get(), &ApismTcpClient::connectTimeout,
|
|||
|
this, &ApismClient::onRequestResponseClientConnectTimeout);
|
|||
|
connect(apismTcpRequestResponseClient.get(), &ApismTcpClient::connectionClosedByRemoteHost,
|
|||
|
this, &ApismClient::onRequestResponseClientConnectionClosedByRemoteHost);
|
|||
|
connect(apismTcpRequestResponseClient.get(), &ApismTcpClient::connectionRefusedError,
|
|||
|
this, &ApismClient::restartApism);
|
|||
|
|
|||
|
connect(apismTcpSendClient.get(), &ApismTcpClient::responseTimeout,
|
|||
|
this, &ApismClient::onSendClientResponseTimeout);
|
|||
|
connect(apismTcpSendClient.get(), &ApismTcpClient::connectionRefusedError,
|
|||
|
this, &ApismClient::restartApism);
|
|||
|
|
|||
|
|
|||
|
// not needed as APISM closes the socket after we send data, so readyRead()
|
|||
|
// might not even fire
|
|||
|
// connect(&m_socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
|
|||
|
|
|||
|
// defined for Qt >= 5.15, we have 5.12
|
|||
|
// qRegisterMetaType<QAbstractSocket::SocketError>();
|
|||
|
// connect(&m_socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
|
|||
|
// this, SLOT(onSocketError(&QAbstractSocket::SocketError)));
|
|||
|
|
|||
|
// switch of DEBUG:
|
|||
|
this->apismTcpSendClient->setDebug(true);
|
|||
|
this->apismTcpRequestResponseClient->setDebug(true);
|
|||
|
}
|
|||
|
|
|||
|
ApismClient::~ApismClient() {
|
|||
|
}
|
|||
|
|
|||
|
void ApismClient::restartApism() {
|
|||
|
QProcess::startDetached("/bin/systemctl", {"restart", "apism"});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void ApismClient::sendSelfTest() {
|
|||
|
this->currentRequest = ISMAS::REQUEST::SELF;
|
|||
|
this->apismTcpRequestResponseClient->sendData("#M=APISM#C=REQ_SELF#J={}");
|
|||
|
}
|
|||
|
|
|||
|
void ApismClient::sendRequestParameter() {
|
|||
|
this->currentRequest = ISMAS::REQUEST::PARAMETER;
|
|||
|
this->apismTcpRequestResponseClient->sendData("#M=APISM#C=REQ_ISMASPARAMETER#J={}");
|
|||
|
}
|
|||
|
|
|||
|
void ApismClient::handleISMASResponseError()
|
|||
|
{
|
|||
|
switch (this->currentRequest) {
|
|||
|
case ISMAS::REQUEST::NO_REQUEST:
|
|||
|
qCritical() << "ApismClient::onReceivedResponse() for unknown Request: " << currentRequest;
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PING:
|
|||
|
//emit this->sendMininformPingResponse(nsApismInterface::RESULT_STATE::ERROR_BACKEND, QJsonObject());
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::SELF:
|
|||
|
//emit this->sendReqSelfResponse(nsApismInterface::RESULT_STATE::ERROR_BACKEND, QJsonObject());
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PARAMETER:
|
|||
|
//emit this->sendReqParameterResponse(nsApismInterface::RESULT_STATE::ERROR_BACKEND, QJsonObject());
|
|||
|
break;
|
|||
|
}
|
|||
|
this->currentRequest = ISMAS::REQUEST::NO_REQUEST;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void ApismClient::handleISMASOfflineResponseError()
|
|||
|
{
|
|||
|
nsApismInterface::RESULT_STATE resultState;
|
|||
|
|
|||
|
if (this->retryCounter < 50) {
|
|||
|
resultState = nsApismInterface::RESULT_STATE::ERROR_RETRY;
|
|||
|
this->retryCounter++;
|
|||
|
}
|
|||
|
else {
|
|||
|
resultState = nsApismInterface::RESULT_STATE::ERROR_BACKEND;
|
|||
|
this->retryCounter = 0;
|
|||
|
}
|
|||
|
|
|||
|
qCritical() << "ApismClient::handleISMASOfflineResponseError(): currentRequest is " << this->currentRequest;
|
|||
|
|
|||
|
|
|||
|
switch (this->currentRequest) {
|
|||
|
case ISMAS::REQUEST::NO_REQUEST:
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PING:
|
|||
|
//emit this->sendMininformPingResponse(resultState, QJsonObject());
|
|||
|
//break;
|
|||
|
case ISMAS::REQUEST::SELF:
|
|||
|
emit this->sendReqSelfResponse(resultState, QJsonObject());
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PARAMETER:
|
|||
|
emit this->sendReqParameterResponse(resultState, QJsonObject());
|
|||
|
break;
|
|||
|
}
|
|||
|
this->currentRequest = ISMAS::REQUEST::NO_REQUEST;
|
|||
|
|
|||
|
// note: this does not work here, because a new request within this error handling method
|
|||
|
// must use a new socket connection!
|
|||
|
// This does not work with an allready open socket connection.
|
|||
|
/* Communication to APISM must be in the following way:
|
|||
|
* 1) establish socket connection
|
|||
|
* 2) send your request to this socket
|
|||
|
* 3) wait for a possible answer
|
|||
|
* 4) receive the answer
|
|||
|
* 5) close socket connection
|
|||
|
*
|
|||
|
* => a request can only be sent to apsim if the socket is closed!
|
|||
|
* => apism (socket) is blocked systemwide until socket is closed!
|
|||
|
* =>
|
|||
|
*/
|
|||
|
|
|||
|
//this->sendSelfTest();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void ApismClient::private_handleErrorResponse(QString errorString)
|
|||
|
{
|
|||
|
qCritical() << "------------------------------------------------------";
|
|||
|
qCritical() << "ApismClient::private_handleErrorResponse(" << errorString << ")";
|
|||
|
qCritical() << " this->retryCounter = " << this->retryCounter;
|
|||
|
qCritical() << "------------------------------------------------------";
|
|||
|
|
|||
|
this->handleISMASOfflineResponseError();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
{\r\n \"REQ_START#53365_Response\": {\r\n \"Aknoledge\": \"OK\"\r\n },
|
|||
|
\r\n \"Response\": {\r\n \"Result\": \"ERR:Ung<6E>ltiger Datums-String: \"\r\n }\r\n}
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
: ISMAS received: "{\r\n \"REQ_PING#30844_Response\": {\r\n \"Aknoledge\": \"OK\"\r\n },
|
|||
|
"PING": { "IsAviable": "TRUE" }
|
|||
|
}"
|
|||
|
*/
|
|||
|
|
|||
|
//void ApismClient::onSendClientResponseTimeout()
|
|||
|
//{
|
|||
|
//
|
|||
|
//}
|
|||
|
|
|||
|
void ApismClient::private_handleReqSelfResponse(QJsonObject response)
|
|||
|
{
|
|||
|
bool ismasConnected = response["ISMAS"].toBool();
|
|||
|
QString brokerConnectedString = response["Broker"].toString();
|
|||
|
|
|||
|
qCritical() << "ApismClient::handleReqSelfResponse() " << endl
|
|||
|
<< " ismasConnected = " << ismasConnected << endl
|
|||
|
<< " brokerConnectedString = " << brokerConnectedString;
|
|||
|
|
|||
|
/* possible values: "Restart connection"
|
|||
|
* "Connected"
|
|||
|
* "NOT CONNECTED"
|
|||
|
*/
|
|||
|
if (brokerConnectedString == "NOT CONNECTED") {
|
|||
|
qCritical() << "ApismClient: \"NOT CONNECTED\": restart APISM";
|
|||
|
this->restartApism();
|
|||
|
}
|
|||
|
|
|||
|
emit this->sendReqSelfResponse(nsApismInterface::RESULT_STATE::SUCCESS, response);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* sample parameter response:
|
|||
|
{
|
|||
|
"REQ_ISMASPARAMETER#4210959_Response": {
|
|||
|
"Aknoledge": "OK"
|
|||
|
},
|
|||
|
"Dev_ID": {
|
|||
|
"Device_Type": "2020",
|
|||
|
"Custom_ID": 332,
|
|||
|
"Device_ID": 99
|
|||
|
},
|
|||
|
"Fileupload": {
|
|||
|
"TRG": ""
|
|||
|
},
|
|||
|
"Parameter": {
|
|||
|
"Location": "An Der Bahn 11",
|
|||
|
"Group": "Group1",
|
|||
|
"Zone": "Zone1",
|
|||
|
"Name": "PSA",
|
|||
|
"SecNumber": "0",
|
|||
|
"LastAcc": "0",
|
|||
|
"GPSLat": "49.6062",
|
|||
|
"GPSLon": "12.1244",
|
|||
|
"TarifID": "none",
|
|||
|
"UserTextID": "1"
|
|||
|
"TERMINALID": "",
|
|||
|
"TERMINALKEY": ""
|
|||
|
},
|
|||
|
"Lock": {
|
|||
|
"Locked": "0"
|
|||
|
}
|
|||
|
}
|
|||
|
*/
|
|||
|
void ApismClient::private_handleParameterResponse(QJsonObject response)
|
|||
|
{
|
|||
|
// extract location info and store location info in persistent data:
|
|||
|
QJsonValue jsonSubVal_Location;
|
|||
|
jsonSubVal_Location = response["Location"];
|
|||
|
|
|||
|
QString locationString = jsonSubVal_Location.toString("no location");
|
|||
|
|
|||
|
//this->persistentData->setParameter("Location", locationString);
|
|||
|
|
|||
|
// feature UserText
|
|||
|
QJsonValue jsonSubVal_UserText;
|
|||
|
jsonSubVal_UserText = response["UserTextID"];
|
|||
|
QString userTextIdString = jsonSubVal_UserText.toString("0");
|
|||
|
//this->persistentData->setParameter("UserTextID", userTextIdString);
|
|||
|
|
|||
|
// TERMINALID
|
|||
|
//QJsonValue jsonSubVal_TERMINALID;
|
|||
|
//jsonSubVal_TERMINALID = response["TERMINALID"];
|
|||
|
//QString terminalIdString = jsonSubVal_TERMINALID.toString("");
|
|||
|
//QString terminalIdFile = this->m_config->getSystemDataPath() + "TERMINALID";
|
|||
|
//QString terminalIdStringOrigin = ATBSystem::readPSAConfigString(terminalIdFile);
|
|||
|
//if ( (terminalIdString.size() > 1) &&
|
|||
|
// (terminalIdString != terminalIdStringOrigin))
|
|||
|
//{
|
|||
|
// qCritical() << "ApismClient::handleParameterResponse(): new TERMINALID: " << terminalIdString;
|
|||
|
// ATBSystem::setPSAConfigString(terminalIdFile, terminalIdString);
|
|||
|
//}
|
|||
|
|
|||
|
// TERMINALKEY
|
|||
|
//QJsonValue jsonSubVal_TERMINALKEY;
|
|||
|
//jsonSubVal_TERMINALKEY = response["TERMINALKEY"];
|
|||
|
//QString terminalKeyString = jsonSubVal_TERMINALKEY.toString("");
|
|||
|
//QString terminalJeyFile = this->m_config->getSystemDataPath() + "TERMINALKEY";
|
|||
|
//QString terminalKeyStringOrigin = ATBSystem::readPSAConfigString(terminalJeyFile);
|
|||
|
//if ( (terminalKeyString.size() > 1) &&
|
|||
|
// (terminalKeyString != terminalKeyStringOrigin))
|
|||
|
//{
|
|||
|
// qCritical() << "ApismClient::handleParameterResponse(): new TERMINALKEY: " << terminalKeyString;
|
|||
|
//
|
|||
|
|
|||
|
// ATBSystem::setPSAConfigString(terminalJeyFile, terminalKeyString);
|
|||
|
//}
|
|||
|
|
|||
|
|
|||
|
//qCritical() << "ApismClient::handleParameterResponse() " << endl
|
|||
|
// << " Location = " << locationString << endl
|
|||
|
// << " UserTextID = " << userTextIdString << endl
|
|||
|
// << " TERMINALID = " << terminalIdString << endl
|
|||
|
// << " TERMINALKEY = " << terminalKeyString;
|
|||
|
|
|||
|
|
|||
|
if (locationString != "no location") {
|
|||
|
this->flagValidParameter = true;
|
|||
|
emit this->sendReqParameterResponse(nsApismInterface::RESULT_STATE::SUCCESS, response);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void ApismClient::private_handleFileUploadResponse(QJsonObject response) {
|
|||
|
QJsonValue jsonSubVal_TRG{response["TRG"]};
|
|||
|
if (jsonSubVal_TRG.isUndefined()) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
bool updateRequested = (jsonSubVal_TRG.toString("") == "WAIT");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************************************
|
|||
|
* operators
|
|||
|
*/
|
|||
|
QDebug operator<< (QDebug debug, ISMAS::REQUEST request)
|
|||
|
{
|
|||
|
switch(request) {
|
|||
|
case ISMAS::REQUEST::NO_REQUEST:
|
|||
|
debug << QString("ISMAS::REQUEST::NO_REQUEST");
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PING:
|
|||
|
debug << QString("ISMAS::REQUEST::PING");
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::SELF:
|
|||
|
debug << QString("ISMAS::REQUEST::SELF");
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PARAMETER:
|
|||
|
debug << QString("ISMAS::REQUEST::PARAMETER");
|
|||
|
break;
|
|||
|
}
|
|||
|
return debug;
|
|||
|
}
|
|||
|
|
|||
|
QString& operator<< (QString& str, ISMAS::REQUEST request)
|
|||
|
{
|
|||
|
switch(request) {
|
|||
|
case ISMAS::REQUEST::NO_REQUEST:
|
|||
|
str = QString("ISMAS::REQUEST::NO_REQUEST");
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PING:
|
|||
|
str = QString("ISMAS::REQUEST::PING");
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::SELF:
|
|||
|
str = QString("ISMAS::REQUEST::SELF");
|
|||
|
break;
|
|||
|
case ISMAS::REQUEST::PARAMETER:
|
|||
|
str = QString("ISMAS::REQUEST::PARAMETER");
|
|||
|
break;
|
|||
|
}
|
|||
|
return str;
|
|||
|
}
|
|||
|
|