/* Speed Climbing Stopwatch - Simple Stopwatch for Climbers Copyright (C) 2018 Itsblue Development - Dorian Zeder This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License. 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ #include "headers/buzzerconn.h" BuzzerConn::BuzzerConn(QObject *parent, QString ip, int port) : QObject(parent) { this->socket = new QTcpSocket(); this->date = new QDateTime; this->latest_button_pressed = 0; this->ip = ip; this->port = port; this->setState("disconnected"); // "http://192.168.4.1" } bool BuzzerConn::connect() { qDebug() << "connecting..."; setState("connecting"); //setup loop to wait until the connection has finished QEventLoop loop; QTimer timer; timer.setSingleShot(true); loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); loop.connect(this->socket, SIGNAL(connected()), &loop, SLOT(quit())); timer.start(3000); //connect this->socket->connectToHost(this->ip, this->port); //wait for the connection to finish loop.exec(); //loop finished if(timer.remainingTime() == -1){ //the time has been triggered -> timeout setState("disconnected"); return(false); } timer.stop(); QList times = gettimes(2000, true); qDebug() << times; if(times[0] == 200.0){ this->latest_button_pressed = times[2]; for(int i=0;i<=100;i++){ this->connection_progress = i; emit this->progressChanged(); if(!calcoffset(this->gettimes(1000, false))){ this->connection_progress = 100; setState("disconnected"); return(false); } } setState("connected"); return(true); } else{ setState("disconnected"); return(false); } } bool BuzzerConn::calcoffset(QList times) { if(times.length() != 2){ return(false); } if(times[0] == 200.0){ double offset = date->currentMSecsSinceEpoch() - times[1]; if(this->latest_offsets.length()>=100){ this->latest_offsets.removeFirst(); } this->latest_offsets.append(offset); double mem = 0; for(int i=0;ioffset = mem / double(latest_offsets.length()); offsetChanged(); //qDebug("%20f", this->offset); return(true); } else { //this->connected = false; return(false); } } QList BuzzerConn::gettimes(int timeout, bool bothTimes) { QList times; signed long ret; ret = this->sendCommand("GET_TIMESTAMP", timeout); if(ret >= 0){ times.append(double(200)); times.append(double(ret)); if(bothTimes){ ret = this->sendCommand("GET_LASTPRESSED", timeout); if(ret >= 0){ times.append(double(ret)); } else { times[0] = ret; } } } else { times.append(ret); } return(times); } double BuzzerConn::get(QString key) { if(key == "offset"){ return(this->offset); } else if (key == "lastpressed") { return(this->latest_button_pressed); } else if( key == "currtime") { return(this->date->currentMSecsSinceEpoch()); } else if( key == "connection_progress") { return(this->connection_progress); } else if( key == "connected") { if(this->state == "connected"){ return(1); } return(0); } return(0); } void BuzzerConn::setIP(const QString &ipAdress){ this->ip = ipAdress; } QString BuzzerConn::getIP() const { return(this->ip); } QString BuzzerConn::getState() const { return(this->state); } void BuzzerConn::setState(QString newState){ this->state = newState; emit stateChanged(); } int BuzzerConn::getProgress() const { return(connection_progress); } double BuzzerConn::getOffset() const { return(this->offset); } double BuzzerConn::getLastTriggered() const { return(this->latest_button_pressed); } bool BuzzerConn::refresh() { if(this->state != "connected"){ return(false); } //send one of the pending commands if(pending_commands.length() > 0){ QString command = this->pending_commands.first(); signed long retval = this->sendCommand(command, 2000); if(retval > 0){ this->pending_commands.removeFirst(); } } //refresh the times QList ret = this->gettimes(2000); if(ret[0] >= 0){ if(ret[2] > this->latest_button_pressed){ this->latest_button_pressed = ret[2]; emit triggered(); } this->errors = 0; return(this->calcoffset(ret)); } else { this->errors ++; if(this->errors > errors_until_disconnect){ this->socket->disconnectFromHost(); this->setState("disconnected"); } return(false); } } signed long BuzzerConn::sendCommand(QString command, int timeout){ //if there is any data in the storage, clear it if(this->socket->bytesAvailable() > 0){ this->socket->readAll(); } //send request to the socket server QByteArray arrBlock; QDataStream out(&arrBlock, QIODevice::WriteOnly); //out.setVersion(QDataStream::Qt_5_10); out << quint16(0) << command; out.device()->seek(0); out << quint16(arrBlock.size() - sizeof(quint16)); this->socket->write(arrBlock); //now wait for the server of the sensor to answer QEventLoop loop; QTimer timer; timer.setSingleShot(true); loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); loop.connect(socket, SIGNAL(readyRead()), &loop, SLOT(quit())); timer.start(timeout); loop.exec(); //loop finished if(timer.remainingTime() == -1){ //the time has been triggered -> timeout return(-1); } timer.stop(); //if the data is not 4 bytes long it is invalid -> clear and terminate if(this->socket->bytesAvailable() != 4){ this->socket->readAll(); return(-2); } long data = 0; this->socket->read((char*)&data,4); //qDebug() << data; //qDebug() << this->socket->bytesAvailable(); return data; } void BuzzerConn::appendCommand(QString command){ this->pending_commands.append(command); }