#include "MainWindow.h" #include "ui_MainWindow.h" #include "rt8016AdcDgr.h" #include #include #include #include #include #include #if defined(__linux__) #include #else #include #endif #include #include #include 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; }