some fixes

This commit is contained in:
Dorian Zedler 2021-01-09 23:12:28 +01:00
parent 92fae09672
commit f088a79c2b
Signed by: dorian
GPG key ID: 989DE36109AFA354
8 changed files with 126 additions and 101 deletions

View file

@ -101,15 +101,14 @@ private:
QString readBuffer;
int nextConnectionId;
unsigned int currentRequestId;
struct waitingRequest {
int id;
struct WaitingRequest {
QEventLoop * loop;
QJsonObject reply;
};
QList<waitingRequest> waitingRequests;
QMap<int, WaitingRequest> waitingRequests;
public slots:
@ -152,7 +151,7 @@ public slots:
* \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
*/
QVariant readRemoteSetting(ScStwSettings::BaseStationSetting key);
QVariant readRemoteSetting(ScStwSettings::BaseStationSetting key, ScStw::StatusCode* status = nullptr);
/*! Getter fuctions */

View file

@ -28,6 +28,7 @@ class ScStwSetting : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant value READ getValue WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(QVariant readonlyValue READ getValue NOTIFY valueChanged)
protected:
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)
{
this->state = DISCONNECTED;
this->nextConnectionId = 1;
this->currentRequestId = 1;
this->extensions = QVariantMap({});
this->signalSubscriptions = signalSubscriptions;
@ -84,7 +84,6 @@ bool ScStwClient::init() {
QVariantMap initResponse = this->sendCommand(1, sessionParams, 3000, false);
if(initResponse["status"] != 200) {
this->closeConnection();
return false;
}
@ -121,7 +120,17 @@ void ScStwClient::deInit() {
if(this->state == DISCONNECTED)
return;
this->currentRequestId = 1;
this->firmwareVersion = "";
this->apiVersion = "";
this->setExtensions(QVariantMap({}));
for(WaitingRequest waitingRequest : this->waitingRequests.values())
if(waitingRequest.loop != nullptr)
waitingRequest.loop->exit(ScStw::NotConnectedError);
this->waitingRequests.clear();
this->setState(DISCONNECTED);
}
@ -160,16 +169,22 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
return {{"status", ScStw::NotConnectedError}, {"data", "not connected"}};
}
// generate id and witing requests entry
int thisId = nextConnectionId;
// pick a new request id that is not already active
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;
nextConnectionId ++;
QEventLoop *loop = new QEventLoop(this);
QTimer *timer = new QTimer(this);
QJsonObject reply;
this->waitingRequests.append({thisId, loop, reply});
this->waitingRequests.insert(thisId, {loop, reply});
QJsonObject requestObj;
requestObj.insert("id", thisId);
@ -180,7 +195,7 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
timer->setSingleShot(true);
// 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
timer->start(timeout);
@ -191,37 +206,38 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
socket->write(jsonRequest.toUtf8());
//wait for an answer to finish (programm gets stuck in here)
loop->exec();
ScStw::StatusCode statusCode = ScStw::StatusCode(loop->exec());
bool replyFound = false;
// delete the timer
timer->deleteLater();
// find reply and delete the request from waiting list
for(int i = 0; i<this->waitingRequests.length(); i++){
if(this->waitingRequests[i].id == thisId){
// request was found
replyFound = true;
// delete event loop
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(this->waitingRequests.contains(thisId)) {
// request was found
// delete event loop
if(this->waitingRequests[thisId].loop != nullptr) {
this->waitingRequests[thisId].loop->deleteLater();
}
}
if(!replyFound) {
// store reply
reply = this->waitingRequests[thisId].reply;
// remove reply from waiting list
this->waitingRequests.remove(thisId);
}
else {
// 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
return {{"status", ScStw::TimeoutError}, {"data", ""}};
}
else if(statusCode == ScStw::NotConnectedError) {
// connection was closed during request
return {{"status", ScStw::NotConnectedError}, {"data", ""}};
}
delete timer;
return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}};
@ -273,7 +289,6 @@ void ScStwClient::handleReadyRead() {
//qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ;
QString reply = socket->readAll();
//qWarning() << "socket read: " << reply;
processSocketMessage(reply);
@ -335,7 +350,7 @@ void ScStwClient::handleSocketMessage(QString reply) {
reply.replace(ScStw::SOCKET_MESSAGE_START_KEY, "");
reply.replace(ScStw::SOCKET_MESSAGE_END_KEY, "");
//qDebug() << "got message: " << reply;
qDebug() << "got message: " << qPrintable(reply);
int id = 0;
@ -352,14 +367,12 @@ void ScStwClient::handleSocketMessage(QString reply) {
}
// 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;
if(this->waitingRequests[i].loop != nullptr){
this->waitingRequests[i].loop->quit();
}
return;
if(this->waitingRequests.contains(id)){
this->waitingRequests[id].reply = replyObj;
if(this->waitingRequests[id].loop != nullptr){
this->waitingRequests[id].loop->exit(ScStw::Success);
}
return;
}
}
@ -404,8 +417,13 @@ ScStw::StatusCode ScStwClient::writeRemoteSetting(ScStwSettings::BaseStationSett
return ScStw::StatusCode(this->sendCommand(3000, requestData)["status"].toInt());
}
QVariant ScStwClient::readRemoteSetting(ScStwSettings::BaseStationSetting key) {
QVariantMap reply = this->sendCommand(3001, int(key));
QVariant ScStwClient::readRemoteSetting(ScStwSettings::BaseStationSetting key, ScStw::StatusCode* status) {
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){
return "false";
}

View file

@ -102,8 +102,8 @@ ScStw::StatusCode ScStwRemoteRace::setTimerDisabled(int timerId, bool disabled)
qDebug() << "+ --- setting timer " << timerId << " to disabled: " << disabled;
QVariantMap requestData = {
{"timerId", timerId},
{"disabled", disabled}
{"timerId", timerId},
{"disabled", disabled}
};
QVariantMap reply = this->scStwClient->sendCommand(ScStw::SetTimerDisabledCommand, QJsonValue::fromVariant(requestData));
@ -125,6 +125,7 @@ void ScStwRemoteRace::handleClientStateChange() {
// delete all obsolete remote timers
for(ScStwRemoteTimer* oldRemoteTimer : this->remoteTimers)
oldRemoteTimer->deleteLater();
this->remoteTimers.clear();
break;
case ScStwClient::DISCONNECTED:
@ -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() {
if(this->scStwClient == nullptr || this->scStwClient->getState() != ScStwClient::CONNECTED)
return LOCAL;
@ -233,43 +258,43 @@ void ScStwRemoteRace::rebuildRemoteTimers(QVariantList remoteTimers) {
}
}
bool ScStwRemoteRace::refreshRemoteTimers(QVariantList remoteTimers) {
bool ScStwRemoteRace::refreshRemoteTimers(QVariantList newRemoteTimers) {
qDebug() << "REFRESHING TIMERS";
if(remoteTimers.length() != this->remoteTimers.length()){
// local timers are out of sync
this->rebuildRemoteTimers(remoteTimers);
qDebug() << "rebuilding remote timers";
}
if(newRemoteTimers.length() != this->remoteTimers.length()){
// local timers are out of sync
this->rebuildRemoteTimers(newRemoteTimers);
qDebug() << "rebuilding remote timers";
}
foreach(QVariant remoteTimer, remoteTimers){
int currId = remoteTimer.toMap()["id"].toInt();
for(QVariant remoteTimer : newRemoteTimers){
int currId = remoteTimer.toMap()["id"].toInt();
if(this->remoteTimers.length() <= currId)
this->rebuildRemoteTimers(remoteTimers);
if(this->remoteTimers.length() <= currId)
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)
this->remoteTimers[currId]->setStopTime(currentMSecsSinceEpoch);
if(newState >= ScStwTimer::WAITING)
this->remoteTimers[currId]->setStopTime(currentMSecsSinceEpoch);
this->remoteTimers[currId]->setReactionTime(remoteTimer.toMap()["reactionTime"].toDouble());
this->remoteTimers[currId]->setLetter(remoteTimer.toMap()["letter"].toString());
this->remoteTimers[currId]->setReadyState(ScStwTimer::ReadyState(remoteTimer.toMap()["readyState"].toInt()));
this->remoteTimers[currId]->setReactionTime(remoteTimer.toMap()["reactionTime"].toDouble());
this->remoteTimers[currId]->setLetter(remoteTimer.toMap()["letter"].toString());
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) {
@ -281,30 +306,6 @@ bool ScStwRemoteRace::addTimer(ScStwTimer* timer) {
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() {
if(this->local())
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;
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) {
@ -66,8 +72,8 @@ bool ScStwRemoteSettings::setDefaultSetting(QString key, QVariant defaultVariant
void ScStwRemoteSettings::handleClientStateChange() {
if(this->scStwClient->getState() == ScStwClient::DISCONNECTED)
emit this->settingChanged(-1, ScStwSettings::KeyLevel, QVariant());
else if(this->scStwClient->getState() == ScStwClient::CONNECTED)
emit this->settingChanged(-1, ScStwSettings::KeyLevel, QVariant());
// Dont't need to do that when changing to connected,
// as the basestation emits a wildcrd setting changed on connect anyway
}
void ScStwRemoteSettings::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {

View file

@ -170,7 +170,7 @@ ScStw::StatusCode ScStwRace::setTimerDisabled(int timerId, 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)
return ScStw::CurrentStateNotVaildForOperationError;
@ -187,7 +187,7 @@ ScStw::StatusCode ScStwRace::setTimerDisabled(ScStwTimer* timer, bool disabled)
if(disabled && enabledTimerCount <= 1)
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);
@ -620,13 +620,12 @@ bool ScStwRace::getIsReadyForNextState() {
* @param {ScStwExtensionControlledTimer*} timer timer to be enabled
*/
void ScStwRace::handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled) {
qDebug() << "Handling timer wants to be disabled";
//qDebug() << "Handling timer wants to be disabled";
if(this->competitionMode)
return;
if(this->state == IDLE) {
qDebug() << "Handling timer wants to be disabled: " << wantsToBeDisabled;
//qDebug() << "Handling timer wants to be disabled: " << wantsToBeDisabled;
this->setTimerDisabled(timer, wantsToBeDisabled);
}
}

View file

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

View file

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