326 lines
9.3 KiB
C++
326 lines
9.3 KiB
C++
/****************************************************************************
|
|
** ScStw Libraries
|
|
** Copyright (C) 2020 Itsblue development
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
****************************************************************************/
|
|
|
|
#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
|
|
Q_PROPERTY(State state READ getState NOTIFY stateChanged)
|
|
Q_PROPERTY(QVariantList extensions READ getExtensions NOTIFY extensionsChanged)
|
|
Q_PROPERTY(QString ipAddress READ getIP WRITE setIP)
|
|
|
|
public:
|
|
/*!
|
|
* The constructor
|
|
*
|
|
* \brief ScStwClient
|
|
*/
|
|
explicit ScStwClient(QObject *parent = nullptr);
|
|
|
|
enum State {DISCONNECTED, CONNECTING, INITIALISING, CONNECTED};
|
|
Q_ENUM(State);
|
|
|
|
const QString API_VERSION = "1.0.0";
|
|
|
|
private:
|
|
// values for the socket connection
|
|
QString ip;
|
|
ushort port = 3563;
|
|
int errors;
|
|
const static int ERRORS_UNTIL_DISCONNECT = 4;
|
|
|
|
QVariantList extensions;
|
|
|
|
//---general status values---//
|
|
|
|
// some meta data of the base station
|
|
QString firmwareVersion;
|
|
QString apiVersion;
|
|
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;
|
|
|
|
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);
|
|
|
|
/*! 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::StatusCode 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 Function to get the extensions and their state from the base station
|
|
* \return a list with all configured extensions and their state
|
|
*/
|
|
QVariantList getExtensions();
|
|
|
|
/*!
|
|
* \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();
|
|
|
|
/*!
|
|
* \brief Function to get the current API version of the base station
|
|
* \return
|
|
*/
|
|
QString getApiVersion();
|
|
|
|
/*! 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 setExtensions(QVariantList extensions);
|
|
|
|
/*!
|
|
* \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);
|
|
|
|
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;
|
|
|
|
#endif // SCSTWCLIENT_H
|