/**************************************************************************** ** 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 . ****************************************************************************/ #ifndef SCSTWCLIENT_H #define SCSTWCLIENT_H #include #include #include #include #include #include #include #include #include #include #include #include #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 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); /*! updater functions */ /*! * \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(); /*! * \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 .. */ 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