further bugfixes, added documentation for timer and sound player
This commit is contained in:
parent
6fbc556991
commit
654b05dec9
8 changed files with 533 additions and 255 deletions
|
@ -4,25 +4,25 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @mainpage ScStw Libraries documentation
|
* \mainpage ScStw Libraries documentation
|
||||||
*
|
*
|
||||||
* @section intro_sec Introduction
|
* \section intro_sec Introduction
|
||||||
*
|
*
|
||||||
* This library is meant for usage with the Speed climbing stopwatch project.
|
* This library is meant for usage with the Speed climbing stopwatch project.
|
||||||
* It contains some helper classes to build a client application for the ScStw basestation with Qt.
|
* It contains some helper classes to build a client application for the ScStw basestation with Qt.
|
||||||
*
|
*
|
||||||
* @section section Installation
|
* \section section Installation
|
||||||
* @code{.sh}
|
* \code{.sh}
|
||||||
* cd yourRepo
|
* cd yourRepo
|
||||||
* git submodule add https://git.itsblue.de/ScStw/shared-libraries/
|
* git submodule add https://git.itsblue.de/ScStw/shared-libraries/
|
||||||
* git submodule update --init --recursive
|
* git submodule update --init --recursive
|
||||||
* @endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* Add to the list of libraries for the Qt-Secret assembly. For an example you can create Main.Pro in which connect Qt-Secret and your project.pro files as subprojects.
|
* Add to the list of libraries for the Qt-Secret assembly. For an example you can create Main.Pro in which connect Qt-Secret and your project.pro files as subprojects.
|
||||||
*
|
*
|
||||||
* Main.pro:
|
* Main.pro:
|
||||||
* @code{.pro}
|
* \code{.pro}
|
||||||
* TEMPLATE = subdirs
|
* TEMPLATE = subdirs
|
||||||
* CONFIG += ordered
|
* CONFIG += ordered
|
||||||
*
|
*
|
||||||
|
@ -31,25 +31,25 @@
|
||||||
* MyProject
|
* MyProject
|
||||||
*
|
*
|
||||||
* ScStwLibraries.file = shared-libraries/ScStwLibraries/ScStwLibraries.pro
|
* ScStwLibraries.file = shared-libraries/ScStwLibraries/ScStwLibraries.pro
|
||||||
* @endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* And in your MyProject.pro include the .pri file:
|
* And in your MyProject.pro include the .pri file:
|
||||||
* @code{.pro}
|
* \code{.pro}
|
||||||
* include($$PWD/../shared-libraries/ScStwLibraries/ScStwLibraries.pri)
|
* include($$PWD/../shared-libraries/ScStwLibraries/ScStwLibraries.pri)
|
||||||
* @endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief The ScStw class provides some shared functions and enums for use in the ScStw project.
|
* \brief The ScStw class provides some shared functions and enums for use in the ScStw project.
|
||||||
*/
|
*/
|
||||||
class ScStw : public QObject {
|
class ScStw : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief The SignalKey enum contains all signal keys a client can subscribe to
|
* \brief The SignalKey enum contains all signal keys a client can subscribe to
|
||||||
*
|
*
|
||||||
* @see ScStw::signalKeyFromInt()
|
* \see ScStw::signalKeyFromInt()
|
||||||
*/
|
*/
|
||||||
enum SignalKey {
|
enum SignalKey {
|
||||||
InvalidSignal = -1,
|
InvalidSignal = -1,
|
||||||
|
@ -60,13 +60,13 @@ public:
|
||||||
};
|
};
|
||||||
Q_ENUM(SignalKey)
|
Q_ENUM(SignalKey)
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief The BaseStationSetting enum contains all settings of the base station that can be changed by a client
|
* \brief The BaseStationSetting enum contains all settings of the base station that can be changed by a client
|
||||||
*
|
*
|
||||||
* @see ScStw::baseStationSettingFromInt()
|
* \see ScStw::baseStationSettingFromInt()
|
||||||
* @see ScStw::baseStationSettingToString()
|
* \see ScStw::baseStationSettingToString()
|
||||||
* @see ScStw::baseStationSettingFromString()
|
* \see ScStw::baseStationSettingFromString()
|
||||||
* @see ScStw::baseStationSettings
|
* \see ScStw::baseStationSettings
|
||||||
*/
|
*/
|
||||||
enum BaseStationSetting {
|
enum BaseStationSetting {
|
||||||
InvalidSetting = -1,
|
InvalidSetting = -1,
|
||||||
|
@ -78,8 +78,8 @@ public:
|
||||||
};
|
};
|
||||||
Q_ENUM(BaseStationSetting)
|
Q_ENUM(BaseStationSetting)
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief The ErrorCode enum contains all error codes that can occur when sending a command to the basestation
|
* \brief The ErrorCode enum contains all error codes that can occur when sending a command to the basestation
|
||||||
*/
|
*/
|
||||||
enum ErrorCode {
|
enum ErrorCode {
|
||||||
Success = 200,
|
Success = 200,
|
||||||
|
@ -91,60 +91,60 @@ public:
|
||||||
};
|
};
|
||||||
Q_ENUM(ErrorCode)
|
Q_ENUM(ErrorCode)
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief SOCKET_MESSAGE_START_KEY contains the key, a message is supposed to start with
|
* \brief SOCKET_MESSAGE_START_KEY contains the key, a message is supposed to start with
|
||||||
*/
|
*/
|
||||||
static const char* SOCKET_MESSAGE_START_KEY;
|
static const char* SOCKET_MESSAGE_START_KEY;
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief SOCKET_MESSAGE_END_KEY contains the key, a message is supposed to end with
|
* \brief SOCKET_MESSAGE_END_KEY contains the key, a message is supposed to end with
|
||||||
*/
|
*/
|
||||||
static const char* SOCKET_MESSAGE_END_KEY;
|
static const char* SOCKET_MESSAGE_END_KEY;
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief baseStationSettings contains a string with reference to all BaseStationSetting values
|
* \brief baseStationSettings contains a string with reference to all BaseStationSetting values
|
||||||
*
|
*
|
||||||
* @see ScStw::BaseStationSetting
|
* \see ScStw::BaseStationSetting
|
||||||
* @see ScStw::baseStationSettingToString()
|
* \see ScStw::baseStationSettingToString()
|
||||||
* @see ScStw::baseStationSettingFromString()
|
* \see ScStw::baseStationSettingFromString()
|
||||||
*/
|
*/
|
||||||
static const QMap<QString, ScStw::BaseStationSetting> baseStationSettings;
|
static const QMap<QString, ScStw::BaseStationSetting> baseStationSettings;
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to convert an int to a BaseStationSetting
|
* \brief Function to convert an int to a BaseStationSetting
|
||||||
* @param i the int to convert
|
* \param i the int to convert
|
||||||
* @return a BaseStationSetting
|
* \return a BaseStationSetting
|
||||||
*
|
*
|
||||||
* @see ScStw::BaseStationSetting
|
* \see ScStw::BaseStationSetting
|
||||||
*/
|
*/
|
||||||
static BaseStationSetting baseStationSettingfromInt(int i);
|
static BaseStationSetting baseStationSettingfromInt(int i);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to convert a QString to a BaseStationSetting
|
* \brief Function to convert a QString to a BaseStationSetting
|
||||||
* @param s the string to convert
|
* \param s the string to convert
|
||||||
* @return a BaseStationSetting
|
* \return a BaseStationSetting
|
||||||
*
|
*
|
||||||
* @see ScStw::BaseStationSetting
|
* \see ScStw::BaseStationSetting
|
||||||
* @see ScStw::baseStationSettingToString()
|
* \see ScStw::baseStationSettingToString()
|
||||||
*/
|
*/
|
||||||
static BaseStationSetting baseStationSettingFromString(QString s);
|
static BaseStationSetting baseStationSettingFromString(QString s);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to convert BaseStationSetting to a QString
|
* \brief Function to convert BaseStationSetting to a QString
|
||||||
* @param s the BaseStationSetting to convert
|
* \param s the BaseStationSetting to convert
|
||||||
* @return a QString
|
* \return a QString
|
||||||
*
|
*
|
||||||
* @see ScStw::BaseStationSetting
|
* \see ScStw::BaseStationSetting
|
||||||
* @see ScStw::baseStationSettingFromString()
|
* \see ScStw::baseStationSettingFromString()
|
||||||
*/
|
*/
|
||||||
static QString baseStationSettingToString(BaseStationSetting s);
|
static QString baseStationSettingToString(BaseStationSetting s);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to convert an int to a SignalKey
|
* \brief Function to convert an int to a SignalKey
|
||||||
* @param i the int to convert
|
* \param i the int to convert
|
||||||
* @return a SignalKey
|
* \return a SignalKey
|
||||||
*
|
*
|
||||||
* @see ScStw::SignalKey
|
* \see ScStw::SignalKey
|
||||||
*/
|
*/
|
||||||
static SignalKey signalKeyFromInt(int i);
|
static SignalKey signalKeyFromInt(int i);
|
||||||
|
|
||||||
|
|
|
@ -16,27 +16,27 @@
|
||||||
|
|
||||||
#include "ScStw.hpp"
|
#include "ScStw.hpp"
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* This class is used to connect and talk to the ScStw basestation.
|
* This class is used to connect and talk to the ScStw basestation.
|
||||||
*
|
*
|
||||||
* @code{.cpp}
|
* \code{.cpp}
|
||||||
* ScStwClient * client = new ScStwClient();
|
* ScStwClient * client = new ScStwClient();
|
||||||
* client->setIp("192.168.4.1");
|
* client->setIp("192.168.4.1");
|
||||||
* client->connectToHost();
|
* client->connectToHost();
|
||||||
* @endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
* @brief The ScStwClient class
|
* \brief The ScStwClient class
|
||||||
* @author Dorian Zedler
|
* \author Dorian Zedler
|
||||||
*/
|
*/
|
||||||
class ScStwClient : public QObject
|
class ScStwClient : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/*!
|
||||||
* The constructor
|
* The constructor
|
||||||
*
|
*
|
||||||
* @brief ScStwClient
|
* \brief ScStwClient
|
||||||
*/
|
*/
|
||||||
explicit ScStwClient();
|
explicit ScStwClient();
|
||||||
|
|
||||||
|
@ -81,232 +81,232 @@ private:
|
||||||
QList<waitingRequest> waitingRequests;
|
QList<waitingRequest> waitingRequests;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/*!
|
||||||
* @brief Is emitted, when the connection state changes
|
* \brief Is emitted, when the connection state changes
|
||||||
*/
|
*/
|
||||||
void stateChanged();
|
void stateChanged();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Is emitted, whenever a reply is recieved which does not match any requests
|
* \brief Is emitted, whenever a reply is recieved which does not match any requests
|
||||||
*
|
*
|
||||||
* @param reply contains the reply
|
* \param reply contains the reply
|
||||||
*/
|
*/
|
||||||
void gotUnexpectedMessage(QString message);
|
void gotUnexpectedMessage(QString message);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Is emitted, when an update signal from the basestation is recieved
|
* \brief Is emitted, when an update signal from the basestation is recieved
|
||||||
*
|
*
|
||||||
* @param data
|
* \param data
|
||||||
*/
|
*/
|
||||||
void gotSignal(ScStw::SignalKey key, QVariant data);
|
void gotSignal(ScStw::SignalKey key, QVariant data);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Is emitted, when there is any network error
|
* \brief Is emitted, when there is any network error
|
||||||
* @param error
|
* \param error
|
||||||
*/
|
*/
|
||||||
void gotError(QAbstractSocket::SocketError error);
|
void gotError(QAbstractSocket::SocketError error);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to connect to the base station
|
* \brief Function to connect to the base station
|
||||||
*/
|
*/
|
||||||
void connectToHost();
|
void connectToHost();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to disconnect from the basestation
|
* \brief Function to disconnect from the basestation
|
||||||
*/
|
*/
|
||||||
void closeConnection();
|
void closeConnection();
|
||||||
|
|
||||||
|
|
||||||
/** socket communication handling */
|
/*! socket communication handling */
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Funtion to send a command to the server (for internal use)
|
* \brief Funtion to send a command to the server (for internal use)
|
||||||
* @param header the command to send
|
* \param header the command to send
|
||||||
* @param data the data to send
|
* \param data the data to send
|
||||||
* @param timeout the timeout
|
* \param timeout the timeout
|
||||||
* @param useTerminationKeys wether to use the termination keys defined in
|
* \param useTerminationKeys wether to use the termination keys defined in
|
||||||
*
|
*
|
||||||
* @return a variant map containing the Keys "status" and "data"
|
* \return a variant map containing the Keys "status" and "data"
|
||||||
*/
|
*/
|
||||||
QVariantMap sendCommand(int header, QJsonValue data = "", int timeout = 3000);
|
QVariantMap sendCommand(int header, QJsonValue data = "", int timeout = 3000);
|
||||||
|
|
||||||
/** updater functions */
|
/*! updater functions */
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to set the timestamp of the base station to match the client
|
* \brief Function to set the timestamp of the base station to match the client
|
||||||
* @see getTimeOffset()
|
* \see getTimeOffset()
|
||||||
* @return true or false
|
* \return true or false
|
||||||
*/
|
*/
|
||||||
bool updateTime();
|
bool updateTime();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to update the firmware of the basestation to the version stored in the client
|
* \brief Function to update the firmware of the basestation to the version stored in the client
|
||||||
* @details will not do anything if the remote firmware is newer or the same as the clients one
|
* \details will not do anything if the remote firmware is newer or the same as the clients one
|
||||||
* @see isFirmwareUpToDate()
|
* \see isFirmwareUpToDate()
|
||||||
* @see getFirmwareVersion()
|
* \see getFirmwareVersion()
|
||||||
* @return true: firmware was updated or is already up-to-date; false: there was an error during the update
|
* \return true: firmware was updated or is already up-to-date; false: there was an error during the update
|
||||||
*/
|
*/
|
||||||
bool updateFirmware();
|
bool updateFirmware();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to check wether the firmware of the base station is up-to-date
|
* \brief Function to check wether the firmware of the base station is up-to-date
|
||||||
* @see getFirmwareVersion()
|
* \see getFirmwareVersion()
|
||||||
* @see updateFirmware()
|
* \see updateFirmware()
|
||||||
* @return true or false
|
* \return true or false
|
||||||
*/
|
*/
|
||||||
bool isFirmwareUpToDate();
|
bool isFirmwareUpToDate();
|
||||||
|
|
||||||
/** helper functions */
|
/*! helper functions */
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to write a setting on the base station
|
* \brief Function to write a setting on the base station
|
||||||
* @param key the key to write to
|
* \param key the key to write to
|
||||||
* @param value the value to write to
|
* \param value the value to write to
|
||||||
* @return the status code returned by the command
|
* \return the status code returned by the command
|
||||||
*/
|
*/
|
||||||
ScStw::ErrorCode writeRemoteSetting(ScStw::BaseStationSetting key, QString value);
|
ScStw::ErrorCode writeRemoteSetting(ScStw::BaseStationSetting key, QString value);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to read a setting on the base station
|
* \brief Function to read a setting on the base station
|
||||||
* @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
|
||||||
*/
|
*/
|
||||||
QString readRemoteSetting(ScStw::BaseStationSetting key);
|
QString readRemoteSetting(ScStw::BaseStationSetting key);
|
||||||
|
|
||||||
/** Getter fuctions */
|
/*! Getter fuctions */
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to get the ip the client will try to connect to.
|
* \brief Function to get the ip the client will try to connect to.
|
||||||
* @see setIP()
|
* \see setIP()
|
||||||
* @return the ip
|
* \return the ip
|
||||||
*/
|
*/
|
||||||
QString getIP();
|
QString getIP();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to get the current state of the client
|
* \brief Function to get the current state of the client
|
||||||
* @return the current state
|
* \return the current state
|
||||||
*/
|
*/
|
||||||
ScStwClient::State getState();
|
ScStwClient::State getState();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Functio to get the extensions and their state from the base station
|
* \brief Functio to get the extensions and their state from the base station
|
||||||
* @return a list with all configured extensions and their state
|
* \return a list with all configured extensions and their state
|
||||||
*/
|
*/
|
||||||
QVariantList getConnections();
|
QVariantList getConnections();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to get the time offset of the base station relative to the clients time
|
* \brief Function to get the time offset of the base station relative to the clients time
|
||||||
* @see updateTime()
|
* \see updateTime()
|
||||||
* @return the time offset in milliseconds
|
* \return the time offset in milliseconds
|
||||||
*/
|
*/
|
||||||
int getTimeOffset();
|
int getTimeOffset();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to get the current firmware version of the base station
|
* \brief Function to get the current firmware version of the base station
|
||||||
* @see updateFirmware()
|
* \see updateFirmware()
|
||||||
* @see isFirmwareUpToDate()
|
* \see isFirmwareUpToDate()
|
||||||
* @return Firmware version as string encoded as <major>.<minor>.<patch>
|
* \return Firmware version as string encoded as <major>.<minor>.<patch>
|
||||||
*/
|
*/
|
||||||
QString getFirmwareVersion();
|
QString getFirmwareVersion();
|
||||||
|
|
||||||
/** setter functions */
|
/*! setter functions */
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to set the ip to connect to
|
* \brief Function to set the ip to connect to
|
||||||
* @see getIP()
|
* \see getIP()
|
||||||
* @param ipAdress
|
* \param ipAdress
|
||||||
*/
|
*/
|
||||||
void setIP(QString ipAdress);
|
void setIP(QString ipAdress);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
/**
|
/*!
|
||||||
* @brief called when timeout timer times out
|
* \brief called when timeout timer times out
|
||||||
*/
|
*/
|
||||||
void connectionTimeout();
|
void connectionTimeout();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function that is connected to the QAbstractSocket::error slot and used to handle upcoming errors
|
* \brief Function that is connected to the QAbstractSocket::error slot and used to handle upcoming errors
|
||||||
* @param err the error that occurred
|
* \param err the error that occurred
|
||||||
*/
|
*/
|
||||||
void handleError(QAbstractSocket::SocketError err);
|
void handleError(QAbstractSocket::SocketError err);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to init a session at the base station
|
* \brief Function to init a session at the base station
|
||||||
* @return true or false
|
* \return true or false
|
||||||
*/
|
*/
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to end a session on the base station
|
* \brief Function to end a session on the base station
|
||||||
*/
|
*/
|
||||||
void deInit();
|
void deInit();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Funtion to send a command to the server (for internal use)
|
* \brief Funtion to send a command to the server (for internal use)
|
||||||
* @param header the command to send
|
* \param header the command to send
|
||||||
* @param data the data to send
|
* \param data the data to send
|
||||||
* @param timeout the timeout
|
* \param timeout the timeout
|
||||||
* @param useTerminationKeys wether to use the termination keys defined in
|
* \param useTerminationKeys wether to use the termination keys defined in
|
||||||
* ScStw::SOCKET_MESSAGE_START_KEY and ScStw::SOCKET_MESSAGE_END_KEY
|
* ScStw::SOCKET_MESSAGE_START_KEY and ScStw::SOCKET_MESSAGE_END_KEY
|
||||||
* @return a variant map containing the Keys "status" and "data"
|
* \return a variant map containing the Keys "status" and "data"
|
||||||
*/
|
*/
|
||||||
QVariantMap sendCommand(int header, QJsonValue data, int timeout, bool useTerminationKeys);
|
QVariantMap sendCommand(int header, QJsonValue data, int timeout, bool useTerminationKeys);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function connected to the QAbstractSocket::readyRead signal
|
* \brief Function connected to the QAbstractSocket::readyRead signal
|
||||||
*/
|
*/
|
||||||
void handleReadyRead();
|
void handleReadyRead();
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to process an incoming string and parse the messages contained in it.
|
* \brief Function to process an incoming string and parse the messages contained in it.
|
||||||
* @param message the message sting to parse
|
* \param message the message sting to parse
|
||||||
*/
|
*/
|
||||||
void processSocketMessage(QString message);
|
void processSocketMessage(QString message);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function that handles a parsed message
|
* \brief Function that handles a parsed message
|
||||||
* @details This fuction looks up the id of the incoming message and tries to find the according waiting request.
|
* \details This fuction looks up the id of the incoming message and tries to find the according waiting request.
|
||||||
* If it is unable to find an accordin request, the signal ScStwClient::gotUnexpectedMessage(QString message) is called.
|
* If it is unable to find an accordin request, the signal ScStwClient::gotUnexpectedMessage(QString message) is called.
|
||||||
* If the recieved message is a signal, the ScStwClient::handleSignal() function is called.
|
* If the recieved message is a signal, the ScStwClient::handleSignal() function is called.
|
||||||
* @see gotUnexpectedMessage()
|
* \see gotUnexpectedMessage()
|
||||||
* @see handleSignal()
|
* \see handleSignal()
|
||||||
* @param reply the massage that needs to be handles
|
* \param reply the massage that needs to be handles
|
||||||
*/
|
*/
|
||||||
void handleSocketMessage(QString reply);
|
void handleSocketMessage(QString reply);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to handle a change of the state of the tcp socket
|
* \brief Function to handle a change of the state of the tcp socket
|
||||||
* @details it is connected to the QAbstractSocket::stateChanged signal
|
* \details it is connected to the QAbstractSocket::stateChanged signal
|
||||||
* @see stateChanged()
|
* \see stateChanged()
|
||||||
* @param socketState
|
* \param socketState
|
||||||
*/
|
*/
|
||||||
void handleSocketStateChange(QAbstractSocket::SocketState socketState);
|
void handleSocketStateChange(QAbstractSocket::SocketState socketState);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to handle a signal from the base station.
|
* \brief Function to handle a signal from the base station.
|
||||||
* @details Called by the ScStwClient::handleSocketMessage function
|
* \details Called by the ScStwClient::handleSocketMessage function
|
||||||
* @see handleSocketMessage()
|
* \see handleSocketMessage()
|
||||||
* @param data
|
* \param data
|
||||||
*/
|
*/
|
||||||
void handleSignal(QVariantMap data);
|
void handleSignal(QVariantMap data);
|
||||||
|
|
||||||
/** Helper Functions */
|
/*! Helper Functions */
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function used to set the local cache of the baseStation connections.
|
* \brief Function used to set the local cache of the baseStation connections.
|
||||||
* @details emits ScStwClient::gotSignal() with a ScStw::ExtensionsChanged signal.
|
* \details emits ScStwClient::gotSignal() with a ScStw::ExtensionsChanged signal.
|
||||||
* @see gotSignal()
|
* \see gotSignal()
|
||||||
* @param connections the list to set the chache to
|
* \param connections the list to set the chache to
|
||||||
*/
|
*/
|
||||||
void setConnections(QVariantList connections);
|
void setConnections(QVariantList connections);
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief Function to set the local state.
|
* \brief Function to set the local state.
|
||||||
* @details emits ScStwClient::stateChanged() when the new state does not match the old one.
|
* \details emits ScStwClient::stateChanged() when the new state does not match the old one.
|
||||||
* @see stateChanged()
|
* \see stateChanged()
|
||||||
* @param newState the state to change to
|
* \param newState the state to change to
|
||||||
*/
|
*/
|
||||||
void setState(ScStwClient::State newState);
|
void setState(ScStwClient::State newState);
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,10 +37,10 @@ private:
|
||||||
// some settings
|
// some settings
|
||||||
double soundVolume;
|
double soundVolume;
|
||||||
|
|
||||||
/**
|
/*!
|
||||||
* @brief stores the start action settings
|
* \brief stores the start action settings
|
||||||
*
|
*
|
||||||
* @details Stores the settings for the action ScStwRace::AtYourMarks and ScStwRace::Ready. The settings keys are: "Enabled" and "Delay"
|
* \details Stores the settings for the action ScStwRace::AtYourMarks and ScStwRace::Ready. The settings keys are: "Enabled" and "Delay"
|
||||||
*/
|
*/
|
||||||
QMap<StartAction, QVariantMap> startActionSettings;
|
QMap<StartAction, QVariantMap> startActionSettings;
|
||||||
|
|
||||||
|
|
|
@ -9,31 +9,94 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The ScStwSoundPlayer class is used for ultra low latency sound playback of the speed clibing start tones and commands
|
||||||
|
*/
|
||||||
class ScStwSoundPlayer : public QObject
|
class ScStwSoundPlayer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief ScStwSoundPlayer constructor
|
||||||
|
* \param parent
|
||||||
|
*/
|
||||||
explicit ScStwSoundPlayer(QObject *parent = nullptr);
|
explicit ScStwSoundPlayer(QObject *parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*!
|
||||||
|
* \brief A map containing all sound files
|
||||||
|
* 0: AtYourMarksSound
|
||||||
|
* 1: ReadySound
|
||||||
|
* 2: StartSound
|
||||||
|
*/
|
||||||
QMap<int, QFile*> soundFiles;
|
QMap<int, QFile*> soundFiles;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Containng the false start sound file
|
||||||
|
*/
|
||||||
QFile *falseStartSoundFile;
|
QFile *falseStartSoundFile;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The audio output object
|
||||||
|
*/
|
||||||
QAudioOutput *audioOutput;
|
QAudioOutput *audioOutput;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The QEventLoop used to wait for the sound to finish
|
||||||
|
*/
|
||||||
QEventLoop *waitLoop;
|
QEventLoop *waitLoop;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The QTimer to wait for the sound to finish
|
||||||
|
*/
|
||||||
QTimer *waitTimer;
|
QTimer *waitTimer;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The action that is currently played
|
||||||
|
*/
|
||||||
int currentlyPlayingAction;
|
int currentlyPlayingAction;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool play(int action, double volume, double *timeOfStop = nullptr);
|
|
||||||
bool cancel(double volume);
|
/*!
|
||||||
|
* \brief Function to begin playing the sound of a certain state
|
||||||
|
* \param action The action to play (0: AtYourMarks, 1:Ready, 2:Start)
|
||||||
|
* \param volume The volume to play at
|
||||||
|
* \param timeOfStop The time the playback actually started (msecs since epoch)
|
||||||
|
* \return true if the playback was successfully started, false otherwise
|
||||||
|
*/
|
||||||
|
bool play(int action, double volume, double *timeOfStart = nullptr);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to wait for the playback to finish
|
||||||
|
* \param timeOfStop the point in time when the plyback actually stopped (msecs since epoch)
|
||||||
|
* \return false if there was any error (eg. there was no playback currently), true otherwise
|
||||||
|
*/
|
||||||
bool waitForSoundFinish(double *timeOfStop = nullptr);
|
bool waitForSoundFinish(double *timeOfStop = nullptr);
|
||||||
//int interrupt();
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to cancel the current playback
|
||||||
|
*
|
||||||
|
* Note that this function will automatically play the false start tone if the currently playing action is 2
|
||||||
|
*
|
||||||
|
* \param volume the volume to play the false start sound at
|
||||||
|
* \return true if the playback was successfully stopped, false otherwise
|
||||||
|
*/
|
||||||
|
bool cancel(double volume = 0);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Handle a state change of the audio output
|
||||||
|
* \param newState the new state of the audio output
|
||||||
|
*/
|
||||||
void handleStateChanged(QAudio::State newState);
|
void handleStateChanged(QAudio::State newState);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Emitted whenever a playback started
|
||||||
|
*/
|
||||||
void playbackStarted();
|
void playbackStarted();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,58 +7,263 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include "ScStw.hpp"
|
#include "ScStw.hpp"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The ScStwTimer class is used for advanced time measurement.
|
||||||
|
*
|
||||||
|
* It does not work on its own though.
|
||||||
|
* It is recommended to use it in combination with the ScStwRace class.
|
||||||
|
*
|
||||||
|
* ## When using standalone:
|
||||||
|
* \code{.cpp}
|
||||||
|
* ScStwTimer timer;
|
||||||
|
* // start the timer
|
||||||
|
* timer.start();
|
||||||
|
* // stop the timer
|
||||||
|
* timer.stop();
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* The timer will now go into ScStw::WAITING state.
|
||||||
|
* That indicates that the timer has stopped and the final result has to be assigned by an external handler.
|
||||||
|
*
|
||||||
|
* \code{.cpp}
|
||||||
|
* // assign result 'won'
|
||||||
|
* timer.setResult(ScStwTimer::WON);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* The timer is now in ScStwTimer::WON state.
|
||||||
|
*
|
||||||
|
* \code{.cpp}
|
||||||
|
* // reset the timer
|
||||||
|
* timer.reset();
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* The timer is not in ScStwTimer::IDLE state again.
|
||||||
|
*/
|
||||||
class ScStwTimer : public QObject
|
class ScStwTimer : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief ScStwTimer constructor
|
||||||
|
* \param parent the parent object
|
||||||
|
*/
|
||||||
explicit ScStwTimer(QObject *parent = nullptr);
|
explicit ScStwTimer(QObject *parent = nullptr);
|
||||||
|
|
||||||
enum TimerState { IDLE, STARTING, WAITING, RUNNING, WON, LOST, FAILED, CANCELLED, DISABLED };
|
/*!
|
||||||
enum StopReason { ManualStop, CancelStop, FailStop, TopPadStop };
|
* \brief The TimerState enum contains all state the timer can be in
|
||||||
|
*/
|
||||||
|
enum TimerState {
|
||||||
|
IDLE, /*!< Timer is waiting to be started */
|
||||||
|
STARTING, /*!< Timer is starting and will react with a false start if the climber starts */
|
||||||
|
RUNNING, /*!< Timer is running */
|
||||||
|
WAITING, /*!< Timer was stopped and is waiting for the result */
|
||||||
|
WON, /*!< Timer has won */
|
||||||
|
LOST, /*!< Timer has lost */
|
||||||
|
FAILED, /*!< A false start occured */
|
||||||
|
CANCELLED, /*!< Timer was cancelled */
|
||||||
|
DISABLED /*!< Timer is disabled */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The StopReason enum contains all possible reasons for a stop
|
||||||
|
*/
|
||||||
|
enum StopReason {
|
||||||
|
ManualStop, /*!< Timer was stopped manually */
|
||||||
|
CancelStop, /*!< Timer was cancelled */
|
||||||
|
FailStop, /*!< A false start occured */
|
||||||
|
TopPadStop /*!< Timer was stopped by a physical trigger (eg. a ScStwExtension) */
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/*!
|
||||||
|
* \brief The current state of the timer
|
||||||
|
*/
|
||||||
TimerState state;
|
TimerState state;
|
||||||
|
|
||||||
// variables for capturing the time
|
/*!
|
||||||
|
* \brief The time the timer was started at
|
||||||
|
*/
|
||||||
double startTime;
|
double startTime;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The time the timer was stopped at
|
||||||
|
*/
|
||||||
double stopTime;
|
double stopTime;
|
||||||
double stoppedTime;
|
|
||||||
|
/*!
|
||||||
|
* \brief the reaction time of the climber
|
||||||
|
*/
|
||||||
double reactionTime;
|
double reactionTime;
|
||||||
|
|
||||||
// values for the startpad
|
|
||||||
double startPadTriggerTime;
|
|
||||||
|
|
||||||
QDateTime *date;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
// --- main functionality ---
|
/*!
|
||||||
|
* \brief Function to start the timer
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::STARTING state!
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and therefore not started, true otherwise
|
||||||
|
*/
|
||||||
bool start();
|
bool start();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to start the timer at a given point in time (present or future)
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::STARTING state!
|
||||||
|
*
|
||||||
|
* \param timeOfStart the point in time (msecs since epoch) when the timer is supposted to be started
|
||||||
|
* \return false if the timer was not in the required state and therefore not started, true otherwise
|
||||||
|
*/
|
||||||
bool start(double timeOfStart);
|
bool start(double timeOfStart);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to cancel the timer
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::IDLE, ScStwTimer::STARTING or ScStwTimer::RUNNING state!
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and therefore not cancelled, true otherwise
|
||||||
|
*/
|
||||||
bool cancel();
|
bool cancel();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to stop the timer
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::RUNNING state!
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and therefore not stopped, true otherwise
|
||||||
|
*/
|
||||||
bool stop();
|
bool stop();
|
||||||
bool stop(TimerState);
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to stop the timer at a given point in time (past or future)
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::RUNNING state!
|
||||||
|
*
|
||||||
|
* \param timeOfStop the point in time (msecs since epoch) when the timer is supposted to be stopped
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and therefore not stopped, true otherwise
|
||||||
|
*/
|
||||||
|
bool stop(double timeOfStop);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to assing the result of the race to the timer
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::WAITING state!
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and the result therefore not set, true otherwise
|
||||||
|
*/
|
||||||
|
bool setResult(TimerState);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to reset the timer
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::WON or ScSTw::LOST state!
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and therefore not reset, true otherwise
|
||||||
|
*/
|
||||||
bool reset();
|
bool reset();
|
||||||
|
|
||||||
// --- helper functions ---
|
// -- helper functions --
|
||||||
|
/*!
|
||||||
|
* \brief Function to get the current state of the timer
|
||||||
|
* \return current state of the timer
|
||||||
|
* \see ScStwTimer::TimerState
|
||||||
|
*/
|
||||||
TimerState getState();
|
TimerState getState();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to get the current time of the timer
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::RUNNING, ScStwTimer::WAITING, ScStwTimer::WON or ScSTw::LOST state!
|
||||||
|
*
|
||||||
|
* \return The current / final time of the timer or -1 if it is not in the required state
|
||||||
|
*/
|
||||||
double getCurrentTime();
|
double getCurrentTime();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to get the reaction time of the climber.
|
||||||
|
* \return The climbers reaction time
|
||||||
|
*/
|
||||||
double getReactionTime();
|
double getReactionTime();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to set if the timer is supposed to be disabled
|
||||||
|
*
|
||||||
|
* !!! CAUTION use this function with care, it immidiately changes the state of the timer !!!
|
||||||
|
* It is recommended to only use this function to change the timers state after the
|
||||||
|
* ScStwTimer::requestTimerEnableChange() signal was called, during the race,
|
||||||
|
* the timer is used in, is in IDLE state.
|
||||||
|
*
|
||||||
|
* \param disabled if the timer is supposed to be diabled
|
||||||
|
*/
|
||||||
void setDisabled(bool disabled);
|
void setDisabled(bool disabled);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief slot to call when the climber has started
|
||||||
|
* \param timeOfStart time (msecs since epoch) when the climber started
|
||||||
|
*/
|
||||||
void handleClimberStart(double timeOfStart);
|
void handleClimberStart(double timeOfStart);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to stop the timer at a given point in time (past or future)
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::RUNNING state!
|
||||||
|
*
|
||||||
|
* \param reason reason for the timer stop
|
||||||
|
* \param timeOfStop the point in time (msecs since epoch) when the timer is supposted to be stopped
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and therefore not stopped, true otherwise
|
||||||
|
*
|
||||||
|
* \see ScStwTimer::StopReason
|
||||||
|
*/
|
||||||
|
bool stop(StopReason reason, double timeOfStop);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Function to stop the timer
|
||||||
|
*
|
||||||
|
* To do this, the timer has to be in ScStwTimer::RUNNING state!
|
||||||
|
*
|
||||||
|
* \param reason reason for the timer stop
|
||||||
|
*
|
||||||
|
* \return false if the timer was not in the required state and therefore not stopped, true otherwise
|
||||||
|
*
|
||||||
|
* \see ScStwTimer::StopReason
|
||||||
|
*/
|
||||||
bool stop(StopReason reason);
|
bool stop(StopReason reason);
|
||||||
|
|
||||||
// --- helper functions ---
|
// --- helper functions ---
|
||||||
|
/*!
|
||||||
|
* \brief Function to change the state of the timer
|
||||||
|
*
|
||||||
|
* Doing this will emit the ScStwTimer::stateChanged() signal (only if the new state differs from the current one)
|
||||||
|
*
|
||||||
|
* \param newState The new state
|
||||||
|
*/
|
||||||
void setState(TimerState newState);
|
void setState(TimerState newState);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
/*!
|
||||||
|
* \brief Emitted when the state of the timer changed
|
||||||
|
*/
|
||||||
void stateChanged();
|
void stateChanged();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Emitted when the start was canceled
|
||||||
|
* \param falseStart Wheter a false start occured
|
||||||
|
*/
|
||||||
void startCanceled(bool falseStart);
|
void startCanceled(bool falseStart);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Emitted when the reaction time changed
|
||||||
|
*/
|
||||||
void reactionTimeChanged();
|
void reactionTimeChanged();
|
||||||
void stopRequested();
|
|
||||||
|
/*!
|
||||||
|
* \brief Emitted when the timer wants its state to be changed by the external handler
|
||||||
|
* \param timer the timer object
|
||||||
|
*/
|
||||||
void requestEnableChange(ScStwTimer* timer);
|
void requestEnableChange(ScStwTimer* timer);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ ScStwRace::ScStwRace(QObject *parent) : QObject(parent)
|
||||||
// configure timer that handles the delay between the start commands
|
// configure timer that handles the delay between the start commands
|
||||||
this->nextActionTimer = new QTimer(this);
|
this->nextActionTimer = new QTimer(this);
|
||||||
nextActionTimer->setSingleShot(true);
|
nextActionTimer->setSingleShot(true);
|
||||||
this->nextActionLoop = new QEventLoop(this);
|
this->nextActionLoop = new QEventLoop();
|
||||||
|
|
||||||
connect(this->nextActionTimer, &QTimer::timeout, this->nextActionLoop, &QEventLoop::quit);
|
connect(this->nextActionTimer, &QTimer::timeout, this->nextActionLoop, &QEventLoop::quit);
|
||||||
|
|
||||||
|
@ -59,12 +59,14 @@ int ScStwRace::stop() {
|
||||||
|
|
||||||
qDebug() << "+ [INFO] stopping race";
|
qDebug() << "+ [INFO] stopping race";
|
||||||
|
|
||||||
|
double timeOfStop = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|
||||||
int returnCode = 900;
|
int returnCode = 900;
|
||||||
|
|
||||||
bool stopOk = true;
|
bool stopOk = true;
|
||||||
|
|
||||||
foreach(ScStwTimer *speedTimer, this->timers){
|
foreach(ScStwTimer *speedTimer, this->timers){
|
||||||
if(!speedTimer->stop() && speedTimer->getState() != ScStwTimer::DISABLED){
|
if(!speedTimer->stop(timeOfStop) && speedTimer->getState() != ScStwTimer::DISABLED){
|
||||||
stopOk = false;
|
stopOk = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,11 +87,10 @@ void ScStwRace::handleTimerStop() {
|
||||||
if(this->state == RUNNING) {
|
if(this->state == RUNNING) {
|
||||||
// find out which timer has won
|
// find out which timer has won
|
||||||
double lowestStoppedTime = -1;
|
double lowestStoppedTime = -1;
|
||||||
QList<int> timersWhichHaveWonIds;
|
QList<ScStwTimer *> timersWhichHaveWonIds;
|
||||||
|
|
||||||
// iterate through all timers and find the lowest time taht was stopped
|
// iterate through all timers and find the lowest time taht was stopped
|
||||||
for(int i = 0; i < this->timers.length(); i++) {
|
foreach(ScStwTimer * timer, this->timers) {
|
||||||
ScStwTimer * timer = this->timers[i];
|
|
||||||
if(timer->getCurrentTime() > 0 && (timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0)) {
|
if(timer->getCurrentTime() > 0 && (timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0)) {
|
||||||
// this is the timer with the lowest stopped time
|
// this is the timer with the lowest stopped time
|
||||||
lowestStoppedTime = timer->getCurrentTime();
|
lowestStoppedTime = timer->getCurrentTime();
|
||||||
|
@ -97,27 +98,28 @@ void ScStwRace::handleTimerStop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the timer(s) with the lowest stopped time to the winner list
|
// append the timer(s) with the lowest stopped time to the winner list
|
||||||
for(int i = 0; i < this->timers.length(); i++) {
|
foreach(ScStwTimer * timer, this->timers) {
|
||||||
ScStwTimer * timer = this->timers[i];
|
if(timer->getCurrentTime() > 0
|
||||||
if(timer->getCurrentTime() > 0 && (timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0)) {
|
&& (timer->getCurrentTime() <= lowestStoppedTime || lowestStoppedTime < 0)
|
||||||
|
&& timer->getState() != ScStwTimer::RUNNING
|
||||||
|
) {
|
||||||
// this is the timer with the lowest stopped time
|
// this is the timer with the lowest stopped time
|
||||||
timersWhichHaveWonIds.append(i);
|
timersWhichHaveWonIds.append(timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the states of all timers
|
// update the states of all timers
|
||||||
for(int i = 0; i < this->timers.length(); i++) {
|
foreach(ScStwTimer * timer, this->timers) {
|
||||||
ScStwTimer * timer = this->timers[i];
|
if(timer->getState() == ScStwTimer::RUNNING)
|
||||||
|
continue;
|
||||||
|
|
||||||
if(!timersWhichHaveWonIds.contains(i) && timer->getCurrentTime() > 0) {
|
if(timersWhichHaveWonIds.contains(timer)) {
|
||||||
timer->stop(ScStwTimer::LOST);
|
timer->setResult(ScStwTimer::WON);
|
||||||
}
|
}
|
||||||
else if (timersWhichHaveWonIds.contains(i)) {
|
else {
|
||||||
qDebug() << "timer " << i << " has won";
|
timer->setResult(ScStwTimer::LOST);
|
||||||
timer->stop(ScStwTimer::WON);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +183,8 @@ bool ScStwRace::playSoundsAndStartTimers(StartAction thisAction) {
|
||||||
if(this->startActionSettings.contains(thisAction) && this->startActionSettings[thisAction]["Enabled"].toBool()) {
|
if(this->startActionSettings.contains(thisAction) && this->startActionSettings[thisAction]["Enabled"].toBool()) {
|
||||||
if(!this->soundPlayer->play(thisAction, this->soundVolume, &timeOfSoundPlaybackStart))
|
if(!this->soundPlayer->play(thisAction, this->soundVolume, &timeOfSoundPlaybackStart))
|
||||||
return false;
|
return false;
|
||||||
|
if(this->state != STARTING)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->nextStartAction = StartAction(thisAction + 1);
|
this->nextStartAction = StartAction(thisAction + 1);
|
||||||
|
@ -262,20 +266,20 @@ void ScStwRace::refreshTimerStates() {
|
||||||
qDebug() << "[INFO][MAIN] refreshing timer states";
|
qDebug() << "[INFO][MAIN] refreshing timer states";
|
||||||
|
|
||||||
// check if the race is over
|
// check if the race is over
|
||||||
int stoppedState = 1;
|
bool raceIsOver = true;
|
||||||
|
|
||||||
foreach(ScStwTimer * timer, this->timers){
|
foreach(ScStwTimer * timer, this->timers){
|
||||||
if(timer->getState() < ScStwTimer::WON){
|
if(timer->getState() < ScStwTimer::WON){
|
||||||
// if the timer is not in stoped state
|
// if the timer is not in stoped state
|
||||||
stoppedState = 0;
|
raceIsOver = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(this->state != RUNNING) {
|
else if(timer->getState() == ScStwTimer::WAITING) {
|
||||||
// TODO athleteProfiles->addResult(timer->getCurrTime(), timer->getReactionTime(), this->speedTimers.indexOf(timer));
|
this->handleTimerStop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(stoppedState == 1){
|
if(raceIsOver){
|
||||||
this->setState(STOPPED);
|
this->setState(STOPPED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +361,6 @@ bool ScStwRace::addTimer(ScStwTimer *timer) {
|
||||||
|
|
||||||
connect(timer, &ScStwTimer::startCanceled, this, &ScStwRace::cancelStart);
|
connect(timer, &ScStwTimer::startCanceled, this, &ScStwRace::cancelStart);
|
||||||
connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::refreshTimerStates);
|
connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::refreshTimerStates);
|
||||||
connect(timer, &ScStwTimer::stopRequested, this, &ScStwRace::handleTimerStop);
|
|
||||||
connect(timer, &ScStwTimer::requestEnableChange, this, &ScStwRace::handleTimerEnable);
|
connect(timer, &ScStwTimer::requestEnableChange, this, &ScStwRace::handleTimerEnable);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -80,6 +80,7 @@ bool ScStwSoundPlayer::cancel(double volume) {
|
||||||
|
|
||||||
// stop playback
|
// stop playback
|
||||||
this->audioOutput->stop();
|
this->audioOutput->stop();
|
||||||
|
this->waitLoop->quit();
|
||||||
|
|
||||||
if(this->currentlyPlayingAction != 2)
|
if(this->currentlyPlayingAction != 2)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -5,7 +5,6 @@ ScStwTimer::ScStwTimer(QObject *parent) : QObject(parent)
|
||||||
|
|
||||||
this->startTime = 0;
|
this->startTime = 0;
|
||||||
this->stopTime = 0;
|
this->stopTime = 0;
|
||||||
this->stoppedTime = 0;
|
|
||||||
this->reactionTime = 0;
|
this->reactionTime = 0;
|
||||||
|
|
||||||
this->state = IDLE;
|
this->state = IDLE;
|
||||||
|
@ -22,7 +21,6 @@ bool ScStwTimer::start(double timeOfStart) {
|
||||||
|
|
||||||
this->startTime = timeOfStart;
|
this->startTime = timeOfStart;
|
||||||
this->stopTime = 0;
|
this->stopTime = 0;
|
||||||
this->stoppedTime = 0;
|
|
||||||
|
|
||||||
if(timeOfStart - QDateTime::currentMSecsSinceEpoch() > 0) {
|
if(timeOfStart - QDateTime::currentMSecsSinceEpoch() > 0) {
|
||||||
this->setState(STARTING);
|
this->setState(STARTING);
|
||||||
|
@ -67,23 +65,18 @@ bool ScStwTimer::cancel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScStwTimer::stop() {
|
bool ScStwTimer::stop() {
|
||||||
return this->stop(ManualStop);
|
return this->stop(QDateTime::currentMSecsSinceEpoch());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScStwTimer::stop(TimerState result) {
|
bool ScStwTimer::stop(double timeOfStop) {
|
||||||
switch (result) {
|
return this->stop(ManualStop, timeOfStop);
|
||||||
case WON:
|
|
||||||
this->setState(WON);
|
|
||||||
return true;
|
|
||||||
case LOST:
|
|
||||||
this->setState(LOST);
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScStwTimer::stop(StopReason reason) {
|
bool ScStwTimer::stop(StopReason reason) {
|
||||||
|
return this->stop(reason, QDateTime::currentMSecsSinceEpoch());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScStwTimer::stop(StopReason reason, double timeOfStop) {
|
||||||
if(this->state != STARTING && this->state != RUNNING && this->state != WAITING){
|
if(this->state != STARTING && this->state != RUNNING && this->state != WAITING){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -95,18 +88,14 @@ bool ScStwTimer::stop(StopReason reason) {
|
||||||
this->setState(CANCELLED);
|
this->setState(CANCELLED);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
this->stopTime = timeOfStop;
|
||||||
|
|
||||||
this->stopTime = this->date->currentMSecsSinceEpoch();
|
// trigger an external state refresh to set the state to either WON or LOST depending on the other timers values (see ScStwRace::refreshTimerStates())
|
||||||
this->stoppedTime = this->stopTime - this->startTime;
|
this->setState(WAITING);
|
||||||
|
|
||||||
// trigger an external state refresh to set the state to either WON or LOST depending on the other timers values (see MainActivity::refreshTimerStates())
|
|
||||||
emit this->stopRequested();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FailStop: {
|
case FailStop: {
|
||||||
this->stoppedTime = 0;
|
|
||||||
|
|
||||||
qDebug() << "+ [INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime;
|
qDebug() << "+ [INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime;
|
||||||
this->setState(FAILED);
|
this->setState(FAILED);
|
||||||
|
|
||||||
|
@ -119,10 +108,26 @@ bool ScStwTimer::stop(StopReason reason) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "+ [INFO][TIMER] Stopped: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << stoppedTime << " reactionTime: " << reactionTime;
|
qDebug() << "+ [INFO][TIMER] Stopped: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << this->getCurrentTime() << " reactionTime: " << reactionTime;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ScStwTimer::setResult(TimerState result) {
|
||||||
|
if(this->state != WAITING)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case WON:
|
||||||
|
this->setState(WON);
|
||||||
|
return true;
|
||||||
|
case LOST:
|
||||||
|
this->setState(LOST);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ScStwTimer::reset(){
|
bool ScStwTimer::reset(){
|
||||||
if( this->state < WON || this->state == DISABLED ){
|
if( this->state < WON || this->state == DISABLED ){
|
||||||
return false;
|
return false;
|
||||||
|
@ -130,11 +135,8 @@ bool ScStwTimer::reset(){
|
||||||
|
|
||||||
this->startTime = 0;
|
this->startTime = 0;
|
||||||
this->stopTime = 0;
|
this->stopTime = 0;
|
||||||
this->stoppedTime = 0;
|
|
||||||
this->reactionTime = 0;
|
this->reactionTime = 0;
|
||||||
|
|
||||||
this->startPadTriggerTime = 0;
|
|
||||||
|
|
||||||
this->setState(IDLE);
|
this->setState(IDLE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -159,11 +161,15 @@ ScStwTimer::TimerState ScStwTimer::getState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
double ScStwTimer::getCurrentTime() {
|
double ScStwTimer::getCurrentTime() {
|
||||||
if(this->state == RUNNING){
|
switch (this->state) {
|
||||||
return this->date->currentMSecsSinceEpoch() - this->startTime;
|
case RUNNING:
|
||||||
|
return QDateTime::currentMSecsSinceEpoch() - this->startTime;
|
||||||
|
default: {
|
||||||
|
if(this->state == WAITING || this->state == WON || this->state == LOST)
|
||||||
|
return this->stopTime - this->startTime;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return this->stoppedTime;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue