From b861ce003c274e6324287e5c9fd2279b4bbda3d2 Mon Sep 17 00:00:00 2001 From: Yury Shuvakin Date: Fri, 15 Aug 2025 18:53:38 +0900 Subject: [PATCH] Now statuses have different colors. Various minor fixes --- BatteryController.cpp | 131 ++++++++++++++----------------------- BatteryController.h | 11 +++- CanController.cpp | 26 ++++---- CanController.h | 21 +++++- Qml/Battery.qml | 24 +++++-- Qml/Controls/Button.qml | 4 ++ Qml/Controls/TextField.qml | 1 - Qml/Main.qml | 2 +- Qml/Palette/Palette.qml | 6 +- StandBatteryView.pro | 2 + main.cpp | 5 ++ 11 files changed, 124 insertions(+), 109 deletions(-) diff --git a/BatteryController.cpp b/BatteryController.cpp index 812d84b..9a3cc34 100644 --- a/BatteryController.cpp +++ b/BatteryController.cpp @@ -2,13 +2,14 @@ #include #include +#include #include -BatteryController::BatteryController( - QObject *parent) +BatteryController::BatteryController(QObject *parent) : QObject{parent} -{} +{ +} BatteryController::~BatteryController() { @@ -182,105 +183,71 @@ void BatteryController::setStatuses(const QVariantList& statuses) emit statusesChanged(); } -void BatteryController::addStatus(const quint16 status) +void BatteryController::addStatus(const quint32 status) { - // QString description; - // auto appendDescription = [&description](const QString& subStatus) - // { - // if (!description.isEmpty()) - // { - // description += ", "; - // } - // description += subStatus; - // }; - - QStringList descriptionList; - auto appendDescription = [&descriptionList](const QString& subStatus) + QVariantList statusList; + auto appendStatus = [&statusList](const QVariant& subStatus) { - descriptionList.append(subStatus); + statusList.append(subStatus); }; - std::bitset<16> descriptionBitset(status); - if (descriptionBitset.test(0)) + QMap statusBitDescriptions = { - appendDescription("Ошибка Т датчика КП"); - } - if (descriptionBitset.test(1)) + {0, {"Ошибка Т датчика КП", StatusSeverity::Error}}, + {1, {"Глубокий разряд АКБ", StatusSeverity::Error}}, + {2, {"Заряд выполнен", StatusSeverity::Info}}, + {3, {"Ошибка Т датчика УКПБ", StatusSeverity::Info}}, + + {4, {"Ток долго не снижается", StatusSeverity::Error}}, + {5, {"Ошибка БПС3000", StatusSeverity::Error}}, + {6, {"U менее 61.25 В", StatusSeverity::Error}}, + {7, {"U выше нормы по КП", StatusSeverity::Error}}, + + {8, {"Останов первого заряда", StatusSeverity::Info}}, + {9, {"Останов разряда", StatusSeverity::Info}}, + {10, {"Останов повторного заряда", StatusSeverity::Info}}, + {11, {"Более 45 градусов", StatusSeverity::Warning}}, + + {12, {"Разночтение в токах", StatusSeverity::Error}}, + {13, {"Разночтение в напряжениях", StatusSeverity::Error}}, + {14, {"Разночтение в температурах", StatusSeverity::Error}}, + {15, {"Разночтение в емкости АКБ", StatusSeverity::Info}}, + + {16, {"Низкий разряд АКБ", StatusSeverity::Info}}, + {17, {"Ошибка контрольного заряда", StatusSeverity::Error}}, + }; + + for (auto it = statusBitDescriptions.constBegin(); it != statusBitDescriptions.constEnd(); ++it) { - appendDescription("Низкий разряд АКБ"); - } - if (descriptionBitset.test(2)) - { - appendDescription("Заряд завершен"); - } - if (descriptionBitset.test(3)) - { - appendDescription("Ошибка Т датчика УКПБ"); + if (status & (1 << it.key())) + { + appendStatus(it.value()); + } } - if (descriptionBitset.test(4)) + if (statusList.isEmpty()) { - appendDescription("Ток долго не снижается"); - } - if (descriptionBitset.test(5)) - { - appendDescription("Ошибка БПС3000"); - } - if (descriptionBitset.test(6)) - { - appendDescription("U менее 61.25 В"); - } - if (descriptionBitset.test(7)) - { - appendDescription("U выше нормы по КП"); - } - - - if (descriptionBitset.test(8)) - { - appendDescription("Останов первого заряда"); - } - if (descriptionBitset.test(9)) - { - appendDescription("Останов разряда"); - } - if (descriptionBitset.test(10)) - { - appendDescription("Останов второго заряда"); - } - if (descriptionBitset.test(11)) - { - appendDescription("Более 45 гр. С"); - } - - if (descriptionBitset.test(12)) - { - appendDescription("Разночтение в токах"); - } - - if (descriptionList.isEmpty()) - { - appendDescription("Штатный режим"); + appendStatus(QVariantList{"Штатный режим", StatusSeverity::Info}); } statuses_.clear(); - for (const auto& description: descriptionList) + for (const auto& statusVariant: statusList) { + const auto statusDescription = statusVariant.toList(); + if (statusDescription.size() < 2) + { + continue; + } + QVariantMap statusMap; statusMap.insert("time", QDateTime::currentDateTime().toString("hh:mm:ss dd-MM-yyyy")); statusMap.insert("status", "0x" + QString::number(status, 16).toUpper().rightJustified(2, '0')); - statusMap.insert("description", description); + statusMap.insert("description", statusDescription.at(0)); + statusMap.insert("severity", statusDescription.at(1)); statuses_.append(statusMap); } emit statusesChanged(); - - // if (statuses_.isEmpty() || statuses_.first().toMap()["status"] != statusMap["status"]) - // { - // qDebug() << "Status:" << statusMap["status"].toString() << statusMap["description"].toString(); - // statuses_.prepend(statusMap); - // emit statusesChanged(); - // } } diff --git a/BatteryController.h b/BatteryController.h index 53f977c..888968c 100644 --- a/BatteryController.h +++ b/BatteryController.h @@ -26,6 +26,15 @@ class BatteryController : public QObject Q_PROPERTY(QVariantList statues READ statuses WRITE setStatuses NOTIFY statusesChanged) public: + enum StatusSeverity + { + Info = 0, + Good = 1, + Warning = 2, + Error = 3 + }; + Q_ENUM(StatusSeverity) + explicit BatteryController(QObject *parent = nullptr); ~BatteryController(); @@ -64,7 +73,7 @@ public: QVariantList statuses() const; void setStatuses(const QVariantList &statuses); - void addStatus(const quint16 status); + void addStatus(const quint32 status); signals: void batteryIndexChanged(); diff --git a/CanController.cpp b/CanController.cpp index 613e13a..ff1ebe4 100644 --- a/CanController.cpp +++ b/CanController.cpp @@ -238,19 +238,19 @@ void CanController::handleControlParameters(const CanMessage* message, qsizetype quint16 capacity = 0; stream >> capacity; - batteries_.at(batteryIndex)->setControlCapacity(parameterToVariant(capacity)); + batteries_.at(batteryIndex)->setControlCapacity(doubleParameterToVariant(capacity)); quint16 temperature = 0; stream >> temperature; - batteries_.at(batteryIndex)->setControlTemperature(parameterToVariant(temperature)); + batteries_.at(batteryIndex)->setControlTemperature(intParameterToVariant(temperature)); - quint16 current = 0; + qint16 current = 0; stream >> current; - batteries_.at(batteryIndex)->setControlCurrent(parameterToVariant(current)); + batteries_.at(batteryIndex)->setControlCurrent(intParameterToVariant(current)); quint16 voltage = 0; stream >> voltage; - batteries_.at(batteryIndex)->setControlVoltage(parameterToVariant(voltage)); + batteries_.at(batteryIndex)->setControlVoltage(doubleParameterToVariant(voltage)); } void CanController::handleMeasuredParameters(const CanMessage* message, qsizetype batteryIndex) @@ -260,19 +260,19 @@ void CanController::handleMeasuredParameters(const CanMessage* message, qsizetyp quint16 capacity = 0; stream >> capacity; - batteries_.at(batteryIndex)->setMeasuredCapacity(parameterToVariant(capacity)); + batteries_.at(batteryIndex)->setMeasuredCapacity(doubleParameterToVariant(capacity)); quint16 temperature = 0; stream >> temperature; - batteries_.at(batteryIndex)->setMeasuredTemperature(parameterToVariant(temperature)); + batteries_.at(batteryIndex)->setMeasuredTemperature(intParameterToVariant(temperature)); - quint16 current = 0; + qint16 current = 0; stream >> current; - batteries_.at(batteryIndex)->setMeasuredCurrent(parameterToVariant(current)); + batteries_.at(batteryIndex)->setMeasuredCurrent(intParameterToVariant(current)); quint16 voltage = 0; stream >> voltage; - batteries_.at(batteryIndex)->setMeasuredVoltage(parameterToVariant(voltage)); + batteries_.at(batteryIndex)->setMeasuredVoltage(doubleParameterToVariant(voltage)); } void CanController::handleStatusParameters(const CanMessage* message, qsizetype batteryIndex) @@ -290,7 +290,7 @@ void CanController::handleStatusParameters(const CanMessage* message, qsizetype stream.skipRawData(1); - quint16 status = 0; + quint32 status = 0; stream >> status; batteries_.at(batteryIndex)->addStatus(status); } @@ -350,7 +350,3 @@ QList CanController::registerAddresses() const return {0x200, 0x280, 0x300, 0x380, 0x400, 0x480, 0x500, 0x580}; } -QVariant CanController::parameterToVariant(quint16 parameter) const -{ - return parameter == 0xFFFF ? QVariant() : QVariant::fromValue(parameter / 10.0); -} diff --git a/CanController.h b/CanController.h index d7f7116..020d260 100644 --- a/CanController.h +++ b/CanController.h @@ -1,6 +1,8 @@ #ifndef CANCONTROLLER_H #define CANCONTROLLER_H +#include + #include #include #include @@ -57,7 +59,24 @@ private: void initializeBatteries(); QList registerAddresses() const; - QVariant parameterToVariant(quint16 parameter) const; + + template + static QVariant doubleParameterToVariant(T parameter) + { + return isParameterEmpty(parameter) ? QVariant() : QVariant::fromValue(parameter / 10.0); + } + + template + static QVariant intParameterToVariant(T parameter) + { + return isParameterEmpty(parameter) ? QVariant() : QVariant::fromValue(parameter); + } + + template + static bool isParameterEmpty(T /*parameter*/) + { + return std::numeric_limits::max(); + } private: bool isConnected_ = false; diff --git a/Qml/Battery.qml b/Qml/Battery.qml index 556a4e9..e0d6785 100644 --- a/Qml/Battery.qml +++ b/Qml/Battery.qml @@ -62,14 +62,14 @@ Rectangle { } CustomControls.TextField { - text: battery ? convertDoubleToString(battery.controlCurrent) : "—" + text: battery ? convertIntToString(battery.controlCurrent) : "—" indicatorText: "А" Layout.fillWidth: true Layout.preferredWidth: 1 } CustomControls.TextField { - text: battery ? convertDoubleToString(battery.measuredCurrent) : "—" + text: battery ? convertIntToString(battery.measuredCurrent) : "—" indicatorText: "А" Layout.fillWidth: true Layout.preferredWidth: 1 @@ -90,14 +90,14 @@ Rectangle { } CustomControls.TextField { - text: battery ? convertDoubleToString(battery.controlTemperature) : "—" + text: battery ? convertIntToString(battery.controlTemperature) : "—" indicatorText: "°C" Layout.fillWidth: true Layout.preferredWidth: 1 } CustomControls.TextField { - text: battery ? convertDoubleToString(battery.measuredTemperature) : "—" + text: battery ? convertIntToString(battery.measuredTemperature) : "—" indicatorText: "°C" implicitWidth: 1 Layout.fillWidth: true @@ -130,7 +130,7 @@ Rectangle { delegate: CustomControls.ColoredLabel { text: modelData.description - backgroundColor: Palette.neutralColor + backgroundColor: statusSeverityToColor(modelData.severity) font.pixelSize: 12 width: parent.width } @@ -183,4 +183,18 @@ Rectangle { return Palette.blueButtonColor } } + + function statusSeverityToColor(severity) { + switch (severity) { + case BatteryController.Good: + return Palette.goodColor + case BatteryController.Warning: + return Palette.warningColor + case BatteryController.Error: + return Palette.errorColor + case BatteryController.Info: + default: + return Palette.infoColor + } + } } diff --git a/Qml/Controls/Button.qml b/Qml/Controls/Button.qml index 7153094..25072a4 100644 --- a/Qml/Controls/Button.qml +++ b/Qml/Controls/Button.qml @@ -11,6 +11,10 @@ Controls.Button { topPadding: 8 bottomPadding: 8 + font.family: "Roboto" + font.pixelSize: 14 + font.weight: Font.Normal + property color backgroundColor: Palette.blueButtonColor contentItem: Text { diff --git a/Qml/Controls/TextField.qml b/Qml/Controls/TextField.qml index 31dc7f0..b5c3f49 100644 --- a/Qml/Controls/TextField.qml +++ b/Qml/Controls/TextField.qml @@ -7,7 +7,6 @@ Controls.TextField { id: control readOnly: true - selectByMouse: true implicitHeight: 34 horizontalAlignment: Text.AlignRight diff --git a/Qml/Main.qml b/Qml/Main.qml index ff304fd..6712c47 100644 --- a/Qml/Main.qml +++ b/Qml/Main.qml @@ -49,7 +49,7 @@ ApplicationWindow { CustomControls.ColoredLabel { text: CanController.isConnected ? "Штатный режим" : "Отсутствует связь с БМФ2" - backgroundColor: CanController.isConnected ? Palette.goodColor : Palette.invalidColor + backgroundColor: CanController.isConnected ? Palette.goodColor : Palette.errorColor } Item { diff --git a/Qml/Palette/Palette.qml b/Qml/Palette/Palette.qml index a05dd27..6f8ea8b 100644 --- a/Qml/Palette/Palette.qml +++ b/Qml/Palette/Palette.qml @@ -16,8 +16,8 @@ QtObject { property color redButtonColor: "#E74245" property color yellowButtonColor: "#F4BB44" - property color informationColor: "#E2EAFF" - property color invalidColor: "#FFEDE3" + property color infoColor: "#E2EAFF" property color goodColor: "#C4FFCA" - property color neutralColor: "#FEFBC6" + property color warningColor: "#FEFBC6" + property color errorColor: "#FFEDE3" } diff --git a/StandBatteryView.pro b/StandBatteryView.pro index 1e4f9ef..4e2fa44 100644 --- a/StandBatteryView.pro +++ b/StandBatteryView.pro @@ -1,5 +1,7 @@ QT += quickcontrols2 quick +CONFIG += c++17 + # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 diff --git a/main.cpp b/main.cpp index 3636319..965938a 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,10 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); +#ifdef __linux__ + QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor)); +#endif + QCoreApplication::setOrganizationName("Tksi"); QCoreApplication::setOrganizationDomain("Tksi.rus"); QCoreApplication::setApplicationName("Tksi monitor");