Now statuses have different colors. Various minor fixes

This commit is contained in:
Yury Shuvakin
2025-08-15 18:53:38 +09:00
parent 978f6ee04d
commit b861ce003c
11 changed files with 124 additions and 109 deletions

View File

@@ -2,13 +2,14 @@
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QTimer>
#include <bitset> #include <bitset>
BatteryController::BatteryController( BatteryController::BatteryController(QObject *parent)
QObject *parent)
: QObject{parent} : QObject{parent}
{} {
}
BatteryController::~BatteryController() BatteryController::~BatteryController()
{ {
@@ -182,105 +183,71 @@ void BatteryController::setStatuses(const QVariantList& statuses)
emit statusesChanged(); emit statusesChanged();
} }
void BatteryController::addStatus(const quint16 status) void BatteryController::addStatus(const quint32 status)
{ {
// QString description; QVariantList statusList;
// auto appendDescription = [&description](const QString& subStatus) auto appendStatus = [&statusList](const QVariant& subStatus)
// {
// if (!description.isEmpty())
// {
// description += ", ";
// }
// description += subStatus;
// };
QStringList descriptionList;
auto appendDescription = [&descriptionList](const QString& subStatus)
{ {
descriptionList.append(subStatus); statusList.append(subStatus);
}; };
std::bitset<16> descriptionBitset(status); QMap<qsizetype, QVariantList> statusBitDescriptions =
if (descriptionBitset.test(0))
{ {
appendDescription("Ошибка Т датчика КП"); {0, {"Ошибка Т датчика КП", StatusSeverity::Error}},
} {1, {"Глубокий разряд АКБ", StatusSeverity::Error}},
if (descriptionBitset.test(1)) {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 (status & (1 << it.key()))
} {
if (descriptionBitset.test(2)) appendStatus(it.value());
{ }
appendDescription("Заряд завершен");
}
if (descriptionBitset.test(3))
{
appendDescription("Ошибка Т датчика УКПБ");
} }
if (descriptionBitset.test(4)) if (statusList.isEmpty())
{ {
appendDescription("Ток долго не снижается"); appendStatus(QVariantList{"Штатный режим", StatusSeverity::Info});
}
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("Штатный режим");
} }
statuses_.clear(); statuses_.clear();
for (const auto& description: descriptionList) for (const auto& statusVariant: statusList)
{ {
const auto statusDescription = statusVariant.toList();
if (statusDescription.size() < 2)
{
continue;
}
QVariantMap statusMap; QVariantMap statusMap;
statusMap.insert("time", QDateTime::currentDateTime().toString("hh:mm:ss dd-MM-yyyy")); 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("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); statuses_.append(statusMap);
} }
emit statusesChanged(); emit statusesChanged();
// if (statuses_.isEmpty() || statuses_.first().toMap()["status"] != statusMap["status"])
// {
// qDebug() << "Status:" << statusMap["status"].toString() << statusMap["description"].toString();
// statuses_.prepend(statusMap);
// emit statusesChanged();
// }
} }

View File

@@ -26,6 +26,15 @@ class BatteryController : public QObject
Q_PROPERTY(QVariantList statues READ statuses WRITE setStatuses NOTIFY statusesChanged) Q_PROPERTY(QVariantList statues READ statuses WRITE setStatuses NOTIFY statusesChanged)
public: public:
enum StatusSeverity
{
Info = 0,
Good = 1,
Warning = 2,
Error = 3
};
Q_ENUM(StatusSeverity)
explicit BatteryController(QObject *parent = nullptr); explicit BatteryController(QObject *parent = nullptr);
~BatteryController(); ~BatteryController();
@@ -64,7 +73,7 @@ public:
QVariantList statuses() const; QVariantList statuses() const;
void setStatuses(const QVariantList &statuses); void setStatuses(const QVariantList &statuses);
void addStatus(const quint16 status); void addStatus(const quint32 status);
signals: signals:
void batteryIndexChanged(); void batteryIndexChanged();

View File

@@ -238,19 +238,19 @@ void CanController::handleControlParameters(const CanMessage* message, qsizetype
quint16 capacity = 0; quint16 capacity = 0;
stream >> capacity; stream >> capacity;
batteries_.at(batteryIndex)->setControlCapacity(parameterToVariant(capacity)); batteries_.at(batteryIndex)->setControlCapacity(doubleParameterToVariant(capacity));
quint16 temperature = 0; quint16 temperature = 0;
stream >> temperature; stream >> temperature;
batteries_.at(batteryIndex)->setControlTemperature(parameterToVariant(temperature)); batteries_.at(batteryIndex)->setControlTemperature(intParameterToVariant(temperature));
quint16 current = 0; qint16 current = 0;
stream >> current; stream >> current;
batteries_.at(batteryIndex)->setControlCurrent(parameterToVariant(current)); batteries_.at(batteryIndex)->setControlCurrent(intParameterToVariant(current));
quint16 voltage = 0; quint16 voltage = 0;
stream >> voltage; stream >> voltage;
batteries_.at(batteryIndex)->setControlVoltage(parameterToVariant(voltage)); batteries_.at(batteryIndex)->setControlVoltage(doubleParameterToVariant(voltage));
} }
void CanController::handleMeasuredParameters(const CanMessage* message, qsizetype batteryIndex) void CanController::handleMeasuredParameters(const CanMessage* message, qsizetype batteryIndex)
@@ -260,19 +260,19 @@ void CanController::handleMeasuredParameters(const CanMessage* message, qsizetyp
quint16 capacity = 0; quint16 capacity = 0;
stream >> capacity; stream >> capacity;
batteries_.at(batteryIndex)->setMeasuredCapacity(parameterToVariant(capacity)); batteries_.at(batteryIndex)->setMeasuredCapacity(doubleParameterToVariant(capacity));
quint16 temperature = 0; quint16 temperature = 0;
stream >> temperature; stream >> temperature;
batteries_.at(batteryIndex)->setMeasuredTemperature(parameterToVariant(temperature)); batteries_.at(batteryIndex)->setMeasuredTemperature(intParameterToVariant(temperature));
quint16 current = 0; qint16 current = 0;
stream >> current; stream >> current;
batteries_.at(batteryIndex)->setMeasuredCurrent(parameterToVariant(current)); batteries_.at(batteryIndex)->setMeasuredCurrent(intParameterToVariant(current));
quint16 voltage = 0; quint16 voltage = 0;
stream >> voltage; stream >> voltage;
batteries_.at(batteryIndex)->setMeasuredVoltage(parameterToVariant(voltage)); batteries_.at(batteryIndex)->setMeasuredVoltage(doubleParameterToVariant(voltage));
} }
void CanController::handleStatusParameters(const CanMessage* message, qsizetype batteryIndex) void CanController::handleStatusParameters(const CanMessage* message, qsizetype batteryIndex)
@@ -290,7 +290,7 @@ void CanController::handleStatusParameters(const CanMessage* message, qsizetype
stream.skipRawData(1); stream.skipRawData(1);
quint16 status = 0; quint32 status = 0;
stream >> status; stream >> status;
batteries_.at(batteryIndex)->addStatus(status); batteries_.at(batteryIndex)->addStatus(status);
} }
@@ -350,7 +350,3 @@ QList<quint16> CanController::registerAddresses() const
return {0x200, 0x280, 0x300, 0x380, 0x400, 0x480, 0x500, 0x580}; return {0x200, 0x280, 0x300, 0x380, 0x400, 0x480, 0x500, 0x580};
} }
QVariant CanController::parameterToVariant(quint16 parameter) const
{
return parameter == 0xFFFF ? QVariant() : QVariant::fromValue(parameter / 10.0);
}

View File

@@ -1,6 +1,8 @@
#ifndef CANCONTROLLER_H #ifndef CANCONTROLLER_H
#define CANCONTROLLER_H #define CANCONTROLLER_H
#include <type_traits>
#include <QObject> #include <QObject>
#include <QVariant> #include <QVariant>
#include <QDateTime> #include <QDateTime>
@@ -57,7 +59,24 @@ private:
void initializeBatteries(); void initializeBatteries();
QList<quint16> registerAddresses() const; QList<quint16> registerAddresses() const;
QVariant parameterToVariant(quint16 parameter) const;
template<typename T>
static QVariant doubleParameterToVariant(T parameter)
{
return isParameterEmpty(parameter) ? QVariant() : QVariant::fromValue(parameter / 10.0);
}
template<typename T>
static QVariant intParameterToVariant(T parameter)
{
return isParameterEmpty(parameter) ? QVariant() : QVariant::fromValue(parameter);
}
template<typename T>
static bool isParameterEmpty(T /*parameter*/)
{
return std::numeric_limits<T>::max();
}
private: private:
bool isConnected_ = false; bool isConnected_ = false;

View File

@@ -62,14 +62,14 @@ Rectangle {
} }
CustomControls.TextField { CustomControls.TextField {
text: battery ? convertDoubleToString(battery.controlCurrent) : "—" text: battery ? convertIntToString(battery.controlCurrent) : "—"
indicatorText: "А" indicatorText: "А"
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredWidth: 1 Layout.preferredWidth: 1
} }
CustomControls.TextField { CustomControls.TextField {
text: battery ? convertDoubleToString(battery.measuredCurrent) : "—" text: battery ? convertIntToString(battery.measuredCurrent) : "—"
indicatorText: "А" indicatorText: "А"
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredWidth: 1 Layout.preferredWidth: 1
@@ -90,14 +90,14 @@ Rectangle {
} }
CustomControls.TextField { CustomControls.TextField {
text: battery ? convertDoubleToString(battery.controlTemperature) : "—" text: battery ? convertIntToString(battery.controlTemperature) : "—"
indicatorText: "°C" indicatorText: "°C"
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredWidth: 1 Layout.preferredWidth: 1
} }
CustomControls.TextField { CustomControls.TextField {
text: battery ? convertDoubleToString(battery.measuredTemperature) : "—" text: battery ? convertIntToString(battery.measuredTemperature) : "—"
indicatorText: "°C" indicatorText: "°C"
implicitWidth: 1 implicitWidth: 1
Layout.fillWidth: true Layout.fillWidth: true
@@ -130,7 +130,7 @@ Rectangle {
delegate: CustomControls.ColoredLabel { delegate: CustomControls.ColoredLabel {
text: modelData.description text: modelData.description
backgroundColor: Palette.neutralColor backgroundColor: statusSeverityToColor(modelData.severity)
font.pixelSize: 12 font.pixelSize: 12
width: parent.width width: parent.width
} }
@@ -183,4 +183,18 @@ Rectangle {
return Palette.blueButtonColor 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
}
}
} }

View File

@@ -11,6 +11,10 @@ Controls.Button {
topPadding: 8 topPadding: 8
bottomPadding: 8 bottomPadding: 8
font.family: "Roboto"
font.pixelSize: 14
font.weight: Font.Normal
property color backgroundColor: Palette.blueButtonColor property color backgroundColor: Palette.blueButtonColor
contentItem: Text { contentItem: Text {

View File

@@ -7,7 +7,6 @@ Controls.TextField {
id: control id: control
readOnly: true readOnly: true
selectByMouse: true
implicitHeight: 34 implicitHeight: 34
horizontalAlignment: Text.AlignRight horizontalAlignment: Text.AlignRight

View File

@@ -49,7 +49,7 @@ ApplicationWindow {
CustomControls.ColoredLabel { CustomControls.ColoredLabel {
text: CanController.isConnected ? "Штатный режим" : "Отсутствует связь с БМФ2" text: CanController.isConnected ? "Штатный режим" : "Отсутствует связь с БМФ2"
backgroundColor: CanController.isConnected ? Palette.goodColor : Palette.invalidColor backgroundColor: CanController.isConnected ? Palette.goodColor : Palette.errorColor
} }
Item { Item {

View File

@@ -16,8 +16,8 @@ QtObject {
property color redButtonColor: "#E74245" property color redButtonColor: "#E74245"
property color yellowButtonColor: "#F4BB44" property color yellowButtonColor: "#F4BB44"
property color informationColor: "#E2EAFF" property color infoColor: "#E2EAFF"
property color invalidColor: "#FFEDE3"
property color goodColor: "#C4FFCA" property color goodColor: "#C4FFCA"
property color neutralColor: "#FEFBC6" property color warningColor: "#FEFBC6"
property color errorColor: "#FFEDE3"
} }

View File

@@ -1,5 +1,7 @@
QT += quickcontrols2 quick QT += quickcontrols2 quick
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs. # You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line. # 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 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

View File

@@ -1,6 +1,7 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QCursor>
#include <QLocale> #include <QLocale>
#include <QTextCodec> #include <QTextCodec>
#include <QTranslator> #include <QTranslator>
@@ -22,6 +23,10 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
#ifdef __linux__
QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
#endif
QCoreApplication::setOrganizationName("Tksi"); QCoreApplication::setOrganizationName("Tksi");
QCoreApplication::setOrganizationDomain("Tksi.rus"); QCoreApplication::setOrganizationDomain("Tksi.rus");
QCoreApplication::setApplicationName("Tksi monitor"); QCoreApplication::setApplicationName("Tksi monitor");