fixed remote base station stuff

This commit is contained in:
Dorian Zedler 2020-04-19 13:09:46 +02:00
parent 315ef27cc5
commit 9d7e26aff0
Signed by: dorian
GPG key ID: 989DE36109AFA354
13 changed files with 83 additions and 1655 deletions

View file

@ -1,79 +0,0 @@
#ifndef BUZZERCONN_H
#define BUZZERCONN_H
#include <QObject>
#include <QObject>
#include <QDir>
#include <QUrl>
#include <QtNetwork>
#include <QAuthenticator>
#include <QDesktopServices>
#include <QDateTime>
#include <QtDebug>
typedef struct strReturnData{
int status_code;
QString text;
}ReturnData_t;
class BuzzerConn : public QObject
{
Q_OBJECT
public:
explicit BuzzerConn(QObject *parent = nullptr, QString ip = "http://192.168.4.1", int port = 80);
double offset;
QList<double> latest_offsets;
double latest_button_pressed;
double starttime;
bool connected;
int connection_progress;
QString ip;
int port;
int errors;
int errors_until_disconnect = 4;
private:
QNetworkAccessManager *networkManager;
QNetworkAccessManager *reloadNetworkManager;
QDateTime *date;
QTcpSocket *socket;
QStringList pending_commands;
//QSemaphore dataPipe(1);
signals:
public slots:
ReturnData_t senddata(QNetworkAccessManager * NetMan, QUrl serviceUrl, int timeout);
//function to communicate with the buzzer
Q_INVOKABLE signed long sendCommand(QString command, int timeout);
//function to send commands to the sensor
//Can be:
//command - return
//GET_TIMESTAMP - timestamp of the sensor
//GET_LASTPRESSED - timestamp of the sensor when it was triggered the last time
//
//error codes:
//(-1) : timeout
//(-2) : invalid data was recieved
Q_INVOKABLE QList<double> gettimes(int timeout);
//function to get the times from the buzzer as a list with the normal network manager
Q_INVOKABLE bool connect();
//function to connect to buzzer
Q_INVOKABLE bool calcoffset(QList<double> times);
//function that calculates the average time offset between the buzzer and the device
Q_INVOKABLE bool buzzer_triggered();
//function that checks ih the buzzer has been pushed since the last call of this function
Q_INVOKABLE bool start();
//syncs the buzzer and the base to make a start possible
Q_INVOKABLE double get(QString key);
//can return some things (offset, lastpressed, currtime, connection_progress, connected)
Q_INVOKABLE QString test();
Q_INVOKABLE bool refresh();
//refreshed the connection to the buzzer
Q_INVOKABLE void appendCommand(QString command);
};
#endif // BUZZERCONN_H

View file

@ -1,116 +0,0 @@
#ifndef CLIMBINGRACE_H
#define CLIMBINGRACE_H
#include <QObject>
#include <QSound>
#include <QSoundEffect>
#include <QMediaPlayer>
#include <scstwclient.h>
#include <ScStw.hpp>
#include "headers/appsettings.h"
#include "headers/speedtimer.h"
class ClimbingRace : public QObject
{
Q_OBJECT
Q_PROPERTY(int state READ getState NOTIFY stateChanged)
Q_PROPERTY(int mode READ getMode NOTIFY modeChanged)
Q_PROPERTY(QVariant timers READ getTimerTextList NOTIFY timerTextChanged)
Q_PROPERTY(QString baseStationState READ getBaseStationState NOTIFY baseStationStateChanged)
Q_PROPERTY(QVariant baseStationConnections READ getBaseStationConnections NOTIFY baseStationConnectionsChanged)
Q_PROPERTY(double nextStartActionDelayProgress READ getNextStartActionDelayProgress NOTIFY nextStartActionDelayProgressChanged)
Q_PROPERTY(int nextStartAction READ getNextStartAction NOTIFY nextStartActionChanged)
Q_PROPERTY(QVariantMap baseStationProperties READ getBaseStationProperties NOTIFY baseStationPropertiesChanged)
public:
explicit ClimbingRace(QObject *parent = nullptr);
enum RaceMode { LOCAL, REMOTE };
RaceMode mode;
private:
AppSettings * appSettings;
ScStwClient * scStwClient;
QMediaPlayer * player;
QTimer * timerTextRefreshTimer;
QTimer * nextStartActionTimer;
QDateTime *date;
QList<SpeedTimer *> speedTimers;
double nextStartActionDelayProgress;
// only used in remote mode:
double nextStartActionDelayStartedAt;
double nextStartActionTotalDelay;
// helper vars
QVariantList qmlTimers;
private slots:
// helper functions
void playSoundsAndStartRace();
bool playSound(QString path);
void setState(ScStw::RaceState newState);
void refreshMode();
void refreshTimerText();
bool refreshRemoteTimers(QVariantList timers);
signals:
void nextStartActionChanged();
void nextStartActionDelayProgressChanged();
void stateChanged(int state);
void modeChanged();
void timerTextChanged();
void baseStationStateChanged();
void baseStationConnectionsChanged();
void baseStationPropertiesChanged();
public slots:
Q_INVOKABLE int startRace();
Q_INVOKABLE int stopRace(int type);
Q_INVOKABLE int resetRace();
// base station sync
void handleBaseStationSignal(ScStw::SignalKey key, QVariant data);
Q_INVOKABLE bool pairConnectedUsbExtensions();
// functions for qml
Q_INVOKABLE int getState();
Q_INVOKABLE int getMode();
Q_INVOKABLE QVariant getTimerTextList();
Q_INVOKABLE double getNextStartActionDelayProgress();
Q_INVOKABLE int getNextStartAction();
Q_INVOKABLE void writeSetting(QString key, QVariant value);
Q_INVOKABLE void writeSetting(ScStw::BaseStationSetting key, QVariant value);
Q_INVOKABLE QString readSetting(QString key);
Q_INVOKABLE QString readSetting(ScStw::BaseStationSetting key);
Q_INVOKABLE void connectBaseStation();
Q_INVOKABLE void disconnectBaseStation();
Q_INVOKABLE QString getBaseStationState();
Q_INVOKABLE QVariant getBaseStationConnections();
Q_INVOKABLE QVariantMap getBaseStationProperties();
Q_INVOKABLE bool updateBasestationFirmware();
Q_INVOKABLE bool updateBasestationTime();
// athlete management
Q_INVOKABLE QVariant getAthletes();
Q_INVOKABLE bool createAthlete( QString userName, QString fullName );
Q_INVOKABLE bool deleteAthlete( QString userName );
Q_INVOKABLE bool selectAthlete( QString userName, int timerId );
Q_INVOKABLE QVariant getResults( QString userName );
Q_INVOKABLE bool reloadBaseStationIpAdress();
};
#endif // CLIMBINGRACE_H

View file

@ -6,19 +6,18 @@
#include <scstwclient.h>
#include <scstwrace.h>
#include <ScStw.hpp>
#include <scstwremotemonitorrace.h>
#include "headers/appsettings.h"
class ScStwAppBackend : public QObject
{
Q_OBJECT
//Q_PROPERTY(int state READ getState NOTIFY stateChanged)
Q_PROPERTY(int mode READ getMode NOTIFY modeChanged)
//Q_PROPERTY(QString baseStationState READ getBaseStationState NOTIFY baseStationStateChanged)
Q_PROPERTY(ScStwRace* race READ getRace NOTIFY raceChanged)
Q_PROPERTY(QVariant baseStationConnections READ getBaseStationConnections NOTIFY baseStationConnectionsChanged)
Q_PROPERTY(QVariantMap baseStationProperties READ getBaseStationProperties NOTIFY baseStationPropertiesChanged)
Q_PROPERTY(ScStwClient *scStwClient READ getScStwClient NOTIFY scStwClientChanged)
public:
explicit ScStwAppBackend(QObject *parent = nullptr);
@ -35,15 +34,12 @@ private:
// TODO: DOINEED? QTimer * nextStartActionTimer;
ScStwRace * localRace;
ScStwRemoteMonitorRace * remoteRace;
public slots:
// base station sync
//void handleBaseStationSignal(ScStw::SignalKey key, QVariant data);
Q_INVOKABLE bool pairConnectedUsbExtensions();
// functions for qml
Q_INVOKABLE ScStwRace *getRace();
//Q_INVOKABLE int getState();
Q_INVOKABLE ScStwClient *getScStwClient();
Q_INVOKABLE int getMode();
Q_INVOKABLE void writeSetting(QString key, QVariant value);
@ -51,15 +47,6 @@ public slots:
Q_INVOKABLE QString readSetting(QString key);
Q_INVOKABLE QString readSetting(ScStw::BaseStationSetting key);
Q_INVOKABLE void connectBaseStation();
Q_INVOKABLE void disconnectBaseStation();
Q_INVOKABLE QString getBaseStationState();
Q_INVOKABLE QVariant getBaseStationConnections();
Q_INVOKABLE QVariantMap getBaseStationProperties();
Q_INVOKABLE bool updateBasestationFirmware();
Q_INVOKABLE bool updateBasestationTime();
// athlete management
Q_INVOKABLE QVariant getAthletes();
Q_INVOKABLE bool createAthlete( QString userName, QString fullName );
@ -67,23 +54,20 @@ public slots:
Q_INVOKABLE bool selectAthlete( QString userName, int timerId );
Q_INVOKABLE QVariant getResults( QString userName );
Q_INVOKABLE bool reloadBaseStationIpAdress();
private slots:
void refreshTimerText();
void refreshMode();
void reloadRaceSettings();
void reloadBaseStationIpAdress();
signals:
void modeChanged();
void raceChanged();
void scStwClientChanged();
void baseStationStateChanged();
void baseStationConnectionsChanged();
void baseStationPropertiesChanged();
};
#endif // SCSTWAPPBACKEND_H

View file

@ -1,48 +0,0 @@
#ifndef SPEEDTIMER_H
#define SPEEDTIMER_H
#include <QObject>
#include <QDateTime>
#include <QEventLoop>
#include <QTimer>
#include <QDebug>
class SpeedTimer : public QObject
{
Q_OBJECT
public:
explicit SpeedTimer(QObject *parent = nullptr);
enum timerState { IDLE, STARTING, WAITING, RUNNING, WON, LOST, FAILED, CANCELLED, DISABLED };
timerState state;
// variables for capturing the time
double startTime;
double stopTime;
double stoppedTime;
double reactionTime;
signals:
void stateChanged(timerState newState);
void startCanceled(bool falseStart);
public slots:
bool start(bool force = false);
bool stop(int type, bool force = false);
bool reset(bool force = false);
void setState(timerState newState);
QString getState();
double getCurrTime();
QString getText();
//helper functions
void delay(int mSecs);
timerState stateFromString(QString state);
private:
QDateTime *date;
};
#endif // SPEEDTIMER_H

View file

