fixed communication issues with the base station caused by data distributed over multiple packets once and for all (hopefully)

This commit is contained in:
Dorian Zedler 2019-05-21 18:40:45 +02:00
parent a0a3d8cfe6
commit 75b193e642
7 changed files with 175 additions and 41 deletions

View file

@ -96,8 +96,12 @@ public slots:
void gotError(QAbstractSocket::SocketError err); void gotError(QAbstractSocket::SocketError err);
// --- socket communication handling ---
Q_INVOKABLE QVariantMap sendCommand(int header, QJsonValue data = ""); Q_INVOKABLE QVariantMap sendCommand(int header, QJsonValue data = "");
// --- helper functions ---
Q_INVOKABLE int writeRemoteSetting(QString key, QString value); Q_INVOKABLE int writeRemoteSetting(QString key, QString value);
Q_INVOKABLE bool refreshConnections(); Q_INVOKABLE bool refreshConnections();
@ -116,6 +120,10 @@ public slots:
private slots: private slots:
void readyRead(); void readyRead();
void processSocketMessage(QString message);
void socketReplyRecieved(QString reply);
void socketStateChanged(QAbstractSocket::SocketState socketState); void socketStateChanged(QAbstractSocket::SocketState socketState);
}; };
extern BaseConn * pGlobalBaseConn; extern BaseConn * pGlobalBaseConn;

View file

