ATBUpdateTool/common/ismas/ApismClient.cpp

337 lines
12 KiB
C++
Raw Normal View History

#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;
}