too many changes to document.

Summary:
- cleaned some stuff up in qml
- separated the timer and the main.qml and put it into "SpeedTimer.qml"
- continued on implementing the base conn connection
- started to get the whole time meassuring procedure out of qml and into c++
  -> added new class (SpeedTimer) for that
This commit is contained in:
Dorian Zedler 2018-10-04 18:35:29 +02:00
parent 0235cfe8f5
commit 1e09ebe027
15 changed files with 827 additions and 328 deletions

View file

@ -7,6 +7,10 @@
#include <QDateTime>
#include <QTimer>
#include <QEventLoop>
#include <QSemaphore>
#include "headers/appsettings.h"
#include "headers/speedtimer.h"
class BaseConn : public QObject
{
@ -15,6 +19,7 @@ class BaseConn : public QObject
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(QStringList connections READ getConnections NOTIFY connectionsChanged)
public:
explicit BaseConn(QObject *parent = nullptr);
@ -32,7 +37,13 @@ public:
// - 'connecting'
// - 'connected'
QStringList connections;
QString latestReadReply;
//---general status values---//
private:
QDateTime *date;
//to get the current time
@ -40,7 +51,7 @@ private:
QTcpSocket *socket;
//socket for communication with the extention
QList<SpeedTimer*> speedTimers;
signals:
void stateChanged();
@ -51,6 +62,8 @@ signals:
void gotReply();
void connectionsChanged();
public slots:
Q_INVOKABLE bool connectToHost();
@ -58,6 +71,16 @@ public slots:
Q_INVOKABLE QString sendCommand(QString command);
Q_INVOKABLE bool refreshConnections();
void refreshTimers();
bool startTimers();
bool stopTimers();
bool resetTimers();
// functions for the qml adapter
QString getIP() const;
void setIP(const QString &ipAdress);
@ -67,8 +90,14 @@ public slots:
int getProgress() const;
QStringList getConnections();
private slots:
void readyRead();
private:
QTimer *refreshTimer;
QSemaphore remoteSessions;
};
#endif // BASECONN_H

View file

@ -11,6 +11,8 @@
#include <QDateTime>
#include <QtDebug>
#include "appsettings.h"
//typedef struct strReturnData{
// int status_code;
// QString text;
@ -123,7 +125,6 @@ public slots:
double getOffset() const;
double getLastTriggered() const;
};
#endif // BUZZERCONN_H

47
headers/speedtimer.h Normal file
View file

@ -0,0 +1,47 @@
#ifndef SPEEDTIMER_H
#define SPEEDTIMER_H
#include <QObject>
#include <QDateTime>
#include <QEventLoop>
#include <QTimer>
#include <QDebug>
class SpeedTimer : public QObject
{
Q_OBJECT
public:
explicit SpeedTimer(QObject *parent = nullptr);
enum timerState { IDLE, STARTING, RUNNING, STOPPED };
timerState state;
// variables for capturing the time
double startTime;
double stopTime;
double stoppedTime;
double reactionTime;
signals:
void stateChanged(timerState newState);
void startCanceled(bool falseStart);
public slots:
void start();
void stop(QString type);
void reset();
void setState(timerState newState);
QString getState();
double getCurrTime();
void handleStartpadTrigger();
void handleToppadTrigger();
void delay(int mSecs);
private:
QDateTime *date;
};
extern SpeedTimer * pGlobalSpeedTimer;
#endif // SPEEDTIMER_H

View file

