- major cleanup

- added global static class ScStw
This commit is contained in:
Dorian Zedler 2020-04-06 17:51:20 +02:00
parent d32fe7733a
commit b752bdeed2
Signed by: dorian
GPG key ID: 989DE36109AFA354
6 changed files with 391 additions and 194 deletions

4
ScStwLibraries/ScStw.cpp Normal file
View file

@ -0,0 +1,4 @@
#include <ScStw.hpp>
const char *ScStw::SOCKET_MESSAGE_START_KEY = "<message>";
const char *ScStw::SOCKET_MESSAGE_END_KEY = "</message>";

53
ScStwLibraries/ScStw.hpp Normal file
View file

@ -0,0 +1,53 @@
#ifndef SCSTW_HPP
#define SCSTW_HPP
#include <QObject>
class ScStw : public QObject {
Q_OBJECT
public:
/**
* Some global enums
*/
enum RaceState { IDLE, STARTING, WAITING, RUNNING, STOPPED };
Q_ENUM(RaceState)
enum SignalKey {
RaceStateChanged = 9000,
TimersChanged = 9001,
ExtensionsChanged = 9002,
NextStartActionChanged = 9003 /*, ProfilesChanged*/
};
Q_ENUM(SignalKey)
enum NextStartAction { AtYourMarks, Ready, Start, None };
Q_ENUM(NextStartAction)
enum BaseStationSetting {
ReadySoundEnableSetting,
ReadySoundDelaySetting,
AtYourMarksSoundEnableSetting,
AtYourMarksSoundDelaySetting,
SoundVolumeSetting
};
Q_ENUM(BaseStationSetting)
enum ErrorCode {
Success = 200,
Error = 900,
NotConnectedError = 910,
TimeoutError = 911,
SettingNotAccessableError = 901
};
Q_ENUM(ErrorCode)
static const char* SOCKET_MESSAGE_START_KEY;
static const char* SOCKET_MESSAGE_END_KEY;
private:
ScStw() : QObject(nullptr) {};
};
#endif // SCSTW_HPP

View file

@ -18,9 +18,11 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \ SOURCES += \
ScStw.cpp \
scstwclient.cpp scstwclient.cpp
HEADERS += \ HEADERS += \
ScStw.hpp \
ScStwLibraries_global.h \ ScStwLibraries_global.h \
scstwclient.h scstwclient.h

View file

@ -9,13 +9,4 @@
# define SCSTWLIBRARIES_EXPORT Q_DECL_IMPORT # define SCSTWLIBRARIES_EXPORT Q_DECL_IMPORT
#endif #endif
/**
* Some global enums
*
*/
enum raceState { IDLE, STARTING, WAITING, RUNNING, STOPPED };
enum signalKey { RaceStateChanged, TimersChanged, ExtensionsChanged, NextStartActionChanged /*, ProfilesChanged*/ };
enum nextStartAction { AtYourMarks, Ready, Start, None };
#endif // SCSTWCLIENT_GLOBAL_H #endif // SCSTWCLIENT_GLOBAL_H

View file