@ -16,7 +16,7 @@ ListView {
spacing: parentObj.rowSpacing
boundsBehavior: Flickable.StopAtBounds
model: speedBackend.baseStationConnections.length
model: speedBackend.scStwClient.extensions.length
delegate: ConnectionDelegate {
opacity: 1
@ -24,7 +24,7 @@ ListView {
width: parent.width
height: parentObj.delegateHeight
text: speedBackend.baseStationConnections[index]["name"]
status: {'status': speedBackend.baseStationConnections[index]["state"], 'progress': speedBackend.baseStationConnections[index]["progress"]}
text: speedBackend.scStwClient.extensions[index]["name"]
status: {'status': speedBackend.scStwClient.extensions[index]["state"], 'progress': speedBackend.scStwClient.extensions[index]["progress"]}
}
}

View file

@ -6,6 +6,9 @@ import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Templates 2.12 as T
import com.itsblue.speedclimbingstopwatch 2.0
import "../components"
Column {
@ -13,7 +16,7 @@ Column {
property string title: qsTr("base station")
property bool baseConnected: speedBackend.baseStationState === "connected"
property bool baseConnected: speedBackend.scStwClient.state === ScStwClient.CONNECTED
property var parentObj
opacity: 0
@ -31,18 +34,32 @@ Column {
onTriggered: {
busyDl.open()
var ret = speedBackend.updateBasestationFirmware()
var ret = speedBackend.scStwClient.updateFirmware()
busyDl.displayMessageAndClose(ret ? "OK":"error", ret ? "#6bd43b":"#e03b2f" )
}
}
ConnectionDelegate {
id: connectToBaseDel
function clientStateToString(state) {
switch(state) {
case ScStwClient.DISCONNECTED:
return "disconnected"
case ScStwClient.CONNECTING:
return "connecting"
case ScStwClient.INITIALISING:
return "connecting"
case ScStwClient.CONNECTED:
return "connected"
}
}
text: status.status === "connected" ? qsTr("disconnect"): status.status === "disconnected" ? qsTr("connect"):qsTr("connecting...")
status: { "status": speedBackend.baseStationState, "progress": 100 }
connect: speedBackend.connectBaseStation
disconnect: speedBackend.disconnectBaseStation
status: { "status": clientStateToString(speedBackend.scStwClient.state), "progress": 100 }
connect: speedBackend.scStwClient.connectToHost
disconnect: speedBackend.scStwClient.closeConnection
type: "baseStation"
width: parent.width
@ -136,7 +153,6 @@ Column {
onInputTextChanged: {
speedBackend.writeSetting("baseStationIpAdress", inputText)
speedBackend.reloadBaseStationIpAdress()
}
width: parent.width
@ -246,8 +262,8 @@ Column {
onClicked: {
busyDl.open()
var ret = speedBackend.pairConnectedUsbExtensions()
busyDl.displayMessageAndClose(ret ? "OK":"error", ret ? "#6bd43b":"#e03b2f" )
var ret = speedBackend.scStwClient.pairConnectedUsbExtensions()
busyDl.displayMessageAndClose(ret === ScStw.Success ? "OK":"error", ret ? "#6bd43b":"#e03b2f" )
}
}
@ -255,8 +271,8 @@ Column {
id: baseStationUpdateDel
// 0: hidden 1: update firmware 2: sync time
property int mode: speedBackend.baseStationProperties["firmware"]["upToDate"] ?
(Math.abs(parseInt(speedBackend.baseStationProperties["timeOffset"])) > 10000 ? 2:0)
property int mode: speedBackend.scStwClient.isFirmwareUpToDate() ?
(Math.abs(parseInt(speedBackend.scStwClient.getTimeOffset())) > 10000 ? 2:0)
:1
width: parent.width
@ -272,7 +288,7 @@ Column {
}
else if(mode === 2){
busyDl.open()
var ret = speedBackend.updateBasestationTime()
var ret = speedBackend.scStwClient.updateTime()
busyDl.displayMessageAndClose(ret ? "OK":"error", ret ? "#6bd43b":"#e03b2f" )
}
@ -312,12 +328,12 @@ Column {
minimumPixelSize: 1
color: appTheme.style.lineColor
text: "version: " + speedBackend.baseStationProperties["firmware"]["version"]
text: "version: " + speedBackend.scStwClient.getFirmwareVersion()
}
Label {
property var date: new Date(new Date().getTime() + parseInt(speedBackend.baseStationProperties["timeOffset"]))
property var date: new Date(new Date().getTime() + parseInt(speedBackend.scStwClient.getTimeOffset()))
anchors {
top: parent.top

View file

@ -10,6 +10,7 @@ SmoothItemDelegate {
property var disconnect
property string type
text: qsTr(type)
enabled: (status.status === "disconnected" && control.connect !== undefined) || ( status.status === "connected" && control.disconnect !== undefined )

View file

@ -67,8 +67,8 @@ Window {
target: speedBackend.race
onStateChanged: {
var stateString
console.log("race state changed to: " + state)
switch (state){
console.log("race state changed to: " + speedBackend.race.state)
switch (speedBackend.race.state){
case ScStwRace.IDLE:
stateString = "IDLE"
break;
@ -200,8 +200,8 @@ Window {
height: parent.height
elide: "ElideRight"
color: ["WON"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.successColor :
["LOST", "FAILED"].includes(speedBackend.timers[index]["state"]) ? appTheme.style.errorColor:
color: [ScStwTimer.WON].includes(speedBackend.race.timers[index]["state"]) ? appTheme.style.successColor :
[ScStwTimer.LOST, ScStwTimer.FAILED].includes(speedBackend.race.timers[index]["state"]) ? appTheme.style.errorColor:
appTheme.style.textColor
enabled: speedBackend.race.timers[index]["state"] !== ScStwTimer.DISABLED
@ -282,7 +282,21 @@ Window {
ConnectionIcon {
id: baseConnConnIcon
status: speedBackend.baseStationState
function clientStateToString(state) {
switch(state) {
case ScStwClient.DISCONNECTED:
return "disconnected"
case ScStwClient.CONNECTING:
return "connecting"
case ScStwClient.INITIALISING:
return "connecting"
case ScStwClient.CONNECTED:
return "connected"
}
}
status: clientStateToString(speedBackend.scStwClient.state)
source: appTheme.style.baseStationIcon
anchors {
@ -311,14 +325,14 @@ Window {
Repeater {
id: connectedExtensionsRep
anchors.fill: parent
model: speedBackend.baseStationConnections.length
model: speedBackend.scStwClient.extensions.lenght
delegate: ConnectionIcon {
id: buzzerConnIcon
status: speedBackend.baseStationConnections[index]["state"]
status: speedBackend.extensions[index]["state"]
source: {
var source
switch(speedBackend.baseStationConnections[index]["type"]){
switch(speedBackend.extensions[index]["type"]){
case "STARTPAD":
source = appTheme.style.startpadIcon
break
@ -373,7 +387,7 @@ Window {
text: "start"
property int size: app.landscape() ? parent.width * 0.5:parent.height * 0.5
property color backgroundColor: appTheme.style.buttonColor
property bool progressControlActivated: speedBackend.baseStationState === "connected" && app.state === "RUNNING"
property bool progressControlActivated: speedBackend.scStwClient.state === ScStwClient.CONNECTED && app.state === "RUNNING"
delay: progressControlActivated ? 2000:0
anchors {
@ -681,7 +695,7 @@ Window {
enabled: height > 0
state: speedBackend.baseStationState === "connected" ? "visible":"hidden"
state: speedBackend.scStwClient.state === ScStwClient.CONNECTED ? "visible":"hidden"
width: height
onClicked: {

View file

@ -1,367 +0,0 @@
/*
Speed Climbing Stopwatch - Simple Stopwatch for Climbers
Copyright (C) 2018 Itsblue Development - Dorian Zeder
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "headers/buzzerconn.h"
BuzzerConn::BuzzerConn(QObject *parent, QString ip, int port) : QObject(parent)
{
this->networkManager = new QNetworkAccessManager();
this->reloadNetworkManager = new QNetworkAccessManager();
this->socket = new QTcpSocket();
this->date = new QDateTime;
this->latest_button_pressed = 0;
this->connected = false;
this->ip = ip;
this->port = port;
// "http://192.168.4.1"
}
bool BuzzerConn::connect()
{
qDebug() << "connecting...";
//wait until the request has finished
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
loop.connect(this->socket, SIGNAL(connected()), &loop, SLOT(quit()));
timer.start(3000);
this->socket->connectToHost(this->ip, this->port);
loop.exec();
timer.stop();
if(timer.remainingTime() == 0){
//the time has been triggered -> timeout
return(false);
}
QList<double> times = gettimes(2000);
qDebug() << times[0];
if(times[0] == 200.0){
this->latest_button_pressed = times[2];
for(int i=0;i<=100;i++){
this->connection_progress = i;
if(!calcoffset(this->gettimes(1000))){
this->connection_progress = 100;
this->connected = false;
return(false);
}
}
this->connected = true;
return(true);
}
else{
this->connected = false;
return(false);
}
}
bool BuzzerConn::calcoffset(QList<double> times)
{
if(times.length() != 3){
return(false);
}
if(times[0] == 200.0){
this->latest_button_pressed = times[2];
double offset = date->currentMSecsSinceEpoch() - times[1];
if(this->latest_offsets.length()>=100){
this->latest_offsets.removeFirst();
}
this->latest_offsets.append(offset);
double mem = 0;
for(int i=0;i<latest_offsets.length();i++){
mem += latest_offsets[i];
}
this->offset = mem / double(latest_offsets.length());
qDebug("%20f", this->offset);
return(true);
}
else {
//this->connected = false;
return(false);
}
}
QList<double> BuzzerConn::gettimes(int timeout)
{
// QList<double> times;
// ReturnData_t ret = senddata(this->networkManager, QUrl(this->ip), timeout);
// times.append(double(ret.status_code));
// if(ret.status_code == 200){
// ret.text.replace("\n","");
// ret.text.replace("\r","");
// QStringList times_cache = ret.text.split("<br>");
// times.append(times_cache[0].toDouble());
// times.append(times_cache[1].toDouble());
// return(times);
// }
// else{
// return(times);
// }
QList<double> times;
signed long ret;
ret = this->sendCommand("GET_TIMESTAMP", timeout);
if(ret >= 0){
times.append(double(200));
times.append(double(ret));
ret = this->sendCommand("GET_LASTPRESSED", timeout);
if(ret >= 0){
times.append(double(ret));
return(times);
}
else {
times[0] = ret;
}
}
else {
times.append(ret);
}
return(times);
}
bool BuzzerConn::buzzer_triggered()
{
if(!this->connected){
return(false);
}
if(pending_commands.length() > 0){
QString command = this->pending_commands.first();
signed long retval = this->sendCommand(command, 800);
if(retval > 0){
this->pending_commands.removeFirst();
}
}
QList<double> times = this->gettimes(1000);
if(times[0] == 200.0){
if(times[2] > this->latest_button_pressed){
this->latest_button_pressed = times[2];
return(true);
}
else {
return(false);
}
}
else{
//this->connected = false;
return(false);
}
}
bool BuzzerConn::start()
{
if(!this->connected){
return(false);
}
QList<double> times = this->gettimes(1000);
if(times[0] == 200.0 && this->connected){
this->latest_button_pressed = times[2];
return(true);
}
else{
this->connected = false;
return(false);
}
}
double BuzzerConn::get(QString key)
{
if(key == "offset"){
return(this->offset);
}
else if (key == "lastpressed") {
return(this->latest_button_pressed);
}
else if( key == "currtime") {
return(this->date->currentMSecsSinceEpoch());
}
else if( key == "connection_progress") {
return(this->connection_progress);
}
else if( key == "connected") {
if(this->connected){
return(1);
}
return(0);
}
}
QString BuzzerConn::test()
{
ReturnData_t ret = this->senddata(this->networkManager, QUrl("http://www.google.de"), 500);
return(ret.text);
}
bool BuzzerConn::refresh()
{
if(!this->connected){
return(false);
}
// QList<double> times;
// ReturnData_t ret = senddata(this->reloadNetworkManager, QUrl(this->ip), 1000);
// times.append(double(ret.status_code));
// if(ret.status_code == 200){
// ret.text.replace("\n","");
// ret.text.replace("\r","");
// QStringList times_cache = ret.text.split("<br>");
// times.append(times_cache[0].toDouble());
// times.append(times_cache[1].toDouble());
// calcoffset(times);
// return(true);
// }
// else{
// //this->connected = false;
// return(false);
// }
if(pending_commands.length() > 0){
QString command = this->pending_commands.first();
signed long retval = this->sendCommand(command, 800);
if(retval > 0){
this->pending_commands.removeFirst();
}
}
//refresh the times
QList<double> ret = this->gettimes(800);
if(ret[0] >= 0){
this->errors = 0;
return(this->calcoffset(ret));
}
else {
this->errors ++;
if(this->errors > errors_until_disconnect){
this->socket->disconnectFromHost();
this->connected = false;
}
return(false);
}
}
ReturnData_t BuzzerConn::senddata(QNetworkAccessManager * NetMan, QUrl serviceUrl, int timeout)
{
ReturnData_t ret; //this is a custom type to store the returned data
// Call the webservice
QNetworkRequest request(serviceUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
//send a POST request with the given url and data to the server
QUrlQuery pdata;
QNetworkReply* reply;
//wait until the request has finished
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
loop.connect(NetMan, SIGNAL(finished(QNetworkReply*)), SLOT(quit()));
timer.start(timeout);
reply = NetMan->post(request, pdata.toString(QUrl::FullyEncoded).toUtf8());
loop.exec();
timer.stop();
//get the status code
QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
ret.status_code = status_code.toInt();
if(ret.status_code == 0){ //if the statuscode is zero, the connecion to the server was not possible
ret.status_code = 444;
}
//get the full text response
ret.text = QString::fromUtf8(reply->readAll());
//return the data
return(ret);
}
signed long BuzzerConn::sendCommand(QString command, int timeout){
//if there is any data in the storage, clear it
if(this->socket->bytesAvailable() > 0){
this->socket->readAll();
}
//send request to the socket server
QByteArray arrBlock;
QDataStream out(&arrBlock, QIODevice::WriteOnly);
//out.setVersion(QDataStream::Qt_5_10);
out << quint16(0) << command;
out.device()->seek(0);
out << quint16(arrBlock.size() - sizeof(quint16));
this->socket->write(arrBlock);
//now wait for the server of the sensor to answer
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
loop.connect(socket, SIGNAL(readyRead()), &loop, SLOT(quit()));
timer.start(timeout);
loop.exec();
//loop finished
timer.stop();
if(timer.remainingTime() == 0){
//the time has been triggered -> timeout
return(-1);
}
//if the data is not 4 bites long if is invalid -> clear and terminate
if(this->socket->bytesAvailable() != 4){
this->socket->readAll();
return(-2);
}
long data = 0;
this->socket->read((char*)&data,4);
qDebug() << data;
qDebug() << this->socket->bytesAvailable();
return data;
}
void BuzzerConn::appendCommand(QString command){
this->pending_commands.append(command);
}

View file

@ -1,656 +0,0 @@
#include "headers/climbingrace.h"
/*
* manages:
* - global state
* - timers
* - sounds
* - next start action
* - next start action delay progress
* - settings (remote and local)
*/
ClimbingRace::ClimbingRace(QObject *parent) : QObject(parent)
{
this->state = ScStw::ScStw::IDLE;
this->mode = LOCAL;
this->appSettings = new AppSettings(this);
this->scStwClient = new ScStwClient();
this->scStwClient->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress"));
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ClimbingRace::baseStationStateChanged);
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ClimbingRace::refreshMode);
connect(this->scStwClient, &ScStwClient::gotSignal, this, &ClimbingRace::handleBaseStationSignal);
connect(this, &ClimbingRace::baseStationStateChanged, this, &ClimbingRace::baseStationPropertiesChanged);
this->speedTimers.append( new SpeedTimer(this) );
this->player = new QMediaPlayer;
this->date = new QDateTime;
this->nextStartActionTimer = new QTimer(this);
nextStartActionTimer->setSingleShot(true);
this->timerTextRefreshTimer = new QTimer(this);
this->timerTextRefreshTimer->setInterval(1);
this->timerTextRefreshTimer->setSingleShot(true);
this->timerTextRefreshTimer->connect(this->timerTextRefreshTimer, &QTimer::timeout, this, &ClimbingRace::refreshTimerText);
this->refreshTimerText();
}
// --------------------------
// --- Main Functionality ---
// --------------------------
int ClimbingRace::startRace() {
if(this->state != ScStw::IDLE) {
return 904;
}
qDebug() << "+ --- starting race";
int returnCode = 900;
switch (this->mode) {
case LOCAL:
{
this->setState(ScStw::STARTING);
this->nextStartAction = ScStw::None;
this->playSoundsAndStartRace();
returnCode = 200;
break;
}
case REMOTE:
{
QVariantMap reply = this->scStwClient->sendCommand(1000);
if(reply["status"] != 200){
//handle Error!!
returnCode = reply["status"].toInt();
}
else {
returnCode = 200;
}
break;
}
}
return returnCode;
}
int ClimbingRace::stopRace(int type) {
if(this->state != ScStw::RUNNING && this->state != ScStw::STARTING) {
return 904;
}
// type can be:
// 0: stopp
// 1: cancel
// 2: fail (fase start)
qDebug() << "+ --- stopping race";
int returnCode = 900;
switch (this->mode) {
case LOCAL:
{
if(type == 1){
this->nextStartActionTimer->stop();
this->player->stop();
this->nextStartAction = ScStw::None;
}
returnCode = this->speedTimers[0]->stop(type) ? 200:904;
if(returnCode == 200) {
this->setState(ScStw::STOPPED);
}
break;
}
case REMOTE:
{
QVariantMap reply = this->scStwClient->sendCommand(1001);
if(reply["status"] != 200){
returnCode = reply["status"].toInt();
}
else {
returnCode = 200;
}
break;
}
}
return returnCode;
}
int ClimbingRace::resetRace() {
if(this->state != ScStw::STOPPED) {
return 904;
}
qDebug() << "+ --- resetting race";
int returnCode = 900;
switch (this->mode) {
case LOCAL:
{
returnCode = this->speedTimers[0]->reset() ? 200:904;
if(returnCode == 200){
this->setState(ScStw::IDLE);
}
break;
}
case REMOTE:
{
QVariantMap reply = this->scStwClient->sendCommand(1002);
if(reply["status"] != 200){
//handle Error!!
returnCode = reply["status"].toInt();
}
else {
returnCode = 200;
}
break;
}
}
return returnCode;
}
// -------------------------
// --- Base Station sync ---
// -------------------------
/**
* @brief ClimbingRace::handleBaseStationUpdate
*
* Function to handle an update, sent by the base station, which indicates
* that some remote value (like a state) has changed
*
* @param data
*/
void ClimbingRace::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {
qDebug() << "got signal: " << data;
switch (key) {
case ScStw::RaceStateChanged:
{
// the remote race state has changed
this->setState( ScStw::RaceState( data.toInt() ) );
break;
}
case ScStw::TimersChanged:
{
// the remote timers have changed
this->refreshRemoteTimers(data.toList());
break;
}
case ScStw::NextStartActionChanged:
{
// the next start action has changed
this->nextStartActionTotalDelay = data.toMap()["nextActionDelay"].toDouble();
this->nextStartActionDelayStartedAt = this->date->currentMSecsSinceEpoch() - (this->nextStartActionTotalDelay * data.toMap()["nextActionDelayProg"].toDouble());
this->nextStartAction = ScStw::NextStartAction( data.toMap()["nextAction"].toInt() );
emit this->nextStartActionChanged();
break;
}
case ScStw::ExtensionsChanged:
{
emit this->baseStationConnectionsChanged();
break;
}
case ScStw::InvalidSignal:
return;
}
}
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()["currentTime"].toDouble();
speedTimers[currId]->stoppedTime = remTimer.toMap()["currentTime"].toDouble();
speedTimers[currId]->reactionTime = remTimer.toMap()["reactionTime"].toDouble();
speedTimers[currId]->setState(SpeedTimer::timerState(remTimer.toMap()["state"].toInt()));
}
return true;
}
// ------------------------
// --- helper functions ---
// ------------------------
void ClimbingRace::playSoundsAndStartRace() {
qDebug() << "next Action: " << nextStartAction;
nextStartActionTimer->disconnect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
switch (this->nextStartAction) {
case ScStw::AtYourMarks:
{
if(!playSound("qrc:/sounds/at_marks_1.wav")){
return;
}
if(appSettings->loadSetting("ready_en") == "true"){
nextStartAction = ScStw::Ready;
nextStartActionTimer->setInterval(appSettings->loadSetting("ready_delay").toInt() <= 0 ? 1:appSettings->loadSetting("ready_delay").toInt());
}
else{
nextStartAction = ScStw::Start;
nextStartActionTimer->setInterval(1);
}
break;
}
case ScStw::Ready:
{
if(!playSound("qrc:/sounds/ready_1.wav")){
return;
}
nextStartAction = ScStw::Start;
nextStartActionTimer->setInterval(1);
break;
}
case ScStw::Start:
{
if(!playSound("qrc:/sounds/IFSC_STARTSIGNAL_SINE.wav")){
return;
}
nextStartAction = ScStw::None;
nextStartActionTimer->disconnect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
this->setState(ScStw::RUNNING);
speedTimers[0]->start();
emit this->nextStartActionChanged();
return;
}
case ScStw::None:
{
this->speedTimers[0]->setState(SpeedTimer::STARTING);
if(appSettings->loadSetting("at_marks_en") == "true"){
nextStartAction = ScStw::AtYourMarks;
nextStartActionTimer->setInterval(appSettings->loadSetting("at_marks_delay").toInt() <= 0 ? 1:appSettings->loadSetting("at_marks_delay").toInt());
}
else if(appSettings->loadSetting("ready_en") == "true"){
nextStartAction = ScStw::Ready;
nextStartActionTimer->setInterval(appSettings->loadSetting("ready_delay").toInt() <= 0 ? 1:appSettings->loadSetting("ready_delay").toInt());
}
else{
nextStartAction = ScStw::Start;
nextStartActionTimer->setInterval(1);
}
break;
}
}
emit this->nextStartActionChanged();
nextStartActionTimer->connect(nextStartActionTimer, SIGNAL(timeout()), this, SLOT(playSoundsAndStartRace()));
nextStartActionTimer->start();
}
bool ClimbingRace::playSound(QString path) {
player->setMedia(QUrl(path));
player->setVolume(50);
player->play();
QTimer timer;
timer.setInterval(1);
timer.setSingleShot(true);
QEventLoop loop;
loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
while (player->mediaStatus() == QMediaPlayer::LoadingMedia || player->mediaStatus() == QMediaPlayer::BufferingMedia || player->mediaStatus() == QMediaPlayer::BufferedMedia) {
timer.start();
loop.exec();
}
if(player->mediaStatus() == QMediaPlayer::EndOfMedia){
return true;
}
else {
return false;
}
}
void ClimbingRace::setState(ScStw::RaceState newState) {
if(newState != this->state) {
this->state = newState;
this->stateChanged(newState);
}
}
void ClimbingRace::refreshMode() {
RaceMode newMode;
if(this->scStwClient->getState() == ScStwClient::CONNECTED){
newMode = REMOTE;
}
else {
newMode = LOCAL;
}
if(this->mode != newMode){
if(newMode == LOCAL){
// if the new mode is local -> connection to base station has been lost
// reset race
// reset state
this->setState(ScStw::IDLE);
// reset timers
// go back to one timer
for (int i = 0;i<this->speedTimers.length();i++) {
delete this->speedTimers[i];
}
this->speedTimers.clear();
this->speedTimers.append(new SpeedTimer);
}
this->mode = newMode;
emit this->modeChanged();
}
}
void ClimbingRace::refreshTimerText() {
// --- refresh timer text ---
QVariantList newTimerTextList;
foreach(SpeedTimer * timer, this->speedTimers){
QVariantMap timerMap = {{"text",timer->getText()}, {"reacttime", timer->reactionTime}, {"state", timer->getState()}, {"id", this->speedTimers.indexOf(timer)}};
newTimerTextList.append(timerMap);
}
if(newTimerTextList != this->qmlTimers){
this->qmlTimers = newTimerTextList;
emit timerTextChanged();
}
// --- refresh next start action delay progress ---
double nextStartActionRemainingDelay = 0;
switch (this->mode) {
case LOCAL: {
// get remaining and total next start action delay time
if(nextStartAction == 0){
this->nextStartActionTotalDelay = appSettings->loadSetting("at_marks_delay").toDouble();
}
else if (nextStartAction == 1) {
this->nextStartActionTotalDelay = appSettings->loadSetting("ready_delay").toDouble();
}
nextStartActionRemainingDelay = this->nextStartActionTimer->remainingTime();
break;
}
case REMOTE: {
// calculate remaining next start action delay time
nextStartActionRemainingDelay = this->nextStartActionTotalDelay - ( this->date->currentMSecsSinceEpoch() - this->nextStartActionDelayStartedAt );
break;
}
}
// calculate next start action delay progress
if(nextStartActionRemainingDelay > 0){
this->nextStartActionDelayProgress = nextStartActionRemainingDelay / this->nextStartActionTotalDelay;
emit this->nextStartActionDelayProgressChanged();
}
else {
this->nextStartActionDelayProgress = 0;
emit this->nextStartActionDelayProgressChanged();
}
/*if (this->mode == REMOTE && this->state == ScStw::IDLE) {
this->nextStartActionDelayProgress = 0;
emit this->nextStartActionDelayProgressChanged();
}*/
this->timerTextRefreshTimer->start();
}
bool ClimbingRace::pairConnectedUsbExtensions() {
QVariantMap ret = this->scStwClient->sendCommand(5002, "", 10000);
qDebug() << ret;
return ret["status"] == 200;
}
// - athlete management -
QVariant ClimbingRace::getAthletes() {
QVariantMap reply = this->scStwClient->sendCommand(4003);
if(reply["status"] != 200){
//handle Error!!
qDebug() << "+ --- error getting athletes: " << reply["status"];
return false;
}
QVariantMap tmpAthletes = reply["data"].toMap();
//qDebug() << tmpAthletes;
return tmpAthletes;
}
bool ClimbingRace::createAthlete(QString userName, QString fullName) {
QVariant requestData = QVariantMap({{"fullName", fullName}, {"userName", userName}});
QVariantMap reply = this->scStwClient->sendCommand(4001, requestData.toJsonValue());
if(reply["status"] != 200){
//handle Error!!
qDebug() << "+ --- error creating athlete: " << reply["status"];
return false;
}
return true;
}
bool ClimbingRace::deleteAthlete( QString userName ){
QVariant requestData = QVariantMap({{"userName", userName}});
QVariantMap reply = this->scStwClient->sendCommand(4002, requestData.toJsonValue());
if(reply["status"] != 200){
//handle Error!!
qDebug() << "+ --- error deleting athlete: " << reply["status"];
return false;
}
return true;
}
bool ClimbingRace::selectAthlete( QString userName, int timerId ){
QVariant requestData = QVariantMap({{"userName", userName}, {"timerId", timerId}});
QVariantMap reply = this->scStwClient->sendCommand(4000, requestData.toJsonValue());
if(reply["status"] != 200){
//handle Error!!
qDebug() << "+ --- error selecting athlete: " << reply["status"];
return false;
}
return true;
}
QVariant ClimbingRace::getResults( QString userName ){
QVariantMap reply = this->scStwClient->sendCommand(4004, userName);
if(reply["status"] != 200){
//handle Error!!
qDebug() << "+ --- error getting results: " << reply["status"];
return false;
}
QVariantList tmpAthletes = reply["data"].toList();
//qDebug() << tmpAthletes;
return tmpAthletes;
}
// -------------------------
// --- functions for qml ---
// -------------------------
int ClimbingRace::getState() {
return this->state;
}
int ClimbingRace::getMode() {
return this->mode;
}
QVariant ClimbingRace::getTimerTextList() {
return this->qmlTimers;
}
double ClimbingRace::getNextStartActionDelayProgress() {
return this->nextStartActionDelayProgress;
}
int ClimbingRace::getNextStartAction() {
return this->nextStartAction;
}
void ClimbingRace::writeSetting(QString key, QVariant value) {
if(this->mode == REMOTE && ScStw::baseStationSettingFromString(key) != ScStw::InvalidSetting ){
this->scStwClient->writeRemoteSetting(ScStw::baseStationSettingFromString(key), value.toString());
}
else {
this->appSettings->writeSetting(key, value);
}
}
void ClimbingRace::writeSetting(ScStw::BaseStationSetting key, QVariant value) {
if(ScStw::baseStationSettingToString(key) != "Invalid" ){
this->writeSetting(ScStw::baseStationSettingToString(key), value);
}
}
QString ClimbingRace::readSetting(QString key) {
if(this->mode == REMOTE && ScStw::baseStationSettingFromString(key) != ScStw::InvalidSetting){
return this->scStwClient->readRemoteSetting(ScStw::baseStationSettingFromString(key));
}
else {
return this->appSettings->loadSetting(key);
}
}
QString ClimbingRace::readSetting(ScStw::BaseStationSetting key) {
if(ScStw::baseStationSettingToString(key) != "Invalid") {
return this->readSetting(ScStw::baseStationSettingToString(key));
}
return "false";
}
void ClimbingRace::connectBaseStation() {
this->reloadBaseStationIpAdress();
this->scStwClient->connectToHost();
}
void ClimbingRace::disconnectBaseStation() {
this->scStwClient->closeConnection();
}
QString ClimbingRace::getBaseStationState() {
switch (this->scStwClient->getState()) {
case ScStwClient::CONNECTED:
return "connected";
case ScStwClient::CONNECTING:
return "connecting";
case ScStwClient::DISCONNECTED:
return "disconnected";
case ScStwClient::INITIALISING:
return "initialising";
}
return "";
}
QVariant ClimbingRace::getBaseStationConnections() {
return scStwClient->getConnections();
}
QVariantMap ClimbingRace::getBaseStationProperties() {
QVariantMap firmware = {{"version", this->scStwClient->getFirmwareVersion()}, {"upToDate", this->scStwClient->isFirmwareUpToDate()}};
return {{"firmware", firmware}, {"timeOffset", this->scStwClient->getTimeOffset()}};
}
bool ClimbingRace::updateBasestationFirmware() {
return this->scStwClient->updateFirmware();
}
bool ClimbingRace::updateBasestationTime() {
return this->scStwClient->updateTime();
}
bool ClimbingRace::reloadBaseStationIpAdress() {
if(this->scStwClient->getState() == ScStwClient::DISCONNECTED){
this->scStwClient->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress"));
return true;
}
return false;
}

View file

@ -58,6 +58,7 @@
#include <scstwtimer.h>
#include <scstwrace.h>
#include <ScStw.hpp>
#include <scstwtimer.h>
#include <QTranslator>
int main(int argc, char *argv[])
@ -93,6 +94,7 @@ int main(int argc, char *argv[])
qmlRegisterType<AppTheme>("com.itsblue.speedclimbingstopwatch", 2, 0, "AppTheme");
//qmlRegisterUncreatableType<ScStw>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStw", "This is a static class and therefore not instantiable");
qmlRegisterType<ScStw>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStw");
qmlRegisterType<ScStwClient>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStwClient");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

View file

@ -5,6 +5,7 @@ ScStwAppBackend::ScStwAppBackend(QObject *parent) : QObject(parent)
this->appSettings = new AppSettings(this);
this->scStwClient = new ScStwClient();
this->localRace = new ScStwRace(this);
this->remoteRace = new ScStwRemoteMonitorRace(this->scStwClient, this);
this->scStwClient->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress"));
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ScStwAppBackend::baseStationStateChanged);
@ -22,86 +23,6 @@ ScStwAppBackend::ScStwAppBackend(QObject *parent) : QObject(parent)
this->refreshTimerText();
}
// -------------------------
// --- Base Station sync ---
// -------------------------
/**
* @brief ScStwAppBackend::handleBaseStationUpdate
*
* Function to handle an update, sent by the base station, which indicates
* that some remote value (like a state) has changed
*
* @param data
*/
/*
void ScStwAppBackend::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {
qDebug() << "got signal: " << data;
switch (key) {
case ScStw::RaceStateChanged:
{
// the remote race state has changed
this->setState( ScStw::RaceState( data.toInt() ) );
break;
}
case ScStw::TimersChanged:
{
// the remote timers have changed
this->refreshRemoteTimers(data.toList());
break;
}
case ScStw::NextStartActionChanged:
{
// the next start action has changed
this->nextStartActionTotalDelay = data.toMap()["nextActionDelay"].toDouble();
this->nextStartActionDelayStartedAt = this->date->currentMSecsSinceEpoch() - (this->nextStartActionTotalDelay * data.toMap()["nextActionDelayProg"].toDouble());
this->nextStartAction = ScStw::NextStartAction( data.toMap()["nextAction"].toInt() );
emit this->nextStartActionChanged();
break;
}
case ScStw::ExtensionsChanged:
{
emit this->baseStationConnectionsChanged();
break;
}
case ScStw::InvalidSignal:
return;
}
}
bool ScStwAppBackend::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()["currentTime"].toDouble();
speedTimers[currId]->stoppedTime = remTimer.toMap()["currentTime"].toDouble();
speedTimers[currId]->reactionTime = remTimer.toMap()["reactionTime"].toDouble();
speedTimers[currId]->setState(SpeedTimer::timerState(remTimer.toMap()["state"].toInt()));
}
return true;
}
*/
// ------------------------
// --- helper functions ---
// ------------------------
@ -126,6 +47,8 @@ void ScStwAppBackend::refreshMode() {
this->mode = newMode;
emit this->modeChanged();
emit this->raceChanged();
emit this->getRace()->stateChanged(this->getRace()->getState());
}
}
@ -145,14 +68,9 @@ void ScStwAppBackend::refreshTimerText() {
this->timerTextRefreshTimer->start();
}
bool ScStwAppBackend::pairConnectedUsbExtensions() {
QVariantMap ret = this->scStwClient->sendCommand(5002, "", 10000);
qDebug() << ret;
return ret["status"] == 200;
}
// - athlete management -
// TODO: move to client
QVariant ScStwAppBackend::getAthletes() {
QVariantMap reply = this->scStwClient->sendCommand(4003);
@ -240,9 +158,14 @@ ScStwRace* ScStwAppBackend::getRace() {
switch (this->mode) {
case LOCAL:
return this->localRace;
default:
return nullptr;
case REMOTE:
return this->remoteRace;
}
return nullptr;
}
ScStwClient* ScStwAppBackend::getScStwClient() {
return this->scStwClient;
}
int ScStwAppBackend::getMode() {
@ -258,6 +181,7 @@ void ScStwAppBackend::writeSetting(QString key, QVariant value) {
}
this->reloadRaceSettings();
this->reloadBaseStationIpAdress();
}
void ScStwAppBackend::writeSetting(ScStw::BaseStationSetting key, QVariant value) {
@ -298,50 +222,14 @@ void ScStwAppBackend::reloadRaceSettings() {
this->getRace()->setSoundVolume(1);
}
void ScStwAppBackend::connectBaseStation() {
this->reloadBaseStationIpAdress();
this->scStwClient->connectToHost();
}
void ScStwAppBackend::disconnectBaseStation() {
this->scStwClient->closeConnection();
}
QString ScStwAppBackend::getBaseStationState() {
switch (this->scStwClient->getState()) {
case ScStwClient::CONNECTED:
return "connected";
case ScStwClient::CONNECTING:
return "connecting";
case ScStwClient::DISCONNECTED:
return "disconnected";
case ScStwClient::INITIALISING:
return "initialising";
}
return "";
}
QVariant ScStwAppBackend::getBaseStationConnections() {
return scStwClient->getConnections();
}
// TODO: move to client
/*
QVariantMap ScStwAppBackend::getBaseStationProperties() {
QVariantMap firmware = {{"version", this->scStwClient->getFirmwareVersion()}, {"upToDate", this->scStwClient->isFirmwareUpToDate()}};
return {{"firmware", firmware}, {"timeOffset", this->scStwClient->getTimeOffset()}};
}
bool ScStwAppBackend::updateBasestationFirmware() {
return this->scStwClient->updateFirmware();
}
bool ScStwAppBackend::updateBasestationTime() {
return this->scStwClient->updateTime();
}
bool ScStwAppBackend::reloadBaseStationIpAdress() {
if(this->scStwClient->getState() == ScStwClient::DISCONNECTED){
this->scStwClient->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress"));
return true;
}
return false;
*/
void ScStwAppBackend::reloadBaseStationIpAdress() {
this->scStwClient->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress"));
}

View file

@ -1,211 +0,0 @@
#include "headers/speedtimer.h"
SpeedTimer::SpeedTimer(QObject *parent) : QObject(parent)
{
this->date = new QDateTime;
this->startTime = 0;
this->stopTime = 0;
this->stoppedTime = 0;
this->reactionTime = 0;
this->state = IDLE;
}
bool SpeedTimer::start(bool force) {
if(this->state != STARTING && !force){
return false;
}
qDebug() << "starting timer";
if(!force){
this->stopTime = 0;
this->stoppedTime = 0;
this->reactionTime = 0;
this->startTime = this->date->currentMSecsSinceEpoch();
}
this->setState(RUNNING);
return true;
}
bool SpeedTimer::stop(int type, bool force) {
// type can be:
// 0: stopped
// 1: cancelled
// 2: failed (fase start)
if( ( this->state != SpeedTimer::STARTING && this->state != SpeedTimer::RUNNING && this->state ) && !force ){
return false;
}
//qDebug() << "Stopping: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << stoppedTime << " reactionTime: " << reactionTime;
switch (type) {
case 0:
{
this->stopTime = this->date->currentMSecsSinceEpoch();
this->stoppedTime = this->stopTime - this->startTime;
this->setState(WON);
break;
}
case 1:
{
this->stoppedTime = 0;
this->setState(CANCELLED);
break;
}
case 2:
{
this->stoppedTime = this->reactionTime;
this->setState(FAILED);
break;
}
}
qDebug() << "Stopped: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << stoppedTime << " reactionTime: " << reactionTime;
return true;
//this->startPad->appendCommand("SET_LED_STARTING");
}
bool SpeedTimer::reset(bool force){
if( ( this->state < WON ) && !force){
return false;
}
this->startTime = 0;
this->stopTime = 0;
this->stoppedTime = 0;
this->reactionTime = 0;
this->setState(IDLE);
return true;
//this->startPad->appendCommand("SET_LED_STARTING");
}
void SpeedTimer::setState(timerState newState){
if(this->state != newState){
this->state = newState;
qDebug() << "+--- timer state changed: " << newState;
emit this->stateChanged(newState);
}
}
QString SpeedTimer::getState(){
switch(state){
case IDLE:
return "IDLE";
case STARTING:
return "STARTING";
case WAITING:
return "WAITING";
case RUNNING:
return "RUNNING";
case WON:
return "WON";
case LOST:
return "LOST";
case FAILED:
return "FAILED";
case CANCELLED:
return "CANCELLED";
case DISABLED:
return "DISABLED";
}
return "ERROR";
}
double SpeedTimer::getCurrTime() {
double currTime;
if(this->state == RUNNING && this->startTime > 0){
currTime = this->date->currentMSecsSinceEpoch() - this->startTime;
}
else {
currTime = this->stoppedTime;
}
return(currTime);
}
QString SpeedTimer::getText() {
//qDebug() << this->getState();
QString newText;
switch (this->state) {
case SpeedTimer::IDLE:
newText = "0.000 sec";
break;
case SpeedTimer::STARTING:
newText = "0.000 sec";
break;
case SpeedTimer::WAITING:
newText = "please wait...";
break;
case SpeedTimer::RUNNING:
newText = QString::number( this->getCurrTime() / 1000.0, 'f', 3 ) + " sec";
break;
case SpeedTimer::WON:
newText = QString::number( this->stoppedTime / 1000.0, 'f', 3 ) + " sec";
break;
case SpeedTimer::LOST:
newText = QString::number( this->stoppedTime / 1000.0, 'f', 3 ) + " sec";
break;
case SpeedTimer::FAILED:
newText = "false start";
break;
case SpeedTimer::CANCELLED:
newText = "cancelled";
break;
case SpeedTimer::DISABLED:
newText = "---";
break;
}
return newText;
}
void SpeedTimer::delay(int mSecs){
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
// start the timer before starting to connect
timer.start(mSecs);
//connect
//wait for the connection to finish (programm gets stuck in here)
loop.exec();
}
SpeedTimer::timerState SpeedTimer::stateFromString(QString state){
if(state == "IDLE"){
return IDLE;
}
else if (state == "STARTING") {
return STARTING;
}
else if (state == "RUNNING") {
return RUNNING;
}
else if (state == "WON") {
return WON;
}
else if (state == "LOST") {
return LOST;
}
else if (state == "FAILED") {
return FAILED;
}
else if(state == "DISABLED") {
return DISABLED;
}
else {
return CANCELLED;
}
}