#include "ApismClient.h" #include #include #include #include #include #include #include #include #include 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(); // 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�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; }