diff --git a/.vscode/settings.json b/.vscode/settings.json index 37cb614..f02b29a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,7 +4,7 @@ "editor.defaultFormatter": "xaver.clang-format", "editor.formatOnSave": true }, - "clang-format.executable": "C:\\Program Files\\LLVM\\bin\\clang-format.exe", + "clang-format.executable": "/opt/homebrew/bin/clang-format", "C_Cpp.codeAnalysis.clangTidy.enabled": true, "C_Cpp.codeAnalysis.clangTidy.path": "C:\\Program Files\\LLVM\\bin\\clang-tidy.exe" } \ No newline at end of file diff --git a/include/CANBusHandler.hpp b/include/CANBusHandler.hpp index 8d79bba..0fb3df9 100644 --- a/include/CANBusHandler.hpp +++ b/include/CANBusHandler.hpp @@ -7,23 +7,29 @@ class CANBusHandler : public QObject { Q_OBJECT Q_PROPERTY(int speed READ getSpeed WRITE setSpeed NOTIFY speedChanged) + Q_PROPERTY( + int battery READ getBattery WRITE setBattery NOTIFY batteryChanged) -public: - explicit CANBusHandler(QObject *parent = nullptr); + public: + explicit CANBusHandler(QObject* parent = nullptr); ~CANBusHandler(); int getSpeed() const; void setSpeed(int speed); + int getBattery() const; + void setBattery(int battery); -signals: + signals: void speedChanged(int speed); + void batteryChanged(int battery); -private slots: + private slots: void readFrames(); -private: - int canSocket; // File descriptor for the CAN socket - int m_speed; // Member variable for the speed + private: + int canSocket; + int m_speed; + int m_battery; }; #endif // CANBUSHANDLER_HPP diff --git a/src/CANBusHandler.cpp b/src/CANBusHandler.cpp index af28be9..23fb595 100644 --- a/src/CANBusHandler.cpp +++ b/src/CANBusHandler.cpp @@ -9,16 +9,15 @@ #include #include "../include/CANBusHandler.hpp" -CANBusHandler::CANBusHandler(QObject *parent) - : QObject(parent), - canSocket(-1), - m_speed(0) +CANBusHandler::CANBusHandler(QObject* parent) + : QObject(parent), canSocket(-1), m_speed(0), m_battery(0) { struct ifreq ifr; struct sockaddr_can addr; canSocket = socket(PF_CAN, SOCK_RAW, CAN_RAW); - if (canSocket < 0) { + if (canSocket < 0) + { qWarning() << "Cannot create CAN socket!"; return; } @@ -26,9 +25,10 @@ CANBusHandler::CANBusHandler(QObject *parent) strcpy(ifr.ifr_name, "can0"); ioctl(canSocket, SIOCGIFINDEX, &ifr); - addr.can_family = AF_CAN; + addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; - if (bind(canSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if (bind(canSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { qWarning() << "Cannot bind CAN socket!"; close(canSocket); return; @@ -37,16 +37,16 @@ CANBusHandler::CANBusHandler(QObject *parent) qDebug() << "CAN socket bound to can0 interface successfully."; // Set up a timer to periodically read frames - QTimer *timer = new QTimer(this); + QTimer* timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [this]() { readFrames(); }); timer->start(10); // Adjust the interval as needed } CANBusHandler::~CANBusHandler() { - if (canSocket >= 0) { - close(canSocket); // Close the CAN socket - canSocket = -1; + if (canSocket >= 0) + { + close(canSocket); // Close the CAN socket } } @@ -57,31 +57,56 @@ int CANBusHandler::getSpeed() const void CANBusHandler::setSpeed(int speed) { - if (m_speed != speed) { + if (m_speed != speed) + { m_speed = speed; emit speedChanged(m_speed); } } +int CANBusHandler::getBattery() const +{ + return m_battery; +} + +void CANBusHandler::setBattery(int battery) +{ + if (m_battery != battery) + { + m_battery = battery; + emit batteryChanged(m_battery); + } +} + void CANBusHandler::readFrames() { struct can_frame frame; int nbytes = read(canSocket, &frame, sizeof(struct can_frame)); - if (nbytes < 0) { + if (nbytes < 0) + { qWarning() << "Error reading CAN frame!"; return; } - if (frame.can_id == 0x01) { + if (frame.can_id == 0x01) + { int speed; memcpy(&speed, frame.data, sizeof(int)); speed = ntohl(speed); - + // qDebug() << "Speed:" << speed; // Print the speed value setSpeed(speed); - } else { - qDebug() << "Received CAN frame with ID:" << frame.can_id; + } + else if (frame.can_id == 0x02) + { + int battery; + memcpy(&battery, frame.data, sizeof(int)); + + battery = ntohl(battery); + + // qDebug() << "Battery:" << battery; // Print the speed value + setBattery(battery); } } diff --git a/src/Main.qml b/src/Main.qml index ea5ed84..e7f8c01 100644 --- a/src/Main.qml +++ b/src/Main.qml @@ -1,6 +1,6 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 -import com.example.canbus 1.0 +import canbus 1.0 ApplicationWindow { visible: true @@ -11,12 +11,13 @@ ApplicationWindow { CANBusHandler { id: canBusHandler onSpeedChanged: speedGauge.requestPaint() + onBatteryChanged: batteryGauge.requestPaint() } Rectangle { anchors.fill: parent - // Background gradient + // Background Gradient Canvas { anchors.fill: parent onPaint: { @@ -59,46 +60,6 @@ ApplicationWindow { } } - Canvas { - id: roadCanvas - anchors.fill: parent - - onPaint: { - var ctx = getContext("2d"); - ctx.clearRect(0, 0, width, height); - - var centerX = width / 2; - var roadWidth = 200; - var roadHeight = height; - - // Perspective variables - var topRoadWidth = 50; // Simulated narrow top width for 3D effect - var bottomRoadWidth = roadWidth; - - // Road boundaries - var leftTop = centerX - topRoadWidth / 2; - var rightTop = centerX + topRoadWidth / 2; - var leftBottom = centerX - bottomRoadWidth / 2; - var rightBottom = centerX + bottomRoadWidth / 2; - - // Draw road edges - ctx.strokeStyle = "white"; - ctx.lineWidth = 3; - - // Left edge - ctx.beginPath(); - ctx.moveTo(leftTop, 0); - ctx.lineTo(leftBottom, roadHeight); - ctx.stroke(); - - // Right edge - ctx.beginPath(); - ctx.moveTo(rightTop, 0); - ctx.lineTo(rightBottom, roadHeight); - ctx.stroke(); - } - } - // Left Speedometer Gauge Canvas { id: speedGauge @@ -108,58 +69,20 @@ ApplicationWindow { anchors.left: parent.left anchors.leftMargin: 20 - property real angle: 0.75 * Math.PI // Initial angle for the arc - onPaint: { var ctx = getContext("2d"); ctx.clearRect(0, 0, width, height); - // Background gradient for the circular gauge - var bgGradient = ctx.createRadialGradient(width / 2, height / 2, 50, width / 2, height / 2, 120); - bgGradient.addColorStop(0, "#001848"); - bgGradient.addColorStop(1, "#002060"); - ctx.fillStyle = bgGradient; - ctx.beginPath(); - ctx.arc(width / 2, height / 2, 120, 0, 2 * Math.PI); - ctx.fill(); - - // Draw Speed Arc based on speed value - var arcStartAngle = 0.75 * Math.PI; // Start at 270 degrees (left) - var arcEndAngle = arcStartAngle + (Math.PI * canBusHandler.speed / 180); // Map speedValue to an arc from 0 to 180 degrees - var arcGradient = ctx.createLinearGradient(0, 0, width, height); - arcGradient.addColorStop(0, "#00ff00"); - arcGradient.addColorStop(1, "#004000"); - ctx.lineWidth = 15; - ctx.strokeStyle = arcGradient; - ctx.beginPath(); - ctx.arc(width / 2, height / 2, 100, arcStartAngle, arcEndAngle); - ctx.stroke(); - // Speed Value - ctx.font = "36px Arial"; + ctx.font = "36px sans-serif"; ctx.fillStyle = "white"; ctx.textAlign = "center"; - ctx.fillText(canBusHandler.speed + " km/h", width / 2, height / 2); + ctx.fillText(canBusHandler.speed, width / 2, height / 2); // Label - ctx.font = "18px Arial"; + ctx.font = "18px sans-serif"; ctx.fillStyle = "lightgray"; - ctx.fillText("km/h", width / 2, height / 2 + 40); - } - - // Speed angle animation with smoother transition - NumberAnimation { - id: speedAnimation - target: speedGauge - property: "angle" - from: speedGauge.angle - to: 0.75 * Math.PI + (Math.PI * canBusHandler.speed / 180) - duration: 1000 // 1 second transition for smoother effect - easing.type: Easing.InOutQuad // Smoother easing - running: true - onRunningChanged: { - speedGauge.requestPaint(); // Trigger repaint when animation is running - } + ctx.fillText("Speed", width / 2, height / 2 + 40); } } @@ -172,59 +95,21 @@ ApplicationWindow { anchors.right: parent.right anchors.rightMargin: 20 - property real angle: 0.75 * Math.PI // Initial angle for the arc - onPaint: { var ctx = getContext("2d"); ctx.clearRect(0, 0, width, height); - // Background gradient for the circular gauge - var bgGradient = ctx.createRadialGradient(width / 2, height / 2, 50, width / 2, height / 2, 120); - bgGradient.addColorStop(0, "#001848"); - bgGradient.addColorStop(1, "#002060"); - ctx.fillStyle = bgGradient; - ctx.beginPath(); - ctx.arc(width / 2, height / 2, 120, 0, 2 * Math.PI); - ctx.fill(); - - // Draw Battery Arc based on battery value - var arcStartAngle = 0.75 * Math.PI; // Start at 270 degrees (left) - var arcEndAngle = arcStartAngle + (Math.PI * batteryValue / 500); // Map batteryValue to an arc from 0 to 180 degrees - var arcGradient = ctx.createLinearGradient(0, 0, width, height); - arcGradient.addColorStop(0, "#ffcc00"); // Yellow arc for battery status - arcGradient.addColorStop(1, "#e0b100"); - ctx.lineWidth = 15; - ctx.strokeStyle = arcGradient; - ctx.beginPath(); - ctx.arc(width / 2, height / 2, 100, arcStartAngle, arcEndAngle); - ctx.stroke(); - // Battery Value - ctx.font = "36px Arial"; + ctx.font = "36px sans-serif"; ctx.fillStyle = "white"; ctx.textAlign = "center"; - ctx.fillText(batteryValue + " km", width / 2, height / 2); + ctx.fillText(canBusHandler.battery + " %", width / 2, height / 2); // Label - ctx.font = "18px Arial"; + ctx.font = "18px sans-serif"; ctx.fillStyle = "lightgray"; ctx.fillText("Battery", width / 2, height / 2 + 40); } - - // Battery angle animation with smoother transition - NumberAnimation { - id: batteryAnimation - target: batteryGauge - property: "angle" - from: batteryGauge.angle - to: 0.75 * Math.PI + (Math.PI * batteryValue / 500) - duration: 1000 // 1 second transition for smoother effect - easing.type: Easing.InOutQuad // Smoother easing - running: true - onRunningChanged: { - batteryGauge.requestPaint(); // Trigger repaint when animation is running - } - } } } } diff --git a/src/main.cpp b/src/main.cpp index bb5e44a..925258e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,29 +1,31 @@ #include #include #include -#include +#include #include #include "../include/CANBusHandler.hpp" -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); - // Set up the QML engine QQmlApplicationEngine engine; - qmlRegisterType("com.example.canbus", 1, 0, "CANBusHandler"); - // Create and expose the CAN bus handler to QML + qmlRegisterType("canbus", 1, 0, "CANBusHandler"); + CANBusHandler canBusHandler; engine.rootContext()->setContextProperty("canBusHandler", &canBusHandler); // Load QML file const QUrl url(QStringLiteral("qrc:/Main.qml")); - QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, - &app, [url](QObject *obj, const QUrl &objUrl) { - if (!obj && url == objUrl) - QCoreApplication::exit(-1); - }, Qt::QueuedConnection); + QObject::connect( + &engine, &QQmlApplicationEngine::objectCreated, &app, + [url](QObject* obj, const QUrl& objUrl) + { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, + Qt::QueuedConnection); engine.load(url); return app.exec();