diff --git a/headers/baseconn.h b/headers/baseconn.h index e3fed20..928aa1f 100644 --- a/headers/baseconn.h +++ b/headers/baseconn.h @@ -67,7 +67,7 @@ private: struct waitingRequest { int id; QEventLoop * loop; - QString reply; + QJsonObject reply; }; QList waitingRequests; @@ -93,12 +93,18 @@ signals: void nextRemoteActionDelayProgChanged(); + void gotError(QString error); + public slots: Q_INVOKABLE bool connectToHost(); //function to connect to the base station - Q_INVOKABLE QString sendCommand(QString command); + Q_INVOKABLE void closeConnection(); + + void gotError(QAbstractSocket::SocketError err); + + Q_INVOKABLE QVariantMap sendCommand(int header, QJsonValue data); Q_INVOKABLE bool refreshConnections(); diff --git a/sources/baseconn.cpp b/sources/baseconn.cpp index c7f2822..e598ec7 100644 --- a/sources/baseconn.cpp +++ b/sources/baseconn.cpp @@ -4,7 +4,9 @@ BaseConn::BaseConn(QObject *parent) : QObject(parent) { socket = new QTcpSocket(); this->setState("disconnected"); - remoteSessions.release(1); + + connect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(gotError(QAbstractSocket::SocketError))); this->nextConnectionId = 1; @@ -55,33 +57,91 @@ bool BaseConn::connectToHost() { return(true); } -QString BaseConn::sendCommand(QString command){ +void BaseConn::closeConnection() +{ + qDebug() << "closing connection"; + switch (socket->state()) + { + case 0: + socket->disconnectFromHost(); + break; + case 2: + socket->abort(); + break; + default: + socket->abort(); + } + setState("disconnected"); +// for(int i = 0; i < this->waitingRequests.length(); i++){ +// this->waitingRequests[i].reply = "ERR_NOT_CONNECTED"; +// this->waitingRequests[i].loop->quit(); +// return; +// } +} + +void BaseConn::gotError(QAbstractSocket::SocketError err) +{ + //qDebug() << "got error"; + QString strError = "unknown"; + switch (err) + { + case 0: + strError = "Connection was refused"; + break; + case 1: + strError = "Remote host closed the connection"; + this->closeConnection(); + break; + case 2: + strError = "Host address was not found"; + break; + case 5: + strError = "Connection timed out"; + break; + default: + strError = "Unknown error"; + } + + emit gotError(strError); + qDebug() << "got socket error: " << strError; +} + +QVariantMap BaseConn::sendCommand(int header, QJsonValue data = ""){ if(this->state != "connected"){ - return "ERR_NOT_CONNECTED"; + return {{"status", 910}, {"data", "not connected"}}; } // generate id and witing requests entry int thisId = nextConnectionId; nextConnectionId ++; - QEventLoop loop; - this->waitingRequests.append({thisId, &loop, ""}); - command = "ID:" + QString::number(thisId) + "_"+command; + QEventLoop loop; + QJsonObject reply; + + this->waitingRequests.append({thisId, &loop, reply}); + + QJsonObject requestObj; + requestObj.insert("id", thisId); + requestObj.insert("header", header); + requestObj.insert("data", data); + + + QString jsonRequest = QJsonDocument(requestObj).toJson(); QByteArray arrBlock; QDataStream out(&arrBlock, QIODevice::WriteOnly); //out.setVersion(QDataStream::Qt_5_10); - out << quint16(0) << command; + out << quint16(0) << jsonRequest; out.device()->seek(0); - out << quint16(arrBlock.size() - sizeof(quint16)); + out << quint16(ulong(arrBlock.size()) - sizeof(quint16)); QTimer timer; timer.setSingleShot(true); // quit the loop when the timer times out loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); - //quit the loop when the connection was established + // quit the loop when the connection was established // loop.connect(this, &BaseConn::gotReply, &loop, &QEventLoop::quit); // start the timer before starting to connect timer.start(3000); @@ -97,11 +157,9 @@ QString BaseConn::sendCommand(QString command){ if(timer.remainingTime() == -1){ //the time has been triggered -> timeout - return("ERR_TIMEOUT"); + return {{"status", 911}, {"data", ""}}; } - QString reply; - for(int i = 0; iwaitingRequests.length(); i++){ if(this->waitingRequests[i].id == thisId){ reply = this->waitingRequests[i].reply; @@ -114,7 +172,8 @@ QString BaseConn::sendCommand(QString command){ timer.deleteLater(); //remoteSessions.release(1); - return(reply); + return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}}; + } void BaseConn::readyRead() { @@ -125,7 +184,7 @@ void BaseConn::readyRead() { { if (!nextBlockSize) { - if (socket->bytesAvailable() < sizeof(quint16)) { break; } + if (ulong(socket->bytesAvailable()) < sizeof(quint16)) { break; } in >> nextBlockSize; } @@ -142,15 +201,16 @@ void BaseConn::readyRead() { nextBlockSize = 0; QString reply = str; int id = 0; - if(reply.startsWith("ID:")){ - reply.replace("ID:", ""); - QStringList temp = reply.split("_"); - reply.replace(temp[0]+"_", ""); - id = temp[0].toInt(); - for(int i = 0; iwaitingRequests.length(); i++){ + QJsonDocument jsonReply = QJsonDocument::fromJson(reply.toUtf8()); + QJsonObject replyObj = jsonReply.object(); + + if(!replyObj.isEmpty()){ + id = replyObj.value("id").toInt(); + + for(int i = 0; i < this->waitingRequests.length(); i++){ if(this->waitingRequests[i].id == id){ - this->waitingRequests[i].reply = reply; + this->waitingRequests[i].reply = replyObj; this->waitingRequests[i].loop->quit(); return; } @@ -176,20 +236,20 @@ void BaseConn::refreshTimers(){ QString tmpNextRemoteAction; QString tmpNextRemoteActionDelayProg; - remoteState = sendCommand("GET_TIMER_STATE"); + remoteState = sendCommand(2000)["data"].toString(); switch (speedTimers[0]->state) { case SpeedTimer::IDLE: break; case SpeedTimer::STARTING: - if(remoteState == "RUNNING"){ + if(remoteState == "2"){ speedTimers[0]->start(); } - else if (remoteState == "STOPPED") { + else if (remoteState == "3") { speedTimers[0]->stop("manual"); } - tmpNextRemoteAction = sendCommand("GET_NEXT_ACTION"); + tmpNextRemoteAction = sendCommand(2004)["data"].toString(); if(tmpNextRemoteAction.startsWith("ERR")){ //handle Error!! } @@ -200,7 +260,7 @@ void BaseConn::refreshTimers(){ } } - tmpNextRemoteActionDelayProg = sendCommand("GET_NEXT_ACTION_DELAY_PROG"); + tmpNextRemoteActionDelayProg = sendCommand(2005)["data"].toFloat(); if(tmpNextRemoteActionDelayProg.startsWith("ERR")){ //handle error!! } @@ -214,7 +274,7 @@ void BaseConn::refreshTimers(){ break; case SpeedTimer::RUNNING: - if(remoteState == "STOPPED"){ + if(remoteState == "2"){ speedTimers[0]->stop("manual"); } remoteTime = sendCommand("GET_CURRTIME");