@ -131,7 +131,7 @@ Popup {
loadData: function () { loadData: function () {
status = 905 status = 905
listData = {} //listData = {}
var retData = speedBackend.getAthletes() var retData = speedBackend.getAthletes()
if(retData === undefined){ if(retData === undefined){
@ -151,8 +151,7 @@ Popup {
text: profileList.listData[index]["fullName"] text: profileList.listData[index]["fullName"]
width: profileList.width - (swipeDelegate.x) width: profileList.width - (swipeDelegate.x)
height: profileList.height / 5
font.pixelSize: profiles_stack.text_pixelSize font.pixelSize: profiles_stack.text_pixelSize
@ -164,8 +163,35 @@ Popup {
profiles_stack.openResults(profileList.listData[index]["userName"]) profiles_stack.openResults(profileList.listData[index]["userName"])
} }
contentItem: Text {
visible: false
}
Text {
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: swipeDelegate.width * 0.05
right: parent.right
rightMargin: swipeDelegate.rightPadding
}
text: swipeDelegate.text
color: appTheme.style.textColor
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
fontSizeMode: Text.Fit
font.pixelSize: swipeDelegate.height * 0.4
minimumPixelSize: 1
}
background: Rectangle { background: Rectangle {
color: Qt.darker( pressed ? Qt.darker("white", 1.1):"white", swipeDelegate.active ? 1.1:0 ) color: pressed ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor
Behavior on color { Behavior on color {
@ -205,6 +231,7 @@ Popup {
radius: width * 0.2 radius: width * 0.2
border.color: control.down ? "#17a81a" : "#21be2b" border.color: control.down ? "#17a81a" : "#21be2b"
color: control.down ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor
Rectangle { Rectangle {
width: parent.width * 0.65 width: parent.width * 0.65
@ -273,7 +300,7 @@ Popup {
Label { Label {
id: deleteLabel id: deleteLabel
text: qsTr("Delete") text: qsTr("Delete")
color: "white" color: appTheme.style.textColor
verticalAlignment: Label.AlignVCenter verticalAlignment: Label.AlignVCenter
padding: 12 padding: 12
height: parent.height height: parent.height
@ -353,6 +380,7 @@ Popup {
signal opened() signal opened()
onOpened: { onOpened: {
loadData() loadData()
} }
@ -364,14 +392,18 @@ Popup {
status = listData.lenght !== false ? 200:0 status = listData.lenght !== false ? 200:0
} }
delegate: ItemDelegate { delegate: SmoothItemDelegate {
id: resultDel id: resultDel
width: parent.width width: parent.width
height: resultView.height / 4
font.pixelSize: profiles_stack.text_pixelSize backgroundRect.radius: 0
text: "result: " + (listData[index]["result"] / 1000).toFixed(3) + " sec \nreaction time: " + listData[index]["reactionTime"].toFixed(0) + " ms" function getDateText(){
var date = new Date(listData[index]["timestamp"]*1000).toLocaleString(Qt.locale(), "dddd, dd.MMM HH:mm")
return date
}
Rectangle { Rectangle {
color: "grey" color: "grey"
@ -384,18 +416,47 @@ Popup {
} }
} }
Column {
anchors.fill: parent
anchors.leftMargin: parent.width * 0.05
Label { Label {
anchors.top: parent.top id: dateLa
anchors.left: parent.left
font.pixelSize: 10 height: parent.height / parent.children.length
text: " " + getText() font.pixelSize: height * 0.8
fontSizeMode: Text.Fit
function getText(){ color: appTheme.style.textColor
var date = new Date(listData[index]["timestamp"]*1000).toLocaleDateString(Qt.locale("de_DE"))
return date text: resultDel.getDateText()
console.log(date) }
Label {
id: resultLa
height: parent.height / parent.children.length
font.pixelSize: height * 0.8
fontSizeMode: Text.Fit
color: appTheme.style.textColor
text: qsTr("result: ") + (listData[index]["result"] / 1000).toFixed(3) + " s"
}
Label {
id: reactionTimeLa
height: parent.height / parent.children.length
font.pixelSize: height * 0.8
fontSizeMode: Text.Fit
color: appTheme.style.textColor
text: qsTr("reaction time: ") + listData[index]["reactionTime"].toFixed(0) + " ms"
} }
} }
} }
@ -548,6 +609,8 @@ Popup {
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
color: appTheme.style.textColor
text: profiles_stack.currentItem.title text: profiles_stack.currentItem.title
} }
@ -611,6 +674,9 @@ Popup {
leftMargin: parent.width/2 - width/2 leftMargin: parent.width/2 - width/2
} }
opacity: profiles_stack.currentItem.secondButt === "add" ? 1:0 opacity: profiles_stack.currentItem.secondButt === "add" ? 1:0
color: appTheme.style.textColor
text: "+" text: "+"
font.pixelSize: parent.height font.pixelSize: parent.height
} }

View file

@ -192,7 +192,6 @@ Popup {
glowOpacity: Math.pow( root.opacity, 100 ) glowOpacity: Math.pow( root.opacity, 100 )
backgroundColor: appTheme.style.buttonColor
image: appTheme.style.backIcon image: appTheme.style.backIcon
onClicked: { onClicked: {

View file

@ -6,7 +6,7 @@ Button {
id: control id: control
property string image property string image
property color backgroundColor: "white" property color backgroundColor: appTheme.style.buttonColor
property real imageScale: 1 property real imageScale: 1
property double glowRadius: 0.001 property double glowRadius: 0.001
property double glowSpread: 0.2 property double glowSpread: 0.2
@ -16,7 +16,7 @@ Button {
scale: control.pressed ? 0.8:1 //scale: control.pressed ? 0.8:1
Behavior on scale { Behavior on scale {
PropertyAnimation { PropertyAnimation {
@ -24,12 +24,6 @@ Button {
} }
} }
Behavior on backgroundColor {
ColorAnimation {
duration: 200
}
}
background: Item { background: Item {
id: controlBackgroundContainer id: controlBackgroundContainer
@ -54,7 +48,13 @@ Button {
radius: height * 0.5 radius: height * 0.5
color: control.backgroundColor color: control.down ? Qt.darker(control.backgroundColor, 1.2) : control.backgroundColor
Behavior on color {
ColorAnimation {
duration: 200
}
}
Image { Image {
id: buttonIcon id: buttonIcon

View file

@ -1,4 +1,4 @@
import QtQuick 2.9 import QtQuick 2.10
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
Item { Item {
@ -7,6 +7,7 @@ Item {
property var loadData property var loadData
property var listData: ({}) property var listData: ({})
property Component delegate property Component delegate
property alias view: listView
property int status: -1 property int status: -1
@ -23,11 +24,12 @@ Item {
anchors.fill: parent anchors.fill: parent
boundsBehavior: Flickable.DragOverBounds
boundsMovement: Flickable.StopAtBounds
//enabled: status === 200 || status === 902 //enabled: status === 200 || status === 902
//opacity: enabled ? 1:0 //opacity: enabled ? 1:0
boundsBehavior: ListView.StopAtBounds
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
parent: listView.parent parent: listView.parent

View file

@ -4,8 +4,8 @@ import QtQuick.Controls 2.2
ItemDelegate { ItemDelegate {
id: control id: control
text: "" text: ""
font.pixelSize: options_stack.text_pixelSize
property color textColor: appTheme.style.textColor property color textColor: appTheme.style.textColor
property alias backgroundRect: backgroundRect
opacity: enabled ? 1 : 0.2 opacity: enabled ? 1 : 0.2
@ -26,16 +26,20 @@ ItemDelegate {
text: control.text text: control.text
color: appTheme.style.textColor color: appTheme.style.textColor
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
fontSizeMode: Text.Fit fontSizeMode: Text.Fit
font.pixelSize: control.height * 0.4 font.pixelSize: control.height * 0.4
minimumPixelSize: 0 minimumPixelSize: 1
} }
width: parent.width width: parent.width
background: Rectangle { background: Rectangle {
id: backgroundRect
color: control.down ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor color: control.down ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor
radius: height * 0.3 radius: height * 0.3

View file

@ -122,6 +122,10 @@ void BaseConn::gotError(QAbstractSocket::SocketError err)
qDebug() << "got socket error: " << strError; qDebug() << "got socket error: " << strError;
} }
// -------------------------------------
// --- socket communication handling ---
// -------------------------------------
QVariantMap BaseConn::sendCommand(int header, QJsonValue data){ QVariantMap BaseConn::sendCommand(int header, QJsonValue data){
if(this->state != "connected"){ if(this->state != "connected"){
return {{"status", 910}, {"data", "not connected"}}; return {{"status", 910}, {"data", "not connected"}};
@ -178,8 +182,6 @@ QVariantMap BaseConn::sendCommand(int header, QJsonValue data){
// stop the timer as the connection has been established // stop the timer as the connection has been established
timer.stop(); timer.stop();
timer.deleteLater();
return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}}; return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}};
} }
@ -189,17 +191,64 @@ void BaseConn::readyRead() {
//qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ; //qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ;
QString reply = socket->readAll(); QString reply = socket->readAll();
if(!reply.endsWith("</message>")){ //qWarning() << "socket read: " << reply;
this->readBuffer += reply;
processSocketMessage(reply);
}
void BaseConn::processSocketMessage(QString message){
QString startKey = "<message>";
QString endKey = "</message>";
//qWarning() << "... processing message now ... : " << message;
if(message == ""){
return; return;
} }
else {
if((message.startsWith(startKey) && message.endsWith(endKey)) && (message.count(startKey) == 1 && message.count(endKey) == 1)){
// non-split message ( e.g.: <message>123456789</message>
}
else if(!message.contains(endKey) && (!this->readBuffer.isEmpty() || message.startsWith(startKey))){
// begin of a split message ( e.g.: <message>123 )
// or middle of a split message ( e.g.: 456 )
//qWarning() << "this is a begin or middle of split a message";
this->readBuffer += message;
return;
}
else if(!message.contains(startKey) && message.endsWith(endKey)) {
// end of a split message ( e.g.: 789</message> )
if(!this->readBuffer.isEmpty()){ if(!this->readBuffer.isEmpty()){
reply = readBuffer + reply; message = readBuffer + message;
readBuffer.clear(); readBuffer.clear();
} }
} }
else if((message.count(startKey) > 1 || message.count(endKey) > 1) || (message.contains(endKey) && !message.endsWith(endKey) && message.contains(startKey) && !message.startsWith(startKey))) {
// multiple messages in one packet ( e.g.: <message>123456789</message><message>987654321</message> )
// or multiple message fragments in one message ( e.g.: 56789</message><message>987654321</message> or 56789</message><message>98765 )
//qDebug() << "detected multiple messages";
int startOfSecondMessage = message.lastIndexOf(startKey);
// process first part of message
QString firstMessage = message.left(startOfSecondMessage);
this->processSocketMessage(firstMessage);
// process second part of message
QString secondMessage = message.right(message.length() - startOfSecondMessage);
this->processSocketMessage(secondMessage);
return;
}
else {
// invalid message
return;
}
//qWarning() << "... done processing, message: " << message;
this->socketReplyRecieved(message);
}
void BaseConn::socketReplyRecieved(QString reply) {
reply.replace("<message>", ""); reply.replace("<message>", "");
reply.replace("</message>", ""); reply.replace("</message>", "");
@ -216,7 +265,9 @@ void BaseConn::readyRead() {
for(int i = 0; i < this->waitingRequests.length(); i++){ for(int i = 0; i < this->waitingRequests.length(); i++){
if(this->waitingRequests[i].id == id){ if(this->waitingRequests[i].id == id){
this->waitingRequests[i].reply = replyObj; this->waitingRequests[i].reply = replyObj;
if(this->waitingRequests[i].loop != nullptr){
this->waitingRequests[i].loop->quit(); this->waitingRequests[i].loop->quit();
}
return; return;
} }
} }
@ -224,9 +275,12 @@ void BaseConn::readyRead() {
latestReadReply = reply; latestReadReply = reply;
emit gotUnexpectedReply(reply); emit gotUnexpectedReply(reply);
} }
// ------------------------
// --- helper functions ---
// ------------------------
int BaseConn::writeRemoteSetting(QString key, QString value) { int BaseConn::writeRemoteSetting(QString key, QString value) {
QJsonArray requestData; QJsonArray requestData;
requestData.append(key); requestData.append(key);
@ -257,6 +311,7 @@ void BaseConn::socketStateChanged(QAbstractSocket::SocketState socketState) {
switch (socketState) { switch (socketState) {
case QAbstractSocket::UnconnectedState: case QAbstractSocket::UnconnectedState:
{ {
this->deInit();
this->setState("disconnected"); this->setState("disconnected");
break; break;
} }