fixed communication issues with the base station caused by data distributed over multiple packets once and for all (hopefully)
This commit is contained in:
parent
a0a3d8cfe6
commit
75b193e642
7 changed files with 175 additions and 41 deletions
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue