started to implement connectivtx to a physical Buzzer

This commit is contained in:
Dorian Zedler 2018-07-25 00:32:20 +02:00
parent d5f70ccad4
commit 9593dd9a4c
8 changed files with 445 additions and 121 deletions

90
SettingsDialog.qml Normal file
View file

@ -0,0 +1,90 @@
import QtQuick 2.9
import QtMultimedia 5.8
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Dialog {
x: startButt.x
y: startButt.y
width: startButt.width
height: startButt.height
modal: false
enabled: false
enter: Transition {
NumberAnimation { properties: "scale"; from: 0; to: 1; duration: 500; easing.type: Easing.InCubic }
}
exit: Transition {
NumberAnimation { properties: "scale"; from: 1; to: 0; duration: 500; easing.type: Easing.OutCubic }
}
background: Rectangle {
radius: width * 0.5
color: "white"
border.color: "grey"
border.width: 1
Label {
text: "Options"
font.pixelSize: headlineUnderline.width * 0.1
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: headlineUnderline.anchors.topMargin / 2 - height / 2
}
}
Rectangle {
id: headlineUnderline
height: 1
width: parent.width
color: "grey"
anchors {
top: parent.top
left: parent.left
right: parent.right
topMargin: parent.height * 0.15
rightMargin: parent.radius - Math.sqrt(Math.pow(parent.radius,2)-Math.pow(parent.radius-anchors.topMargin,2))
leftMargin: parent.radius - Math.sqrt(Math.pow(parent.radius,2)-Math.pow(parent.radius-anchors.topMargin,2))
}
}
}
Column {
anchors.fill: parent
ItemDelegate {
id: connect_del
anchors.fill: parent
text: "connect"
onClicked: {
var i;
if(i === 100){
i = 0
running = false
}
var theUrl = "http://192.168.4.1";
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false );
xmlHttp.setRequestHeader("Content-type", "text/plain;charset=UTF-8");
xmlHttp.send( null );
var response = xmlHttp.responseText
var response_status = xmlHttp.status
connect_del.text = response
var res = response.split("<br>");
var time_now = new Date().getTime()
console.log(time_now)
console.log(res[1])
console.log(time_now-res[0])
root.buzzer_offset = time_now-res[0]
root.last_button_pressed = res[1]
console.log("buzzer_offset: "+root.buzzer_offset)
connect_del.text = response
}
}
}
}

94
buzzerconn.cpp Normal file
View file

