Fix: race problems when reading and writing data

This commit is contained in:
Dorian Zedler 2022-08-02 22:08:30 +02:00
parent ae659ac875
commit bd9bfe858e
Signed by: dorian
GPG key ID: 989DE36109AFA354
6 changed files with 71 additions and 53 deletions

View file

@ -110,6 +110,8 @@ void LedDisplayBackend::handleFoundNewDevice(QBluetoothLeUartDevice* device) {
void LedDisplayBackend::handleDisplayTextModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { void LedDisplayBackend::handleDisplayTextModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) {
if(this->state == Initing) return;
qDebug() << "Data changed: topLeft: " << topLeft << " bottomRight: " << bottomRight << " roles: " << roles; qDebug() << "Data changed: topLeft: " << topLeft << " bottomRight: " << bottomRight << " roles: " << roles;
for(int role : roles) for(int role : roles)
@ -140,6 +142,13 @@ void LedDisplayBackend::sendBluetoothCommand(OmobiDisplayCommand command, QVaria
qDebug() << "Sending command: \n" << qPrintable(doc.toJson(QJsonDocument::Compact)); qDebug() << "Sending command: \n" << qPrintable(doc.toJson(QJsonDocument::Compact));
if((this->state != Initing && this->waitingCommands > 0) || (this->state == Initing && this->waitingCommands > 1)) {
QEventLoop loop;
loop.connect(this, &LedDisplayBackend::commandFinished, &loop, &QEventLoop::quit);
loop.exec();
if(this->state == Idle) return;
}
this->waitingCommands ++; this->waitingCommands ++;
if(this->state == Connected) if(this->state == Connected)
@ -169,6 +178,8 @@ void LedDisplayBackend::handleBluetoothDataReceived(QString s){
QVariantMap data = doc.toVariant().toMap()["data"].toMap(); QVariantMap data = doc.toVariant().toMap()["data"].toMap();
OmobiDisplayStatusCode status = OmobiDisplayStatusCode(doc.toVariant().toMap()["status"].toInt()); OmobiDisplayStatusCode status = OmobiDisplayStatusCode(doc.toVariant().toMap()["status"].toInt());
qDebug() << "Header is:" << header;
switch (header) { switch (header) {
case AuthenticateCommand: { case AuthenticateCommand: {
if(status != Success) { if(status != Success) {
@ -180,9 +191,9 @@ void LedDisplayBackend::handleBluetoothDataReceived(QString s){
this->settings->setValue(this->bleClient->getCurrentDevice()->getAddress(), this->lastDisplaySecret); this->settings->setValue(this->bleClient->getCurrentDevice()->getAddress(), this->lastDisplaySecret);
this->waitingCommands = 0; this->waitingCommands = 0;
emit this->commandFinished();
this->setState(Initing); this->setState(Initing);
this->sendBluetoothCommand(GetAllTextSetsCommand); this->sendBluetoothCommand(GetAllTextSetsCommand);
this->sendBluetoothCommand(GetDisplayBrightnessCommand);
break; break;
} }
@ -191,7 +202,7 @@ void LedDisplayBackend::handleBluetoothDataReceived(QString s){
} }
case GetAllTextSetsCommand: { case GetAllTextSetsCommand: {
// indicates that all existing txt sets have been sent over after GetAllTextSetsCommand was called // indicates that all existing text sets have been sent over after GetAllTextSetsCommand was called
if(status != Success) if(status != Success)
// TODO: handle error // TODO: handle error
break; break;
@ -199,11 +210,16 @@ void LedDisplayBackend::handleBluetoothDataReceived(QString s){
this->displayTextModel->maximumTextLength = data["maximumTextLength"].toInt(); this->displayTextModel->maximumTextLength = data["maximumTextLength"].toInt();
this->displayTextModel->maximumTextSets = data["maximumTextSets"].toInt(); this->displayTextModel->maximumTextSets = data["maximumTextSets"].toInt();
qDebug() << "text sets are: " << this->textSetsBuffer; this->displayTextModel->setTexts({});
this->displayTextModel->setTexts(this->textSetsBuffer);
this->textSetsBuffer.clear(); this->textSetsBuffer.clear();
for(int i = 0; i < this->displayTextModel->maximumTextSets; i++) {
for(int param = 0; param < DisplayTextSetParameterCount; param++) {
this->sendBluetoothCommand(GetTextSetParameterCommand, QVariantMap({{"index", i}, {"parameter", param}}));
}
}
this->sendBluetoothCommand(GetDisplayBrightnessCommand);
this->refreshLoadingState(); this->refreshLoadingState();
break; break;
@ -224,9 +240,9 @@ void LedDisplayBackend::handleBluetoothDataReceived(QString s){
this->textSetsBuffer[index].insert(parameter, QVariant()); this->textSetsBuffer[index].insert(parameter, QVariant());
this->textSetsBuffer[index][parameter] = data["value"].toString(); this->textSetsBuffer[index][parameter] = data["value"].toString();
qDebug() << "Got value: " << this->textSetsBuffer[index][parameter];
if(this->state != Initing) this->displayTextModel->setTexts(this->textSetsBuffer);
this->refreshLoadingState(); this->refreshLoadingState();
break; break;
} }
@ -284,6 +300,7 @@ void LedDisplayBackend::refreshLoadingState() {
return; return;
qDebug() << "Refreshing loading state! Waiting: " << this->waitingCommands; qDebug() << "Refreshing loading state! Waiting: " << this->waitingCommands;
emit this->commandFinished();
if(this->waitingCommands <= 1) { if(this->waitingCommands <= 1) {
this->waitingCommands = 0; this->waitingCommands = 0;
@ -302,8 +319,11 @@ void LedDisplayBackend::setState(OmobiDisplayAppState state) {
qDebug() << "Now in " << state << " state"; qDebug() << "Now in " << state << " state";
if(this->state == Idle) if(this->state == Idle) {
this->waitingCommands = 0;
emit this->commandFinished();
this->bleClient->startScanningForDevices(); this->bleClient->startScanningForDevices();
}
} }
QVariantMap LedDisplayBackend::getDisplayBrightness() { QVariantMap LedDisplayBackend::getDisplayBrightness() {

View file

@ -6,6 +6,7 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QSettings> #include <QSettings>
#include <QEventLoop>
#include <qbluetoothleuartclient.h> #include <qbluetoothleuartclient.h>
#include <leddisplaytextmodel.h> #include <leddisplaytextmodel.h>
@ -54,6 +55,21 @@ private:
SetDisplayNameCommand = 23 SetDisplayNameCommand = 23
}; };
enum OmobiDisplayTextSetParameter
{
TextParameter = 0,
ActiveParameter,
RuntimeParameter,
ColorParameter,
AlignmentParameter,
ScrollParameter,
ScrollDirectionParameter,
ScrollSpeedParameter,
ScrollCountParameter,
IndexParameter,
DisplayTextSetParameterCount /*!< Just for helping purposes */
};
enum OmobiDisplayStatusCode { enum OmobiDisplayStatusCode {
Success = 200, Success = 200,
DisplayControllerError = 501 DisplayControllerError = 501
@ -105,6 +121,7 @@ signals:
void bleClientChanged(); void bleClientChanged();
void displayTextModelChanged(); void displayTextModelChanged();
void displayBrightnessChanged(); void displayBrightnessChanged();
void commandFinished();
}; };

View file

@ -135,8 +135,10 @@ bool LedDisplayTextModel::setTexts(QList<QMap<int, QVariant>> texts) {
this->texts.clear(); this->texts.clear();
this->endResetModel(); this->endResetModel();
for(QMap<int, QVariant> text : texts) for(QMap<int, QVariant> text : texts) {
if(text[0].toString().isEmpty()) continue;
this->append(text); this->append(text);
}
return true; return true;
} }

View file

@ -17,10 +17,6 @@ ApplicationWindow {
state: backend.state state: backend.state
onStateChanged: {
console.log("new state: " + state)
}
anchors.fill: parent anchors.fill: parent
Material.accent: "#0094ff" Material.accent: "#0094ff"

View file

@ -17,7 +17,8 @@
"ostream": "cpp", "ostream": "cpp",
"numeric": "cpp", "numeric": "cpp",
"streambuf": "cpp", "streambuf": "cpp",
"utility": "cpp" "utility": "cpp",
"string_view": "cpp"
}, },
"svn.ignoreMissingSvnWarning": true "svn.ignoreMissingSvnWarning": true
} }

View file

@ -86,44 +86,6 @@ void OmobiLedDisplay::onDataReceived(String dataString)
case GetAllTextSetsCommand: case GetAllTextSetsCommand:
{ {
// cycle through all text sets
for (int textSetIndex = 0; textSetIndex < LedDisplayController::maximumTextSets; textSetIndex++)
{
if (this->ledDisplayController->getTextSetParameter(textSetIndex, LedDisplayController::TextParameter) == "")
continue;
Serial.println("Adding index " + String(textSetIndex) + " with text: " + this->ledDisplayController->getTextSetParameter(textSetIndex, LedDisplayController::TextParameter));
// if a set isn't empty, go through all parameters
for (int textSetParameter = 0; textSetParameter < LedDisplayController::DisplayTextSetParameterCount; textSetParameter++)
{
// send each parameter to the client
const size_t capacity = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + LedDisplayController::maximumTextLength; //200;
DynamicJsonDocument doc(capacity);
doc["header"] = GetTextSetParameterCommand;
JsonObject data = doc.createNestedObject("data");
data["index"] = textSetIndex;
data["parameter"] = textSetParameter;
data["value"] = this->ledDisplayController->getTextSetParameter(
textSetIndex,
LedDisplayController::DisplayTextSetParameter(textSetParameter));
Serial.println("sending parameter: " + String(textSetParameter) + " with value: '" + this->ledDisplayController->getTextSetParameter(
textSetIndex,
LedDisplayController::DisplayTextSetParameter(textSetParameter)) + "'");
String json;
serializeJson(doc, json);
Serial.println("JSON: '" + json + "'");
this->bleServer->sendData(json);
}
}
replyStatus = Success; replyStatus = Success;
replyData["maximumTextSets"] = LedDisplayController::maximumTextSets; replyData["maximumTextSets"] = LedDisplayController::maximumTextSets;
replyData["maximumTextLength"] = LedDisplayController::maximumTextLength; replyData["maximumTextLength"] = LedDisplayController::maximumTextLength;
@ -137,6 +99,25 @@ void OmobiLedDisplay::onDataReceived(String dataString)
replyStatus = Success; replyStatus = Success;
break; break;
} }
case GetTextSetParameterCommand:
{
int index = requestData["index"];
LedDisplayController::DisplayTextSetParameter parameter = requestData["parameter"];
// send each parameter to the client
replyData["index"] = index;
replyData["parameter"] = parameter;
replyStatus = Success;
replyData["value"] = this->ledDisplayController->getTextSetParameter(
index,
parameter);
Serial.println("sending parameter: " + String(parameter) + " with value: '" + this->ledDisplayController->getTextSetParameter(
index,
parameter) + "'");
break;
}
case SetTextSetParameterCommand: case SetTextSetParameterCommand:
{ {
@ -195,6 +176,7 @@ void OmobiLedDisplay::onDataReceived(String dataString)
replyDoc["status"] = replyStatus; replyDoc["status"] = replyStatus;
String json; String json;
serializeJson(replyDoc, json); serializeJson(replyDoc, json);
Serial.println("Primary JSON: '" + json + "'");
this->bleServer->sendData(json); this->bleServer->sendData(json);