This repository has been archived on 2024-06-03. You can view files and clone it, but cannot push or open issues or pull requests.
shared-libraries/ScStwLibraries/scstwclient.h

316 lines
8.7 KiB
C++

#ifndef SCSTWCLIENT_H
#define SCSTWCLIENT_H
#include <QObject>
#include <QTcpSocket>
#include <QDataStream>
#include <QDateTime>
#include <QTimer>
#include <QEventLoop>
#include <QSemaphore>
#include <QThread>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
#include <string.h>
#include <QByteArray>
#include <ScStw.hpp>
/**
* This class is used to connect and talk to the ScStw basestation.
*
* @code{.cpp}
* ScStwClient * client = new ScStwClient();
* client->setIp("192.168.4.1");
* client->connectToHost();
* @endcode
*
* @brief The ScStwClient class
* @author Dorian Zedler
*/
class ScStwClient : public QObject
{
Q_OBJECT
public:
/**
* The constructor
*
* @brief ScStwClient
*/
explicit ScStwClient();
enum State {DISCONNECTED, CONNECTING, INITIALISING, CONNECTED};
private:
// values for the socket connection
QString ip;
ushort port = 3563;
int errors;
const static int ERRORS_UNTIL_DISCONNECT = 4;
QVariantList connections;
//---general status values---//
// some meta data of the base station
QString firmwareVersion;
double timeOffset;
// the current state
ScStwClient::State state;
QDateTime *date;
//to get the current time
QTcpSocket *socket;
//socket for communication with the extention
QTimer *timeoutTimer;
QString readBuffer;
int nextConnectionId;
struct waitingRequest {
int id;
QEventLoop * loop;
QJsonObject reply;
};
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:
/**
* @brief Function to connect to the base station
*/
void connectToHost();
/**
* @brief Function to disconnect from the basestation
*/
void closeConnection();
/** socket communication handling */
/**
* @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 */
/**
* @brief Function to set the timestamp of the base station to match the client
* @see getTimeOffset()
* @return true or false
*/
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();
/**
* @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();
/** helper functions */
/**
* @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);
/**
* @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);
/** Getter fuctions */
/**
* @brief Function to get the ip the client will try to connect to.
* @see setIP()
* @return the ip
*/
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);
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();
/**
* @brief Function to end a session on the base station
*/
void deInit();
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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;
#endif // SCSTWCLIENT_H