Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dorian Zedler 2021-03-19 12:05:51 +01:00
commit 43d9f80f60
Signed by: dorian
GPG Key ID: 989DE36109AFA354
8 changed files with 130 additions and 102 deletions

View File

@ -101,15 +101,14 @@ private:
QString readBuffer; QString readBuffer;
int nextConnectionId; unsigned int currentRequestId;
struct waitingRequest { struct WaitingRequest {
int id;
QEventLoop * loop; QEventLoop * loop;
QJsonObject reply; QJsonObject reply;
}; };
QList<waitingRequest> waitingRequests; QMap<int, WaitingRequest> waitingRequests;
public slots: public slots:
@ -152,7 +151,7 @@ public slots:
* \param key the key to read from * \param key the key to read from
* \return the value of the key or "false" if the key is not found or an error occured * \return the value of the key or "false" if the key is not found or an error occured
*/ */
QVariant readRemoteSetting(ScStwSettings::BaseStationSetting key); QVariant readRemoteSetting(ScStwSettings::BaseStationSetting key, ScStw::StatusCode* status = nullptr);
/*! Getter fuctions */ /*! Getter fuctions */

View File

@ -28,6 +28,7 @@ class ScStwSetting : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QVariant value READ getValue WRITE setValue NOTIFY valueChanged) Q_PROPERTY(QVariant value READ getValue WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(QVariant readonlyValue READ getValue NOTIFY valueChanged)
protected: protected:
explicit ScStwSetting(int key, int keyLevel, ScStwSettings*scStwSettings, QObject *parent); explicit ScStwSetting(int key, int keyLevel, ScStwSettings*scStwSettings, QObject *parent);

View File

@ -23,7 +23,7 @@ ScStwClient * pGlobalScStwClient = nullptr;
ScStwClient::ScStwClient(QObject * parent, QList<ScStw::SignalKey> signalSubscriptions) : QObject(parent) ScStwClient::ScStwClient(QObject * parent, QList<ScStw::SignalKey> signalSubscriptions) : QObject(parent)
{ {
this->state = DISCONNECTED; this->state = DISCONNECTED;
this->nextConnectionId = 1; this->currentRequestId = 1;
this->extensions = QVariantMap({}); this->extensions = QVariantMap({});
this->signalSubscriptions = signalSubscriptions; this->signalSubscriptions = signalSubscriptions;
@ -50,6 +50,9 @@ ScStwClient::ScStwClient(QObject * parent, QList<ScStw::SignalKey> signalSubscri
void ScStwClient::connectToHost() { void ScStwClient::connectToHost() {
if(this->state != DISCONNECTED)
return;
setState(CONNECTING); setState(CONNECTING);
//connect //connect
@ -84,7 +87,6 @@ bool ScStwClient::init() {
QVariantMap initResponse = this->sendCommand(1, sessionParams, 3000, false); QVariantMap initResponse = this->sendCommand(1, sessionParams, 3000, false);
if(initResponse["status"] != 200) { if(initResponse["status"] != 200) {
this->closeConnection();
return false; return false;
} }
@ -121,7 +123,17 @@ void ScStwClient::deInit() {
if(this->state == DISCONNECTED) if(this->state == DISCONNECTED)
return; return;
this->currentRequestId = 1;
this->firmwareVersion = "";
this->apiVersion = "";
this->setExtensions(QVariantMap({})); this->setExtensions(QVariantMap({}));
for(WaitingRequest waitingRequest : this->waitingRequests.values())
if(waitingRequest.loop != nullptr)
waitingRequest.loop->exit(ScStw::NotConnectedError);
this->waitingRequests.clear();
this->setState(DISCONNECTED); this->setState(DISCONNECTED);
} }
@ -160,16 +172,22 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
return {{"status", ScStw::NotConnectedError}, {"data", "not connected"}}; return {{"status", ScStw::NotConnectedError}, {"data", "not connected"}};
} }
// generate id and witing requests entry // pick a new request id that is not already active
int thisId = nextConnectionId; do {
if(this->currentRequestId >= 99)
this->currentRequestId = 0;
else
this->currentRequestId ++;
} while(this->waitingRequests.contains(this->currentRequestId));
int thisId = currentRequestId;
//qDebug() << "sending command: " << header << " with data: " << data << " and id: " << thisId; //qDebug() << "sending command: " << header << " with data: " << data << " and id: " << thisId;
nextConnectionId ++;
QEventLoop *loop = new QEventLoop(this); QEventLoop *loop = new QEventLoop(this);
QTimer *timer = new QTimer(this); QTimer *timer = new QTimer(this);
QJsonObject reply; QJsonObject reply;
this->waitingRequests.append({thisId, loop, reply}); this->waitingRequests.insert(thisId, {loop, reply});
QJsonObject requestObj; QJsonObject requestObj;
requestObj.insert("id", thisId); requestObj.insert("id", thisId);
@ -180,7 +198,7 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
timer->setSingleShot(true); timer->setSingleShot(true);
// quit the loop when the timer times out // quit the loop when the timer times out
loop->connect(timer, SIGNAL(timeout()), loop, SLOT(quit())); connect(timer, &QTimer::timeout, [=]{loop->exit(ScStw::TimeoutError);});
// start the timer before starting to connect // start the timer before starting to connect
timer->start(timeout); timer->start(timeout);
@ -191,37 +209,38 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
socket->write(jsonRequest.toUtf8()); socket->write(jsonRequest.toUtf8());
//wait for an answer to finish (programm gets stuck in here) //wait for an answer to finish (programm gets stuck in here)
loop->exec(); ScStw::StatusCode statusCode = ScStw::StatusCode(loop->exec());
// delete the timer
timer->deleteLater();
bool replyFound = false;
// find reply and delete the request from waiting list // find reply and delete the request from waiting list
for(int i = 0; i<this->waitingRequests.length(); i++){ if(this->waitingRequests.contains(thisId)) {
if(this->waitingRequests[i].id == thisId){ // request was found
// request was found // delete event loop
replyFound = true; if(this->waitingRequests[thisId].loop != nullptr) {
// delete event loop this->waitingRequests[thisId].loop->deleteLater();
if(this->waitingRequests[i].loop != nullptr) {
delete this->waitingRequests[i].loop;
}
// store reply
reply = this->waitingRequests[i].reply;
// remove reply from waiting list
this->waitingRequests.removeAt(i);
} }
}
if(!replyFound) { // store reply
reply = this->waitingRequests[thisId].reply;
// remove reply from waiting list
this->waitingRequests.remove(thisId);
}
else {
// some internal error occured // some internal error occured
return {{"status", ScStw::Error}, {"data", ""}}; return {{"status", ScStw::InternalError}, {"data", ""}};
} }
if(timer->remainingTime() == -1){ if(statusCode == ScStw::TimeoutError){
//the time has been triggered -> timeout //the time has been triggered -> timeout
return {{"status", ScStw::TimeoutError}, {"data", ""}}; return {{"status", ScStw::TimeoutError}, {"data", ""}};
} }
else if(statusCode == ScStw::NotConnectedError) {
// connection was closed during request
return {{"status", ScStw::NotConnectedError}, {"data", ""}};
}
delete timer; delete timer;
return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}}; return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}};
@ -273,7 +292,6 @@ void ScStwClient::handleReadyRead() {
//qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ; //qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ;
QString reply = socket->readAll(); QString reply = socket->readAll();
//qWarning() << "socket read: " << reply; //qWarning() << "socket read: " << reply;
processSocketMessage(reply); processSocketMessage(reply);
@ -335,7 +353,7 @@ void ScStwClient::handleSocketMessage(QString reply) {
reply.replace(ScStw::SOCKET_MESSAGE_START_KEY, ""); reply.replace(ScStw::SOCKET_MESSAGE_START_KEY, "");
reply.replace(ScStw::SOCKET_MESSAGE_END_KEY, ""); reply.replace(ScStw::SOCKET_MESSAGE_END_KEY, "");
//qDebug() << "got message: " << reply; qDebug() << "got message: " << qPrintable(reply);
int id = 0; int id = 0;
@ -352,14 +370,12 @@ void ScStwClient::handleSocketMessage(QString reply) {
} }
// this message is the reply to a command! // this message is the reply to a command!
for(int i = 0; i < this->waitingRequests.length(); i++){ if(this->waitingRequests.contains(id)){
if(this->waitingRequests[i].id == id){ this->waitingRequests[id].reply = replyObj;
this->waitingRequests[i].reply = replyObj; if(this->waitingRequests[id].loop != nullptr){
if(this->waitingRequests[i].loop != nullptr){ this->waitingRequests[id].loop->exit(ScStw::Success);
this->waitingRequests[i].loop->quit();
}
return;
} }
return;
} }
} }
@ -404,8 +420,13 @@ ScStw::StatusCode ScStwClient::writeRemoteSetting(ScStwSettings::BaseStationSett
return ScStw::StatusCode(this->sendCommand(3000, requestData)["status"].toInt()); return ScStw::StatusCode(this->sendCommand(3000, requestData)["status"].toInt());
} }
QVariant ScStwClient::readRemoteSetting(ScStwSettings::BaseStationSetting key) { QVariant ScStwClient::readRemoteSetting(ScStwSettings::BaseStationSetting key, ScStw::StatusCode* status) {
QVariantMap reply = this->sendCommand(3001, int(key)); QVariantMap reply = this->sendCommand(3001, int(key), 10000);
qDebug() << "Setting read status is: " << reply["status"];
if(status != nullptr)
*status = ScStw::StatusCode(reply["status"].toInt());
if(reply["status"] != 200){ if(reply["status"] != 200){
return "false"; return "false";
} }

View File

@ -102,8 +102,8 @@ ScStw::StatusCode ScStwRemoteRace::setTimerDisabled(int timerId, bool disabled)
qDebug() << "+ --- setting timer " << timerId << " to disabled: " << disabled; qDebug() << "+ --- setting timer " << timerId << " to disabled: " << disabled;
QVariantMap requestData = { QVariantMap requestData = {
{"timerId", timerId}, {"timerId", timerId},
{"disabled", disabled} {"disabled", disabled}
}; };
QVariantMap reply = this->scStwClient->sendCommand(ScStw::SetTimerDisabledCommand, QJsonValue::fromVariant(requestData)); QVariantMap reply = this->scStwClient->sendCommand(ScStw::SetTimerDisabledCommand, QJsonValue::fromVariant(requestData));
@ -125,11 +125,12 @@ void ScStwRemoteRace::handleClientStateChange() {
// delete all obsolete remote timers // delete all obsolete remote timers
for(ScStwRemoteTimer* oldRemoteTimer : this->remoteTimers) for(ScStwRemoteTimer* oldRemoteTimer : this->remoteTimers)
oldRemoteTimer->deleteLater(); oldRemoteTimer->deleteLater();
this->remoteTimers.clear(); this->remoteTimers.clear();
break; break;
case ScStwClient::DISCONNECTED: case ScStwClient::DISCONNECTED:
this->remoteTimers.clear(); this->remoteTimers.clear();
this->setTimers(this->localTimers, true); this->setTimers(this->localTimers, false);
emit this->timersChanged(); emit this->timersChanged();
emit this->detailsChanged(); emit this->detailsChanged();
emit this->currentStartDelayChanged(); emit this->currentStartDelayChanged();
@ -141,6 +142,30 @@ void ScStwRemoteRace::handleClientStateChange() {
} }
} }
void ScStwRemoteRace::setTimers(QList<ScStwTimer*> timers, bool deleteOldTimers) {
// disconnect all signals of all current timers
//qDebug() << "SETTING TIMERS";
foreach(ScStwTimer *existingTimer, this->timers) {
disconnect(existingTimer, &ScStwTimer::stateChanged, this, &ScStwRace::handleTimerStateChange);
disconnect(existingTimer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged);
disconnect(existingTimer, &ScStwTimer::wantsToBeDisabledChanged, this, &ScStwRace::handleTimerWantsToBeDisabledChange);
disconnect(existingTimer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged);
disconnect(existingTimer, &ScStwTimer::readyStateChanged, this, &ScStwRace::handleTimerReadyStateChange);
disconnect(existingTimer, &ScStwTimer::readyStateChanged, this, &ScStwRace::isReadyForNextStateChanged);
if(deleteOldTimers)
existingTimer->deleteLater();
}
this->timers.clear();
for(ScStwTimer* timer : timers) {
this->addTimer(timer);
}
}
ScStwRemoteRace::RaceMode ScStwRemoteRace::getMode() { ScStwRemoteRace::RaceMode ScStwRemoteRace::getMode() {
if(this->scStwClient == nullptr || this->scStwClient->getState() != ScStwClient::CONNECTED) if(this->scStwClient == nullptr || this->scStwClient->getState() != ScStwClient::CONNECTED)
return LOCAL; return LOCAL;
@ -233,43 +258,43 @@ void ScStwRemoteRace::rebuildRemoteTimers(QVariantList remoteTimers) {
} }
} }
bool ScStwRemoteRace::refreshRemoteTimers(QVariantList remoteTimers) { bool ScStwRemoteRace::refreshRemoteTimers(QVariantList newRemoteTimers) {
qDebug() << "REFRESHING TIMERS"; qDebug() << "REFRESHING TIMERS";
if(remoteTimers.length() != this->remoteTimers.length()){ if(newRemoteTimers.length() != this->remoteTimers.length()){
// local timers are out of sync // local timers are out of sync
this->rebuildRemoteTimers(remoteTimers); this->rebuildRemoteTimers(newRemoteTimers);
qDebug() << "rebuilding remote timers"; qDebug() << "rebuilding remote timers";
} }
foreach(QVariant remoteTimer, remoteTimers){ for(QVariant remoteTimer : newRemoteTimers){
int currId = remoteTimer.toMap()["id"].toInt(); int currId = remoteTimer.toMap()["id"].toInt();
if(this->remoteTimers.length() <= currId) if(this->remoteTimers.length() <= currId)
this->rebuildRemoteTimers(remoteTimers); this->rebuildRemoteTimers(newRemoteTimers);
ScStwTimer::TimerState newState = ScStwTimer::TimerState(remoteTimer.toMap()["state"].toInt()); ScStwTimer::TimerState newState = ScStwTimer::TimerState(remoteTimer.toMap()["state"].toInt());
qDebug() << "refreshing timers: id: " << currId << " state: " << newState << " readyState: " << remoteTimer.toMap()["readyState"].toInt() << " currentTime: " << remoteTimer.toMap()["currentTime"].toDouble(); qDebug() << "refreshing timers: id: " << currId << " state: " << newState << " readyState: " << remoteTimer.toMap()["readyState"].toInt() << " currentTime: " << remoteTimer.toMap()["currentTime"].toDouble();
double currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); double currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
this->remoteTimers[currId]->setStartTime(currentMSecsSinceEpoch - remoteTimer.toMap()["currentTime"].toDouble()); this->remoteTimers[currId]->setStartTime(currentMSecsSinceEpoch - remoteTimer.toMap()["currentTime"].toDouble());
if(newState >= ScStwTimer::WAITING) if(newState >= ScStwTimer::WAITING)
this->remoteTimers[currId]->setStopTime(currentMSecsSinceEpoch); this->remoteTimers[currId]->setStopTime(currentMSecsSinceEpoch);
this->remoteTimers[currId]->setReactionTime(remoteTimer.toMap()["reactionTime"].toDouble()); this->remoteTimers[currId]->setReactionTime(remoteTimer.toMap()["reactionTime"].toDouble());
this->remoteTimers[currId]->setLetter(remoteTimer.toMap()["letter"].toString()); this->remoteTimers[currId]->setLetter(remoteTimer.toMap()["letter"].toString());
this->remoteTimers[currId]->setReadyState(ScStwTimer::ReadyState(remoteTimer.toMap()["readyState"].toInt())); this->remoteTimers[currId]->setReadyState(ScStwTimer::ReadyState(remoteTimer.toMap()["readyState"].toInt()));
this->remoteTimers[currId]->setState(newState); this->remoteTimers[currId]->setState(newState);
} }
emit this->timersChanged(); emit this->timersChanged();
return true; return true;
} }
bool ScStwRemoteRace::addTimer(ScStwTimer* timer) { bool ScStwRemoteRace::addTimer(ScStwTimer* timer) {
@ -281,30 +306,6 @@ bool ScStwRemoteRace::addTimer(ScStwTimer* timer) {
return false; return false;
} }
void ScStwRemoteRace::setTimers(QList<ScStwTimer*> timers, bool deleteOldTimers) {
// disconnect all signals of all current timers
qDebug() << "SETTING TIMERS";
foreach(ScStwTimer *existingTimer, this->timers) {
disconnect(existingTimer, &ScStwTimer::stateChanged, this, &ScStwRace::handleTimerStateChange);
disconnect(existingTimer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged);
disconnect(existingTimer, &ScStwTimer::wantsToBeDisabledChanged, this, &ScStwRace::handleTimerWantsToBeDisabledChange);
disconnect(existingTimer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged);
disconnect(existingTimer, &ScStwTimer::readyStateChanged, this, &ScStwRace::handleTimerReadyStateChange);
disconnect(existingTimer, &ScStwTimer::readyStateChanged, this, &ScStwRace::isReadyForNextStateChanged);
if(deleteOldTimers)
existingTimer->deleteLater();
}
this->timers.clear();
for(ScStwTimer* timer : timers) {
this->addTimer(timer);
}
}
QVariantMap ScStwRemoteRace::getCurrentStartDelay() { QVariantMap ScStwRemoteRace::getCurrentStartDelay() {
if(this->local()) if(this->local())
return ScStwRace::getCurrentStartDelay(); return ScStwRace::getCurrentStartDelay();

View File

@ -41,7 +41,13 @@ QVariant ScStwRemoteSettings::readSetting(QString key, int keyInt, int keyLevel)
qDebug() << "Setting read: keyLevel: " << keyLevel << " key: " << key; qDebug() << "Setting read: keyLevel: " << keyLevel << " key: " << key;
return this->scStwClient->readRemoteSetting(ScStwSettings::BaseStationSetting(keyInt)); ScStw::StatusCode status;
QVariant value = this->scStwClient->readRemoteSetting(ScStwSettings::BaseStationSetting(keyInt), &status);
if(status == ScStw::Success)
return value;
else
return QVariant();
} }
bool ScStwRemoteSettings::writeSetting(QString key, QVariant value, int keyInt, int keyLevel) { bool ScStwRemoteSettings::writeSetting(QString key, QVariant value, int keyInt, int keyLevel) {
@ -66,8 +72,8 @@ bool ScStwRemoteSettings::setDefaultSetting(QString key, QVariant defaultVariant
void ScStwRemoteSettings::handleClientStateChange() { void ScStwRemoteSettings::handleClientStateChange() {
if(this->scStwClient->getState() == ScStwClient::DISCONNECTED) if(this->scStwClient->getState() == ScStwClient::DISCONNECTED)
emit this->settingChanged(-1, ScStwSettings::KeyLevel, QVariant()); emit this->settingChanged(-1, ScStwSettings::KeyLevel, QVariant());
else if(this->scStwClient->getState() == ScStwClient::CONNECTED) // Dont't need to do that when changing to connected,
emit this->settingChanged(-1, ScStwSettings::KeyLevel, QVariant()); // as the basestation emits a wildcrd setting changed on connect anyway
} }
void ScStwRemoteSettings::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) { void ScStwRemoteSettings::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {

View File

@ -172,7 +172,7 @@ ScStw::StatusCode ScStwRace::setTimerDisabled(int timerId, bool disabled) {
} }
ScStw::StatusCode ScStwRace::setTimerDisabled(ScStwTimer* timer, bool disabled) { ScStw::StatusCode ScStwRace::setTimerDisabled(ScStwTimer* timer, bool disabled) {
qDebug() << "[INFO][RACE] Setting timer "<< timer->getLetter() << " to disabled: " << disabled << " this state: " << this->state; //qDebug() << "[INFO][RACE] Setting timer "<< timer->getLetter() << " to disabled: " << disabled << " this state: " << this->state;
if(this->state != IDLE && this->state != WAITING) if(this->state != IDLE && this->state != WAITING)
return ScStw::CurrentStateNotVaildForOperationError; return ScStw::CurrentStateNotVaildForOperationError;
@ -189,7 +189,7 @@ ScStw::StatusCode ScStwRace::setTimerDisabled(ScStwTimer* timer, bool disabled)
if(disabled && enabledTimerCount <= 1) if(disabled && enabledTimerCount <= 1)
return ScStw::LastTimerCannotBeDisabledError; return ScStw::LastTimerCannotBeDisabledError;
qDebug() << "[INFO][RACE] Setting timer "<< timer->getLetter() << " to disabled: " << disabled; //qDebug() << "[INFO][RACE] Setting timer "<< timer->getLetter() << " to disabled: " << disabled;
timer->setDisabled(disabled); timer->setDisabled(disabled);
@ -623,13 +623,12 @@ bool ScStwRace::getIsReadyForNextState() {
* @param {ScStwExtensionControlledTimer*} timer timer to be enabled * @param {ScStwExtensionControlledTimer*} timer timer to be enabled
*/ */
void ScStwRace::handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled) { void ScStwRace::handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled) {
qDebug() << "Handling timer wants to be disabled"; //qDebug() << "Handling timer wants to be disabled";
if(this->competitionMode) if(this->competitionMode)
return; return;
if(this->state == IDLE) { if(this->state == IDLE) {
//qDebug() << "Handling timer wants to be disabled: " << wantsToBeDisabled;
qDebug() << "Handling timer wants to be disabled: " << wantsToBeDisabled;
this->setTimerDisabled(timer, wantsToBeDisabled); this->setTimerDisabled(timer, wantsToBeDisabled);
} }
} }

View File

@ -30,6 +30,7 @@ ScStwSetting::ScStwSetting(int key, int keyLevel, ScStwSettings*scStwSettings, Q
} }
QVariant ScStwSetting::getValue() { QVariant ScStwSetting::getValue() {
qDebug() << "Getting setting: " << this->key << " has to reload: " << this->hasToReload;
if(this->hasToReload) { if(this->hasToReload) {
this->valueCache = this->scStwSettings->readSetting(this->key, this->keyLevel); this->valueCache = this->scStwSettings->readSetting(this->key, this->keyLevel);
this->hasToReload = false; this->hasToReload = false;

View File

@ -29,7 +29,7 @@ ScStwTimer::ScStwTimer(QString letter, QObject *parent) : QObject(parent)
else else
this->letter = letter; this->letter = letter;
qDebug() << "Timer created with letter: " << letter; //qDebug() << "Timer created with letter: " << letter;
this->startTime = 0; this->startTime = 0;
this->stopTime = 0; this->stopTime = 0;