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 <QDebug>
#include <QTimer>
#include <bitset>
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<qsizetype, QVariantList> statusBitDescriptions =
{
appendDescription("Ошибка Т датчика КП");
{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)
{
if (status & (1 << it.key()))
{
appendStatus(it.value());
}
if (descriptionBitset.test(1))
{
appendDescription("Низкий разряд АКБ");
}
if (descriptionBitset.test(2))
{
appendDescription("Заряд завершен");
}
if (descriptionBitset.test(3))
{
appendDescription("Ошибка Т датчика УКПБ");
}
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();
// }
}

View File

@@ -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();

View File

@@ -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<quint16> 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);
}

View File

@@ -1,6 +1,8 @@
#ifndef CANCONTROLLER_H
#define CANCONTROLLER_H
#include <type_traits>
#include <QObject>
#include <QVariant>
#include <QDateTime>
@@ -57,7 +59,24 @@ private:
void initializeBatteries();
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:
bool isConnected_ = false;

View File

@@ -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
}
}
}

View File

@@ -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 {

View File

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

View File

@@ -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 {

View File

@@ -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"
}

View File

@@ -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

View File

@@ -1,6 +1,7 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QCursor>
#include <QLocale>
#include <QTextCodec>
#include <QTranslator>
@@ -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");