Sat, 11 Feb 2023 15:48:02 +0100
Monitor iSpindels: use global variables instead of repeated expensive MySQL calls. Use the yeast temperature ranges for the colors on the thermometer scale. Don't show SVG and ABV if the OG is not yet known. Turn statusfield red if offline. Extra mon_ispindles fields yeast_lo and yeast_hi. Need at least bmsd version 0.3.42. If a websocket message is received that cannot be parsed, show the whole received message.
--- a/src/DetailiSpindel.cpp Fri Feb 10 17:28:46 2023 +0100 +++ b/src/DetailiSpindel.cpp Sat Feb 11 15:48:02 2023 +0100 @@ -32,7 +32,9 @@ { QSqlQuery query; +#ifdef DEBUG_MONITOR qDebug() << "DetailiSpindel record:" << id; +#endif ui->setupUi(this); this->recno = id; setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint); @@ -54,7 +56,6 @@ connect(ui->codePick, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DetailiSpindel::code_changed); connect(ui->modeEdit, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DetailiSpindel::mode_changed); - connect(ui->logButton, SIGNAL(clicked()), this, SLOT(on_ChartButton_clicked())); connect(parent, SIGNAL(updateiSpindel(QString)), this, SLOT(refreshiSpindel(QString))); emit refreshTable(); } @@ -64,7 +65,7 @@ { QSqlQuery query; - qDebug() << "refreshTable ispindel rec:" << this->recno; + qDebug() << "DetailiSpindel::refreshTable()"; query.prepare("SELECT * FROM mon_ispindels WHERE record = :recno"); query.bindValue(":recno", this->recno); @@ -80,24 +81,31 @@ _beercode = query.value("beercode").toString(); _beername = query.value("beername").toString(); + bool alarm = (query.value("alarm").toInt() != 0) ? true:false; + bool online = (query.value("online").toInt() != 0) ? true:false; + bool mode = (query.value("mode").toString() == "ON") ? true:false; + ui->uuidEdit->setText(_uuid); ui->systemEdit->setText(_node+"/"+_alias); ui->codePick->setItemText(0, _alias.toUpper()+" - "+_alias); + ui->alarmLED->setChecked(alarm); - if (query.value("online").toInt()) { + if (online) { ui->statusEdit->setText(tr("Online")); + ui->statusEdit->setStyleSheet(""); ui->codeEdit->setText(_beercode+" - "+_beername); + ui->thermoMeter->setNominal(query.value("yeast_lo").toDouble()); + ui->thermoMeter->setCritical(query.value("yeast_hi").toDouble()); + + ui->powerLED->setChecked(mode); ui->modeEdit->show(); - if (query.value("mode").toString() == "OFF") { - ui->powerLED->setChecked(false); + if (mode) { + ui->modeEdit->setCurrentIndex(1); + ui->codePick->hide(); + } else { ui->modeEdit->setCurrentIndex(0); ui->codePick->show(); - } else { - ui->powerLED->setChecked(true); - ui->modeEdit->setCurrentIndex(1); - ui->codePick->hide(); } - ui->alarmLED->setChecked((query.value("alarm").toInt() != 0) ? true:false); ui->voltEdit->setText(QString("%1").arg(query.value("battery").toDouble(), 4, 'f', 3, '0')); ui->tiltEdit->setText(QString("%1").arg(query.value("angle").toDouble(), 6, 'f', 5, '0')); @@ -106,16 +114,24 @@ ui->sgEdit->setText(QString("%1").arg(sg, 5, 'f', 4, '0')); if (query.value("gravity").toDouble()) { - double og = Utils::plato_to_sg(query.value("og_gravity").toDouble()); + double o_plato = query.value("og_gravity").toDouble(); + double og = Utils::plato_to_sg(o_plato); double svg = Utils::calc_svg(og, sg); ui->ogVal->setText(QString("%1").arg(og, 5, 'f', 4, '0')); - ui->ogVal2->setText(QString("%1°P").arg(query.value("og_gravity").toDouble(), 4, 'f', 3, '0')); + ui->ogVal2->setText(QString("%1°P").arg(o_plato, 4, 'f', 3, '0')); ui->sgVal->setText(QString("%1").arg(sg, 5, 'f', 4, '0')); ui->sgVal2->setText(QString("%1°P").arg(query.value("gravity").toDouble(), 4, 'f', 3, '0')); - ui->svgVal->setText(QString("%1%").arg(svg, 2, 'f', 1, '0')); - ui->svgBar->setValue(svg); - ui->abvVal->setText(QString("%1%").arg(Utils::abvol(og, sg), 3, 'f', 2, '0')); + if (o_plato > 0.1) { + ui->svgVal->setText(QString("%1%").arg(svg, 2, 'f', 1, '0')); + ui->svgBar->setValue(svg); + ui->abvVal->setText(QString("%1%").arg(Utils::abvol(og, sg), 3, 'f', 2, '0')); + } else { + /* o_plato is 0 if a new beer is selected. */ + ui->svgVal->setText(""); + ui->svgBar->setValue(0); + ui->abvVal->setText(""); + } } else { ui->ogVal->setText(""); ui->ogVal2->setText(""); @@ -140,6 +156,7 @@ } else { /* Offline */ ui->statusEdit->setText(tr("Offline")); + ui->statusEdit->setStyleSheet("background-color: red"); ui->powerLED->setChecked(false); ui->alarmLED->setChecked(true); ui->codePick->hide(); @@ -154,7 +171,6 @@ DetailiSpindel::~DetailiSpindel() { - qDebug() << "DetailiSpindel done"; delete ui; emit entry_changed(); } @@ -172,7 +188,7 @@ } -void DetailiSpindel::on_ChartButton_clicked() +void DetailiSpindel::on_logButton_clicked() { ChartiSpindel dialog(_beercode, _beername, this); } @@ -189,7 +205,9 @@ { QStringList mode ({ "OFF", "ON" }); QString msg = QString("{\"device\":\"ispindels\",\"node\":\"" + _node + "\",\"unit\":\"" + _alias + "\",\"mode\":\"" + mode[val] + "\"}"); +#ifdef DEBUG_MONITOR qDebug() << "mode_changed" << val << msg; +#endif webSocket->sendTextMessage(msg); } @@ -203,18 +221,44 @@ if (val == 0) { msg.append(QString("\"beeruuid\":\"") + _uuid + "\","); msg.append(QString("\"beercode\":\"") + _alias.toUpper() + "\","); - msg.append(QString("\"beername\":\"") + _alias + "\"}"); + msg.append(QString("\"beername\":\"") + _alias + "\","); + msg.append(QString("\"yeast_lo\":20.0,")); + msg.append(QString("\"yeast_hi\":25.0}")); } else { query.exec("SELECT code,name,uuid,stage,json_yeasts FROM products WHERE stage='1' OR stage='2' OR stage='3' OR stage='4' OR stage='5' OR stage='6' OR stage='7' ORDER BY code"); for (int i = 0; i < val; i++) { query.next(); } + double yl = 0; + double yh = 40; + const auto& y_json = query.value("json_yeasts").toString(); + if (! y_json.trimmed().isEmpty()) { + const auto& formattedJson = QString("%1").arg(y_json); + QJsonDocument yeasts = QJsonDocument::fromJson(formattedJson.toUtf8(), &parseError); + if (parseError.error != QJsonParseError::NoError) { + qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ; + } else if (yeasts.isArray()) { + for (int i = 0; i < yeasts.array().size(); i++) { + QJsonObject obj = yeasts.array().at(i).toObject(); + if (obj["y_use"].toInt() == 0) { // Primary yeast + if (obj["y_min_temperature"].toDouble() > yl) + yl = obj["y_min_temperature"].toDouble(); + if (obj["y_max_temperature"].toDouble() < yh) + yh = obj["y_max_temperature"].toDouble(); + } + } + } + } msg.append(QString("\"beeruuid\":\"") + query.value("uuid").toString() + "\","); msg.append(QString("\"beercode\":\"") + query.value("code").toString() + "\","); - msg.append(QString("\"beername\":\"") + query.value("name").toString() + "\"}"); + msg.append(QString("\"beername\":\"") + query.value("name").toString() + "\","); + msg.append(QString("\"yeast_lo\":%1,").arg(yl)); + msg.append(QString("\"yeast_hi\":%1}").arg(yh)); } +#ifdef DEBUG_MONITOR qDebug() << "code_changed" << val << msg; +#endif webSocket->sendTextMessage(msg); }
--- a/src/DetailiSpindel.h Fri Feb 10 17:28:46 2023 +0100 +++ b/src/DetailiSpindel.h Sat Feb 11 15:48:02 2023 +0100 @@ -30,7 +30,7 @@ void refreshTable(void); void mode_changed(int val); void code_changed(int val); - void on_ChartButton_clicked(); + void on_logButton_clicked(); public slots: void refreshiSpindel(QString);
--- a/src/MainWindow.cpp Fri Feb 10 17:28:46 2023 +0100 +++ b/src/MainWindow.cpp Sat Feb 11 15:48:02 2023 +0100 @@ -344,6 +344,7 @@ if (parseError.error != QJsonParseError::NoError) { qWarning() << "wsTextMessageReceived error:" << parseError.errorString() << "at" << parseError.offset ; + qWarning() << message; return; }
--- a/translations/bmsapp_en.ts Fri Feb 10 17:28:46 2023 +0100 +++ b/translations/bmsapp_en.ts Sat Feb 11 15:48:02 2023 +0100 @@ -996,17 +996,17 @@ <translation type="unfinished"></translation> </message> <message> - <location filename="../src/DetailiSpindel.cpp" line="39"/> + <location filename="../src/DetailiSpindel.cpp" line="41"/> <source>BMSapp - Details iSpindel</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/DetailiSpindel.cpp" line="88"/> + <location filename="../src/DetailiSpindel.cpp" line="96"/> <source>Online</source> <translation type="unfinished"></translation> </message> <message> - <location filename="../src/DetailiSpindel.cpp" line="142"/> + <location filename="../src/DetailiSpindel.cpp" line="160"/> <source>Offline</source> <translation type="unfinished"></translation> </message>
--- a/translations/bmsapp_nl.ts Fri Feb 10 17:28:46 2023 +0100 +++ b/translations/bmsapp_nl.ts Sat Feb 11 15:48:02 2023 +0100 @@ -1073,17 +1073,17 @@ <translation>Log</translation> </message> <message> - <location filename="../src/DetailiSpindel.cpp" line="39"/> + <location filename="../src/DetailiSpindel.cpp" line="41"/> <source>BMSapp - Details iSpindel</source> <translation>BMSapp - Detail iSpindel</translation> </message> <message> - <location filename="../src/DetailiSpindel.cpp" line="88"/> + <location filename="../src/DetailiSpindel.cpp" line="96"/> <source>Online</source> <translation>Online</translation> </message> <message> - <location filename="../src/DetailiSpindel.cpp" line="142"/> + <location filename="../src/DetailiSpindel.cpp" line="160"/> <source>Offline</source> <translation>Offline</translation> </message>