@ -0,0 +1,94 @@
#include "buzzerconn.h"
BuzzerConn::BuzzerConn(QObject *parent) : QObject(parent)
{
this->networkManager = new QNetworkAccessManager();
connect();
}
bool BuzzerConn::connect()
{
QList<double> times = gettimes();
if(times[0] == 200.0){
this->connected = true;
calcoffset();
calcoffset();
calcoffset();
return(true);
}
else{
return(false);
}
}
void BuzzerConn::calcoffset()
{
QList<double> times = gettimes();
QDateTime * date = new QDateTime;
double offset = date->currentMSecsSinceEpoch() - times[2];
this->latest_offsets.append(offset);
double mem = 0;
for(int i=0;i<latest_offsets.length();i++){
qDebug()<<latest_offsets[i];
mem += latest_offsets[i];
}
this->offset = mem / double(latest_offsets.length());
}
QList<double> BuzzerConn::gettimes()
{
QList<double> times;
ReturnData_t ret = senddata(QUrl("http://192.168.4.1"));
times.append(double(ret.status_code));
if(ret.status_code == 200){
qDebug()<<ret.text;
ret.text.replace("\n","");
ret.text.replace("\r","");
QStringList times_cache = ret.text.split("<br>");
times.append(times_cache[0].toDouble());
times.append(times_cache[1].toDouble());
return(times);
}
else{
return(times);
}
}
ReturnData_t BuzzerConn::senddata(QUrl serviceUrl)
{
ReturnData_t ret; //this is a custom type to store the returned data
// Call the webservice
QNetworkRequest request(serviceUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
//set ssl configuration
//send a POST request with the given url and data to the server
QUrlQuery pdata;
QNetworkReply* reply;
reply = this->networkManager->post(request, pdata.toString(QUrl::FullyEncoded).toUtf8());
//wait until the request has finished
QEventLoop loop;
loop.connect(this->networkManager, SIGNAL(finished(QNetworkReply*)), SLOT(quit()));
loop.exec();
//get the status code
QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
ret.status_code = status_code.toInt();
if(ret.status_code == 0){ //if tehstatus code is zero, the connecion to the server was not possible
ret.status_code = 444;
}
//get the full text response
ret.text = QString::fromUtf8(reply->readAll());
//return the data
return(ret);
}

39
buzzerconn.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef BUZZERCONN_H
#define BUZZERCONN_H
#include <QObject>
#include <QObject>
#include <QDir>
#include <QUrl>
#include <QtNetwork>
#include <QAuthenticator>
#include <QDesktopServices>
#include <QDateTime>
typedef struct strReturnData{
int status_code;
QString text;
}ReturnData_t;
class BuzzerConn : public QObject
{
Q_OBJECT
public:
explicit BuzzerConn(QObject *parent = nullptr);
double offset;
QList<double> latest_offsets;
bool connected;
private:
QNetworkAccessManager *networkManager;
signals:
public slots:
ReturnData_t senddata(QUrl serviceUrl);
QList<double> gettimes();
bool connect();
void calcoffset();
};
#endif // BUZZERCONN_H

View file

@ -6,11 +6,34 @@
#include <QFile>
#include <QDir>
#include <QStandardPaths>
#include <QtWebView/QtWebView>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QGuiApplication>
#include <QQuickView>
#include <QStandardPaths>
#include <QtQml>
#include <QtNetwork>
#include <QQmlApplicationEngine>
#include <QFile>
#include <QDesktopServices>
#include <QtCore/QUrl>
#include <QtCore/QCommandLineOption>
#include <QtCore/QCommandLineParser>
#include <QGuiApplication>
#include <QStyleHints>
#include <QScreen>
#include <QQmlApplicationEngine>
#include <QtQml/QQmlContext>
#include <QtWebView/QtWebView>
#ifdef Q_OS_ANDROID
#include <QtAndroidExtras>
#endif
#include "sqlstoragemodel.h"
#include "sqlprofilemodel.h"
#include "buzzerconn.h"
static void connectToDatabase()
{
@ -44,11 +67,15 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QAndroidJniObject jactivity=QtAndroid::androidActivity();
if(jactivity.isValid())
jactivity.callMethod<void>("setVolumeControlStream","(I)V",3);
#ifdef Q_OS_ANDROID
//set the standard volume to media
QAndroidJniObject jactivity=QtAndroid::androidActivity();
if(jactivity.isValid())
jactivity.callMethod<void>("setVolumeControlStream","(I)V",3);
#endif
connectToDatabase();
BuzzerConn * pBuzzerConn = new BuzzerConn;
//setup the sql storage model as a qml model
qmlRegisterType<SqlProfileModel>("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlProfileModel");
@ -59,5 +86,7 @@ int main(int argc, char *argv[])
if (engine.rootObjects().isEmpty())
return -1;
engine.rootContext()->setContextProperty("_cppBuzzerConn", pBuzzerConn);
return app.exec();
}

300
main.qml
View file

@ -23,6 +23,10 @@ Window {
property double stoppedTime: 0
property double currTime: new Date().getTime()
property double buzzer_offset
property double last_button_pressed
state: "IDLE"
Timer {
@ -32,6 +36,33 @@ Window {
interval: 1
onTriggered: {
root.currTime = new Date().getTime()
}
}
Timer {
id: running_refresh_timer
running: root.state === "RUNNING"
repeat: true
interval: 1
onTriggered: {
var theUrl = "http://192.168.4.1";
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false );
xmlHttp.send( null );
var response = xmlHttp.responseText
var res = response.split("<br>");
startButt.text = res[0]
if(res[1]>root.last_button_pressed){
root.last_button_pressed = res[1]
root.stoppedTime = (root.last_button_pressed + root.buzzer_offset) - root.startTime
console.log("STOPPED: "+root.stoppedTime)
time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
root.state = "STOPPED"
}
}
}
@ -86,96 +117,100 @@ Window {
/*----------------------
Start button
----------------------*/
Rectangle {
id: startButt
Button {
id : startButt
property string text: "start"
text: "start"
property int size: root.landscape() ? parent.width * 0.5:parent.height * 0.5
anchors {
bottom: parent.bottom
bottomMargin: parent.height * 0.5 - height * 0.5
bottomMargin: root.height * 0.5 - height * 0.5
right: parent.right
rightMargin: parent.width * 0.5 - width * 0.5
rightMargin: root.width * 0.5 - width * 0.5
}
contentItem: Text {
//make text disappear
}
height: root.landscape() ? size > parent.height * 0.9 ? parent.height * 0.9:size : size
width: root.landscape() ? size : size > parent.width * 0.9 ? parent.width * 0.9:size
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Label {
id: startButt_text
text: parent.text
anchors.centerIn: parent
font.pixelSize: parent.height * 0.16
font.family: "Helvetica"
}
MouseArea {
enabled: startButt.enabled
anchors.fill: parent
onPressed: parent.color = "lightgrey"
onReleased: parent.color = "white"
onClicked: {
switch(root.state) {
case "":
root.state = "IDLE"
case "IDLE":
root.state = "STARTING"
startSound.play()
break
case "RUNNING":
root.stoppedTime = new Date().getTime() - root.startTime
time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
root.state = "STOPPED"
break
case "STOPPED":
root.state = "IDLE"
break
}
onPressedChanged: {
if(pressed){
background.color = "lightgrey"
}
else {
background.color = "white"
}
}
background: Rectangle {
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Label {
id: startButt_text
text: startButt.text
anchors.centerIn: parent
font.pixelSize: parent.height * 0.16
font.family: "Helvetica"
}
}
onClicked: {
switch(root.state) {
case "":
root.state = "IDLE"
case "IDLE":
root.state = "STARTING"
startSound.play()
break
case "RUNNING":
root.stoppedTime = new Date().getTime() - root.startTime
time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
root.state = "STOPPED"
break
case "STOPPED":
root.state = "IDLE"
break
}
}
}
/*----------------------
Cancel button
----------------------*/
Rectangle {
RoundButton {
id: cancelButt
property string text: "cancel"
text: "cancel"
anchors {
right: startButt.right
bottom: startButt.bottom
}
contentItem: Text {
//make text disappear
}
height: startButt.height * 0.3
scale: 0
width: height
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Label {
id: cancelButt_text
text: parent.text
anchors.centerIn: parent
font.pixelSize: parent.height * 0.16
font.family: "Helvetica"
}
MouseArea {
enabled: startSound.playing
anchors.fill: parent
onPressed: parent.color = "lightgrey"
onReleased: parent.color = "white"
onClicked: {
startSound.stop()
root.stoppedTime = 0
time.text = "false start"
root.state = "STOPPED"
enabled: startSound.playing
onPressedChanged: {
if(pressed){
background.color = "lightgrey"
}
else {
background.color = "white"
}
}
onClicked: {
startSound.stop()
root.stoppedTime = 0
time.text = "false start"
root.state = "STOPPED"
}
Behavior on scale {
@ -183,8 +218,29 @@ Window {
duration: 200
}
}
background: Rectangle {
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Label {
id: cancelButt_text
text: cancelButt.text
anchors.centerIn: parent
font.pixelSize: parent.height * 0.16
font.family: "Helvetica"
}
}
}
/*------
Popups
------*/
SettingsDialog{
id:settingsDialog
}
/*-------------------
lower line and menu
-------------------*/
@ -208,10 +264,9 @@ Window {
leftMargin: root.landscape() ? parent.width * 0.05:0
}
Rectangle {
RoundButton {
id: settingsButt
property string text: "cancel"
anchors {
//center
verticalCenter: root.landscape() ? undefined:parent.verticalCenter
@ -223,45 +278,52 @@ Window {
topMargin: root.landscape() ? (parent.height - (height * 2)) / 3:undefined
//align in portrait mode
leftMargin: root.landscape() ? undefined:(parent.width - width * 2) / 3
}
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
width: height
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Image {
id: settungsButt_Image
source: "qrc:/graphics/icons/settings.png"
anchors.centerIn: parent
height: parent.height * 0.7
width: parent.width * 0.7
mipmap: true
}
MouseArea {
enabled: root.state === "IDLE"
anchors.fill: parent
onPressed: parent.color = "lightgrey"
onReleased: parent.color = "white"
onClicked: {
onPressedChanged: {
if(pressed){
background.color = "lightgrey"
}
else {
background.color = "white"
}
}
Behavior on scale {
PropertyAnimation {
duration: 200
onClicked: {
if(settingsDialog.enabled === false){
settingsDialog.open()
settingsDialog.enabled = true
}
else {
settingsDialog.enabled = false
settingsDialog.close()
}
}
background: Rectangle {
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Image {
id: settungsButt_Image
source: "qrc:/graphics/icons/settings.png"
anchors.centerIn: parent
height: parent.height * 0.7
width: parent.width * 0.7
mipmap: true
}
}
}
Rectangle {
RoundButton {
id: profilesButt
property string text: "cancel"
anchors {
verticalCenter: root.landscape() ? undefined:parent.verticalCenter
horizontalCenter: root.landscape() ? parent.horizontalCenter:undefined
@ -270,39 +332,45 @@ Window {
topMargin: root.landscape() ? (parent.height - (height * 2)) / 3:undefined
leftMargin: root.landscape() ? undefined:(parent.width - width * 2) / 3
}
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
width: height
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Image {
id: profilesButt_Image
source: "qrc:/graphics/icons/user.png"
anchors.centerIn: parent
height: parent.height * 0.5
width: parent.width * 0.5
mipmap: true
}
MouseArea {
enabled: root.state === "IDLE"
anchors.fill: parent
onPressed: parent.color = "lightgrey"
onReleased: parent.color = "white"
onClicked: {
onPressedChanged: {
if(pressed){
background.color = "lightgrey"
}
else {
background.color = "white"
}
}
Behavior on scale {
PropertyAnimation {
duration: 200
onClicked: {
var theUrl = "http://192.168.4.1";
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false );
xmlHttp.send( null );
console.log(xmlHttp.responseText)
}
background: Rectangle {
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Image {
id: profilesButt_Image
source: "qrc:/graphics/icons/user.png"
anchors.centerIn: parent
height: parent.height * 0.5
width: parent.width * 0.5
mipmap: true
}
}
}
}

View file

@ -2,5 +2,6 @@
<qresource prefix="/">
<file>main.qml</file>
<file>FadeAnimation.qml</file>
<file>SettingsDialog.qml</file>
</qresource>
</RCC>

View file

@ -21,7 +21,8 @@ TARGET = speedclimbing_stw
SOURCES += \
main.cpp \
sqlstoragemodel.cpp \
sqlprofilemodel.cpp
sqlprofilemodel.cpp \
buzzerconn.cpp
RESOURCES += qml.qrc \
shared.qrc
@ -50,4 +51,5 @@ android {
HEADERS += \
sqlstoragemodel.h \
sqlprofilemodel.h
sqlprofilemodel.h \
buzzerconn.h

View file

@ -6,6 +6,7 @@
class SqlStorageModel : public QObject
{
Q_OBJECT
public:
explicit SqlStorageModel(QObject *parent = nullptr);