#ifndef SCSTWCLIENT_H #define SCSTWCLIENT_H #include #include #include #include #include #include #include #include #include #include #include #include #include /** * 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 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 .. */ 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