@ -165,59 +165,19 @@ Popup {
id: settings_col
/*----Connect to external devices----*/
ItemDelegate {
NextPageDelegate {
id: connect_del
text: qsTr("connections")
contentItem: Text {
text: parent.text
color: StyleSettings.textColor
font.pixelSize: options_stack.text_pixelSize
}
width: parent.width
Image {
id: connect_del_image
source: StyleSettings.backIcon
rotation: 180
height: options_stack.text_pixelSize
width: height
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 10
}
}
text: qsTr("extentions")
onClicked: {
options_stack.push(connect)
}
}
/*----Automated Start----*/
ItemDelegate {
NextPageDelegate {
id: autostart_del
text: qsTr("start sequence")
width: parent.width
contentItem: Text {
text: parent.text
color: StyleSettings.textColor
font.pixelSize: options_stack.text_pixelSize
}
Image {
id: autostart_del_image
source: StyleSettings.backIcon
rotation: 180
height: options_stack.text_pixelSize
width: height
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 10
}
}
onClicked: {
options_stack.push(autostart)
}
@ -235,18 +195,6 @@ Popup {
font.pixelSize: options_stack.text_pixelSize
}
Image {
id: style_image
source: StyleSettings.backIcon
rotation: 180
height: options_stack.text_pixelSize
width: height
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 10
}
}
onClicked: {
StyleSettings.setTheme()
}
@ -259,33 +207,13 @@ Popup {
id: connect
Column {
id: connect_col
property string title: qsTr("connections")
property string title: qsTr("extentions")
property int delegateHeight: height*0.18
ItemDelegate {
NextPageDelegate {
id: baseConn_del
text: qsTr("Base Station")
contentItem: Text {
text: parent.text
color: StyleSettings.textColor
font.pixelSize: options_stack.text_pixelSize
}
width: parent.width
Image {
id: connect_del_image
source: StyleSettings.backIcon
rotation: 180
height: options_stack.text_pixelSize
width: height
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 10
}
}
onClicked: {
options_stack.push(baseStation)
}
@ -294,12 +222,6 @@ Popup {
ConnectionDelegate {
id: connect_buzz_del
contentItem: Text {
text: parent.text
color: StyleSettings.textColor
font.pixelSize: options_stack.text_pixelSize
}
status: root.connections.buzzer
connect: root.connect
type: "buzzer"
@ -311,12 +233,6 @@ Popup {
ConnectionDelegate {
id: connect_stap_del
contentItem: Text {
text: parent.text
color: StyleSettings.textColor
font.pixelSize: options_stack.text_pixelSize
}
status: root.connections.startpad
connect: root.connect
type: "startpad"
@ -335,6 +251,29 @@ Popup {
property string title: "Autostart"
property int delegateHeight: height*0.18
function updateSett(key, val, del){
del.enabled = false
_cppAppSettings.writeSetting(key, val)
if(baseConn.state === "connected"){
switch(key){
case "ready_en":
key = "READY_EN"
break
case "ready_delay":
key = "READY_DELAY"
break
case "at_marks_en":
key = "AT_MARKS_EN"
break
case "at_marks_delay":
key = "AT_MARKS_DELAY"
break
}
baseConn.sendCommand("SET_SETTING_"+key+"_"+val)
}
del.enabled = true
}
SwitchDelegate {
id: ready_del
text: qsTr("say 'ready'")
@ -351,7 +290,8 @@ Popup {
font.pixelSize: options_stack.text_pixelSize
onCheckedChanged: {
_cppAppSettings.writeSetting("ready_en",checked)
parent.updateSett("ready_en",checked, ready_del)
}
indicator: SimpleIndicator{}
@ -383,7 +323,7 @@ Popup {
text: _cppAppSettings.loadSetting("ready_delay")
onTextChanged: {
_cppAppSettings.writeSetting("ready_delay", text)
autostart_col.updateSett("ready_delay", text, ready_delay_del)
}
}
}
@ -404,7 +344,7 @@ Popup {
font.pixelSize: options_stack.text_pixelSize
onCheckedChanged: {
_cppAppSettings.writeSetting("at_marks_en",at_marks_del.checked)
parent.updateSett("at_marks_en",at_marks_del.checked, at_marks_del)
}
indicator: SimpleIndicator{}
@ -437,7 +377,7 @@ Popup {
text: _cppAppSettings.loadSetting("at_marks_delay")
onTextChanged: {
_cppAppSettings.writeSetting("at_marks_delay",text)
autostart_col.updateSett("at_marks_delay",text, at_marks_delay_del)
}
}
}
@ -455,11 +395,6 @@ Popup {
ConnectionDelegate {
id: connect_base_del
text: "connect"
contentItem: Text {
text: parent.text
color: StyleSettings.textColor
font.pixelSize: options_stack.text_pixelSize
}
status: root.connections.baseStation
connect: root.connect
@ -468,7 +403,50 @@ Popup {
width: parent.width
font.pixelSize: options_stack.text_pixelSize
}
NextPageDelegate {
id: baseStationConnections_del
text: qsTr("connected extentions")
onClicked: {
baseConn.refreshConnections()
options_stack.push(baseStationConnections)
}
}
}
}
/*-----Page to view devices that core connected to the pase startion-----*/
Component{
id: baseStationConnections
ListView {
function getModel(){
var keys = Object.keys(baseConn.connections);
var len = keys.length
return(len)
}
function getDetails(index){
var ret = baseConn.connections[index]
var details = ret.split("|")
return(details)
}
id: baseStationConnections_list
property string title: qsTr("connections")
property int delegateHeight: height*0.18
model: getModel()
delegate: ConnectionDelegate {
enabled: false
font.pixelSize: options_stack.text_pixelSize
width: parent.width
height: baseStationConnections_list.delegateHeight
text: baseStationConnections_list.getDetails(index)[2]
status: {'status': baseStationConnections_list.getDetails(index)[4], 'progress': 0}
}
}
}

183
qml/SpeedTimer.qml Normal file
View file

@ -0,0 +1,183 @@
import QtQuick 2.9
import QtMultimedia 5.8
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import "."
import "./components"
import "./styles"
Item {
id: control
property color color
property string text: qsTr("Click start to start")
property string elide
property int pixelSize: 100
property int scale: 1
property var toppadConn
property var startpadConn
property var baseConn
property double startTime: 0
property double stopTime: 0
property double stoppedTime: 0
property double reactionTime: 0
property double currTime: 0
signal stopped()
signal startCanceled(bool falseStart)
anchors.fill: parent
state: "IDLE"
Label {
id: time
text: parent.text
scale: parent.scale
anchors.centerIn: parent
font.pixelSize: parent.pixelSize
elide: parent.elide
color: StyleSettings.textColor
Behavior on text {
enabled: control.state !== "RUNNING"
FadeAnimation {
target: time
}
}
}
function setStarting(){
control.state = "STARTING"
}
function start(inMilliSeconds){
control.state = "STARTING"
control.startTime = new Date().getTime() + inMilliSeconds //set the startime to be 0 after the starttone
startTimer.interval = inMilliSeconds
startTimer.start()
}
function stop(type){
//_cppStartpadConn.appendCommand("SET_LED_STARTING");
switch(type){
case "toppad":
//the buzzer was pushed
control.stopTime = control.toppadConn.lastTriggered + control.toppadConn.offset
control.stoppedTime = control.stopTime - control.startTime
control.stopped()
//time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
//console.log("STOPPED: "+control.stoppedTime + " started at: " + control.startTime + " offset: "+ control.buzzer_offset + "lastpressed: " + control.last_button_pressed)
break
case "manual":
//the stop button was pressed
if(baseConn.state === "connected"){
control.stoppedTime = baseConn.getTime("raw")
time.text = (control.stoppedTime / 1000).toFixed(3) + " sec"
return
}
control.stopTime = new Date().getTime()
control.stoppedTime = control.stopTime - control.startTime
control.stopped()
break
case "false":
//there was a false start
control.stoppedTime = -1
startTimer.stop()
control.state = "STOPPED"
control.startCanceled(true)
break
case "cancel":
//the cancel button was pressed
control.stoppedTime = 0
startTimer.stop()
control.state = "STOPPED"
control.startCanceled(false)
break
}
control.state = "STOPPED"
}
function reset(){
control.startTime = 0
control.stopTime = 0
control.stoppedTime = 0
if(baseConn.state === "connected"){
var ret = baseConn.sendCommand("CMD_RESET_TIMER")
if(ret !== "OK"){
control.state = "IDLE"
return
}
}
control.state = "IDLE"
}
function handleStartpad(){
console.log("startpad triggered")
var offset = control.startpadConn.offset
var last_pressed = control.startpadConn.lastTriggered
var trigger_time = (last_pressed + offset)
control.reactionTime = trigger_time - control.startTime
if(trigger_time - control.startTime <= 0){
stop("false")
}
}
function handleToppad(){
console.log(lastTriggered)
stop("toppad")
}
Timer {
id: startTimer
running: false
repeat: false
onTriggered: {
console.log("started")
control.state = "RUNNING"
}
}
Timer {
//timer that updates the currTime variable
running: true
repeat: true
interval: 1
onTriggered: {
control.currTime = new Date().getTime()
}
}
states: [
State {
name: "IDLE"
//state for the start page
PropertyChanges { target: time; text: qsTr("Click start to start");}
},
State {
name: "STARTING"
//state for the start sequence
PropertyChanges { target: time; text: control.text;}
},
State {
name: "RUNNING"
//state when the timer is running
PropertyChanges { target: time; text: Math.abs( ( ( control.currTime - control.startTime ) / 1000 ) ).toFixed(3) + " sec";}
},
State {
name: "STOPPED"
//state when the meassuring is over
PropertyChanges {
target: time;
text: control.stoppedTime >= 0 ? ( control.stoppedTime / 1000 ).toFixed(3) + " sec":qsTr("false start");
}
}
]
}

View file

@ -1,5 +1,6 @@
import QtQuick 2.0
import QtQuick.Controls 2.2
import "../styles"
ItemDelegate {
id: control
@ -18,6 +19,12 @@ ItemDelegate {
}
}
contentItem: Text {
text: parent.text
color: StyleSettings.textColor
font.pixelSize: options_stack.text_pixelSize
}
Timer {
id: shortDelay
running: false

View file

@ -0,0 +1,31 @@
import QtQuick 2.0
import QtQuick.Controls 2.2
import "../styles"
ItemDelegate {
id: control
text: ""
font.pixelSize: options_stack.text_pixelSize
property color textColor: StyleSettings.textColor
contentItem: Text {
text: parent.text
color: control.textColor
font.pixelSize: parent.font.pixelSize
}
width: parent.width
Image {
id: forwardImage
source: StyleSettings.backIcon
rotation: 180
height: control.font.pixelSize
width: height
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 10
}
}
}

View file

@ -69,117 +69,141 @@ 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")
}
}
Item {
id: connections
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")
BuzzerConn {
id: buzzerConn
ipAdress: "192.168.4.10"
property var status: {'status': buzzerConn.state, 'progress': buzzerConn.progress}
onLastTriggeredChanged: {
timer_1.handleToppad()
}
}
}
Timer {
id: startpadRefreshTimer
running: startpadConn.state === "connected"
interval: root.state === "RUNNING" || root.state === "STARTING" ? 1:1000
repeat: false
onTriggered: {
startpadConn.refresh()
this.start()
}
}
BaseStationConn {
id: baseConn
ipAdress: "localhost"
property var status: {'status': baseConn.state, 'progress': baseConn.progress}
function getTime(type){
var time = parseInt(sendCommand("GET_CURRTIME"))
if(type === "readable"){
return(time / 1000).toFixed(3)
}
else if(type === "raw"){
return(time)
Timer {
id: buzzerRefreshTimer
running: buzzerConn.state === "connected"
interval: root.state === "RUNNING" ? 1:1000
repeat: false
onTriggered: {
buzzerConn.refresh()
this.start()
}
}
}
Timer {
id: baseRefreshTimer
running: baseConn.state === "connected"
repeat: false
interval: 1
onTriggered: {
if(root.state === "RUNNING"){
var baseReactTime = parseInt(baseConn.sendCommand("GET_REACTTIME"))
if(baseReactTime !== 0){
root.last_run.react_time = baseReactTime
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: {
timer_1.handleStartpad()
}
}
Timer {
id: startpadRefreshTimer
running: startpadConn.state === "connected"
interval: root.state === "RUNNING" || root.state === "STARTING" ? 1:1000
repeat: false
onTriggered: {
startpadConn.refresh()
this.start()
}
}
BaseStationConn {
id: baseConn
ipAdress: "localhost"//"raspberrypi.local"
property var status: {'status': baseConn.state, 'progress': baseConn.progress, 'connections': baseConn.connections}
function getTime(type){
var time = parseInt(sendCommand("GET_CURRTIME"))
if(type === "readable"){
return(time / 1000).toFixed(3)
}
time.text = baseConn.getTime("readable") + " sec"
if(baseConn.sendCommand("GET_TIMER_STATE") === "STOPPED"){
root.stop("manual")
else if(type === "raw"){
return(time)
}
}
if(root.state === "STARTING"){
var baseReactTime = parseInt(baseConn.sendCommand("GET_REACTTIME"))
if(baseReactTime !== 0){
root.last_run.react_time = baseReactTime
}
var baseState = baseConn.sendCommand("GET_TIMER_STATE")
if(baseState === "RUNNING"){
root.state = "RUNNING";
}
else if(baseState === "STOPPED"){
root.state = "STOPPED"
}
}
start()
}
Timer {
id: baseRefreshTimer
running: baseConn.state === "connected"
repeat: false
interval: 1
onTriggered: {
switch(root.state){
case "RUNNING":
var baseReactTime = parseInt(baseConn.sendCommand("GET_REACTTIME"))
console.log(baseReactTime)
if(baseReactTime !== 0){
root.last_run.react_time = baseReactTime
}
timer_1.text = baseConn.getTime("readable") + " sec"
if(baseConn.sendCommand("GET_TIMER_STATE") === "STOPPED"){
root.stop("manual")
}
break
case "STARTING":
var baseReactTime = parseInt(baseConn.sendCommand("GET_REACTTIME"))
if(baseReactTime !== 0){
root.last_run.react_time = baseReactTime
}
var baseNextAction = baseConn.sendCommand("GET_NEXT_ACTION")
if(baseNextAction === "at_marks"){
timer_1.text = qsTr("at your\nmarks")
var baseNextActionDelay = parseFloat(baseConn.sendCommand("GET_NEXT_ACTION_DELAY_PROG"))
prog.progress = baseNextActionDelay * 100
}
else if(baseNextAction === "ready"){
timer_1.text = qsTr("ready")
var baseNextActionDelay = parseFloat(baseConn.sendCommand("GET_NEXT_ACTION_DELAY_PROG"))
prog.progress = baseNextActionDelay * 100
}
else if(baseNextAction === "start"){
timer_1.text = "0.000 sec"
}
var baseState = baseConn.sendCommand("GET_TIMER_STATE")
console.log(baseState)
if(baseState === "RUNNING"){
timer_1.start(1)
root.state = "RUNNING";
}
else if(baseState === "STOPPED"){
var baseReactTime = parseInt(baseConn.sendCommand("GET_REACTTIME"))
if(baseReactTime<0){
root.stop("false")
}
else{
root.stop("cancel")
}
root.state = "STOPPED"
}
break
}
start()
}
}
}
Timer {
//timer that updates the currTime variable
running: true
repeat: true
interval: 1
onTriggered: {
root.currTime = new Date().getTime()
}
}
Timer {
id: next_actionTimer
@ -193,18 +217,18 @@ Window {
if(!running){
started_at = 0
if(action == "NONE"){
time.text = "0.000 sec"
timer_1.text = "0.000 sec"
}
return
}
if(action === "at_marks"){
started_at = new Date().getTime()
time.text = "at your\nmarks"
timer_1.text = "at your\nmarks"
}
else if(action === "ready"){
started_at = new Date().getTime()
time.text = "ready"
timer_1.text = "ready"
}
}
onTriggered: {
@ -219,62 +243,61 @@ Window {
}
}
SoundEffect {
id: at_marksSound
source: "qrc:/sounds/at_marks_1.wav"
Item {
id: sounds
SoundEffect {
id: at_marksSound
source: "qrc:/sounds/at_marks_1.wav"
onPlayingChanged: {
if(!playing && root.state==="STARTING"){
if(_cppAppSettings.loadSetting("ready_en") === "true"){
next_actionTimer.action = "ready"
next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")>0 ? _cppAppSettings.loadSetting("ready_delay"):1
next_actionTimer.start()
onPlayingChanged: {
if(!playing && root.state==="STARTING"){
if(_cppAppSettings.loadSetting("ready_en") === "true"){
next_actionTimer.action = "ready"
next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")>0 ? _cppAppSettings.loadSetting("ready_delay"):1
next_actionTimer.start()
}
else{
startSound.play()
}
}
else{
}
}
SoundEffect {
id: readySound
source: "qrc:/sounds/ready_1.wav"
onPlayingChanged: {
if(!playing && root.state==="STARTING"){
startSound.play()
}
}
}
}
SoundEffect {
id: readySound
source: "qrc:/sounds/ready_1.wav"
onPlayingChanged: {
if(!playing && root.state==="STARTING"){
SoundEffect {
//start sound
id: startSound
source: "qrc:/sounds/OFFICAL_IFSC_STARTIGNAL.wav"
startSound.play()
onPlayingChanged: {
if(!playing && root.state==="STARTING"){
root.state = "RUNNING"
}
else if(playing) {
console.log("start sound started")
timer_1.start(3100)
}
}
}
}
SoundEffect {
//start sound
id: startSound
source: "qrc:/sounds/OFFICAL_IFSC_STARTIGNAL.wav"
onPlayingChanged: {
if(!playing && root.state==="STARTING"){
console.log(root.startTime)
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 = new Date().getTime() + 3100 //set the startime to be 0 after the starttone
}
}
SoundEffect {
//false-start sound
id: falseSound
source: "qrc:/sounds/false.wav"
}
}
SoundEffect {
//false-start sound
id: falseSound
source: "qrc:/sounds/false.wav"
}
/*------------------------
Timer text an upper line
------------------------*/
@ -294,19 +317,29 @@ Window {
color: StyleSettings.menuColor
}
//height: root.landscape() ? undefined:parent.height * 0.15
Label {
id: time
text: qsTr("Click start to start")
SpeedTimer {
id: timer_1
anchors.centerIn: parent
//font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3
elide: "ElideRight"
color: StyleSettings.textColor
Behavior on text {
enabled: root.state !== "RUNNING"
FadeAnimation {
target: time
toppadConn: buzzerConn
baseConn: baseConn
startpadConn: startpadConn
text: "0.000 sec"
onStopped: {
root.state = "STOPPED"
}
onStartCanceled: {
root.state = "STOPPED"
next_actionTimer.stop()
at_marksSound.stop()
readySound.stop()
startSound.stop()
if(falseStart && baseConn.state !== "connected"){
falseSound.play()
}
}
}
@ -319,7 +352,7 @@ Window {
color: StyleSettings.textColor
anchors {
horizontalCenter: parent.horizontalCenter
top: time.bottom
top: timer_1.bottom
topMargin: parent.height * 0.1
}
Timer {
@ -431,19 +464,21 @@ Window {
ProgressCircle {
id: prog
anchors.fill: startButt
opacity: next_actionTimer.started_at > 0 ? 1:0
opacity: baseConn.state !== "connected" ?
next_actionTimer.started_at > 0 ? 1:0
:progress > 0 ? 1:0
lineWidth: 5
property int progress: 0
arcBegin: 0
arcEnd: 360 * (( next_actionTimer.interval - ( new Date().getTime() - next_actionTimer.started_at ) ) / next_actionTimer.interval)
arcEnd: baseConn.state !== "connected" ? 360 * (( next_actionTimer.interval - ( new Date().getTime() - next_actionTimer.started_at ) ) / next_actionTimer.interval)
:(360/100) * progress
colorCircle: "grey"
animationDuration: 0
animationDuration: baseConn.state === "connected" ? 150:0
Timer {
id: prog_refresh
running: parent.opacity === 1
running: parent.opacity === 1 && baseConn.state !== "connected"
interval: 1
repeat: true
onTriggered: {
@ -473,7 +508,7 @@ Window {
enabled: root.state === "STARTING"
onClicked: {
root.stop("false")
root.stop("cancel")
}
Behavior on scale {
@ -511,9 +546,9 @@ Window {
case "startpad":
startpadConn.connect()
break
case "baseStation":
baseConn.connectToHost()
break
case "baseStation":
baseConn.connectToHost()
break
}
}
}
@ -648,7 +683,7 @@ Window {
State {
name: "IDLE"
//state for the start page
PropertyChanges { target: time; text: qsTr("Click start to start"); font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3; scale: 1 }
PropertyChanges { target: timer_1; pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3; scale: 1 }
PropertyChanges {
target: time_container;
anchors.bottomMargin: root.landscape() ? undefined:parent.height * 0.1;
@ -670,14 +705,14 @@ Window {
anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
}
PropertyChanges { target: time; text: "0.000 sec"; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
PropertyChanges { target: timer_1; pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
PropertyChanges { target: cancelButt; scale: 1}
PropertyChanges { target: menu_container; }
},
State {
name: "RUNNING"
//state when the timer is running
PropertyChanges { target: time; text: Math.abs( ( ( root.currTime - root.startTime ) / 1000 ) ).toFixed(3) + " sec"; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
PropertyChanges { target: timer_1; pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
PropertyChanges { target: startButt; enabled: true;
text: "stop"
anchors.rightMargin: root.landscape() ? parent.width * 0.05:parent.width * 0.5 - startButt.width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
@ -690,9 +725,8 @@ Window {
name: "STOPPED"
//state when the meassuring is over
PropertyChanges {
target: time;
text: root.stoppedTime > 0 ? ( root.stoppedTime / 1000 ).toFixed(3) + " sec":qsTr("false start");
font.pixelSize: root.landscape() ? parent.width * 0.15:parent.height * 0.1;
target: timer_1;
pixelSize: root.landscape() ? parent.width * 0.15:parent.height * 0.1;
scale: 1
}
PropertyChanges {
@ -715,15 +749,15 @@ Window {
----------------------*/
transitions: [
Transition {
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize,pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
},
Transition {
to: "STOPPED"
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize,pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
},
Transition {
to: "IDLE"
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize,pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
},
Transition {
@ -745,12 +779,14 @@ Window {
var ret = baseConn.sendCommand("CMD_START_TIMER")
if(ret === "OK"){
root.state = "STARTING"
timer_1.setStarting()
return
}
}
root.state = "STARTING"
timer_1.setStarting()
if(_cppAppSettings.loadSetting("at_marks_en") === "true"){
next_actionTimer.action = "at_marks"
next_actionTimer.interval = _cppAppSettings.loadSetting("at_marks_delay")>0 ? _cppAppSettings.loadSetting("at_marks_delay"):1
@ -768,58 +804,22 @@ Window {
}
function stop(type){
//_cppStartpadConn.appendCommand("SET_LED_STARTING");
switch(type){
case "buzzer":
//the buzzer was pushed
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 + " started at: " + root.startTime + " offset: "+ root.buzzer_offset + "lastpressed: " + root.last_button_pressed)
break
case "manual":
//the stop button was pressed
if(type === "manual" || type === "cancel"){
if(baseConn.state === "connected"){
root.stoppedTime = baseConn.getTime("raw")
time.text = (root.stoppedTime / 1000).toFixed(3) + " sec"
baseConn.sendCommand("CMD_STOP_TIMER")
root.state = "STOPPED"
return
}
root.stoppedTime = new Date().getTime() - root.startTime
time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
root.state = "STOPPED"
break
case "false":
//the cancel button was pressed
root.last_run.reaction_time = parseInt(baseConn.sendCommand("GET_REACTTIME"))
root.stoppedTime = 0
time.text = "false start"
root.state = "STOPPED"
next_actionTimer.stop()
at_marksSound.stop()
readySound.stop()
startSound.stop()
falseSound.play()
break
}
root.state = "STOPPED"
timer_1.stop(type)
}
function reset(){
if(baseConn.state === "connected"){
var ret = baseConn.sendCommand("CMD_RESET_TIMER")
if(ret !== "OK"){
return
}
baseConn.sendCommand("CMD_RESET_TIMER")
}
timer_1.reset()
root.state = "IDLE"
root.last_run.react_time = 0
}
}
}

View file

@ -13,5 +13,7 @@
<file>styles/Light.js</file>
<file>styles/Default.js</file>
<file>components/ConnectionIcon.qml</file>
<file>SpeedTimer.qml</file>
<file>components/NextPageDelegate.qml</file>
</qresource>
</RCC>

View file

@ -110,12 +110,15 @@ Item {
function refreshTheme(){
switch(_cppAppSettings.loadSetting("theme")){
case "Dark":
case "Default":
theme = Dark
break
case "Light":
case "Dark":
theme = Light
break
case "Light":
theme = Default
break
}
}
@ -135,13 +138,17 @@ Item {
function setTheme()
{
switch(_cppAppSettings.loadSetting("theme")){
case "Default":
_cppAppSettings.writeSetting("theme", "Dark")
theme = Dark
break
case "Dark":
_cppAppSettings.writeSetting("theme", "Light")
theme = Light
break
case "Light":
_cppAppSettings.writeSetting("theme", "Dark")
theme = Dark
_cppAppSettings.writeSetting("theme", "Default")
theme = Default
break
}
}

View file

@ -17,6 +17,8 @@
#include "headers/appsettings.h"
AppSettings * pGlobalAppSettings = nullptr;
AppSettings::AppSettings(QObject* parent)
:QObject(parent)
{

View file

@ -4,10 +4,18 @@ BaseConn::BaseConn(QObject *parent) : QObject(parent)
{
socket = new QTcpSocket();
this->setState("disconnected");
remoteSessions.release(2);
this->speedTimers.append(pGlobalSpeedTimer);
this->refreshTimer = new QTimer();
refreshTimer->setInterval(1);
refreshTimer->setSingleShot(true);
refreshTimer->connect(this->refreshTimer, &QTimer::timeout, this, &BaseConn::refreshTimers);
}
bool BaseConn::connectToHost() {
qDebug() << "connecting";
setState("connecting");
this->connection_progress = 0;
QEventLoop loop;
@ -26,7 +34,7 @@ bool BaseConn::connectToHost() {
//wait for the connection to finish (programm gets stuck in here)
loop.exec();
//loop finished
//loop finish
if(timer.remainingTime() == -1){
//the time has been triggered -> timeout
@ -44,6 +52,10 @@ bool BaseConn::connectToHost() {
}
QString BaseConn::sendCommand(QString command){
if(this->state != "connected"){
return "ERR_NOT_CONNECTED";
}
remoteSessions.acquire(1);
QByteArray arrBlock;
QDataStream out(&arrBlock, QIODevice::WriteOnly);
//out.setVersion(QDataStream::Qt_5_10);
@ -79,12 +91,11 @@ QString BaseConn::sendCommand(QString command){
// stop the timer as the connection has been established
timer.stop();
remoteSessions.release(1);
return(this->latestReadReply);
}
void BaseConn::readyRead() {
qDebug() << "readyRead";
QDataStream in(socket);
//in.setVersion(QDataStream::Qt_5_10);
qint16 nextBlockSize = 0;
@ -112,6 +123,69 @@ void BaseConn::readyRead() {
}
}
/*-----Functions to control the local stopwatch-----*/
void BaseConn::refreshTimers(){
if(this->state != "connected"){
return;
}
QString remoteState;
switch (speedTimers[0]->state) {
case SpeedTimer::IDLE:
break;
case SpeedTimer::STARTING:
remoteState = sendCommand("GET_TIMER_STATE");
if(remoteState == "RUNNING"){
speedTimers[0]->start();
}
else if (remoteState == "STOPPED") {
speedTimers[0]->stop("manual");
}
break;
case SpeedTimer::RUNNING:
remoteState = sendCommand("GET_TIMER_STATE");
if(remoteState == "STOPPED"){
speedTimers[0]->stop("manual");
}
break;
case SpeedTimer::STOPPED:
break;
}
this->refreshTimer->start();
}
bool BaseConn::startTimers(){
qDebug() << "starting timers";
QString ret = this->sendCommand("CMD_START_TIMER");
if(ret.startsWith("ERR")){
//handle Error!!
return false;
}
this->speedTimers[0]->setState(SpeedTimer::STARTING);
return true;
}
bool BaseConn::stopTimers(){
qDebug() << "stopping timers";
QString ret = this->sendCommand("CMD_STOP_TIMER");
if(ret.startsWith("ERR")){
//handle Error!
return false;
}
this->speedTimers[0]->stop("manual");
return true;
}
void BaseConn::setIP(const QString &ipAdress){
this->ip = ipAdress;
}
@ -136,3 +210,17 @@ int BaseConn::getProgress() const
return(connection_progress);
}
bool BaseConn::refreshConnections() {
QString ret = this->sendCommand("GET_CONNECTIONS");
if(ret.startsWith("ERR")){
return false;
}
connections = ret.split("|||");
return true;
}
QStringList BaseConn::getConnections() {
return(connections);
}

View file

@ -23,7 +23,7 @@
#include <QFile>
#include <QDir>
#include <QStandardPaths>
#include <QtWebView/QtWebView>
//#include <QtWebView/QtWebView>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
@ -44,7 +44,7 @@
#include <QScreen>
#include <QQmlApplicationEngine>
#include <QtQml/QQmlContext>
#include <QtWebView/QtWebView>
//#include <QtWebView/QtWebView>
#ifdef Q_OS_ANDROID
#include <QtAndroidExtras>
#endif
@ -53,6 +53,7 @@
#include "headers/buzzerconn.h"
#include "headers/appsettings.h"
#include "headers/baseconn.h"
#include "headers/speedtimer.h"
#include <QTranslator>
static void connectToDatabase()
@ -109,6 +110,10 @@ int main(int argc, char *argv[])
//BuzzerConn * pBuzzerConn = new BuzzerConn(nullptr, "192.168.4.10", 80);
//BuzzerConn * pStartpadConn = new BuzzerConn(nullptr, "192.168.4.11", 80);
AppSettings * pAppSettings = new AppSettings();
pGlobalAppSettings = pAppSettings;
SpeedTimer * pSpeedTimer = new SpeedTimer();
pGlobalSpeedTimer = pSpeedTimer;
//setup the sql storage model as a qml model
qmlRegisterType<SqlProfileModel>("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlProfileModel");
@ -132,6 +137,7 @@ int main(int argc, char *argv[])
return -1;
engine.rootContext()->setContextProperty("_cppAppSettings", pAppSettings);
engine.rootContext()->setContextProperty("_cppSpeedTimer", pSpeedTimer);
int iRet = 0;
iRet = app.exec();

115
sources/speedtimer.cpp Normal file
View file

@ -0,0 +1,115 @@
#include "headers/speedtimer.h"
SpeedTimer * pGlobalSpeedTimer = nullptr;
SpeedTimer::SpeedTimer(QObject *parent) : QObject(parent)
{
this->date = new QDateTime;
this->startTime = 0;
this->stopTime = 0;
this->stoppedTime = 0;
this->reactionTime = 0;
this->state = IDLE;
}
void SpeedTimer::start() {
if(this->state != STARTING){
return;
}
this->stopTime = 0;
this->stoppedTime = 0;
this->reactionTime = 0;
this->startTime = this->date->currentMSecsSinceEpoch();
this->setState(RUNNING);
//this->startPad->appendCommand("SET_LED_RUNNING");
}
void SpeedTimer::stop(QString type) {
if(this->state != SpeedTimer::STARTING && this->state != SpeedTimer::RUNNING){
return;
}
qDebug() << "Stopping: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << stoppedTime << " reactionTime: " << reactionTime;
if(type == "manual"){
if(this->state == STARTING){
emit startCanceled(false);
}
this->stopTime = this->date->currentMSecsSinceEpoch();
this->stoppedTime = this->stopTime - this->startTime;
}
else if(type == "topPad"){
//this->stopTime = this->topPad->latest_button_pressed + this->topPad->offset;
this->stoppedTime = this->stopTime - this->startTime;
}
else if(type == "falseStart"){
emit startCanceled(true);
this->stoppedTime = this->reactionTime;
}
this->setState(STOPPED);
qDebug() << "Stopped: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << stoppedTime << " reactionTime: " << reactionTime;
//this->startPad->appendCommand("SET_LED_STARTING");
}
void SpeedTimer::reset(){
if(this->state != STOPPED){
return;
}
this->startTime = 0;
this->stopTime = 0;
this->stoppedTime = 0;
this->reactionTime = 0;
this->setState(IDLE);
//this->startPad->appendCommand("SET_LED_STARTING");
}
void SpeedTimer::setState(timerState newState){
this->state = newState;
qDebug() << "tmer state changed: " << newState;
emit this->stateChanged(newState);
}
QString SpeedTimer::getState(){
switch(state){
case IDLE:
return("IDLE");
case STARTING:
return("STARTING");
case RUNNING:
return("RUNNING");
case STOPPED:
return("STOPPED");
}
}
double SpeedTimer::getCurrTime() {
double currTime;
if(this->state == RUNNING){
currTime = this->date->currentMSecsSinceEpoch() - this->startTime;
}
else {
currTime = this->stoppedTime;
}
return(currTime);
}
void SpeedTimer::delay(int mSecs){
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
// quit the loop when the timer times out
loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
//quit the loop when the connection was established
// start the timer before starting to connect
timer.start(mSecs);
//connect
//wait for the connection to finish (programm gets stuck in here)
loop.exec();
}

View file

@ -25,14 +25,16 @@ SOURCES += \
sources/sqlprofilemodel.cpp \
sources/buzzerconn.cpp \
sources/appsettings.cpp \
sources/baseconn.cpp
sources/baseconn.cpp \
sources/speedtimer.cpp
HEADERS += \
headers/sqlstoragemodel.h \
headers/sqlprofilemodel.h \
headers/buzzerconn.h \
headers/appsettings.h \
headers/baseconn.h
headers/baseconn.h \
headers/speedtimer.h
RESOURCES += \
shared.qrc \
@ -51,7 +53,8 @@ QTPLUGIN += qtaudio_coreaudio
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
#else: unix:!android: target.path = /opt/$${TARGET}/bin
else: unix:!android: target.path = /home/pi/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
DISTFILES += \