diff --git a/headers/baseconn.h b/headers/baseconn.h index 5be052e..467eafe 100644 --- a/headers/baseconn.h +++ b/headers/baseconn.h @@ -55,8 +55,6 @@ private: QString readBuffer; - QSemaphore remoteSessions; - int nextConnectionId; struct waitingRequest { @@ -76,6 +74,8 @@ signals: void gotUnexpectedReply(QString reply); + void gotUpdate(QVariant data); + void connectionsChanged(); void connectionSlotReleased(); diff --git a/headers/climbingrace.h b/headers/climbingrace.h index c64d49c..f85e932 100644 --- a/headers/climbingrace.h +++ b/headers/climbingrace.h @@ -63,7 +63,7 @@ private slots: void refreshMode(); void refreshTimerText(); - bool refreshRemoteTimers(); + bool refreshRemoteTimers(QVariantList timers); signals: void nextStartActionChanged(int nextStartAction); @@ -80,7 +80,9 @@ public slots: Q_INVOKABLE int stopRace(int type); Q_INVOKABLE int resetRace(); + // base station sync void syncWithBaseStation(); + void handleBaseStationUpdate(QVariant data); // functions for qml Q_INVOKABLE int getState(); diff --git a/sources/baseconn.cpp b/sources/baseconn.cpp index b948530..3bb8a16 100644 --- a/sources/baseconn.cpp +++ b/sources/baseconn.cpp @@ -47,6 +47,16 @@ bool BaseConn::init() { connect(this->socket, &QTcpSocket::readyRead, this, &BaseConn::readyRead); this->connection_progress = 50; + this->setState("connected"); + + // init remote session + QJsonArray updateSubs = {"onRaceStateChanged", "onTimersChanged"}; + QJsonObject sessionParams = {{"updateSubs", updateSubs}}; + + if(this->sendCommand(1, sessionParams)["status"] != 200) { + return false; + } + return true; } @@ -115,10 +125,7 @@ void BaseConn::socketStateChanged(QAbstractSocket::SocketState socketState) { } case QAbstractSocket::ConnectedState: { - if(this->init()) { - this->setState("connected"); - } - else { + if(!this->init()) { this->closeConnection(); } @@ -274,11 +281,16 @@ void BaseConn::socketReplyRecieved(QString reply) { QJsonDocument jsonReply = QJsonDocument::fromJson(reply.toUtf8()); QJsonObject replyObj = jsonReply.object(); - //qDebug() << "got: " << reply; - if(!replyObj.isEmpty()){ id = replyObj.value("id").toInt(); + if(id == -1) { + // this message is an update!! + emit this->gotUpdate(replyObj.toVariantMap()); + return; + } + + // this message is the reply to a command! for(int i = 0; i < this->waitingRequests.length(); i++){ if(this->waitingRequests[i].id == id){ this->waitingRequests[i].reply = replyObj; diff --git a/sources/climbingrace.cpp b/sources/climbingrace.cpp index ba58039..62685dc 100644 --- a/sources/climbingrace.cpp +++ b/sources/climbingrace.cpp @@ -22,6 +22,7 @@ ClimbingRace::ClimbingRace(QObject *parent) : QObject(parent) connect(this->baseConn, &BaseConn::stateChanged, this, &ClimbingRace::baseStationStateChanged); connect(this->baseConn, &BaseConn::stateChanged, this, &ClimbingRace::refreshMode); connect(this->baseConn, &BaseConn::connectionsChanged, this, &ClimbingRace::baseStationConnectionsChanged); + connect(this->baseConn, &BaseConn::gotUpdate, this, &ClimbingRace::handleBaseStationUpdate); this->speedTimers.append( new SpeedTimer(this) ); @@ -32,7 +33,7 @@ ClimbingRace::ClimbingRace(QObject *parent) : QObject(parent) nextStartActionTimer->setSingleShot(true); this->baseStationSyncTimer = new QTimer(this); - this->baseStationSyncTimer->setInterval(100); + this->baseStationSyncTimer->setInterval(1000); this->baseStationSyncTimer->setSingleShot(true); this->baseStationSyncTimer->connect(this->baseStationSyncTimer, &QTimer::timeout, this, &ClimbingRace::syncWithBaseStation); this->baseStationSyncTimer->start(); @@ -213,7 +214,17 @@ void ClimbingRace::syncWithBaseStation() { case 1: { // case STARTING - this->refreshRemoteTimers(); + + // refresh remote timers + tmpReply = this->baseConn->sendCommand(2007); + + if(tmpReply["status"].toInt() != 200){ + //handle error!! + qDebug() << "+ --- getting timers from basestation failed"; + } + else { + this->refreshRemoteTimers(tmpReply["data"].toList()); + } tmpReply = this->baseConn->sendCommand(2005); if(tmpReply["status"] != 200){ @@ -232,7 +243,15 @@ void ClimbingRace::syncWithBaseStation() { default: { - this->refreshRemoteTimers(); + tmpReply = this->baseConn->sendCommand(2007); + + if(tmpReply["status"].toInt() != 200){ + //handle error!! + qDebug() << "+ --- getting timers from basestation failed"; + } + else { + this->refreshRemoteTimers(tmpReply["data"].toList()); + } break; } @@ -241,6 +260,65 @@ void ClimbingRace::syncWithBaseStation() { this->baseStationSyncTimer->start(); } +/** + * @brief ClimbingRace::handleBaseStationUpdate + * + * Function to handle a update, sent by the base station, which indicates + * that some remote value (like a state) has changed + * + * @param data + */ +void ClimbingRace::handleBaseStationUpdate(QVariant data) { + qDebug() << "got update: " << data; + int header = data.toMap()["header"].toInt(); + switch (header) { + case 9000: + { + // the remote race state has changed + this->setState( raceState( data.toMap()["data"].toInt() ) ); + break; + } + case 9001: + { + // the remote timers have changed + this->refreshRemoteTimers(data.toMap()["data"].toList()); + break; + } + + } +} + +bool ClimbingRace::refreshRemoteTimers(QVariantList timers) { + + if(timers.length() != speedTimers.length()){ + // local timers are out of sync + + // delete all current timers + foreach(SpeedTimer * locTimer, this->speedTimers){ + delete locTimer; + } + + speedTimers.clear(); + + foreach(QVariant remTimer, timers){ + // create a local timer for each remote timer + this->speedTimers.append(new SpeedTimer(this)); + } + } + + foreach(QVariant remTimer, timers){ + int currId = remTimer.toMap()["id"].toInt(); + speedTimers[currId]->startTime = this->date->currentMSecsSinceEpoch() - remTimer.toMap()["currTime"].toDouble(); + speedTimers[currId]->stoppedTime = remTimer.toMap()["currTime"].toDouble(); + speedTimers[currId]->reactionTime = remTimer.toMap()["reactTime"].toDouble(); + + speedTimers[currId]->setState(SpeedTimer::timerState(remTimer.toMap()["state"].toInt())); + } + + return true; + +} + // ------------------------ // --- helper functions --- // ------------------------ @@ -435,48 +513,6 @@ void ClimbingRace::refreshTimerText() { this->timerTextRefreshTimer->start(); } -bool ClimbingRace::refreshRemoteTimers() { - // get current time - QVariantMap tmpReply = this->baseConn->sendCommand(2007); - - if(tmpReply["status"].toInt() != 200){ - //handle error!! - qDebug() << "+ --- getting timers from basestation failed"; - this->baseStationSyncTimer->start(); - return false; - } - else { - QVariantList timers = tmpReply["data"].toList(); - - if(timers.length() != speedTimers.length()){ - // local timers are out of sync - - // delete all current timers - foreach(SpeedTimer * locTimer, this->speedTimers){ - delete locTimer; - } - - speedTimers.clear(); - - foreach(QVariant remTimer, timers){ - // create a local timer for each remote timer - this->speedTimers.append(new SpeedTimer(this)); - } - } - - foreach(QVariant remTimer, timers){ - int currId = remTimer.toMap()["id"].toInt(); - speedTimers[currId]->startTime = this->date->currentMSecsSinceEpoch() - remTimer.toMap()["currTime"].toDouble(); - speedTimers[currId]->stoppedTime = remTimer.toMap()["currTime"].toDouble(); - speedTimers[currId]->reactionTime = remTimer.toMap()["reactTime"].toDouble(); - - speedTimers[currId]->setState(SpeedTimer::timerState(remTimer.toMap()["state"].toInt())); - } - - return true; - } -} - // - athlete management - QVariant ClimbingRace::getAthletes() {