@ -2,31 +2,36 @@
ScStwClient * pGlobalScStwClient = nullptr; ScStwClient * pGlobalScStwClient = nullptr;
ScStwClient::ScStwClient(QObject *parent) : QObject(parent) ScStwClient::ScStwClient() : QObject(nullptr)
{ {
pGlobalScStwClient = this; this->state = DISCONNECTED;
this->nextConnectionId = 1;
this->connections = QVariantList({});
socket = new QTcpSocket(this); this->socket = new QTcpSocket(this);
this->timeoutTimer = new QTimer(this); this->timeoutTimer = new QTimer(this);
this->timeoutTimer->setSingleShot(true); this->timeoutTimer->setSingleShot(true);
this->state = "disconnected"; connect(this->timeoutTimer, &QTimer::timeout,
[=](){this->handleError(QAbstractSocket::ProxyConnectionTimeoutError);});
connect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)), connect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(gotError(QAbstractSocket::SocketError))); this, SLOT(handleError(QAbstractSocket::SocketError)));
connect(this->socket, &QAbstractSocket::stateChanged, this, &ScStwClient::socketStateChanged); connect(this->socket, &QAbstractSocket::stateChanged,
this, &ScStwClient::handleSocketStateChange);
this->nextConnectionId = 1; connect(this->socket, &QTcpSocket::readyRead,
this->connections = QVariantList({}); this, &ScStwClient::handleReadyRead);
pGlobalScStwClient = this;
} }
void ScStwClient::connectToHost() { void ScStwClient::connectToHost() {
qDebug() << "connecting";
setState("connecting");
connect(this->timeoutTimer, SIGNAL(timeout()), this, SLOT(connectionTimeout())); setState(CONNECTING);
//connect //connect
this->socket->connectToHost(this->ip, this->port); this->socket->connectToHost(this->ip, this->port);
@ -35,48 +40,52 @@ void ScStwClient::connectToHost() {
} }
void ScStwClient::connectionTimeout() { void ScStwClient::connectionTimeout() {
if(this->state != CONNECTING)
return;
this->socket->abort(); this->socket->abort();
disconnect(this->timeoutTimer, SIGNAL(timeout()), this, SLOT(connectionTimeout())); disconnect(this->timeoutTimer, SIGNAL(timeout()), this, SLOT(connectionTimeout()));
} }
bool ScStwClient::init() { bool ScStwClient::init() {
disconnect(this->timeoutTimer, SIGNAL(timeout()), this, SLOT(connectionTimeout())); if(this->state != CONNECTING)
return false;
this->setState(INITIALISING);
this->timeoutTimer->stop(); this->timeoutTimer->stop();
connect(this->socket, &QTcpSocket::readyRead, this, &ScStwClient::readyRead);
this->setState("connected");
// init remote session // init remote session
QJsonArray updateSubs = {"onRaceStateChanged", "onTimersChanged", "onExtensionConnectionsChanged", "onNextStartActionChanged"}; QJsonArray updateSubs = {ScStw::RaceStateChanged, ScStw::TimersChanged, ScStw::ExtensionsChanged, ScStw::NextStartActionChanged};
QJsonObject sessionParams = {{"updateSubs", updateSubs}, {"init", true}, {"usingTerminationKeys", true}}; QJsonObject sessionParams = {{"updateSubs", updateSubs}, {"init", true}, {"usingTerminationKeys", true}};
QVariantMap initResponse = this->sendCommand(1, sessionParams, false); QVariantMap initResponse = this->sendCommand(1, sessionParams, 3000, false);
if(initResponse["status"] != 200) { if(initResponse["status"] != 200) {
this->closeConnection();
return false; return false;
} }
this->firmwareVersion = initResponse["data"].toMap()["version"].toString(); this->firmwareVersion = initResponse["data"].toMap()["version"].toString();
this->timeOffset = initResponse["data"].toMap()["time"].toDouble() - this->date->currentMSecsSinceEpoch(); this->timeOffset = initResponse["data"].toMap()["time"].toDouble() - this->date->currentMSecsSinceEpoch();
this->firmwareUpToDate = this->isFirmwareUpToDate();
emit this->propertiesChanged(); qDebug() << "[INFO][BaseStation] Init done! firmware: version: " << this->firmwareVersion << " up-to-date: " << this->isFirmwareUpToDate() << " time offset: " << this->timeOffset;
qDebug() << "[INFO][BaseStation] Init done! firmware: version: " << this->firmwareVersion << " up-to-date: " << this->firmwareUpToDate << " time offset: " << this->timeOffset;
this->setState(CONNECTED);
return true; return true;
} }
void ScStwClient::deInit() { void ScStwClient::deInit() {
this->connections.clear(); if(this->state == DISCONNECTED)
emit this->connectionsChanged(); return;
this->setState("disconnected");
this->setConnections(QVariantList({}));
this->setState(DISCONNECTED);
} }
void ScStwClient::closeConnection() void ScStwClient::closeConnection()
{ {
this->connections = QVariantList({}); if(this->getState() == DISCONNECTED)
emit this->connectionsChanged(); return;
qDebug() << "closing connection"; qDebug() << "closing connection";
switch (socket->state()) switch (socket->state())
@ -90,67 +99,22 @@ void ScStwClient::closeConnection()
default: default:
socket->abort(); socket->abort();
} }
setState("disconnected");
}
void ScStwClient::gotError(QAbstractSocket::SocketError err)
{
//qDebug() << "got error";
QString strError = "unknown";
switch (err)
{
case 0:
strError = "Connection was refused";
break;
case 1:
strError = "Remote host closed the connection";
this->closeConnection();
break;
case 2:
strError = "Host address was not found";
break;
case 5:
strError = "Connection timed out";
break;
default:
strError = "Unknown error";
}
emit gotError(strError);
qDebug() << "got socket error: " << strError;
} }
// ------------------------------------- // -------------------------------------
// --- socket communication handling --- // --- socket communication handling ---
// ------------------------------------- // -------------------------------------
void ScStwClient::socketStateChanged(QAbstractSocket::SocketState socketState) { QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout) {
switch (socketState) { if(this->state != CONNECTED)
case QAbstractSocket::UnconnectedState: return {{"status", ScStw::NotConnectedError}, {"data", "not connected"}};
{
this->deInit();
break;
}
case QAbstractSocket::ConnectedState:
{
if(!this->init()) {
this->closeConnection();
}
break; return this->sendCommand(header, data, timeout, false);
}
default:
{
//qDebug() << "+ --- UNKNOWN SOCKET STATE: " << socketState;
break;
}
}
} }
QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, bool useTerminationKeys, int timeout) { QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, bool useTerminationKeys) {
if(this->state != "connected"){ if(this->state != CONNECTED && this->state != INITIALISING){
return {{"status", 910}, {"data", "not connected"}}; return {{"status", ScStw::NotConnectedError}, {"data", "not connected"}};
} }
// generate id and witing requests entry // generate id and witing requests entry
@ -174,8 +138,6 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, bool useTermin
timer->setSingleShot(true); timer->setSingleShot(true);
// quit the loop when the timer times out // quit the loop when the timer times out
loop->connect(timer, SIGNAL(timeout()), loop, SLOT(quit())); loop->connect(timer, SIGNAL(timeout()), loop, SLOT(quit()));
// quit the loop when the connection was established
// loop.connect(this, &ScStwClient::gotReply, &loop, &QEventLoop::quit);
// start the timer before starting to connect // start the timer before starting to connect
timer->start(timeout); timer->start(timeout);
@ -215,7 +177,7 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, bool useTermin
if(timer->remainingTime() == -1){ if(timer->remainingTime() == -1){
//the time has been triggered -> timeout //the time has been triggered -> timeout
return {{"status", 911}, {"data", ""}}; return {{"status", ScStw::TimeoutError}, {"data", ""}};
} }
delete timer; delete timer;
@ -223,7 +185,47 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, bool useTermin
} }
void ScStwClient::readyRead() { void ScStwClient::handleSocketStateChange(QAbstractSocket::SocketState socketState) {
switch (socketState) {
case QAbstractSocket::UnconnectedState:
{
break;
}
case QAbstractSocket::ConnectedState:
{
if(!this->init()) {
this->closeConnection();
}
break;
}
default:
{
//qDebug() << "+ --- UNKNOWN SOCKET STATE: " << socketState;
break;
}
}
}
void ScStwClient::handleError(QAbstractSocket::SocketError err)
{
if(err == QAbstractSocket::ProxyConnectionClosedError)
this->closeConnection();
switch (err) {
case QAbstractSocket::ProxyConnectionTimeoutError:
if(this->state == CONNECTING)
this->closeConnection();
break;
default:
break;
}
emit gotError(err);
qDebug() << "got socket error: " << err;
}
void ScStwClient::handleReadyRead() {
//qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ; //qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ;
QString reply = socket->readAll(); QString reply = socket->readAll();
@ -234,15 +236,15 @@ void ScStwClient::readyRead() {
} }
void ScStwClient::processSocketMessage(QString message) { void ScStwClient::processSocketMessage(QString message) {
QString startKey = "<message>";
QString endKey = "</message>";
//qWarning() << "... processing message now ... : " << message; //qWarning() << "... processing message now ... : " << message;
QString startKey = ScStw::SOCKET_MESSAGE_START_KEY;
QString endKey = ScStw::SOCKET_MESSAGE_END_KEY;
if(message == ""){ if(message == ""){
return; return;
} }
if((message.startsWith(startKey) && message.endsWith(endKey)) && (message.count(startKey) == 1 && message.count(endKey) == 1)){ if((message.startsWith(startKey) && message.endsWith(endKey)) && (message.count(startKey) == 1 && message.count(endKey) == 1)){
// non-split message ( e.g.: <message>123456789</message> // non-split message ( e.g.: <message>123456789</message>
} }
@ -282,12 +284,12 @@ void ScStwClient::processSocketMessage(QString message) {
} }
//qWarning() << "... done processing, message: " << message; //qWarning() << "... done processing, message: " << message;
this->socketReplyRecieved(message); this->handleSocketMessage(message);
} }
void ScStwClient::socketReplyRecieved(QString reply) { void ScStwClient::handleSocketMessage(QString reply) {
reply.replace("<message>", ""); reply.replace(ScStw::SOCKET_MESSAGE_START_KEY, "");
reply.replace("</message>", ""); reply.replace(ScStw::SOCKET_MESSAGE_END_KEY, "");
int id = 0; int id = 0;
@ -299,7 +301,7 @@ void ScStwClient::socketReplyRecieved(QString reply) {
if(id == -1) { if(id == -1) {
// this message is an update!! // this message is an update!!
emit this->gotUpdate(replyObj.toVariantMap()); emit this->handleSignal(replyObj.toVariantMap());
return; return;
} }
@ -315,8 +317,28 @@ void ScStwClient::socketReplyRecieved(QString reply) {
} }
} }
latestReadReply = reply; emit gotUnexpectedMessage(reply);
emit gotUnexpectedReply(reply); }
void ScStwClient::handleSignal(QVariantMap data) {
// get the signal type
ScStw::SignalKey signalKey = ScStw::SignalKey(data["header"].toInt());
switch (signalKey) {
case ScStw::ExtensionsChanged:
{
// the extension connections have changed
// -> handle locally
this->setConnections(data["data"].toList());
return;
break;
}
default: {
break;
}
}
// forward to external handlers
emit this->gotSignal(signalKey, data["data"]);
} }
// ------------------------- // -------------------------
@ -336,12 +358,15 @@ bool ScStwClient::updateTime() {
} }
bool ScStwClient::updateFirmware() { bool ScStwClient::updateFirmware() {
if(this->state != CONNECTED)
return false;
QString file = ":/ScStwBasestation.sb64"; QString file = ":/ScStwBasestation.sb64";
QFile f(file); QFile f(file);
if (!f.open(QFile::ReadOnly)) return false; if (!f.open(QFile::ReadOnly)) return false;
QString fileContents = f.readAll(); QString fileContents = f.readAll();
if(this->firmwareUpToDate) { if(this->isFirmwareUpToDate()) {
return true; return true;
} }
@ -375,15 +400,23 @@ bool ScStwClient::isFirmwareUpToDate() {
// --- helper functions --- // --- helper functions ---
// ------------------------ // ------------------------
int ScStwClient::writeRemoteSetting(QString key, QString value) { ScStw::ErrorCode ScStwClient::writeRemoteSetting(ScStw::BaseStationSetting key, QString value) {
QJsonArray requestData; QJsonArray requestData;
requestData.append(key); requestData.append(key);
requestData.append(value); requestData.append(value);
return this->sendCommand(3000, requestData)["status"].toInt(); return ScStw::ErrorCode(this->sendCommand(3000, requestData)["status"].toInt());
} }
void ScStwClient::setIP(QString ipAdress){ QString ScStwClient::readRemoteSetting(ScStw::BaseStationSetting key) {
this->ip = ipAdress; QVariantMap reply = this->sendCommand(3001, key);
if(reply["status"] != 200){
return "false";
}
return reply["data"].toString();
}
void ScStwClient::setIP(QString newIp){
this->ip = newIp;
} }
QString ScStwClient::getIP() QString ScStwClient::getIP()
@ -391,60 +424,37 @@ QString ScStwClient::getIP()
return this->ip; return this->ip;
} }
QString ScStwClient::getState() ScStwClient::State ScStwClient::getState()
{ {
return this->state; return this->state;
} }
void ScStwClient::setState(QString newState){ void ScStwClient::setState(ScStwClient::State newState){
if(this->state != newState) { if(this->state != newState) {
qDebug() << "+--- ScStwClient state changed: " << newState; qDebug() << "+--- ScStwClient state changed: " << newState;
this->state = newState; this->state = newState;
emit stateChanged(); emit stateChanged();
if(this->state == "disconnected") { if(this->state == DISCONNECTED) {
this->deInit(); this->deInit();
} }
} }
} }
bool ScStwClient::refreshConnections() { QVariantList ScStwClient::getConnections() {
/* return connections;
"id": "id of the extention (int)",
"type": "type of the extention (can be: 'STARTPAD', 'TOPPAD')",
"name": "name of the extention",
"ip": "ip-adress of he extention (string)",
"state": "state of the extention (can be: 'disconnected', 'connecting', 'connected')"
*/
QVariantMap reply = this->sendCommand(2006);
if(reply["status"] != 200){
//handle Error!!
if(reply["status"] == 910){
this->connections = QVariantList({});
return true;
}
qDebug() << "+ --- error refreshing connections: " << reply["status"];
return false;
}
QVariantList tmpConnections = reply["data"].toList();
if(this->connections != reply["data"].toList()){
this->connections = reply["data"].toList();
emit this->connectionsChanged();
}
return true;
} }
QVariant ScStwClient::getConnections() { int ScStwClient::getTimeOffset() {
return connections; return this->timeOffset;
}
QString ScStwClient::getFirmwareVersion() {
return this->firmwareVersion;
} }
void ScStwClient::setConnections(QVariantList connections) { void ScStwClient::setConnections(QVariantList connections) {
if(this->connections != connections){ if(this->connections != connections){
this->connections = connections; this->connections = connections;
emit this->connectionsChanged(); emit this->gotSignal(ScStw::ExtensionsChanged, this->getConnections());
} }
} }

View file

@ -14,6 +14,8 @@
#include <string.h> #include <string.h>
#include <QByteArray> #include <QByteArray>
#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.
* *
@ -32,31 +34,25 @@ public:
*/ */
explicit ScStwClient(); explicit ScStwClient();
enum State {DISCONNECTED, CONNECTING, INITIALISING, CONNECTED};
private: private:
// values for the socket connection // values for the socket connection
QString ip; QString ip;
ushort port = 3563; ushort port = 3563;
int errors; int errors;
int errors_until_disconnect = 4; const static int ERRORS_UNTIL_DISCONNECT = 4;
QVariant connections; QVariantList connections;
QString latestReadReply;
//---general status values---// //---general status values---//
// some meta data of the base // some meta data of the base station
QString firmwareVersion; QString firmwareVersion;
bool firmwareUpToDate;
double timeOffset; double timeOffset;
// the current state // the current state
QString state; ScStwClient::State state;
// can be:
// - 'disconnected'
// - 'connecting'
// - 'connected'
QDateTime *date; QDateTime *date;
//to get the current time //to get the current time
@ -80,94 +76,235 @@ private:
signals: signals:
/** /**
* Is emitted, when the connection state changes * @brief Is emitted, when the connection state changes
*
* @brief stateChanged
*/ */
void stateChanged(); void stateChanged();
/** /**
* 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
* *
* @brief gotUnexpectedReply
* @param reply contains the reply * @param reply contains the reply
*/ */
void gotUnexpectedReply(QString reply); void gotUnexpectedMessage(QString message);
/** /**
* Is emitted, when an update signal from the basestation is recieved * @brief Is emitted, when an update signal from the basestation is recieved
* *
* @brief gotUpdate
* @param data * @param data
*/ */
void gotUpdate(QVariant data); void gotSignal(ScStw::SignalKey key, QVariant data);
void connectionsChanged(); /**
* @brief Is emitted, when there is any network error
void connectionSlotReleased(); * @param error
*/
void nextRemoteActionChanged(); void gotError(QAbstractSocket::SocketError error);
void nextRemoteActionDelayProgChanged();
void gotError(QString error);
void propertiesChanged();
public slots: public slots:
/**
* @brief Function to connect to the base station
*/
void connectToHost(); void connectToHost();
//function to connect to the base station
void connectionTimeout();
/**
* @brief Function to disconnect from the basestation
*/
void closeConnection(); void closeConnection();
void gotError(QAbstractSocket::SocketError err);
// --- socket communication handling --- /** socket communication handling */
QVariantMap sendCommand(int header, QJsonValue data = "", bool useTerminationKeys = true, int timeout = 3000); /**
* @brief Funtion to send a command to the server (for internal use)
* @param header the command to send
* @param data the data to send
* @param timeout the timeout
* @param useTerminationKeys wether to use the termination keys defined in
*
* @return a variant map containing the Keys "status" and "data"
*/
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
* @see getTimeOffset()
* @return true or false
*/
bool updateTime(); bool updateTime();
/**
* @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
* @see isFirmwareUpToDate()
* @see getFirmwareVersion()
* @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
* @see getFirmwareVersion()
* @see updateFirmware()
* @return true or false
*/
bool isFirmwareUpToDate(); bool isFirmwareUpToDate();
// --- helper functions --- /** helper functions */
int writeRemoteSetting(QString key, QString value); /**
* @brief Function to write a setting on the base station
* @param key the key to write to
* @param value the value to write to
* @return the status code returned by the command
*/
ScStw::ErrorCode writeRemoteSetting(ScStw::BaseStationSetting key, QString value);
bool refreshConnections(); /**
* @brief Function to read a setting on the base station
* @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
*/
QString readRemoteSetting(ScStw::BaseStationSetting key);
// functions for the qml adapter /** Getter fuctions */
/**
* @brief Function to get the ip the client will try to connect to.
* @see setIP()
* @return the ip
*/
QString getIP(); QString getIP();
/**
* @brief Function to get the current state of the client
* @return the current state
*/
ScStwClient::State getState();
/**
* @brief Functio to get the extensions and their state from the base station
* @return a list with all configured extensions and their state
*/
QVariantList getConnections();
/**
* @brief Function to get the time offset of the base station relative to the clients time
* @see updateTime()
* @return the time offset in milliseconds
*/
int getTimeOffset();
/**
* @brief Function to get the current firmware version of the base station
* @see updateFirmware()
* @see isFirmwareUpToDate()
* @return Firmware version as string encoded as <major>.<minor>.<patch>
*/
QString getFirmwareVersion();
/** setter functions */
/**
* @brief Function to set the ip to connect to
* @see getIP()
* @param ipAdress
*/
void setIP(QString ipAdress); void setIP(QString ipAdress);
QString getState();
void setState(QString newState);
int getProgress();
QVariant getConnections();
private slots: private slots:
/**
* @brief called when timeout timer times out
*/
void connectionTimeout();
/**
* @brief Function that is connected to the QAbstractSocket::error slot and used to handle upcoming errors
* @param err the error that occurred
*/
void handleError(QAbstractSocket::SocketError err);
/**
* @brief Function to init a session at the base station
* @return true or false
*/
bool init(); bool init();
/**
* @brief Function to end a session on the base station
*/
void deInit(); void deInit();
void readyRead(); /**
* @brief Funtion to send a command to the server (for internal use)
* @param header the command to send
* @param data the data to send
* @param timeout the timeout
* @param useTerminationKeys wether to use the termination keys defined in
* ScStw::SOCKET_MESSAGE_START_KEY and ScStw::SOCKET_MESSAGE_END_KEY
* @return a variant map containing the Keys "status" and "data"
*/
QVariantMap sendCommand(int header, QJsonValue data, int timeout, bool useTerminationKeys);
/**
* @brief Function connected to the QAbstractSocket::readyRead signal
*/
void handleReadyRead();
/**
* @brief Function to process an incoming string and parse the messages contained in it.
* @param message the message sting to parse
*/
void processSocketMessage(QString message); void processSocketMessage(QString message);
void socketReplyRecieved(QString reply); /**
* @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.
* 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.
* @see gotUnexpectedMessage()
* @see handleSignal()
* @param reply the massage that needs to be handles
*/
void handleSocketMessage(QString reply);
void socketStateChanged(QAbstractSocket::SocketState socketState); /**
* @brief Function to handle a change of the state of the tcp socket
* @details it is connected to the QAbstractSocket::stateChanged signal
* @see stateChanged()
* @param socketState
*/
void handleSocketStateChange(QAbstractSocket::SocketState socketState);
/**
* @brief Function to handle a signal from the base station.
* @details Called by the ScStwClient::handleSocketMessage function
* @see handleSocketMessage()
* @param data
*/
void handleSignal(QVariantMap data);
/** Helper Functions */
/**
* @brief Function used to set the local cache of the baseStation connections.
* @details emits ScStwClient::gotSignal() with a ScStw::ExtensionsChanged signal.
* @see gotSignal()
* @param connections the list to set the chache to
*/
void setConnections(QVariantList connections); void setConnections(QVariantList connections);
/**
* @brief Function to set the local state.
* @details emits ScStwClient::stateChanged() when the new state does not match the old one.
* @see stateChanged()
* @param newState the state to change to
*/
void setState(ScStwClient::State newState);
}; };
extern ScStwClient * pGlobalScStwClient; extern ScStwClient * pGlobalScStwClient;
#endif // SCSTWCLIENT_H #endif // SCSTWCLIENT_H