- major cleanup
- added global static class ScStw
This commit is contained in:
parent
d32fe7733a
commit
b752bdeed2
6 changed files with 391 additions and 194 deletions
4
ScStwLibraries/ScStw.cpp
Normal file
4
ScStwLibraries/ScStw.cpp
Normal 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
53
ScStwLibraries/ScStw.hpp
Normal 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
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Reference in a new issue