This repository has been archived on 2024-06-03. You can view files and clone it, but cannot push or open issues or pull requests.
app/sources/baseconn.cpp
Dorian Zedler eeb939ed26 - added 'disconnect' functionality for base station
- made IP->adress of base station editable
- some cleanup
2019-03-29 23:42:56 +01:00

284 lines
7.3 KiB
C++

#include "headers/baseconn.h"
BaseConn * pGlobalBaseConn = nullptr;
BaseConn::BaseConn(QObject *parent) : QObject(parent)
{
pGlobalBaseConn = this;
socket = new QTcpSocket();
this->setState("disconnected");
connect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(gotError(QAbstractSocket::SocketError)));
connect(this->socket, &QAbstractSocket::stateChanged, this, &BaseConn::socketStateChanged);
this->nextConnectionId = 1;
this->connections = QVariantList({});
}
bool BaseConn::connectToHost() {
qDebug() << "connecting";
setState("connecting");
this->connection_progress = 0;
QEventLoop loop;
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
loop.connect(this->socket, SIGNAL(connected()), &loop, SLOT(quit()));
// start the timer before starting to connect
timer.start(3000);
//connect
this->socket->connectToHost(this->ip, this->port);
//wait for the connection to finish (programm gets stuck in here)
loop.exec();
//loop finish
if(timer.remainingTime() == -1){
//the time has been triggered -> timeout
this->socket->abort();
setState("disconnected");
return(false);
}
// stop the timer as the connection has been established
timer.stop();
connect(this->socket, &QTcpSocket::readyRead, this, &BaseConn::readyRead);
this->connection_progress = 100;
setState("connected");
return(true);
}
void BaseConn::closeConnection()
{
this->connections = QVariantList({});
emit this->connectionsChanged();
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 {{"status", 910}, {"data", "not connected"}};
}
// generate id and witing requests entry
int thisId = nextConnectionId;
nextConnectionId ++;
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();
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
// loop.connect(this, &BaseConn::gotReply, &loop, &QEventLoop::quit);
// start the timer before starting to connect
timer.start(3000);
//write data
socket->write(jsonRequest.toLatin1());
//wait for an answer to finish (programm gets stuck in here)
loop.exec();
//loop finished
if(timer.remainingTime() == -1){
//the time has been triggered -> timeout
return {{"status", 911}, {"data", ""}};
}
for(int i = 0; i<this->waitingRequests.length(); i++){
if(this->waitingRequests[i].id == thisId){
reply = this->waitingRequests[i].reply;
}
}
// stop the timer as the connection has been established
timer.stop();
timer.deleteLater();
//remoteSessions.release(1);
return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}};
}
void BaseConn::readyRead() {
QString reply = socket->readAll();
int id = 0;
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 = replyObj;
this->waitingRequests[i].loop->quit();
return;
}
}
}
latestReadReply = reply;
emit gotUnexpectedReply(reply);
}
int BaseConn::writeRemoteSetting(QString key, QString value) {
QJsonArray requestData;
requestData.append(key);
requestData.append(value);
return this->sendCommand(3000, requestData)["status"].toInt();
}
void BaseConn::setIP(const QString &ipAdress){
this->ip = ipAdress;
}
QString BaseConn::getIP() const
{
return(this->ip);
}
QString BaseConn::getState() const
{
return(this->state);
}
void BaseConn::setState(QString newState){
this->state = newState;
emit stateChanged();
}
void BaseConn::socketStateChanged(QAbstractSocket::SocketState socketState) {
switch (socketState) {
case QAbstractSocket::UnconnectedState:
{
this->setState("disconnected");
break;
}
case QAbstractSocket::ConnectedState:
{
this->setState("connected");
break;
}
default:
{
qDebug() << "+ --- UNKNOWN SOCKET STATE: " << socketState;
break;
}
}
}
int BaseConn::getProgress() const
{
return(connection_progress);
}
bool BaseConn::refreshConnections() {
QVariantMap reply = this->sendCommand(2006);
if(reply["status"] != 200){
//handle Error!!
if(reply["status"] == 910){
this->connections = QVariantList({});
return true;
}
qDebug() << "+ --- error refreshing connections: " << reply["status"];
return false;
}
QVariantList tmpConnections = reply["data"].toList();
if(this->connections != reply["data"].toList()){
this->connections = reply["data"].toList();
emit this->connectionsChanged();
}
return true;
}
QVariant BaseConn::getConnections() {
return(connections);
/*
"id": "id of the extention (int)",
"type": "type of the extention (can be: 'STARTPAD', 'TOPPAD')",
"name": "name of the extention",
"ip": "ip-adress of he extention (string)",
"state": "state of the extention (can be: 'disconnected', 'connecting', 'connected')"
*/
//QVariantMap conn = {{"id",0}, {"type","STARTPAD"}, {"name", "startpad1"}, {"ip", "192.168.4.11"}, {"state", "connected"}};
//QVariantMap conn1 = {{"id",0}, {"type","TOPPAD"}, {"name", "buzzer1"}, {"ip", "192.168.4.10"}, {"state", "connected"}};
//QVariantList conns = {conn, conn1};
//return conns;
}