Files
VkuMonitor/cpp/CanController.cpp
2024-07-03 19:11:29 +09:00

255 lines
7.3 KiB
C++

#include "CanController.h"
#include <core/MeasurementSetup.h>
#include <core/MeasurementNetwork.h>
#include <core/MeasurementInterface.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 <QDateTime>
#include <QDebug>
#include <QTimer>
#include <QSettings>
CanController::CanController(QObject* parent)
: QObject{parent}
{
setupDrivers();
setupDefaultParameters();
auto& backend = Backend::instance();
connect(backend.getTrace(), &CanTrace::messageEnqueued, this, &CanController::handlePackage);
QSettings settings("settings.ini", QSettings::IniFormat);
auto sendParametersTimeout = settings.value("sendParametersTimeout", 50).toInt();
const auto sendParametersTimer = new QTimer(this);
sendParametersTimer->start(sendParametersTimeout);
connect(sendParametersTimer, &QTimer::timeout, this, &CanController::sendParameters);
// auto statusTimer = new QTimer(this);
// statusTimer->start(5000);
// statusTimer->callOnTimeout([this]
// {
// QVariantMap statusMap;
// statusMap.insert("time", QDateTime::currentDateTime().toString());
// statusMap.insert("status", "0x" + QString::number(0xff, 16).toUpper().rightJustified(2, '0'));
// statusMap.insert("description", "asdfasdfasdf");
// statuses_.prepend(statusMap);
// emit statusesChanged();
// });
QTimer::singleShot(0, this, &CanController::connectCan);
}
CanController::~CanController()
{
}
QObject* CanController::qmlInstance(QQmlEngine* /*engine*/, QJSEngine* /*scriptEngine*/)
{
return new CanController;
}
void CanController::connectCan()
{
auto& backend = Backend::instance();
backend.clearTrace();
QSettings settings("settings.ini", QSettings::IniFormat);
auto bitrate = settings.value("bitrate", 100000).toInt();
for (auto* network: backend.getSetup().getNetworks())
{
for (auto* mi: network->interfaces())
{
mi->setBitrate(bitrate);
}
}
backend.startMeasurement();
}
void CanController::disconnectCan()
{
Backend::instance().stopMeasurement();
}
void CanController::vkuClosure()
{
CanMessage message(0x201);
message.setLength(8);
message.setByte(0, 0x01);
auto& backend = Backend::instance();
for (const auto interfaceId: backend.getInterfaceList())
{
auto interface = backend.getInterfaceById(interfaceId);
if (interface)
{
interface->sendMessage(message);
}
}
}
void CanController::emergencyReset()
{
CanMessage message(0x201);
message.setLength(8);
message.setByte(0, 0x02);
auto& backend = Backend::instance();
for (const auto interfaceId: backend.getInterfaceList())
{
auto interface = backend.getInterfaceById(interfaceId);
if (interface)
{
interface->sendMessage(message);
}
}
}
void CanController::sendParameters()
{
CanMessage message(0x202);
message.setLength(8);
const auto maximumCurrent = maximumCurrent_.toUInt();
message.setByte(0, maximumCurrent & 0xFF);
const auto breakingDelay = breakingDelay_.toUInt();
message.setByte(1, (breakingDelay >> 8) & 0xFF);
message.setByte(2, breakingDelay & 0xFF);
const auto breakingCurrent = breakingCurrent_.toUInt();
message.setByte(3, breakingCurrent & 0xFF);
const auto emergencyDelay = emergencyDelay_.toUInt();
message.setByte(4, emergencyDelay & 0xFF);
const auto retriesAfterEmergencyBreak = retriesAfterEmergencyBreak_.toUInt();
message.setByte(5, retriesAfterEmergencyBreak & 0xFF);
// qDebug() << "Sending parameters: " << maximumCurrent;
auto& backend = Backend::instance();
for (const auto interfaceId: backend.getInterfaceList())
{
auto interface = backend.getInterfaceById(interfaceId);
if (interface)
{
interface->sendMessage(message);
}
}
}
void CanController::handlePackage(int index)
{
auto& backend = Backend::instance();
auto message = backend.getTrace()->getMessage(index);
if (!message)
{
return;
}
if (message->getId() == 0x501)
{
handleCurrentState(message);
}
if (message->getId() == 0x502)
{
handleStatus(message);
}
}
void CanController::handleCurrentState(const CanMessage* message)
{
quint16 inputVoltage = (message->getByte(0) << 8) + message->getByte(1);
setProperty("inputVoltage", QString::number(inputVoltage));
quint16 outputVoltage = (message->getByte(2) << 8) + message->getByte(3);
setProperty("outputVoltage", QString::number(outputVoltage));
quint8 outputCurrent = message->getByte(4);
setProperty("outputCurrent", QString::number(outputCurrent));
qint16 radiatorTemperature = (message->getByte(5) << 8) + message->getByte(6);
setProperty("radiatorTemperature", QString::number(radiatorTemperature));
}
void CanController::handleStatus(const CanMessage* message)
{
QMap<quint8, QString> statusDescriptionMap =
{
{0x00, tr("Reset")},
{0x01, tr("No incoming messages via CAN interface")},
{0x03, tr("Waiting for a command for closing")},
{0x04, tr("Work via CAN")},
{0x05, tr("Work via button signal")},
{0x06, tr("Work via CAN or button signal")},
{0x20, tr("Exceeding input voltage")},
{0x22, tr("Exceeding maximum current")},
{0x18, tr("Exceeding radiator temperature")},
{0x02, tr("Pause after breaking")},
{0x80, tr("Blocking due to emergency")}
};
quint8 status = message->getByte(0);
auto statusDescription = statusDescriptionMap.value(status, tr("Unknown status"));
QVariantMap statusMap;
statusMap.insert("time", QDateTime::currentDateTime().toString());
statusMap.insert("status", "0x" + QString::number(status, 16).toUpper().rightJustified(2, '0'));
statusMap.insert("description", statusDescription);
if (statuses_.isEmpty() || statuses_.first().toMap()["status"] != statusMap["status"])
{
statuses_.prepend(statusMap);
emit statusesChanged();
}
quint8 emergencyCounter = message->getByte(1);
setProperty("emergencyCounter", QString::number(emergencyCounter));
bool isVkuClosed = (message->getByte(2) & 0x1) == 1;
setProperty("isVkuClosed", isVkuClosed);
}
void CanController::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 CanController::setupDefaultParameters()
{
setProperty("maximumCurrent", QString::number(95));
setProperty("emergencyDelay", QString::number(2));
setProperty("breakingDelay", QString::number(0));
setProperty("retriesAfterEmergencyBreak", QString::number(2));
setProperty("breakingCurrent", QString::number(100));
}