From 24f9dcbc6ffba8032d49f8abf17ae1c54d3017dd Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Mon, 17 Sep 2018 23:06:34 +0200 Subject: [PATCH] changed the integration of the c++ classes into the qml code to make things cleaner, everything seems to be working again added false start sound --- headers/buzzerconn.h | 25 ++++++++ qml/connections/BuzzerConn.qml | 96 ------------------------------ qml/connections/StartpadConn.qml | 97 ------------------------------- qml/main.qml | 84 ++++++++++++++++++++++---- qml/qml.qrc | 2 - shared.qrc | 1 + sounds/false.wav | Bin 0 -> 70208 bytes sources/buzzerconn.cpp | 75 +++++++++++++++++------- sources/main.cpp | 12 ++-- 9 files changed, 157 insertions(+), 235 deletions(-) delete mode 100644 qml/connections/BuzzerConn.qml delete mode 100644 qml/connections/StartpadConn.qml create mode 100644 sounds/false.wav diff --git a/headers/buzzerconn.h b/headers/buzzerconn.h index 8255edb..9918979 100644 --- a/headers/buzzerconn.h +++ b/headers/buzzerconn.h @@ -19,6 +19,12 @@ typedef struct strReturnData{ class BuzzerConn : public QObject { Q_OBJECT + Q_PROPERTY(double lastTriggered READ getLastTriggered NOTIFY triggered) + Q_PROPERTY(QString ipAdress WRITE setIP READ getIP) + Q_PROPERTY(QString state READ getState NOTIFY stateChanged) + Q_PROPERTY(int progress READ getProgress NOTIFY progressChanged) + Q_PROPERTY(double offset READ getOffset NOTIFY offsetChanged) + public: explicit BuzzerConn(QObject *parent = nullptr, QString ip = "http://192.168.4.1", int port = 80); double offset; @@ -31,6 +37,7 @@ public: int port; int errors; int errors_until_disconnect = 4; + QString state; @@ -42,6 +49,13 @@ private: QStringList pending_commands; //QSemaphore dataPipe(1); signals: + void triggered(); + + void stateChanged(); + + void progressChanged(); + + void offsetChanged(); public slots: ReturnData_t senddata(QNetworkAccessManager * NetMan, QUrl serviceUrl, int timeout); @@ -73,6 +87,17 @@ public slots: //refreshed the connection to the buzzer Q_INVOKABLE void appendCommand(QString command); + void setIP(const QString &ipAdress); + QString getIP() const; + + QString getState() const; + void setState(QString newState); + + int getProgress() const; + + double getOffset() const; + + double getLastTriggered() const; }; diff --git a/qml/connections/BuzzerConn.qml b/qml/connections/BuzzerConn.qml deleted file mode 100644 index aa10808..0000000 --- a/qml/connections/BuzzerConn.qml +++ /dev/null @@ -1,96 +0,0 @@ -import QtQuick 2.0 - -Item { - id: buzzerConn - height: 0 - width: 0 - opacity: 0 - visible: false - - signal pushed() - property bool connected: false - property var status: {'status': buzzerConn.state, 'progress': get_progress()} - - Timer { - //timer that refreshes the connection state to the buzzer - id: connectionRefreshTimer - running: root.state !== "RUNNING" && root.state !== "STARTING" && buzzerConn.status !== "connecting" - repeat: false - interval: 1000 - onTriggered: { - _cppBuzzerConn.refresh() - if(!_cppBuzzerConn.get("connected") && buzzerConn.state !== "connecting"){ - buzzerConn.state = "disconnected" - } - - connectionRefreshTimer.start() - } - } - - Timer { - //timer that checks, if the button has been pushed - id: running_refresh_timer - running: root.state === "RUNNING" - repeat: false - interval: 1 - - onTriggered: { - if(_cppBuzzerConn.buzzer_triggered()){ - buzzerConn.pushed() - - } - if(root.state === "RUNNING"){ - running_refresh_timer.start() - } - } - } - - Timer { - id: prog_refresh - running: buzzerConn.state === "connecting" - interval: 1 - repeat: true - onTriggered: { - buzzerConn.status.progress = get_progress() - } - } - - states: [ - State { - name: "disconnected" - PropertyChanges { - target: buzzerConn - } - }, - State { - name: "connecting" - PropertyChanges { - target: buzzerConn - } - }, - State { - name: "connected" - PropertyChanges { - target: buzzerConn - } - } - ] - - function connect(){ - buzzerConn.state = "connecting" - if(_cppBuzzerConn.connect()){ - buzzerConn.state = "connected" - return(true) - } - else { - buzzerConn.state = "disconnected" - return(false) - } - - - } - - function get_progress(){ - return(_cppBuzzerConn.get("connection_progress")) - } -} diff --git a/qml/connections/StartpadConn.qml b/qml/connections/StartpadConn.qml deleted file mode 100644 index 8a49176..0000000 --- a/qml/connections/StartpadConn.qml +++ /dev/null @@ -1,97 +0,0 @@ -import QtQuick 2.0 - -Item { - id: startpadConn - height: 0 - width: 0 - opacity: 0 - visible: false - - signal pushed() - property bool connected: false - property var status: {'status': startpadConn.state, 'progress': get_progress()} - property bool active - - Timer { - //timer that refreshes the connection state to the buzzer - id: connectionRefreshTimer - running: root.state !== "RUNNING" && root.state !== "STARTING" && startpadConn.status !== "connecting" - repeat: false - interval: 1000 - onTriggered: { - _cppStartpadConn.refresh() - if(!_cppStartpadConn.get("connected") && startpadConn.state !== "connecting"){ - startpadConn.state = "disconnected" - } - - connectionRefreshTimer.start() - } - } - - Timer { - //timer that checks, if the button has been pushed - id: running_refresh_timer - running: (root.state === "RUNNING" || root.state === "STARTING") && active - repeat: false - interval: 1 - - onTriggered: { - if(_cppStartpadConn.buzzer_triggered()){ - startpadConn.pushed() - - } - if(root.state === "RUNNING" || root.state === "STARTING" && active){ - running_refresh_timer.start() - } - } - } - - Timer { - id: prog_refresh - running: startpadConn.state === "connecting" - interval: 1 - repeat: true - onTriggered: { - startpadConn.status.progress = get_progress() - } - } - - states: [ - State { - name: "disconnected" - PropertyChanges { - target: startpadConn - } - }, - State { - name: "connecting" - PropertyChanges { - target: startpadConn - } - }, - State { - name: "connected" - PropertyChanges { - target: startpadConn - } - } - ] - - function connect(){ - startpadConn.state = "connecting" - if(_cppStartpadConn.connect()){ - startpadConn.state = "connected" - return(true) - } - else { - startpadConn.state = "disconnected" - return(false) - } - - - } - - function get_progress(){ - return(_cppStartpadConn.get("connection_progress")) - } -} diff --git a/qml/main.qml b/qml/main.qml index 09abe66..312ab4e 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -21,7 +21,6 @@ import QtQuick.Window 2.2 import QtQuick.Controls 2.2 import "." import "./components" -import "./connections" import "./styles" //import QtQuick.Layouts 1.11 @@ -47,8 +46,8 @@ Window { property double stoppedTime: 0 property double currTime - property double buzzer_offset - property double last_button_pressed + property double buzzer_offset: buzzerConn.offset + property double last_button_pressed: buzzerConn.lastTriggered property var last_run : { 'stop_type': "", 'time': 0, 'react_time': 0 @@ -69,6 +68,62 @@ Window { color: StyleSettings.backgroundColor } + BuzzerConn { + id: buzzerConn + ipAdress: "192.168.4.10" + property var status: {'status': buzzerConn.state, 'progress': buzzerConn.progress} + onLastTriggeredChanged: { + console.log(lastTriggered) + root.stop("buzzer") + } + } + + Timer { + id: buzzerRefreshTimer + running: buzzerConn.state === "connected" + interval: root.state === "RUNNING" ? 1:1000 + repeat: false + onTriggered: { + buzzerConn.refresh() + this.start() + } + } + + StartpadConn { + id: startpadConn + ipAdress: "192.168.4.11" + property var status: {'status': startpadConn.state, 'progress': startpadConn.progress} + property string color: root.state === "RUNNING" ? "SET_LED_RUNNING":"SET_LED_STARTING" + onColorChanged: { + appendCommand(color) + } + + onLastTriggeredChanged: { + console.log("startpad triggered") + var offset = startpadConn.offset + var last_pressed = startpadConn.lastTriggered + var trigger_time = (last_pressed + offset) + root.last_run.react_time = trigger_time - root.startTime + if(trigger_time - root.startTime <= 0){ + root.stop("false") + } + } + } + + Timer { + id: startpadRefreshTimer + running: startpadConn.state === "connected" + interval: root.state === "RUNNING" || root.state === "STARTING" ? 1:1000 + repeat: false + onTriggered: { + startpadConn.refresh() + this.start() + } + } + + + +/* BuzzerConn { id: buzzerConn onPushed: { @@ -96,7 +151,7 @@ Window { } } } - +*/ Timer { //timer that updates the currTime variable running: true @@ -183,20 +238,24 @@ Window { if(!playing && root.state==="STARTING"){ console.log(root.startTime) - _cppStartpadConn.appendCommand("SET_LED_RUNNING") root.currTime = root.startTime time.text = ( ( root.currTime - root.startTime ) / 1000 ).toFixed(3) + " sec" root.state = "RUNNING" } else if(playing) { console.log("start sound started") - root.startTime = _cppBuzzerConn.get("currtime") + 3100 //set the startime to be 0 after the starttone - startpadConn.active = true + root.startTime = new Date().getTime() + 3100 //set the startime to be 0 after the starttone } } } + SoundEffect { + //start sound + id: falseSound + source: "qrc:/sounds/false.wav" + } + /*------------------------ Timer text an upper line ------------------------*/ @@ -687,16 +746,16 @@ Window { } function stop(type){ - _cppStartpadConn.appendCommand("SET_LED_STARTING"); + //_cppStartpadConn.appendCommand("SET_LED_STARTING"); switch(type){ case "buzzer": //the buzzer was pushed - root.buzzer_offset = _cppBuzzerConn.get("offset") - root.last_button_pressed = _cppBuzzerConn.get("lastpressed") + root.buzzer_offset = buzzerConn.offset + root.last_button_pressed = buzzerConn.lastTriggered root.stoppedTime = (root.last_button_pressed + root.buzzer_offset) - root.startTime root.state = "STOPPED" //time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec" - console.log("STOPPED: "+root.stoppedTime) + console.log("STOPPED: "+root.stoppedTime + " started at: " + root.startTime + " offset: "+ root.buzzer_offset + "lastpressed: " + root.last_button_pressed) break case "manual": //the stop button was pressed @@ -713,9 +772,10 @@ Window { at_marksSound.stop() readySound.stop() startSound.stop() + falseSound.play() break } - startpadConn.active = true + //tartpadConn.active = true } function reset(){ diff --git a/qml/qml.qrc b/qml/qml.qrc index 2faba7a..d95c7a4 100644 --- a/qml/qml.qrc +++ b/qml/qml.qrc @@ -7,8 +7,6 @@ components/SimpleIndicator.qml components/ConnectionDelegate.qml components/FadeAnimation.qml - connections/BuzzerConn.qml - connections/StartpadConn.qml styles/StyleSettings.qml styles/qmldir styles/Dark.js diff --git a/shared.qrc b/shared.qrc index 4f8acc8..1e8a3ea 100644 --- a/shared.qrc +++ b/shared.qrc @@ -20,5 +20,6 @@ translations/de_DE.ts graphics/icons/settings_black.png graphics/icons/startpad_black.png + sounds/false.wav diff --git a/sounds/false.wav b/sounds/false.wav new file mode 100644 index 0000000000000000000000000000000000000000..ae4daa7f88305d9c9e51edf7217d3d31b818f2a9 GIT binary patch literal 70208 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ⅈcvlX&>HrIeWvdrzHMdoc_h!4 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 = ip; this->port = port; + + this->setState("disconnected"); // "http://192.168.4.1" } @@ -37,6 +39,8 @@ bool BuzzerConn::connect() { qDebug() << "connecting..."; + setState("connecting"); + //wait until the request has finished QEventLoop loop; QTimer timer; @@ -62,17 +66,21 @@ bool BuzzerConn::connect() 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))){ this->connection_progress = 100; this->connected = false; + setState("disconnected"); return(false); } } this->connected = true; + setState("connected"); return(true); } else{ this->connected = false; + setState("disconnected"); return(false); } } @@ -95,7 +103,8 @@ bool BuzzerConn::calcoffset(QList times) mem += latest_offsets[i]; } this->offset = mem / double(latest_offsets.length()); - qDebug("%20f", this->offset); + offsetChanged(); + //qDebug("%20f", this->offset); return(true); } else { @@ -215,6 +224,41 @@ double BuzzerConn::get(QString key) } 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); } QString BuzzerConn::test() @@ -228,36 +272,23 @@ bool BuzzerConn::refresh() if(!this->connected){ return(false); } -// QList times; -// ReturnData_t ret = senddata(this->reloadNetworkManager, QUrl(this->ip), 1000); -// times.append(double(ret.status_code)); - -// if(ret.status_code == 200){ -// ret.text.replace("\n",""); -// ret.text.replace("\r",""); -// QStringList times_cache = ret.text.split("
"); -// times.append(times_cache[0].toDouble()); -// times.append(times_cache[1].toDouble()); -// calcoffset(times); -// return(true); -// } -// else{ -// //this->connected = false; -// return(false); -// } if(pending_commands.length() > 0){ QString command = this->pending_commands.first(); - signed long retval = this->sendCommand(command, 800); + signed long retval = this->sendCommand(command, 2000); if(retval > 0){ this->pending_commands.removeFirst(); } } //refresh the times - QList ret = this->gettimes(800); + 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)); } @@ -356,8 +387,8 @@ signed long BuzzerConn::sendCommand(QString command, int timeout){ long data = 0; this->socket->read((char*)&data,4); - qDebug() << data; - qDebug() << this->socket->bytesAvailable(); + //qDebug() << data; + //qDebug() << this->socket->bytesAvailable(); return data; } diff --git a/sources/main.cpp b/sources/main.cpp index cf3dbc8..17a3cc8 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -105,14 +105,18 @@ int main(int argc, char *argv[]) #endif connectToDatabase(); - BuzzerConn * pBuzzerConn = new BuzzerConn(nullptr, "192.168.4.10", 80); - BuzzerConn * pStartpadConn = new BuzzerConn(nullptr, "192.168.4.11", 80); + //BuzzerConn * pBuzzerConn = new BuzzerConn(nullptr, "192.168.4.10", 80); + //BuzzerConn * pStartpadConn = new BuzzerConn(nullptr, "192.168.4.11", 80); AppSettings * pAppSettings = new AppSettings(); //setup the sql storage model as a qml model qmlRegisterType("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlProfileModel"); qmlRegisterType("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlStorageModel"); + //setup the startpad and buzzer conn qml objects + qmlRegisterType("com.itsblue.speedclimbingstopwatch", 1, 0, "BuzzerConn"); + qmlRegisterType("com.itsblue.speedclimbingstopwatch", 1, 0, "StartpadConn"); + //setup translation engine //to the language of the system //if the system language is not found the language is set to english @@ -125,16 +129,12 @@ int main(int argc, char *argv[]) if (engine.rootObjects().isEmpty()) return -1; - engine.rootContext()->setContextProperty("_cppBuzzerConn", pBuzzerConn); - engine.rootContext()->setContextProperty("_cppStartpadConn", pStartpadConn); engine.rootContext()->setContextProperty("_cppAppSettings", pAppSettings); int iRet = 0; iRet = app.exec(); //call the destructors of all objects - delete pBuzzerConn; - delete pStartpadConn; delete pAppSettings; return iRet;