- some improvements and fixes
- added remote monitor race
This commit is contained in:
parent
73d62d01d8
commit
f4ee962c98
8 changed files with 372 additions and 47 deletions
|
@ -21,6 +21,7 @@ SOURCES += \
|
|||
sources/ScStw.cpp \
|
||||
sources/scstwclient.cpp \
|
||||
sources/scstwrace.cpp \
|
||||
sources/scstwremotemonitorrace.cpp \
|
||||
sources/scstwsoundplayer.cpp \
|
||||
sources/scstwtimer.cpp
|
||||
|
||||
|
@ -29,6 +30,7 @@ HEADERS += \
|
|||
headers/ScStwLibraries_global.h \
|
||||
headers/scstwrace.h \
|
||||
headers/scstwclient.h \
|
||||
headers/scstwremotemonitorrace.h \
|
||||
headers/scstwsoundplayer.h \
|
||||
headers/scstwtimer.h
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
class ScStwClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(State state READ getState NOTIFY stateChanged)
|
||||
Q_PROPERTY(QVariantList extensions READ getExtensions NOTIFY extensionsChanged)
|
||||
|
||||
public:
|
||||
/*!
|
||||
|
@ -41,6 +43,7 @@ public:
|
|||
explicit ScStwClient();
|
||||
|
||||
enum State {DISCONNECTED, CONNECTING, INITIALISING, CONNECTED};
|
||||
Q_ENUM(State);
|
||||
|
||||
private:
|
||||
// values for the socket connection
|
||||
|
@ -49,7 +52,7 @@ private:
|
|||
int errors;
|
||||
const static int ERRORS_UNTIL_DISCONNECT = 4;
|
||||
|
||||
QVariantList connections;
|
||||
QVariantList extensions;
|
||||
|
||||
//---general status values---//
|
||||
|
||||
|
@ -80,32 +83,6 @@ private:
|
|||
|
||||
QList<waitingRequest> waitingRequests;
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Is emitted, when the connection state changes
|
||||
*/
|
||||
void stateChanged();
|
||||
|
||||
/*!
|
||||
* \brief Is emitted, whenever a reply is recieved which does not match any requests
|
||||
*
|
||||
* \param reply contains the reply
|
||||
*/
|
||||
void gotUnexpectedMessage(QString message);
|
||||
|
||||
/*!
|
||||
* \brief Is emitted, when an update signal from the basestation is recieved
|
||||
*
|
||||
* \param data
|
||||
*/
|
||||
void gotSignal(ScStw::SignalKey key, QVariant data);
|
||||
|
||||
/*!
|
||||
* \brief Is emitted, when there is any network error
|
||||
* \param error
|
||||
*/
|
||||
void gotError(QAbstractSocket::SocketError error);
|
||||
|
||||
public slots:
|
||||
|
||||
/*!
|
||||
|
@ -191,10 +168,10 @@ public slots:
|
|||
ScStwClient::State getState();
|
||||
|
||||
/*!
|
||||
* \brief Functio to get the extensions and their state from the base station
|
||||
* \brief Function to get the extensions and their state from the base station
|
||||
* \return a list with all configured extensions and their state
|
||||
*/
|
||||
QVariantList getConnections();
|
||||
QVariantList getExtensions();
|
||||
|
||||
/*!
|
||||
* \brief Function to get the time offset of the base station relative to the clients time
|
||||
|
@ -300,7 +277,7 @@ private slots:
|
|||
* \see gotSignal()
|
||||
* \param connections the list to set the chache to
|
||||
*/
|
||||
void setConnections(QVariantList connections);
|
||||
void setExtensions(QVariantList extensions);
|
||||
|
||||
/*!
|
||||
* \brief Function to set the local state.
|
||||
|
@ -309,6 +286,37 @@ private slots:
|
|||
* \param newState the state to change to
|
||||
*/
|
||||
void setState(ScStwClient::State newState);
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Is emitted, when the connection state changes
|
||||
*/
|
||||
void stateChanged();
|
||||
|
||||
/*!
|
||||
* \brief Is emitted, whenever a reply is recieved which does not match any requests
|
||||
*
|
||||
* \param reply contains the reply
|
||||
*/
|
||||
void gotUnexpectedMessage(QString message);
|
||||
|
||||
/*!
|
||||
* \brief Is emitted, when an update signal from the basestation is recieved
|
||||
*
|
||||
* \param data
|
||||
*/
|
||||
void gotSignal(ScStw::SignalKey key, QVariant data);
|
||||
|
||||
/*!
|
||||
* \brief Is emitted, when there is any network error
|
||||
* \param error
|
||||
*/
|
||||
void gotError(QAbstractSocket::SocketError error);
|
||||
|
||||
/*!
|
||||
* \brief Is emitted, when the extensions of the base station changed
|
||||
*/
|
||||
void extensionsChanged();
|
||||
};
|
||||
|
||||
extern ScStwClient * pGlobalScStwClient;
|
||||
|
|
|
@ -30,10 +30,14 @@ public:
|
|||
};
|
||||
Q_ENUM(NextStartActionDetailAttributes);
|
||||
|
||||
protected:
|
||||
StartAction nextStartAction;
|
||||
QList<ScStwTimer *> timers;
|
||||
void setState(RaceState newState);
|
||||
|
||||
private:
|
||||
RaceState state;
|
||||
|
||||
QList<ScStwTimer *> timers;
|
||||
QList<ScStwTimer*> timerEnableQueque;
|
||||
|
||||
QTimer *nextActionTimer;
|
||||
|
@ -42,7 +46,6 @@ private:
|
|||
// sounds
|
||||
ScStwSoundPlayer * soundPlayer;
|
||||
|
||||
StartAction nextStartAction;
|
||||
|
||||
// some settings
|
||||
double soundVolume;
|
||||
|
@ -54,12 +57,10 @@ private:
|
|||
*/
|
||||
QMap<StartAction, QVariantMap> startActionSettings;
|
||||
|
||||
void setState(RaceState newState);
|
||||
|
||||
public slots:
|
||||
int start();
|
||||
int stop();
|
||||
void handleTimerStop();
|
||||
int reset();
|
||||
void cancelStart(bool falseStart);
|
||||
|
||||
|
@ -74,10 +75,14 @@ public slots:
|
|||
QVariantList getNextStartActionDetails();
|
||||
QVariantList getTimerDetailList();
|
||||
|
||||
protected slots:
|
||||
|
||||
|
||||
private slots:
|
||||
void refreshTimerStates();
|
||||
void handleTimerEnable(ScStwTimer* timer);
|
||||
bool playSoundsAndStartTimers(StartAction thisAction);
|
||||
void handleTimerStop();
|
||||
|
||||
signals:
|
||||
void startTimers();
|
||||
|
|
35
ScStwLibraries/headers/scstwremotemonitorrace.h
Normal file
35
ScStwLibraries/headers/scstwremotemonitorrace.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef SCSTWREMOTEMONITORRACE_H
|
||||
#define SCSTWREMOTEMONITORRACE_H
|
||||
|
||||
#include <QObject>
|
||||
#include "scstwrace.h"
|
||||
#include "scstwclient.h"
|
||||
|
||||
class ScStwRemoteMonitorRace : public ScStwRace
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScStwRemoteMonitorRace(ScStwClient *monitorClient, QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
double nextStartActionTotalDelay;
|
||||
double nextStartActionDelayStartedAt;
|
||||
|
||||
private:
|
||||
ScStwClient *scStwClient;
|
||||
|
||||
public slots:
|
||||
int start();
|
||||
void cancelStart();
|
||||
int stop();
|
||||
int reset();
|
||||
bool addTimer(ScStwTimer *timer);
|
||||
|
||||
private slots:
|
||||
void handleClientStateChanged();
|
||||
void handleBaseStationSignal(ScStw::SignalKey key, QVariant data);
|
||||
bool refreshRemoteTimers(QVariantList remoteTimers);
|
||||
|
||||
};
|
||||
|
||||
#endif // SCSTWREMOTEMONITORRACE_H
|
|
@ -46,8 +46,9 @@ public:
|
|||
/*!
|
||||
* \brief ScStwTimer constructor
|
||||
* \param parent the parent object
|
||||
* \param directControlEnabled Defines if protected properties (startTimer, stopTime, reactionTime and state) can be directly set from outside.
|
||||
*/
|
||||
explicit ScStwTimer(QObject *parent = nullptr);
|
||||
explicit ScStwTimer(QObject *parent = nullptr, bool directControlEnabled = false);
|
||||
|
||||
/*!
|
||||
* \brief The TimerState enum contains all state the timer can be in
|
||||
|
@ -96,6 +97,11 @@ protected:
|
|||
*/
|
||||
double reactionTime;
|
||||
|
||||
/*!
|
||||
* \brief Defines if protected properties (startTimer, stopTime, reactionTime and state) can be directly set from outside.
|
||||
*/
|
||||
bool directControlEnabled;
|
||||
|
||||
public slots:
|
||||
|
||||
/*!
|
||||
|
@ -205,6 +211,48 @@ public slots:
|
|||
*/
|
||||
void setDisabled(bool disabled);
|
||||
|
||||
/*!
|
||||
* \brief Function to change the state of the timer
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
* Doing this will emit the ScStwTimer::stateChanged() signal (only if the new state differs from the current one)
|
||||
*
|
||||
* \param newState The new state
|
||||
* \param force whether to force the state change (just to distinguish between protected and public function)
|
||||
* \return false when directControlEnabled or force is set to false and the startTime was therefore not modified, true otherwise
|
||||
*/
|
||||
bool setState(TimerState newState, bool force);
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the start time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param startTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the startTime was therefore not modified, true otherwise
|
||||
*/
|
||||
bool setStartTime(double startTime);
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the stop time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param stopTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the stopTime was therefore not modified, true otherwise
|
||||
*/
|
||||
bool setStopTime(double stopTime);
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the rection time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param reactionTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the reactionTime was therefore not modified, true otherwise
|
||||
*/
|
||||
bool setReactionTime(double rectionTime);
|
||||
|
||||
protected slots:
|
||||
|
||||
/*!
|
||||
|
@ -240,7 +288,6 @@ protected slots:
|
|||
*/
|
||||
bool stop(StopReason reason);
|
||||
|
||||
// --- helper functions ---
|
||||
/*!
|
||||
* \brief Function to change the state of the timer
|
||||
*
|
||||
|
@ -250,6 +297,7 @@ protected slots:
|
|||
*/
|
||||
void setState(TimerState newState);
|
||||
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Emitted when the state of the timer changed
|
||||
|
|
|
@ -6,7 +6,7 @@ ScStwClient::ScStwClient() : QObject(nullptr)
|
|||
{
|
||||
this->state = DISCONNECTED;
|
||||
this->nextConnectionId = 1;
|
||||
this->connections = QVariantList({});
|
||||
this->extensions = QVariantList({});
|
||||
|
||||
this->socket = new QTcpSocket(this);
|
||||
|
||||
|
@ -78,7 +78,7 @@ void ScStwClient::deInit() {
|
|||
if(this->state == DISCONNECTED)
|
||||
return;
|
||||
|
||||
this->setConnections(QVariantList({}));
|
||||
this->setExtensions(QVariantList({}));
|
||||
this->setState(DISCONNECTED);
|
||||
}
|
||||
|
||||
|
@ -335,7 +335,7 @@ void ScStwClient::handleSignal(QVariantMap data) {
|
|||
{
|
||||
// the extension connections have changed
|
||||
// -> handle locally
|
||||
this->setConnections(data["data"].toList());
|
||||
this->setExtensions(data["data"].toList());
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
@ -448,8 +448,8 @@ void ScStwClient::setState(ScStwClient::State newState){
|
|||
}
|
||||
}
|
||||
|
||||
QVariantList ScStwClient::getConnections() {
|
||||
return connections;
|
||||
QVariantList ScStwClient::getExtensions() {
|
||||
return this->extensions;
|
||||
}
|
||||
|
||||
int ScStwClient::getTimeOffset() {
|
||||
|
@ -460,9 +460,10 @@ QString ScStwClient::getFirmwareVersion() {
|
|||
return this->firmwareVersion;
|
||||
}
|
||||
|
||||
void ScStwClient::setConnections(QVariantList connections) {
|
||||
if(this->connections != connections){
|
||||
this->connections = connections;
|
||||
emit this->gotSignal(ScStw::ExtensionsChanged, this->getConnections());
|
||||
void ScStwClient::setExtensions(QVariantList extensions) {
|
||||
if(this->extensions != extensions){
|
||||
this->extensions = extensions;
|
||||
emit this->gotSignal(ScStw::ExtensionsChanged, this->getExtensions());
|
||||
emit this->extensionsChanged();
|
||||
}
|
||||
}
|
||||
|
|
194
ScStwLibraries/sources/scstwremotemonitorrace.cpp
Normal file
194
ScStwLibraries/sources/scstwremotemonitorrace.cpp
Normal file
|
@ -0,0 +1,194 @@
|
|||
#include "../headers/scstwremotemonitorrace.h"
|
||||
|
||||
ScStwRemoteMonitorRace::ScStwRemoteMonitorRace(ScStwClient *monitorClient, QObject *parent) : ScStwRace(parent)
|
||||
{
|
||||
this->scStwClient = monitorClient;
|
||||
|
||||
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ScStwRemoteMonitorRace::handleClientStateChanged);
|
||||
connect(this->scStwClient, &ScStwClient::gotSignal, this, &ScStwRemoteMonitorRace::handleBaseStationSignal);
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// --- Main Functionality ---
|
||||
// --------------------------
|
||||
|
||||
int ScStwRemoteMonitorRace::start() {
|
||||
|
||||
if(this->getState() != ScStwRace::IDLE) {
|
||||
return 904;
|
||||
}
|
||||
|
||||
qDebug() << "+ --- starting race";
|
||||
|
||||
int returnCode = 900;
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(1000);
|
||||
|
||||
if(reply["status"] != 200){
|
||||
//handle Error!!
|
||||
returnCode = reply["status"].toInt();
|
||||
}
|
||||
else {
|
||||
|
||||
returnCode = 200;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
void ScStwRemoteMonitorRace::cancelStart() {
|
||||
return;
|
||||
}
|
||||
|
||||
int ScStwRemoteMonitorRace::stop() {
|
||||
|
||||
if(this->getState() != ScStwRace::RUNNING && this->getState() != ScStwRace::STARTING) {
|
||||
return 904;
|
||||
}
|
||||
|
||||
// type can be:
|
||||
// 0: stopp
|
||||
// 1: cancel
|
||||
// 2: fail (fase start)
|
||||
|
||||
qDebug() << "+ --- stopping race";
|
||||
|
||||
int returnCode = 900;
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(1001);
|
||||
|
||||
if(reply["status"] != 200){
|
||||
returnCode = reply["status"].toInt();
|
||||
}
|
||||
else {
|
||||
returnCode = 200;
|
||||
}
|
||||
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
int ScStwRemoteMonitorRace::reset() {
|
||||
|
||||
if(this->getState() != ScStwRace::STOPPED) {
|
||||
return 904;
|
||||
}
|
||||
|
||||
qDebug() << "+ --- resetting race";
|
||||
|
||||
int returnCode = 900;
|
||||
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(1002);
|
||||
|
||||
if(reply["status"] != 200){
|
||||
//handle Error!!
|
||||
returnCode = reply["status"].toInt();
|
||||
}
|
||||
else {
|
||||
returnCode = 200;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------
|
||||
// --- Base Station sync ---
|
||||
// -------------------------
|
||||
|
||||
void ScStwRemoteMonitorRace::handleClientStateChanged() {
|
||||
// TODO
|
||||
switch (this->scStwClient->getState()) {
|
||||
case ScStwClient::CONNECTED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 ScStwRemoteMonitorRace::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {
|
||||
qDebug() << "got signal: " << data;
|
||||
switch (key) {
|
||||
case ScStw::RaceStateChanged:
|
||||
{
|
||||
// the remote race state has changed
|
||||
this->setState( ScStwRace::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.toList()[ScStwRace::NextStartActionTotalDelay].toDouble();
|
||||
this->nextStartActionDelayStartedAt = QDateTime::currentMSecsSinceEpoch() - (this->nextStartActionTotalDelay * data.toList()[ScStwRace::NextStartActionDelayProgress].toDouble());
|
||||
this->nextStartAction = ScStwRace::StartAction( data.toList()[ScStwRace::NextStartAction].toInt() );
|
||||
|
||||
emit this->nextStartActionChanged();
|
||||
break;
|
||||
}
|
||||
case ScStw::InvalidSignal:
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScStwRemoteMonitorRace::refreshRemoteTimers(QVariantList remoteTimers) {
|
||||
|
||||
if(remoteTimers.length() != this->timers.length()){
|
||||
// local timers are out of sync
|
||||
|
||||
// delete all current timers
|
||||
foreach(ScStwTimer * locTimer, this->timers){
|
||||
delete locTimer;
|
||||
}
|
||||
|
||||
this->timers.clear();
|
||||
|
||||
foreach(QVariant remoteTimer, remoteTimers){
|
||||
// create a local timer for each remote timer
|
||||
this->timers.append(new ScStwTimer(this, true));
|
||||
}
|
||||
}
|
||||
|
||||
foreach(QVariant remoteTimer, remoteTimers){
|
||||
int currId = remoteTimer.toMap()["id"].toInt();
|
||||
ScStwTimer::TimerState newState = ScStwTimer::TimerState(remoteTimer.toMap()["state"].toInt());
|
||||
double currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
this->timers[currId]->setStartTime(currentMSecsSinceEpoch - remoteTimer.toMap()["currentTime"].toDouble());
|
||||
|
||||
if(newState >= ScStwTimer::WAITING)
|
||||
this->timers[currId]->setStopTime(currentMSecsSinceEpoch);
|
||||
|
||||
this->timers[currId]->setReactionTime(remoteTimer.toMap()["reactionTime"].toDouble());
|
||||
|
||||
this->timers[currId]->setState(newState, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwRemoteMonitorRace::addTimer(ScStwTimer* timer) {
|
||||
Q_UNUSED(timer)
|
||||
return false;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
#include "../headers/scstwtimer.h"
|
||||
|
||||
ScStwTimer::ScStwTimer(QObject *parent) : QObject(parent)
|
||||
ScStwTimer::ScStwTimer(QObject *parent, bool directControlEnabled) : QObject(parent)
|
||||
{
|
||||
|
||||
this->directControlEnabled = directControlEnabled;
|
||||
this->startTime = 0;
|
||||
this->stopTime = 0;
|
||||
this->reactionTime = 0;
|
||||
|
@ -145,6 +145,38 @@ bool ScStwTimer::reset(){
|
|||
// --- helper functions ---
|
||||
// ------------------------
|
||||
|
||||
bool ScStwTimer::setStartTime(double startTime) {
|
||||
if(!this->directControlEnabled)
|
||||
return false;
|
||||
|
||||
this->startTime = startTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwTimer::setStopTime(double stopTime) {
|
||||
if(!this->directControlEnabled)
|
||||
return false;
|
||||
|
||||
this->stopTime = stopTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwTimer::setReactionTime(double reactionTime) {
|
||||
if(!this->directControlEnabled)
|
||||
return false;
|
||||
|
||||
this->reactionTime = reactionTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwTimer::setState(TimerState newState, bool force) {
|
||||
if(!this->directControlEnabled || !force)
|
||||
return false;
|
||||
|
||||
this->setState(newState);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScStwTimer::setState(TimerState newState){
|
||||
if(this->state == DISABLED && newState != IDLE)
|
||||
return;
|
||||
|
|
Reference in a new issue