Files
TkrMonitor/MainWindow.cpp
2024-07-10 17:30:45 +09:00

293 lines
8.8 KiB
C++

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "rt8016AdcDgr.h"
#include <core/MeasurementSetup.h>
#include <core/CanTrace.h>
#include <core/Log.h>
#include <driver/CanInterface.h>
#include <driver/SLCANDriver/SLCANDriver.h>
#include <driver/CANBlastDriver/CANBlasterDriver.h>
#if defined(__linux__)
#include <driver/SocketCanDriver/SocketCanDriver.h>
#else
#include <driver/CandleApiDriver/CandleApiDriver.h>
#endif
#include <window/SetupDialog/SetupDialog.h>
#include <QTimer>
#include <QDebug>
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, dateTimeTimer_(new QTimer(this))
, canStatusTimer_(new QTimer(this))
, lastPackageDateTime_(QDateTime::fromMSecsSinceEpoch(0))
{
ui->setupUi(this);
setupDrivers();
setupTables();
auto& backend = Backend::instance();
connect(backend.getTrace(), &CanTrace::messageEnqueued, this, &MainWindow::handlePackage);
dateTimeTimer_->start(1000);
connect(dateTimeTimer_, &QTimer::timeout, this, &MainWindow::updateDateTime);
canStatusTimer_->start(1000);
connect(canStatusTimer_, &QTimer::timeout, this, &MainWindow::updateCanStatus);
updateDateTime();
connectCan();
}
MainWindow::~MainWindow()
{
disconnectCan();
delete ui;
}
void MainWindow::connectCan()
{
auto& backend = Backend::instance();
backend.clearTrace();
backend.startMeasurement();
QTimer::singleShot(100, this, [this]{ updateCanStatus(); });
// for (const auto interfaceId: backend.getInterfaceList())
// {
// log_info(backend.getInterfaceById(interfaceId)->getName());
// }
// MeasurementSetup new_setup(&backend);
// new_setup.cloneFrom(backend.getSetup());
// auto setupDlg = new SetupDialog(Backend::instance(), 0);
// if (setupDlg->showSetupDialog(new_setup)) {
// auto& backend = Backend::instance();
// for (const auto interfaceId: backend.getInterfaceList())
// {
// log_info(backend.getInterfaceById(interfaceId)->getName());
// }
// backend.setSetup(new_setup);
// backend.clearTrace();
// backend.startMeasurement();
// }
}
void MainWindow::disconnectCan()
{
Backend::instance().stopMeasurement();
}
void MainWindow::handlePackage(int index)
{
log_info("Received message: " + QString::number(index));
lastPackageDateTime_ = QDateTime::currentDateTime();
auto& backend = Backend::instance();
auto message = backend.getTrace()->getMessage(index);
if (!message)
{
return;
}
if (message->getId() != 0x60)
{
return;
}
quint16 frequency = ((message->getByte(1) << 8) + message->getByte(0)) & 0x7FFF;
quint8 sign = ((message->getByte(1) & 0x80) >> 7);
double frequencyValue = (sign ? -1 : 1) * frequency;
frequencyValue /= 128;
parameterModel_->setItem(1, 1, new QStandardItem(QString::number(frequencyValue, 'f', 2)));
quint16 inputVoltage = (message->getByte(2) << 2) + ((message->getByte(7) & 0x03) >> 0);
inputVoltage /= 1.137;
parameterModel_->setItem(0, 1, new QStandardItem(QString::number(inputVoltage)));
quint16 coolantTemperatureIndex = (message->getByte(4) << 2) + ((message->getByte(7) & 0x30) >> 4);
if (coolantTemperatureIndex > 1023)
{
coolantTemperatureIndex = 0;
}
qint16 coolantTemperature = FlashTdegr[coolantTemperatureIndex << 2] - 55;
parameterModel_->setItem(5, 1, new QStandardItem(QString::number(coolantTemperature)));
quint16 outputPhaseCurrent = (message->getByte(3) << 2) + ((message->getByte(7) & 0x0C) >> 2);
outputPhaseCurrent /= 3.1;
quint8 phaseNumber = ((message->getByte(7) & 0xC0) >> 6);
switch (phaseNumber)
{
case 0x00:
parameterModel_->setItem(2, 1, new QStandardItem(QString::number(outputPhaseCurrent)));
break;
case 0x01:
parameterModel_->setItem(3, 1, new QStandardItem(QString::number(outputPhaseCurrent)));
break;
case 0x02:
parameterModel_->setItem(4, 1, new QStandardItem(QString::number(outputPhaseCurrent)));
break;
default:
break;
}
auto status = message->getByte(5);
if (status != lastStatus_)
{
lastStatus_ = status;
statusModel_->appendRow({new QStandardItem(message->getDateTime().toString("dd.MM.yyyy hh:mm:ss")),
new QStandardItem(statusToString(status)),
new QStandardItem(statusToDescription(status))});
}
}
void MainWindow::updateDateTime()
{
const auto currentDateTime = QDateTime::currentDateTime();
ui->dateLabel->setText(currentDateTime.toString("dd.MM.yyyy"));
ui->timeLabel->setText(currentDateTime.toString("hh:mm:ss"));
}
void MainWindow::updateCanStatus()
{
// auto isConnected = false;
// auto& backend = Backend::instance();
// for (const auto interfaceId: backend.getInterfaceList())
// {
// isConnected |= backend.getInterfaceById(interfaceId)->isOpen();
// }
auto isConnected = lastPackageDateTime_.msecsTo(QDateTime::currentDateTime()) < 5000;
auto pallette = QPalette();
auto color = QColor(isConnected ? Qt::darkGreen : Qt::darkRed);
color.setAlphaF(0.7);
pallette.setColor(QPalette::Window, color);
ui->titleLabel->setAutoFillBackground(true);
ui->titleLabel->setPalette(pallette);
}
void MainWindow::setupDrivers()
{
auto& backend = Backend::instance();
#if defined(__linux__)
backend.addCanDriver(*(new SocketCanDriver(backend)));
#else
backend.addCanDriver(*(new CandleApiDriver(backend)));
#endif
// backend.addCanDriver(*(new SLCANDriver(backend)));
// backend.addCanDriver(*(new CANBlasterDriver(backend)));
backend.setDefaultSetup();
}
void MainWindow::setupTables()
{
parameterModel_ = new QStandardItemModel(6, 2, this);
statusModel_ = new QStandardItemModel(0, 3, this);
parameterModel_->setHorizontalHeaderLabels({tr("Parameter"), tr("Value")});
statusModel_->setHorizontalHeaderLabels({tr("Time"), tr("Module status"), tr("Module status description")});
parameterModel_->setItem(0, 0, new QStandardItem(tr("Input voltage, V")));
parameterModel_->setItem(1, 0, new QStandardItem(tr("Input voltage frequency, Hz")));
parameterModel_->setItem(2, 0, new QStandardItem(tr("Phase A input current, A")));
parameterModel_->setItem(3, 0, new QStandardItem(tr("Phase B input current, A")));
parameterModel_->setItem(4, 0, new QStandardItem(tr("Phase C input current, A")));
parameterModel_->setItem(5, 0, new QStandardItem(tr("Coolant temperature, °C")));
ui->parameterTableView->setModel(parameterModel_);
ui->statusTableView->setModel(statusModel_);
ui->parameterTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->statusTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->parameterTableView->horizontalHeader()->setStretchLastSection(true);
ui->statusTableView->horizontalHeader()->setStretchLastSection(true);
ui->parameterTableView->verticalHeader()->hide();
ui->parameterTableView->setColumnWidth(0, 280);
ui->statusTableView->setColumnWidth(0, 150);
}
QString MainWindow::statusToString(quint8 status)
{
return "0x" + QString::number(status, 16).rightJustified(2, '0');
}
QString MainWindow::statusToDescription(quint8 status)
{
QString description;
status &= 0x7F;
switch (status)
{
case 0x00:
description = tr("Supply voltage 110[V] to the control circuit");
break;
case 0x01:
description = tr("Pause after blocking");
break;
case 0x03:
description = tr("Waiting for the required DC link voltage level. 670[V]. Input voltage");
break;
case 0x04:
description = tr("Waiting for a CAN command to start work");
break;
case 0x07:
description = tr("Normal operation");
break;
case 0x08:
description = tr("Normal operation with output current limitation");
break;
case 0x10:
description = tr("DC link overvoltage. Input voltage");
break;
case 0x11:
description = tr("Fault half bridge 1");
break;
case 0x12:
description = tr("Fault half bridge 2");
break;
case 0x14:
description = tr("Fault half bridge 3");
break;
case 0x18:
description = tr("Cooler overheating");
break;
case 0x21:
description = tr("Instantaneous total current fault (270 A)");
break;
case 0x22:
description = tr("Large total current for 15 seconds (200 A)");
break;
case 0x27:
description = tr("Instant current fault in one of the phases (396 A)");
break;
case 0x25:
description = tr("No incoming messages via CAN");
break;
default:
description = tr("Unknown status");
break;
}
return description;
}