diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..07ed0c7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "MiddleWare/Libs"] + path = MiddleWare/Libs + url = git@github.com:SEAME-pt/Team02-Libs.git diff --git a/Arduino b/Arduino deleted file mode 160000 index 9979666..0000000 --- a/Arduino +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 99796662b861fb00b3e617685f4a8a9d7a1af412 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f428e0..7c64b5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,27 +1,30 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.10) -project(HelloQt6 LANGUAGES CXX) -message("CMAKE_SYSROOT " ${CMAKE_SYSROOT}) -message("CMAKE_LIBRARY_ARCHITECTURE " ${CMAKE_LIBRARY_ARCHITECTURE}) -set(CMAKE_CXX_STANDARD 11) +project(Cluster LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(zenohc_DIR "/usr/local/lib/cmake/zenohc") +set(zenohcxx_DIR "/usr/local/lib/cmake/zenohcxx") -find_package(Qt6 COMPONENTS Core Quick DBus SerialBus REQUIRED) +find_package(Qt6 COMPONENTS Core Quick DBus REQUIRED) +find_package(zenohc REQUIRED) +find_package(zenohcxx REQUIRED) -set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wl,-rpath-link, ${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} -L${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wl,-rpath-link,${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} -L${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}") -# Enable automatic MOC, UIC, and RCC processing +# Enable Qt's Automatic MOC, UIC, and RCC set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -qt_add_resources(QT_RESOURCES ./src/resources.qrc) +# Add Resource File (QML and Other Resources) +qt_add_resources(QT_RESOURCES ./ui/resources.qrc) -add_executable(speedometer ${QT_RESOURCES} +# Define Executable Target +add_executable(InstrumentCluster + ${QT_RESOURCES} ./src/main.cpp - ./src/CANBusHandler.cpp - ./include/CANBusHandler.hpp + ./src/InstrumentCluster.cpp + ./include/InstrumentCluster.hpp ) -target_link_libraries(speedometer -lm -ldl Qt6::Core Qt6::DBus Qt6::Quick Qt6::SerialBus) - +target_link_libraries(InstrumentCluster zenohcxx::zenohc -lm -ldl Qt6::Core Qt6::DBus Qt6::Quick) diff --git a/MiddleWare/CMakeLists.txt b/MiddleWare/CMakeLists.txt new file mode 100644 index 0000000..c1de850 --- /dev/null +++ b/MiddleWare/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.10) + +project(Middelware LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(zenohc_DIR "/usr/local/lib/cmake/zenohc") +set(zenohcxx_DIR "/usr/local/lib/cmake/zenohcxx") + +find_package(zenohc REQUIRED) +find_package(zenohcxx REQUIRED) + +add_executable(middleWare + ./src/main.cpp +) + +target_link_libraries(middleWare PRIVATE zenohcxx::zenohc) diff --git a/MiddleWare/Libs b/MiddleWare/Libs new file mode 160000 index 0000000..7f38a66 --- /dev/null +++ b/MiddleWare/Libs @@ -0,0 +1 @@ +Subproject commit 7f38a66dbbf353c0a477578ca87646fb77df0599 diff --git a/MiddleWare/src/main.cpp b/MiddleWare/src/main.cpp new file mode 100644 index 0000000..740c371 --- /dev/null +++ b/MiddleWare/src/main.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "zenoh.hxx" + +using namespace zenoh; + +int main(int argc, char** argv) +{ + struct ifreq ifr; + struct sockaddr_can addr; + + int canSocket = socket(PF_CAN, SOCK_RAW, CAN_RAW); + if (canSocket < 0) + { + std::cerr << "Cannot create CAN socket!" << std::endl; + exit(-1); + } + + strcpy(ifr.ifr_name, "can0"); + ioctl(canSocket, SIOCGIFINDEX, &ifr); + + addr.can_family = AF_CAN; + addr.can_ifindex = ifr.ifr_ifindex; + if (bind(canSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) + { + std::cerr << "Cannot bind CAN socket!" << std::endl; + close(canSocket); + exit(1); + } + + std::cout << "CAN socket bound to can0 interface successfully." + << std::endl; + + Config config = Config::create_default(); + auto session = Session::open(std::move(config)); + + auto pubSpeed = + session.declare_publisher(KeyExpr("seame/car/1/speedSensor")); + auto pubBattery = + session.declare_publisher(KeyExpr("seame/car/1/batterySensor")); + + while (1) + { + struct can_frame frame; + + int nbytes = read(canSocket, &frame, sizeof(struct can_frame)); + if (nbytes < 0) + { + std::cerr << "Error reading CAN frame!" << std::endl; + continue; + } + if (frame.can_id == 0x01) + { + int speed; + double wheelDiame = 0.067; + + memcpy(&speed, frame.data, sizeof(int)); + speed = ntohl(speed); + speed = wheelDiame * 3.14 * speed * 10 / 60; + std::string speed_str = std::to_string(speed); + + printf("Publishing speed: '%d'\n", speed); + pubSpeed.put(speed_str.c_str()); + } + else if (frame.can_id == 0x02) + { + int battery; + memcpy(&battery, frame.data, sizeof(int)); + battery = ntohl(battery); + std::string battery_str = std::to_string(battery); + + printf("Publishing battery: '%d\n", battery); + pubBattery.put(battery_str.c_str()); + } + usleep(10); + } + return 0; +} diff --git a/assets/icons/back_fog_on.png b/assets/icons/back_fog_on.png new file mode 100644 index 0000000..3b0f4f6 Binary files /dev/null and b/assets/icons/back_fog_on.png differ diff --git a/assets/icons/battery-1.png b/assets/icons/battery-1.png new file mode 100644 index 0000000..23bbb61 Binary files /dev/null and b/assets/icons/battery-1.png differ diff --git a/assets/icons/battery-2.png b/assets/icons/battery-2.png new file mode 100644 index 0000000..4bc7eed Binary files /dev/null and b/assets/icons/battery-2.png differ diff --git a/assets/icons/battery-3.png b/assets/icons/battery-3.png new file mode 100644 index 0000000..8d4bfbc Binary files /dev/null and b/assets/icons/battery-3.png differ diff --git a/assets/icons/battery-4.png b/assets/icons/battery-4.png new file mode 100644 index 0000000..36baf94 Binary files /dev/null and b/assets/icons/battery-4.png differ diff --git a/assets/icons/battery-5.png b/assets/icons/battery-5.png new file mode 100644 index 0000000..e484dc8 Binary files /dev/null and b/assets/icons/battery-5.png differ diff --git a/assets/icons/front_fog_on.png b/assets/icons/front_fog_on.png new file mode 100644 index 0000000..1d3e35a Binary files /dev/null and b/assets/icons/front_fog_on.png differ diff --git a/assets/icons/green-battery.png b/assets/icons/green-battery.png new file mode 100644 index 0000000..be1d5a3 Binary files /dev/null and b/assets/icons/green-battery.png differ diff --git a/assets/icons/high_beam_on.png b/assets/icons/high_beam_on.png new file mode 100644 index 0000000..2cbf1ae Binary files /dev/null and b/assets/icons/high_beam_on.png differ diff --git a/assets/icons/low_beam_on.png b/assets/icons/low_beam_on.png new file mode 100644 index 0000000..a486d46 Binary files /dev/null and b/assets/icons/low_beam_on.png differ diff --git a/assets/icons/parking_lights_on.png b/assets/icons/parking_lights_on.png new file mode 100644 index 0000000..2c68afb Binary files /dev/null and b/assets/icons/parking_lights_on.png differ diff --git a/assets/icons/seame-logo.png b/assets/icons/seame-logo.png new file mode 100644 index 0000000..892240a Binary files /dev/null and b/assets/icons/seame-logo.png differ diff --git a/assets/icons/turn_left_on.png b/assets/icons/turn_left_on.png new file mode 100644 index 0000000..9b1bea2 Binary files /dev/null and b/assets/icons/turn_left_on.png differ diff --git a/assets/icons/turn_right_on.png b/assets/icons/turn_right_on.png new file mode 100644 index 0000000..f633119 Binary files /dev/null and b/assets/icons/turn_right_on.png differ diff --git a/include/CANBusHandler.hpp b/include/CANBusHandler.hpp deleted file mode 100644 index 0fb3df9..0000000 --- a/include/CANBusHandler.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CANBUSHANDLER_HPP -#define CANBUSHANDLER_HPP - -#include - -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); - ~CANBusHandler(); - - int getSpeed() const; - void setSpeed(int speed); - int getBattery() const; - void setBattery(int battery); - - signals: - void speedChanged(int speed); - void batteryChanged(int battery); - - private slots: - void readFrames(); - - private: - int canSocket; - int m_speed; - int m_battery; -}; - -#endif // CANBUSHANDLER_HPP diff --git a/include/InstrumentCluster.hpp b/include/InstrumentCluster.hpp new file mode 100644 index 0000000..9d8590e --- /dev/null +++ b/include/InstrumentCluster.hpp @@ -0,0 +1,97 @@ +#ifndef INSTRUMENTCLUSTER_HPP +#define INSTRUMENTCLUSTER_HPP + +#include +#include +#include "zenoh.hxx" + +using namespace zenoh; + +class InstrumentCluster : public QObject +{ + Q_OBJECT + Q_PROPERTY(int speed READ getSpeed NOTIFY speedChanged) + Q_PROPERTY(int battery READ getBattery NOTIFY batteryChanged) + Q_PROPERTY( + bool rightBlinker READ getRightBlinker NOTIFY rightBlinkerChanged) + Q_PROPERTY(bool leftBlinker READ getLeftBlinker NOTIFY leftBlinkerChanged) + Q_PROPERTY(bool lowBeam READ getLowBeam NOTIFY lowBeamChanged) + Q_PROPERTY(bool highBeam READ getHighBeam NOTIFY highBeamChanged) + Q_PROPERTY( + bool frontFogLight READ getFrontFogLight NOTIFY frontFogLightChanged) + Q_PROPERTY( + bool readFogLight READ getRearFogLight NOTIFY rearFogLightChanged) + Q_PROPERTY(bool hazardLight READ getHazardLight NOTIFY hazardLightChanged) + Q_PROPERTY( + bool parkingLight READ getParkingLight NOTIFY parkingLightChanged) + Q_PROPERTY(GearPosition gear READ getGear NOTIFY gearChanged) + + public: + enum class GearPosition + { + PARK, + REVERSE, + NEUTRAL, + DRIVE + }; + + Q_ENUM(GearPosition) + + private: + int m_speed; + int m_battery; + bool m_rightBlinker; + bool m_leftBlinker; + bool m_lowBeam; + bool m_highBeam; + bool m_frontFogLight; + bool m_rearFogLight; + bool m_hazardLight; + bool m_parkingLight; + GearPosition m_gear; + + Session& m_session; + + public: + explicit InstrumentCluster(Session& session, QObject* parent = nullptr); + ~InstrumentCluster(); + + int getSpeed() const; + int getBattery() const; + bool getRightBlinker() const; + bool getLeftBlinker() const; + bool getLowBeam() const; + bool getHighBeam() const; + bool getFrontFogLight() const; + bool getRearFogLight() const; + bool getHazardLight() const; + bool getParkingLight() const; + GearPosition getGear() const; + + void setSpeed(int speed); + void setBattery(int battery); + void setRightBlinker(bool rightBlinker); + void setLeftBlinker(bool leftBlinker); + void setLowBeam(bool lowBeam); + void setHighBeam(bool highBeam); + void setFrontFogLight(bool frontFogLight); + void setRearFogLight(bool readFogLight); + void setHazardLight(bool hazardLight); + void setParkingLight(bool parkingLight); + void setGear(GearPosition gear); + + signals: + void speedChanged(int speed); + void batteryChanged(int battery); + void rightBlinkerChanged(bool rightBlinker); + void leftBlinkerChanged(bool leftBlinker); + void lowBeamChanged(bool lowBeam); + void highBeamChanged(bool highBeam); + void frontFogLightChanged(bool frontFogLight); + void rearFogLightChanged(bool readFogLight); + void hazardLightChanged(bool hazardLight); + void parkingLightChanged(bool parkingLight); + void gearChanged(GearPosition gear); +}; + +#endif // INSTRUMENTCLUSTER_HPP diff --git a/src/CANBusHandler.cpp b/src/CANBusHandler.cpp deleted file mode 100644 index 23fb595..0000000 --- a/src/CANBusHandler.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../include/CANBusHandler.hpp" - -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) - { - qWarning() << "Cannot create CAN socket!"; - return; - } - - strcpy(ifr.ifr_name, "can0"); - ioctl(canSocket, SIOCGIFINDEX, &ifr); - - addr.can_family = AF_CAN; - addr.can_ifindex = ifr.ifr_ifindex; - if (bind(canSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) - { - qWarning() << "Cannot bind CAN socket!"; - close(canSocket); - return; - } - - qDebug() << "CAN socket bound to can0 interface successfully."; - - // Set up a timer to periodically read frames - 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 - } -} - -int CANBusHandler::getSpeed() const -{ - return m_speed; -} - -void CANBusHandler::setSpeed(int 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) - { - qWarning() << "Error reading CAN frame!"; - return; - } - - 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 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/InstrumentCluster.cpp b/src/InstrumentCluster.cpp new file mode 100644 index 0000000..d8c0f11 --- /dev/null +++ b/src/InstrumentCluster.cpp @@ -0,0 +1,168 @@ +#include "../include/InstrumentCluster.hpp" + +InstrumentCluster::InstrumentCluster(Session& session, QObject* parent) + : QObject(parent), m_speed(0), m_battery(0), m_rightBlinker(false), + m_leftBlinker(false), m_lowBeam(false), m_highBeam(false), + m_frontFogLight(false), m_rearFogLight(false), m_hazardLight(false), + m_parkingLight(false), m_gear(GearPosition::PARK), m_session(session) +{ +} + +InstrumentCluster::~InstrumentCluster() +{ + m_session.close(); +} + +int InstrumentCluster::getSpeed() const +{ + return m_speed; +} + +int InstrumentCluster::getBattery() const +{ + return m_battery; +} + +bool InstrumentCluster::getRightBlinker() const +{ + return m_rightBlinker; +} + +bool InstrumentCluster::getLeftBlinker() const +{ + return m_leftBlinker; +} + +bool InstrumentCluster::getLowBeam() const +{ + return m_lowBeam; +} + +bool InstrumentCluster::getHighBeam() const +{ + return m_highBeam; +} + +bool InstrumentCluster::getFrontFogLight() const +{ + return m_frontFogLight; +} + +bool InstrumentCluster::getRearFogLight() const +{ + return m_rearFogLight; +} + +bool InstrumentCluster::getHazardLight() const +{ + return m_hazardLight; +} + +bool InstrumentCluster::getParkingLight() const +{ + return m_parkingLight; +} + +InstrumentCluster::GearPosition InstrumentCluster::getGear() const +{ + return m_gear; +} + +void InstrumentCluster::setSpeed(int speed) +{ + if (m_speed != speed) + { + m_speed = speed; + emit speedChanged(m_speed); + } +} + +void InstrumentCluster::setBattery(int battery) +{ + if (m_battery != battery) + { + m_battery = battery; + emit batteryChanged(m_battery); + } +} + +void InstrumentCluster::setRightBlinker(bool rightBlinker) +{ + if (m_rightBlinker != rightBlinker) + { + m_rightBlinker = rightBlinker; + emit rightBlinkerChanged(m_rightBlinker); + } +} + +void InstrumentCluster::setLeftBlinker(bool leftBlinker) +{ + if (m_leftBlinker != leftBlinker) + { + m_leftBlinker = leftBlinker; + emit leftBlinkerChanged(m_leftBlinker); + } +} + +void InstrumentCluster::setLowBeam(bool lowBeam) +{ + if (m_lowBeam != lowBeam) + { + m_lowBeam = lowBeam; + emit lowBeamChanged(m_lowBeam); + } +} + +void InstrumentCluster::setHighBeam(bool highBeam) +{ + if (m_highBeam != highBeam) + { + m_highBeam = highBeam; + emit highBeamChanged(m_highBeam); + } +} + +void InstrumentCluster::setFrontFogLight(bool frontFogLight) +{ + if (m_frontFogLight != frontFogLight) + { + m_frontFogLight = frontFogLight; + emit frontFogLightChanged(m_frontFogLight); + } +} + +void InstrumentCluster::setRearFogLight(bool rearFogLight) +{ + if (m_rearFogLight != rearFogLight) + { + m_rearFogLight = rearFogLight; + emit rearFogLightChanged(m_rearFogLight); + } +} + +void InstrumentCluster::setHazardLight(bool hazardLight) +{ + if (m_hazardLight != hazardLight) + { + m_hazardLight = hazardLight; + emit hazardLightChanged(m_hazardLight); + } +} + +void InstrumentCluster::setParkingLight(bool parkingLight) +{ + if (m_parkingLight != parkingLight) + { + m_parkingLight = parkingLight; + emit parkingLightChanged(m_parkingLight); + } +} + +void InstrumentCluster::setGear(GearPosition gear) +{ + if (m_gear != gear) + { + m_gear = gear; + emit gearChanged(m_gear); + } +} diff --git a/src/Main.qml b/src/Main.qml deleted file mode 100644 index e7f8c01..0000000 --- a/src/Main.qml +++ /dev/null @@ -1,115 +0,0 @@ -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import canbus 1.0 - -ApplicationWindow { - visible: true - width: Screen.width - height: Screen.height - title: "Instrument Cluster with Smooth Transitions" - - CANBusHandler { - id: canBusHandler - onSpeedChanged: speedGauge.requestPaint() - onBatteryChanged: batteryGauge.requestPaint() - } - - Rectangle { - anchors.fill: parent - - // Background Gradient - Canvas { - anchors.fill: parent - onPaint: { - var ctx = getContext("2d"); - var gradient = ctx.createLinearGradient(0, 0, 0, height); - gradient.addColorStop(0, "#001848"); // Top dark blue - gradient.addColorStop(1, "#000022"); // Bottom darker blue - ctx.fillStyle = gradient; - ctx.fillRect(0, 0, width, height); - } - } - - // Top Highlight Bar - Canvas { - height: 50 - width: parent.width - anchors.top: parent.top - onPaint: { - var ctx = getContext("2d"); - var gradient = ctx.createLinearGradient(0, 0, 0, height); - gradient.addColorStop(0, "rgba(255, 255, 255, 0.1)"); - gradient.addColorStop(1, "transparent"); - ctx.fillStyle = gradient; - ctx.fillRect(0, 0, width, height); - } - } - - // Bottom Shadow Bar - Canvas { - height: 50 - width: parent.width - anchors.bottom: parent.bottom - onPaint: { - var ctx = getContext("2d"); - var gradient = ctx.createLinearGradient(0, 0, 0, height); - gradient.addColorStop(0, "transparent"); - gradient.addColorStop(1, "rgba(0, 0, 0, 0.5)"); - ctx.fillStyle = gradient; - ctx.fillRect(0, 0, width, height); - } - } - - // Left Speedometer Gauge - Canvas { - id: speedGauge - width: 300 - height: 300 - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 20 - - onPaint: { - var ctx = getContext("2d"); - ctx.clearRect(0, 0, width, height); - - // Speed Value - ctx.font = "36px sans-serif"; - ctx.fillStyle = "white"; - ctx.textAlign = "center"; - ctx.fillText(canBusHandler.speed, width / 2, height / 2); - - // Label - ctx.font = "18px sans-serif"; - ctx.fillStyle = "lightgray"; - ctx.fillText("Speed", width / 2, height / 2 + 40); - } - } - - // Right Battery Status Gauge - Canvas { - id: batteryGauge - width: 300 - height: 300 - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 20 - - onPaint: { - var ctx = getContext("2d"); - ctx.clearRect(0, 0, width, height); - - // Battery Value - ctx.font = "36px sans-serif"; - ctx.fillStyle = "white"; - ctx.textAlign = "center"; - ctx.fillText(canBusHandler.battery + " %", width / 2, height / 2); - - // Label - ctx.font = "18px sans-serif"; - ctx.fillStyle = "lightgray"; - ctx.fillText("Battery", width / 2, height / 2 + 40); - } - } - } -} diff --git a/src/main.cpp b/src/main.cpp index 925258e..ffbc34f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,22 +1,20 @@ #include #include -#include #include -#include -#include "../include/CANBusHandler.hpp" +#include "../include/InstrumentCluster.hpp" int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); - QQmlApplicationEngine engine; - qmlRegisterType("canbus", 1, 0, "CANBusHandler"); + Config config = Config::create_default(); + auto session = Session::open(std::move(config)); - CANBusHandler canBusHandler; - engine.rootContext()->setContextProperty("canBusHandler", &canBusHandler); + InstrumentCluster instrumentCluster(session); + engine.rootContext()->setContextProperty("instrumentCluster", + &instrumentCluster); - // Load QML file const QUrl url(QStringLiteral("qrc:/Main.qml")); QObject::connect( &engine, &QQmlApplicationEngine::objectCreated, &app, @@ -28,5 +26,117 @@ int main(int argc, char* argv[]) Qt::QueuedConnection); engine.load(url); + auto speed_handler = [&instrumentCluster](const Sample& sample) + { + int speed = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub speed: " << speed << std::endl; + instrumentCluster.setSpeed(speed); + }; + + auto battery_handler = [&instrumentCluster](const Sample& sample) + { + int battery = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub battery: " << battery << std::endl; + instrumentCluster.setBattery(battery); + }; + + auto rightBlinker_handler = [&instrumentCluster](const Sample& sample) + { + int rightBlinker = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub rightBlinker: " << rightBlinker << std::endl; + instrumentCluster.setRightBlinker(rightBlinker); + }; + + auto leftBlinker_handler = [&instrumentCluster](const Sample& sample) + { + int leftBlinker = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub leftBlinker: " << leftBlinker << std::endl; + instrumentCluster.setLeftBlinker(leftBlinker); + }; + + auto lowBeam_handler = [&instrumentCluster](const Sample& sample) + { + int lowBeam = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub lowBeam: " << lowBeam << std::endl; + instrumentCluster.setLowBeam(lowBeam); + }; + + auto highBeam_handler = [&instrumentCluster](const Sample& sample) + { + int highBeam = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub highBeam: " << highBeam << std::endl; + instrumentCluster.setHighBeam(highBeam); + }; + + auto frontFogLight_handler = [&instrumentCluster](const Sample& sample) + { + int frontFogLight = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub frontFogLight: " << frontFogLight << std::endl; + instrumentCluster.setFrontFogLight(frontFogLight); + }; + + auto rearFogLight_handler = [&instrumentCluster](const Sample& sample) + { + int rearFogLight = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub rearFogLight: " << rearFogLight << std::endl; + instrumentCluster.setRearFogLight(rearFogLight); + }; + + auto hazardLight_handler = [&instrumentCluster](const Sample& sample) + { + int hazardLight = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub frontFogLight: " << hazardLight << std::endl; + instrumentCluster.setHazardLight(hazardLight); + }; + + auto parkingLight_handler = [&instrumentCluster](const Sample& sample) + { + int parkingLight = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub parkingLight: " << parkingLight << std::endl; + instrumentCluster.setParkingLight(parkingLight); + }; + + auto gear_handler = [&instrumentCluster](const Sample& sample) + { + int gear = std::stoi(sample.get_payload().as_string()); + std::cout << "Sub gear: " << gear << std::endl; + instrumentCluster.setGear(InstrumentCluster::GearPosition::PARK); + }; + + auto subSpeed = session.declare_subscriber("seame/car/1/speedSensor", + speed_handler, closures::none); + + auto subBattery = session.declare_subscriber( + "seame/car/1/batterySensor", battery_handler, closures::none); + + auto subRightBlinker = session.declare_subscriber( + "seame/car/1/rightBlinker", rightBlinker_handler, closures::none); + + auto subLeftBlinker = session.declare_subscriber( + "seame/car/1/leftBlinker", leftBlinker_handler, closures::none); + + auto subLowBeam = session.declare_subscriber( + "seame/car/1/lowBeam", lowBeam_handler, closures::none); + + auto subHighBeam = session.declare_subscriber( + "seame/car/1/highBeam", highBeam_handler, closures::none); + + auto subFrontFogLight = session.declare_subscriber( + "seame/car/1/frontFogLight", frontFogLight_handler, closures::none); + + auto subRearFogLight = session.declare_subscriber( + "seame/car/1/rearFogLight", rearFogLight_handler, closures::none); + + auto subHazardLight = session.declare_subscriber( + "seame/car/1/hazardLight", hazardLight_handler, closures::none); + + auto subParkingLight = session.declare_subscriber( + "seame/car/1/parkingLight", parkingLight_handler, closures::none); + + auto subGear = session.declare_subscriber("seame/car/1/gear", gear_handler, + closures::none); + + std::cout << "Subs created!" << std::endl; + return app.exec(); } diff --git a/src/resources.qrc b/src/resources.qrc deleted file mode 100644 index f907b18..0000000 --- a/src/resources.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - Main.qml - - diff --git a/ui/FootbarInfo.qml b/ui/FootbarInfo.qml new file mode 100644 index 0000000..66ea725 --- /dev/null +++ b/ui/FootbarInfo.qml @@ -0,0 +1,91 @@ +import QtQuick 2.15 + +Row { + width: parent.width + height: 50 + spacing: 30 + padding: 10 + Column { + + Row { + + anchors.verticalCenterOffset: -10 + Image { + id: batteryLevel + // source: { + // if (canBusHandler.battery >= 80) { + // "qrc:/assets/icons/battery-5.png" + // } else if (canBusHandler.battery >= 60) { + // "qrc:/assets/icons/battery-4.png" + // } else if (canBusHandler.battery >= 40) { + // "qrc:/assets/icons/battery-3.png" + // } else if (canBusHandler.battery >= 20) { + // "qrc:/assets/icons/battery-2.png" + // } else { + // "qrc:/assets/icons/battery-1.png" + // } + // } + width: 80 + visible: true + fillMode: Image.PreserveAspectFit + source: "qrc:/assets/icons/battery-5.png" + // Adjust this value to move the image up or down + } + } + // Row { + // spacing: 5 + + // Text { + // font.family: "Open Sans" + // //text: canBusHandler.battery + // text: "100" + // font.pixelSize: app.letterSize + // color: "white" + // } + // Text { + // font.family: "Open Sans" + // text: "%" + // font.pixelSize: app.letterSize + // color: "gray" + // } + // } + } + + Column { + + Row { + spacing: 5 + Text { + font.family: "Open Sans" + text: "256" + font.pixelSize: app.letterSize + color: "white" + } + Text { + font.family: "Open Sans" + text: "mi" + font.pixelSize: app.letterSize + color: "gray" + } + } + } + Column { + + Row { + spacing: 5 + Text { + font.family: "Open Sans" + text: "22°" + font.pixelSize: app.letterSize + color: "white" + } + Text { + font.family: "Open Sans" + text: "C" + font.pixelSize: app.letterSize + color: "gray" + } + } + } + +} diff --git a/ui/GearShiftInfo.qml b/ui/GearShiftInfo.qml new file mode 100644 index 0000000..ef5bbce --- /dev/null +++ b/ui/GearShiftInfo.qml @@ -0,0 +1,29 @@ +import QtQuick 2.15 + +Column { + spacing: 10 + Text { + font.family: "Open Sans" + text: "P" + font.pixelSize: app.letterSize + color: "gray" + } + Text { + font.family: "Open Sans" + text: "R" + font.pixelSize: app.letterSize + color: "gray" + } + Text { + font.family: "Open Sans" + text: "N" + font.pixelSize: app.letterSize + color: "gray" + } + Text { + font.family: "Open Sans" + text: "D" + font.pixelSize: app.letterSize + color: "blue" + } +} \ No newline at end of file diff --git a/ui/LightInfo.qml b/ui/LightInfo.qml new file mode 100644 index 0000000..0994884 --- /dev/null +++ b/ui/LightInfo.qml @@ -0,0 +1,46 @@ +import QtQuick 2.15 + +Row { + spacing: 10 + padding: 10 + + Image { + id: lowBeamSignal + source: "qrc:/assets/icons/low_beam_on.png" + width: app.iconWidth + height: app.iconHeight + visible: true + } + + Image { + id: highBeamSignal + source: "qrc:/assets/icons/high_beam_on.png" + width: app.iconWidth + height: app.iconHeight + visible: true + } + + Image { + id: frontFogSignal + source: "qrc:/assets/icons/front_fog_on.png" + width: app.iconWidth + height: app.iconHeight + visible: true + } + + Image { + id: parkingLightsSignal + source: "qrc:/assets/icons/parking_lights_on.png" + width: app.iconWidth + height: app.iconHeight + visible: true + } + + Image { + id: backFogSignal + source: "qrc:/assets/icons/back_fog_on.png" + width: app.iconWidth + height: app.iconHeight + visible: true + } +} diff --git a/ui/Main.qml b/ui/Main.qml new file mode 100644 index 0000000..37c78f3 --- /dev/null +++ b/ui/Main.qml @@ -0,0 +1,136 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +ApplicationWindow { + id: app + visible: true + width: Screen.width + height: Screen.height + // flags: Qt.FramelessWindowHint + + property int letterSize: 25 + property int iconWidth: 40 + property int iconHeight: 40 + property bool carClusterVisible: true + + property bool showSplash: true + + font.family: "Roboto" + font.pixelSize: 30 + font.bold: false + + // Car CLuster + Rectangle { + anchors.fill: parent + visible: app.carClusterVisible + + // Background Gradient + Canvas { + anchors.fill: parent + onPaint: { + var ctx = getContext("2d"); + ctx.fillStyle = "#000000"; + ctx.fillRect(0, 0, width, height); + } + } + + Row { + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 100 + spacing: 10 + + TurnSignals { + isLeft: true + isBlinking: true + } + SpeedDisplay {} + TurnSignals { + isLeft: false + isBlinking: false + } + } + + GearShiftInfo { + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 20 + } + + LightInfo { + anchors.top: parent.top + anchors.topMargin: 30 + anchors.left: parent.left + anchors.leftMargin: 70 + } + + FootbarInfo { + anchors.bottom: parent.bottom + anchors.bottomMargin: 60 + anchors.left: parent.left + anchors.leftMargin: 70 + } + + TimeInfo { + anchors.bottom: parent.bottom + anchors.bottomMargin: 60 + anchors.right: parent.right + anchors.rightMargin: 70 + } + } + + // Logo Screen + Rectangle { + id: splashScreen + visible: app.showSplash + anchors.fill: parent + color: "black" + + // O retângulo sempre fica visível, mas apenas o logo tem a opacidade animada + Image { + id: logo + source: "qrc:/assets/icons/seame-logo.png" // Substitua pelo logo do carro + anchors.centerIn: parent + width: parent.width * 0.5 + height: parent.width * 0.5 + fillMode: Image.PreserveAspectFit + opacity: 1.0 // Começa visível + + SequentialAnimation { + running: true + loops: 1 + + // Transição para mostrar o logo + PropertyAnimation { + target: logo + property: "opacity" + from: 0.0 + to: 1.0 + duration: 3000 // 3 segundos + } + + PauseAnimation { duration: 1000 } // Aguarda 1 segundo com o logo visível + + // Transição para esconder o logo + PropertyAnimation { + target: logo + property: "opacity" + from: 1.0 + to: 0.0 + duration: 2000 // 2 segundos + } + + PauseAnimation { duration: 1000 } // Aguarda 2 segundos com a tela preta + + ScriptAction { + script: { + app.showSplash = false; // Oculta a splash screen + app.carClusterVisible = true; // Mostra o cluster + } + } + } + } + } + + +} \ No newline at end of file diff --git a/ui/SpeedDisplay.qml b/ui/SpeedDisplay.qml new file mode 100644 index 0000000..b7f1e3a --- /dev/null +++ b/ui/SpeedDisplay.qml @@ -0,0 +1,21 @@ +import QtQuick 2.15 + +Column { + spacing: 5 + + Text { + font.family: "Open Sans" + text: instrumentCluster.speed + font.pixelSize: 110 + color: "white" + opacity: 1.0 + } + + Text { + anchors.horizontalCenter: parent.horizontalCenter + font.family: "Open Sans" + text: "DM/S" + font.pixelSize: app.letterSize + color: "gray" + } +} diff --git a/ui/TimeInfo.qml b/ui/TimeInfo.qml new file mode 100644 index 0000000..af12b9b --- /dev/null +++ b/ui/TimeInfo.qml @@ -0,0 +1,60 @@ +import QtQuick 2.15 + +Row { + spacing: 5 + + // Hora + Text { + font.family: "Open Sans" + id: timeDisplay + text: "11:11" + font.pixelSize: app.letterSize + color: "white" + opacity: 0.0 + } + + // AM/PM + Text { + font.family: "Open Sans" + id: amPmDisplay + text: "AM" + font.pixelSize: app.letterSize + color: "gray" + opacity: 0.0 + } + + Timer { + id: clockTimer + interval: 1000 // Atualiza a cada 1 segundo + running: true + repeat: true + onTriggered: { + timeDisplay.text = timeHelper.getCurrentTime(); + timeDisplay.opacity = 1.0 + + amPmDisplay.text = timeHelper.getCurrentAmPm(); + amPmDisplay.opacity = 1.0 + } + } + + // Funções encapsuladas em um QtObject + QtObject { + id: timeHelper + + function getCurrentTime() { + const currentDate = new Date(); + let hours = currentDate.getHours(); + let minutes = currentDate.getMinutes(); + + hours = hours % 12 || 12; + minutes = minutes < 10 ? "0" + minutes : minutes + + return hours + ":" + minutes; + } + + function getCurrentAmPm() { + const currentDate = new Date(); + return currentDate.getHours() >= 12 ? "PM" : "AM"; + } + } +} \ No newline at end of file diff --git a/ui/TurnSignals.qml b/ui/TurnSignals.qml new file mode 100644 index 0000000..3d33a4e --- /dev/null +++ b/ui/TurnSignals.qml @@ -0,0 +1,32 @@ +import QtQuick 2.15 + +Row { + id: root + spacing: 10 + + property bool isLeft: true + property bool isBlinking: false + + Image { + anchors.verticalCenter: parent.verticalCenter + id: turnSignal + source: isLeft ? "qrc:/assets/icons/turn_left_on.png" : "qrc:/assets/icons/turn_right_on.png" + width: 70 + height: 70 + opacity: 0.0 + + Timer { + id: blinkTimer + interval: 500 + running: root.isBlinking + repeat: true + onTriggered: { + if (turnSignal.isBlinking) { + turnSignal.opacity = turnSignal.opacity === 1.0 ? 0.0 : 1.0; + } else { + turnSignal.opacity = 0.0; + } + } + } + } +} diff --git a/ui/resources.qrc b/ui/resources.qrc new file mode 100644 index 0000000..27ab5eb --- /dev/null +++ b/ui/resources.qrc @@ -0,0 +1,29 @@ + + + Main.qml + TurnSignals.qml + SpeedDisplay.qml + LightInfo.qml + FootbarInfo.qml + GearShiftInfo.qml + TimeInfo.qml + + + + + ../assets/icons/back_fog_on.png + ../assets/icons/front_fog_on.png + ../assets/icons/green-battery.png + ../assets/icons/high_beam_on.png + ../assets/icons/low_beam_on.png + ../assets/icons/parking_lights_on.png + ../assets/icons/turn_left_on.png + ../assets/icons/turn_right_on.png + ../assets/icons/seame-logo.png + ../assets/icons/battery-1.png + ../assets/icons/battery-2.png + ../assets/icons/battery-3.png + ../assets/icons/battery-4.png + ../assets/icons/battery-5.png + + \ No newline at end of file