diff --git a/CMakeLists.txt b/CMakeLists.txt index af9d77b..1502f7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ if (NOT Boost_FOUND) URL https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2 ) FetchContent_MakeAvailable(boost) - # Adjust the include path as needed based on how Boost is structured when fetched + endif () ####### Testing Configuration ####### @@ -105,13 +105,11 @@ function(add_hardware_test TEST_NAME TEST_FILE) add_test(NAME ${TEST_NAME}UnitTest COMMAND ${TEST_NAME}) endfunction(add_hardware_test) - -# Assuming the Timer class is part of the 'utils' group of files -set(TIMER_SOURCES include/utils/Timer.h) # Adjust path as necessary - # Define a function for non-hardware tests if not already existing function(add_unit_test TEST_NAME TEST_FILE) - add_executable(${TEST_NAME} ${TEST_FILE} ${TIMER_SOURCES}) + cmake_parse_arguments(ADD_UNIT_TEST "" "ADDITIONAL_SOURCES" "" ${ARGN}) + + add_executable(${TEST_NAME} ${TEST_FILE} ${ADD_UNIT_TEST_ADDITIONAL_SOURCES}) # Include additional sources if provided target_link_libraries(${TEST_NAME} ${Boost_LIBRARIES} cpr::cpr) # Add other dependencies as needed target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include) add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) @@ -127,20 +125,18 @@ else () message(STATUS "Configuring tests for non-Raspberry Pi environment.") include_directories(${CMAKE_SOURCE_DIR}/include) + # Add hardware tests for actuators and sensors add_hardware_test(BuzzerTest "tests/hardware_tests/actuators/Buzzer_test.cpp") add_hardware_test(LEDTest "tests/hardware_tests/actuators/LED_test.cpp") add_hardware_test(UltrasonicSensorTest "tests/hardware_tests/sensors/Ultrasonic_test.cpp") - - # Ideas of tests to be implemented (priority order): - # add_hardware_test(CameraSensorTest "tests/hardware_tests/sensors/Camera_test.cpp") - # add_hardware_test(PushButtonTest "tests/hardware_tests/sensors/PushButton_test.cpp") - add_unit_test(TimerTest "tests/TimerTest.cpp") - # add_unit_test(CheckingSystemTest "tests/hardware_tests/main/CheckingSystem_test.cpp") - # add_unit_test(WarningSystemTest "tests/hardware_tests/main/WarningSystem_test.cpp") - # add_unit_test(TrafficLightTest "tests/hardware_tests/models/TrafficLight_test.cpp") - # add_unit_test(CarsTrafficLightSystemTest "tests/hardware_tests/main/CarsTrafficLightSystem_test.cpp") - # add_unit_test(PedestriansTrafficLightSystemTest "tests/hardware_tests/main/PedestriansTrafficLightSystem_test.cpp") - # add_unit_test(FirestoreLoggerTest "tests/hardware_tests/utils/FirestoreLogger_test.cpp") - # add_unit_test(MainSystemTest "tests/hardware_tests/main/MainSystem_test.cpp") + add_hardware_test(PushButtonTest "tests/hardware_tests/sensors/PushButton_test.cpp") + + # Add logic tests for the main system and its components + add_hardware_test(CheckingSystemTest "tests/logic_tests/main/CheckingSystem_test.cpp") + add_hardware_test(WarningSystemTest "tests/logic_tests/main/WarningSystem_test.cpp") + add_hardware_test(TrafficLightTest "tests/logic_tests/models/TrafficLight_test.cpp") + + # Add unit tests for the utility classes + add_unit_test(TimerTest "tests/logic_tests/utils/Timer_test.cpp" ADDITIONAL_SOURCES "include/utils/Timer.h") endif () diff --git a/Doxyfile b/Doxyfile index 937413e..01192f0 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2502,7 +2502,7 @@ HIDE_UNDOC_RELATIONS = YES # set to NO # The default value is: NO. -HAVE_DOT = NO +HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed # to run in parallel. When set to 0 doxygen will base this on the number of @@ -2566,7 +2566,7 @@ DOT_FONTPATH = # The default value is: YES. CLASS_GRAPH = YES - +CLASS_DIAGRAMS = YES # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a # graph for each documented class showing the direct and indirect implementation # dependencies (inheritance, containment, and class references variables) of the @@ -2596,7 +2596,7 @@ GROUP_GRAPHS = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -UML_LOOK = NO +UML_LOOK = YES # If the UML_LOOK tag is enabled, the fields and methods are shown inside the # class node. If there are many fields or methods and many nodes the graph may @@ -2745,7 +2745,7 @@ INTERACTIVE_SVG = NO # found. If left blank, it is assumed the dot tool can be found in the path. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_PATH = +DOT_PATH = /opt/homebrew/bin/dot # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the \dotfile diff --git a/include/main/CheckingSystem.h b/include/main/CheckingSystem.h index 85c3a0a..7fa7f47 100644 --- a/include/main/CheckingSystem.h +++ b/include/main/CheckingSystem.h @@ -33,7 +33,7 @@ class CheckingSystem { public: - CheckingSystem(); ///< Constructor to initialize the system with default states and sensor configurations. + CheckingSystem(); ///< Constructor to initialize the system with default states and sensor configurations. ~CheckingSystem(); ///< Destructor to clean up resources, ensuring all threads are joined if necessary. void initialize(); ///< Initialize sensors and system components. @@ -42,23 +42,28 @@ class CheckingSystem { void onPedestriansButtonPress(); ///< Handler for pedestrian button presses. - void registerCarsMotionCallback(const std::function& callback); - void registerPedestriansMotionCallback(const std::function& callback); - void registerPedestriansButtonCallback(const std::function& callback); + void registerCarsMotionCallback(const std::function &callback); + + void registerPedestriansMotionCallback(const std::function &callback); + + void registerPedestriansButtonCallback(const std::function &callback); void enablePedestriansMotionDetection(); + void disablePedestriansMotionDetection(); void enableCarsMotionDetection(); + void disableCarsMotionDetection(); void enablePedestriansButton(); + void disablePedestriansButton(); void enableSensing(); ///< Enable all sensors and detection mechanisms. void disableSensing(); ///< Disable all sensors and detection mechanisms. - + bool isRoadMotionDetected(); private: std::atomic isActive; ///< Indicates if the system is currently active. @@ -82,6 +87,7 @@ class CheckingSystem { void monitorPedestrian(); ///< Function to monitor pedestrian movements continuously. void monitorRoad(); ///< Function to monitor vehicle movements continuously. + void monitorPedestriansButton(); }; #endif // CHECKINGSYSTEM_H diff --git a/include/main/WarningSystem.h b/include/main/WarningSystem.h index 8db6f77..a7ee17d 100644 --- a/include/main/WarningSystem.h +++ b/include/main/WarningSystem.h @@ -17,8 +17,7 @@ * activation, and deactivation methods. Utilizes predefined pin numbers * from the Constants class for LED and buzzer components. */ -class WarningSystem : public SystemInterface -{ +class WarningSystem : public SystemInterface { public: /** * @brief Constructs a new Warning System instance. @@ -35,6 +34,13 @@ class WarningSystem : public SystemInterface */ void initialize() override; + /** + * @brief Getter of the isInitialized_ variable + * + * Return the value of isInitialized_. + */ + bool isInitialized() const { return isInitialized_; } + /** * @brief Activates the warning system. * @@ -59,7 +65,7 @@ class WarningSystem : public SystemInterface LED warningLED2; ///< Second LED component. LED warningLED3; ///< Third LED component. Buzzer warningBuzzer; ///< Buzzer component. - bool isInitialized; ///< Flag indicating whether the system has been initialized. + bool isInitialized_; ///< Flag indicating whether the system has been initialized. }; #endif // WARNING_SYSTEM_H diff --git a/include/pigpio_stub.h b/include/pigpio_stub.h index f823b5a..07d013a 100644 --- a/include/pigpio_stub.h +++ b/include/pigpio_stub.h @@ -17,6 +17,7 @@ extern const int PI_LOW; #define PI_PUD_DOWN 0 #define PI_PUD_OFF 0 #define FALLING_EDGE 0 +#define RISING_EDGE 1 // Function declarations to mimic those in the pigpio library. int gpioInitialise(); diff --git a/include/sensors/PushButton.h b/include/sensors/PushButton.h index f832a15..ed135d3 100644 --- a/include/sensors/PushButton.h +++ b/include/sensors/PushButton.h @@ -31,12 +31,12 @@ class PushButton { * @param pin The GPIO pin number associated with the button. */ PushButton(int pin); - - /** - * @brief Destructor that cleans up ISR handling if necessary. - */ + + /** + * @brief Destructor that cleans up ISR handling if necessary. + */ ~PushButton(); - + /** * @brief Initializes the button's GPIO pin and sets up the interrupt service routine. * @@ -44,13 +44,34 @@ class PushButton { * that is triggered on the falling edge (button press). */ void initialize(); - + + /** + * @brief Detaches the interrupt service routine from the GPIO pin. + */ + void detachInterruptHandler(); + + /** + * @brief Attaches the interrupt service routine to the GPIO pin. + */ + void attachInterruptHandler(); + + /** + * @brief Initializes the GPIO pin as an input. + */ + void gpioInit(); + /** * @brief Registers a callback function to be called when the button is pressed. * @param callback The function to call when the button is pressed. */ void registerButtonPressCallback(ButtonCallback callback); + /** + * @brief Registers a callback function to be called when the button is released. + * @param callback The function to call when the button is released. + */ + void registerButtonReleaseCallback(ButtonCallback callback); + // Disabling copy constructor and assignment operator PushButton(const PushButton &) = delete; @@ -60,6 +81,7 @@ class PushButton { private: int gpioPin; ///< GPIO pin number. ButtonCallback buttonPressCallback; ///< User-defined callback function to handle button press events. + ButtonCallback buttonReleaseCallback; ///< User-defined callback function to handle button release events. /** * @brief Static method used as the interrupt service routine for button presses. @@ -72,4 +94,4 @@ class PushButton { }; -#endif //CROSSGUARD_PUSHBUTTON_H +#endif //CROSSGUARD_PUSHBUTTON_H \ No newline at end of file diff --git a/include/utils/FirestoreLogger.h b/include/utils/FirestoreLogger.h index 61b06f6..725007e 100644 --- a/include/utils/FirestoreLogger.h +++ b/include/utils/FirestoreLogger.h @@ -43,6 +43,10 @@ class FirestoreLogger { */ static void Log(const std::string &level, const std::string &message); + static std::string GetApiKey(); + + static std::string GetBaseUrl(); + private: /** * @brief Generates a timestamp string in ISO 8601 format. diff --git a/src/main.cpp b/src/main.cpp index 5d31ac2..d418c78 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,14 +44,16 @@ void initApplication() { try { FirestoreLogger::Initialize("INITIALIZE"); FirestoreLogger::Log("INFO", "Application Started!"); - } catch (const std::exception &e) { + } + catch (const std::exception &e) { std::cerr << "Failed to connect to firebase: " << e.what() << std::endl; } try { Logger::init("app.log"); Logger::logInfo("Application starting"); - } catch (const std::exception &e) { + } + catch (const std::exception &e) { std::cerr << "Failed to initialize logger: " << e.what() << std::endl; } } @@ -63,9 +65,8 @@ void closeApplication(MainSystem &mainSystem) { try { Logger::logInfo("Application stopping"); Logger::close(); - } catch (const std::exception &e) { + } + catch (const std::exception &e) { std::cerr << "Failed to close logger: " << e.what() << std::endl; } - - } \ No newline at end of file diff --git a/src/main/CheckingSystem.cpp b/src/main/CheckingSystem.cpp index e6edcbd..2d9ad5d 100644 --- a/src/main/CheckingSystem.cpp +++ b/src/main/CheckingSystem.cpp @@ -19,8 +19,10 @@ CheckingSystem::CheckingSystem() : isActive(false), monitorPedestriansActive(false), monitorRoadsActive(false), pedestriansButtonEnabled(false), - pedestrianSensor(Constants::CheckingSystemUltrasonic2TriggerPin, Constants::CheckingSystemUltrasonic2EchoPin), - roadSensor(Constants::CheckingSystemUltrasonic1TriggerPin, Constants::CheckingSystemUltrasonic1EchoPin), + pedestrianSensor(Constants::CheckingSystemUltrasonic2TriggerPin, + Constants::CheckingSystemUltrasonic2EchoPin), + roadSensor(Constants::CheckingSystemUltrasonic1TriggerPin, + Constants::CheckingSystemUltrasonic1EchoPin), pedestriansPushButton(Constants::CheckingSystemButtonPin) {} /** @@ -28,8 +30,7 @@ CheckingSystem::CheckingSystem() : isActive(false), * Ensures all components are properly deactivated and threads are joined before destruction. */ -CheckingSystem::~CheckingSystem() -{ +CheckingSystem::~CheckingSystem() { deactivate(); // Ensure threads are properly joined and sensors are deactivated } @@ -37,14 +38,12 @@ CheckingSystem::~CheckingSystem() * @brief Initializes sensors and registers button press callbacks. * Configures and initializes all associated sensors and registers callback for the pedestrian button. */ -void CheckingSystem::initialize() -{ +void CheckingSystem::initialize() { // Initialize sensors and register button press callbacks pedestrianSensor.initialize(); roadSensor.initialize(); pedestriansPushButton.initialize(); - pedestriansPushButton.registerButtonPressCallback([this]() - { this->onPedestriansButtonPress(); }); + pedestriansPushButton.registerButtonPressCallback([this]() { this->onPedestriansButtonPress(); }); } /** @@ -62,8 +61,7 @@ void CheckingSystem::initialize() * @throws std::system_error if thread creation fails. * @see initialize(), enableSensing(), disableSensing() */ -void CheckingSystem::run() -{ +void CheckingSystem::run() { isActive = true; enablePedestriansMotionDetection(); @@ -71,24 +69,28 @@ void CheckingSystem::run() enableCarsMotionDetection(); // Launch monitoring threads - std::thread pedestrianThread([this]() - { this->monitorPedestrian(); }); - std::thread roadThread([this]() - { this->monitorRoad(); }); + std::thread pedestrianThread([this]() { this->monitorPedestrian(); }); + std::thread roadThread([this]() { this->monitorRoad(); }); + std::thread buttonThread([this]() { this->monitorPedestriansButton(); }); - // Threads are joined to ensure the system does not exit prematurely - pedestrianThread.join(); + // Threads are joined to ensure the system does not exit prematurely + pedestrianThread.join(); roadThread.join(); } +// TODO: {Saleem & Alex} +void CheckingSystem::monitorPedestriansButton() { + if (pedestriansButtonClicked) { + pedestriansButtonClicked(); // Call the registered callback + } +} + /** * @brief Handles actions to be performed when the pedestrian button is pressed. * If the button is enabled and the callback is set, it triggers the registered callback. */ -void CheckingSystem::onPedestriansButtonPress() -{ - if (pedestriansButtonEnabled && pedestriansButtonClicked) - { +void CheckingSystem::onPedestriansButtonPress() { + if (pedestriansButtonEnabled && pedestriansButtonClicked) { pedestriansButtonClicked(); } } @@ -100,14 +102,10 @@ void CheckingSystem::onPedestriansButtonPress() * * @note This function is intended to run in a separate thread to avoid blocking the main application flow. */ -void CheckingSystem::monitorPedestrian() -{ - while (isActive) - { - if (monitorPedestriansActive && pedestrianSensor.isMotionDetected()) - { - if (pedestriansMotionDetected) - { +void CheckingSystem::monitorPedestrian() { + while (isActive) { + if (monitorPedestriansActive && pedestrianSensor.isMotionDetected()) { + if (pedestriansMotionDetected) { pedestriansMotionDetected(); // Call the registered callback } } @@ -123,14 +121,10 @@ void CheckingSystem::monitorPedestrian() * * @note Designed to run in a background thread, independently of other system operations. */ -void CheckingSystem::monitorRoad() -{ - while (isActive) - { - if (monitorRoadsActive && roadSensor.isMotionDetected()) - { - if (carsMotionDetected) - { +void CheckingSystem::monitorRoad() { + while (isActive) { + if (monitorRoadsActive && roadSensor.isMotionDetected()) { + if (carsMotionDetected) { carsMotionDetected(); // Call the registered callback } } @@ -139,12 +133,15 @@ void CheckingSystem::monitorRoad() } } +bool CheckingSystem::isRoadMotionDetected() { + return roadSensor.isMotionDetected(); +} + /** * @brief Deactivates the system and ensures a clean shutdown. * Sets isActive to false and waits for a brief period to allow threads to finish gracefully. */ -void CheckingSystem::deactivate() -{ +void CheckingSystem::deactivate() { isActive = false; // Give time for threads to finish any ongoing work std::this_thread::sleep_for(std::chrono::seconds(1)); // Adjust as needed @@ -155,48 +152,42 @@ void CheckingSystem::deactivate() /** * @brief Enables the motion detection for pedestrians. */ -void CheckingSystem::enablePedestriansMotionDetection() -{ +void CheckingSystem::enablePedestriansMotionDetection() { monitorRoadsActive = true; } /** * @brief Disables the motion detection for pedestrians. */ -void CheckingSystem::disablePedestriansMotionDetection() -{ +void CheckingSystem::disablePedestriansMotionDetection() { monitorRoadsActive = false; } /** * @brief Enables the motion detection for cars. */ -void CheckingSystem::enableCarsMotionDetection() -{ +void CheckingSystem::enableCarsMotionDetection() { monitorPedestriansActive = true; } /** * @brief Disables the motion detection for cars. */ -void CheckingSystem::disableCarsMotionDetection() -{ +void CheckingSystem::disableCarsMotionDetection() { monitorRoadsActive = false; } /** * @brief Enables the use of the pedestrian button. */ -void CheckingSystem::enablePedestriansButton() -{ +void CheckingSystem::enablePedestriansButton() { pedestriansButtonEnabled = true; } /** * @brief Disables the pedestrian button to prevent its use. */ -void CheckingSystem::disablePedestriansButton() -{ +void CheckingSystem::disablePedestriansButton() { pedestriansButtonEnabled = false; } @@ -204,8 +195,7 @@ void CheckingSystem::disablePedestriansButton() * @brief Registers a callback function for car motion detection. * @param callback Function to call when car motion is detected. */ -void CheckingSystem::registerCarsMotionCallback(const std::function &callback) -{ +void CheckingSystem::registerCarsMotionCallback(const std::function &callback) { Logger::logInfo("MainSystem::initialize called"); carsMotionDetected = callback; } @@ -214,8 +204,7 @@ void CheckingSystem::registerCarsMotionCallback(const std::function &cal * @brief Registers a callback function for pedestrian motion detection. * @param callback Function to call when pedestrian motion is detected. */ -void CheckingSystem::registerPedestriansMotionCallback(const std::function &callback) -{ +void CheckingSystem::registerPedestriansMotionCallback(const std::function &callback) { pedestriansMotionDetected = callback; } @@ -223,8 +212,7 @@ void CheckingSystem::registerPedestriansMotionCallback(const std::function &callback) -{ +void CheckingSystem::registerPedestriansButtonCallback(const std::function &callback) { pedestriansButtonClicked = callback; } @@ -232,8 +220,7 @@ void CheckingSystem::registerPedestriansButtonCallback(const std::functiononCarsMotionDetected(); }); - checkingSystem.registerPedestriansMotionCallback([this]() - { this->onPedestriansMotionDetected(); }); - checkingSystem.registerPedestriansButtonCallback([this]() - { this->onPedestriansButtonClicked(); }); + checkingSystem.registerCarsMotionCallback([this]() { this->onCarsMotionDetected(); }); + checkingSystem.registerPedestriansMotionCallback([this]() { this->onPedestriansMotionDetected(); }); + checkingSystem.registerPedestriansButtonCallback([this]() { this->onPedestriansButtonClicked(); }); } /** * @brief Runs all subsystems. * This function runs all subsystems of the traffic light system. */ -void MainSystem::runSystems() -{ +void MainSystem::runSystems() { enableTrafficLightsNormalBehaviour(); std::thread trafficLightsThread(&MainSystem::runTrafficLightsNormalBehaviour, this); - std::thread checkingSystemThread([this]() - { checkingSystem.run(); }); + std::thread checkingSystemThread([this]() { checkingSystem.run(); }); trafficLightsThread.join(); checkingSystemThread.join(); // Enable running warning system if needed @@ -65,8 +58,7 @@ void MainSystem::runSystems() * @brief Shuts down all subsystems. * This function shuts down all subsystems of the traffic light system. */ -void MainSystem::shutdown() -{ +void MainSystem::shutdown() { carsTrafficLight.deactivate(); pedestriansTrafficLight.deactivate(); checkingSystem.deactivate(); @@ -78,12 +70,10 @@ void MainSystem::shutdown() * @brief Callback for when cars motion is detected. * This function is called when the CheckingSystem detects motion from cars. It checks the current traffic light state and takes appropriate action. */ -void MainSystem::onCarsMotionDetected() -{ +void MainSystem::onCarsMotionDetected() { Logger::logInfo("Cars motion detected"); std::cout << "Cars motion detected" << std::endl; - if (trafficLightState != CARS_RED_PEDESTRIANS_GREEN) - { + if (trafficLightState != CARS_RED_PEDESTRIANS_GREEN) { return; // Do Nothing } @@ -94,24 +84,22 @@ void MainSystem::onCarsMotionDetected() warningSystem.activate(); // after 10 seconds - mainSystemTimer.setTimeout([this] - { + mainSystemTimer.setTimeout([this] { warningSystem.deactivate(); enableTrafficLightsNormalBehaviour(); runTrafficLightsNormalBehaviour(); - checkingSystem.enableSensing(); }, 10000); + checkingSystem.enableSensing(); + }, 10000); } /** * @brief Callback for when pedestrians motion is detected. * This function is called when the CheckingSystem detects motion from pedestrians. It checks the current traffic light state and takes appropriate action. */ -void MainSystem::onPedestriansMotionDetected() -{ +void MainSystem::onPedestriansMotionDetected() { Logger::logInfo("Pedestrians motion detected"); std::cout << "Pedestrians motion detected" << std::endl; - if (trafficLightState != CARS_GREEN_PEDESTRIANS_RED) - { + if (trafficLightState != CARS_GREEN_PEDESTRIANS_RED) { return; // Do Nothing } @@ -122,26 +110,31 @@ void MainSystem::onPedestriansMotionDetected() warningSystem.activate(); // after 10 seconds - mainSystemTimer.setTimeout([this] - { + mainSystemTimer.setTimeout([this] { warningSystem.deactivate(); enableTrafficLightsNormalBehaviour(); runTrafficLightsNormalBehaviour(); - checkingSystem.enableSensing(); }, 10000); + checkingSystem.enableSensing(); + }, 10000); } /** * @brief Callback for when the pedestrians button is clicked. * This function is called when the CheckingSystem detects a click on the pedestrians button. It checks the current traffic light state and takes appropriate action. */ -void MainSystem::onPedestriansButtonClicked() -{ +void MainSystem::onPedestriansButtonClicked() { std::cout << "Pedestrians button clicked" << std::endl; - if (trafficLightState != CARS_GREEN_PEDESTRIANS_RED) - { + if (trafficLightState != CARS_GREEN_PEDESTRIANS_RED) { return; // Do Nothing } + if (checkingSystem.isRoadMotionDetected()) { + std::cout << "checkingSystem::isRoadMotionDetected" << std::endl; + return; // Do Nothing + } + + std::cout << "Road is empty" << std::endl; + turnPedestriansTrafficLightGreen(); // State is CARS_GREEN_PEDESTRIANS_RED // if road status is empty (sensor or camera) -> turn to CARS_RED_PEDESTRIANS_GREEN // continue normal behaviour @@ -151,8 +144,7 @@ void MainSystem::onPedestriansButtonClicked() * @brief Enables the normal behaviour of traffic lights. * This function enables the normal operation of traffic lights. */ -void MainSystem::enableTrafficLightsNormalBehaviour() -{ +void MainSystem::enableTrafficLightsNormalBehaviour() { isTrafficLightRunningInNormalBehaviour = true; } @@ -160,8 +152,7 @@ void MainSystem::enableTrafficLightsNormalBehaviour() * @brief Disables the normal behaviour of traffic lights. * This function disables the normal operation of traffic lights. */ -void MainSystem::disableTrafficLightsNormalBehaviour() -{ +void MainSystem::disableTrafficLightsNormalBehaviour() { isTrafficLightRunningInNormalBehaviour = false; carsTrafficLightTimer.stopTimer(); pedestriansTrafficLightTimer.stopTimer(); @@ -172,21 +163,19 @@ void MainSystem::disableTrafficLightsNormalBehaviour() * @brief Turns the cars traffic light green. * This function turns the cars traffic light green and initiates a sequence for pedestrians traffic light. */ -void MainSystem::turnCarsTrafficLightGreen() -{ +void MainSystem::turnCarsTrafficLightGreen() { Logger::logInfo("turnCarsTrafficLightGreen called"); - if (!isTrafficLightRunningInNormalBehaviour) - { + if (!isTrafficLightRunningInNormalBehaviour) { return; } carsTrafficLight.turnYellow(); pedestriansTrafficLight.turnRed(); - yellowTrafficLightTimer.setTimeout([this] - { + yellowTrafficLightTimer.setTimeout([this] { carsTrafficLight.turnGreen(); pedestriansTrafficLight.turnRed(); trafficLightState = CARS_GREEN_PEDESTRIANS_RED; - pedestriansTrafficLightTimer.setTimeout([this] { turnPedestriansTrafficLightGreen(); }, 20000); }, 2000); + pedestriansTrafficLightTimer.setTimeout([this] { turnPedestriansTrafficLightGreen(); }, 20000); + }, 2000); Logger::logInfo("turnCarsTrafficLightGreen finished"); } @@ -195,18 +184,15 @@ void MainSystem::turnCarsTrafficLightGreen() * @brief Turns the pedestrians traffic light green. * This function turns the pedestrians traffic light green and initiates a sequence for cars traffic light. */ -void MainSystem::turnPedestriansTrafficLightGreen() -{ +void MainSystem::turnPedestriansTrafficLightGreen() { Logger::logInfo("turnPedestriansTrafficLightGreen called"); - if (!isTrafficLightRunningInNormalBehaviour) - { + if (!isTrafficLightRunningInNormalBehaviour) { return; } carsTrafficLight.turnRed(); pedestriansTrafficLight.turnGreen(); trafficLightState = CARS_RED_PEDESTRIANS_GREEN; - carsTrafficLightTimer.setTimeout([this] - { turnCarsTrafficLightGreen(); }, 20000); + carsTrafficLightTimer.setTimeout([this] { turnCarsTrafficLightGreen(); }, 20000); Logger::logInfo("turnPedestriansTrafficLightGreen finished"); } @@ -214,8 +200,7 @@ void MainSystem::turnPedestriansTrafficLightGreen() * @brief Turns all traffic lights red. * This function turns all traffic lights red, stopping both car and pedestrian traffic. */ -void MainSystem::turnAllTrafficLightsRed() -{ +void MainSystem::turnAllTrafficLightsRed() { Logger::logInfo("turnAllTrafficLightsRed called"); carsTrafficLight.turnRed(); pedestriansTrafficLight.turnRed(); @@ -226,8 +211,7 @@ void MainSystem::turnAllTrafficLightsRed() * @brief Runs the normal behavior of traffic lights. * This function initiates the normal operation of traffic lights. */ -void MainSystem::runTrafficLightsNormalBehaviour() -{ +void MainSystem::runTrafficLightsNormalBehaviour() { Logger::logInfo("runTrafficLightsNormalBehaviour called"); turnCarsTrafficLightGreen(); } \ No newline at end of file diff --git a/src/main/WarningSystem.cpp b/src/main/WarningSystem.cpp index dcff98c..1193825 100644 --- a/src/main/WarningSystem.cpp +++ b/src/main/WarningSystem.cpp @@ -10,12 +10,12 @@ * The constructor initializes LED and Buzzer objects using predefined pins * from the Constants class. Initially sets the system to an uninitialized state. */ -WarningSystem::WarningSystem() - : warningLED(ledPin), - warningLED2(ledPin2), - warningLED3(ledPin3), - warningBuzzer(buzzerPin), - isInitialized(false) {} +WarningSystem::WarningSystem() + : warningLED(ledPin), + warningLED2(ledPin2), + warningLED3(ledPin3), + warningBuzzer(buzzerPin), + isInitialized_(false) {} /** * @brief Initializes the warning system by setting all components to the off state. @@ -24,11 +24,9 @@ WarningSystem::WarningSystem() * start in the off state and sets the system as initialized. */ void WarningSystem::initialize() { - warningLED.off(); - warningLED2.off(); - warningLED3.off(); - warningBuzzer.off(); - isInitialized = true; + // Initialize the LED and buzzer (if necessary) + // For example, you might set an initial state or perform a self-check + isInitialized_ = true; } /** @@ -38,7 +36,7 @@ void WarningSystem::initialize() { * and the buzzer to signal a warning state. */ void WarningSystem::activate() { - if (isInitialized) { + if (isInitialized_) { warningLED.on(); warningLED2.on(); warningLED3.on(); @@ -53,7 +51,7 @@ void WarningSystem::activate() { * returning the system to a non-alert state. */ void WarningSystem::deactivate() { - if (isInitialized) { + if (isInitialized_) { warningLED.off(); warningLED2.off(); warningLED3.off(); diff --git a/src/pigpio_stub.cpp b/src/pigpio_stub.cpp index c29c235..3d333e4 100644 --- a/src/pigpio_stub.cpp +++ b/src/pigpio_stub.cpp @@ -37,8 +37,7 @@ unsigned int simulatedTick = 0; * * @return Always returns 0 in this stub implementation. */ -int gpioInitialise() -{ +int gpioInitialise() { Logger::logInfo("gpioInitialise() called"); pinStates.clear(); // Clear pin states upon initialization simulatedTick = 0; // Reset simulated tick on initialization @@ -50,8 +49,7 @@ int gpioInitialise() * * Clears the pin states. Optional in this implementation. */ -void gpioTerminate() -{ +void gpioTerminate() { Logger::logInfo("gpioTerminate() called"); pinStates.clear(); // Optionally clear pin states upon termination } @@ -64,8 +62,7 @@ void gpioTerminate() * @param pin The GPIO pin number. * @param mode The mode to set for the pin (input or output). */ -void gpioSetMode(unsigned pin, unsigned mode) -{ +void gpioSetMode(unsigned pin, unsigned mode) { string message = "gpioSetMode(pin: " + to_string(pin) + ", mode: " + to_string(mode) + ") called"; Logger::logInfo(message); // Mode setting not simulated in pinStates map, as it's primarily for direction @@ -79,8 +76,7 @@ void gpioSetMode(unsigned pin, unsigned mode) * @param pin The GPIO pin number. * @param level The level to write to the pin (high or low). */ -void gpioWrite(unsigned pin, unsigned level) -{ +void gpioWrite(unsigned pin, unsigned level) { string message = "gpioWrite(pin: " + to_string(pin) + ", level: " + to_string(level) + ") called"; Logger::logInfo(message); // Save the level of the pin in the map @@ -95,18 +91,14 @@ void gpioWrite(unsigned pin, unsigned level) * @param pin The GPIO pin number to read. * @return The level of the pin (high or low). */ -int gpioRead(unsigned pin) -{ +int gpioRead(unsigned pin) { string message = "gpioRead(pin: " + to_string(pin) + ") called"; Logger::logInfo(message); // Return the stored state if available, otherwise default to LOW auto it = pinStates.find(pin); - if (it != pinStates.end()) - { + if (it != pinStates.end()) { return it->second; - } - else - { + } else { return PI_LOW; // Default to LOW if not set } } @@ -118,8 +110,7 @@ int gpioRead(unsigned pin) * * @param micros The number of microseconds to delay. */ -void gpioDelay(unsigned micros) -{ +void gpioDelay(unsigned micros) { string message = "gpioDelay(" + to_string(micros) + " microseconds) called"; Logger::logInfo(message); // Simulate delay by incrementing the simulatedTick counter @@ -131,12 +122,46 @@ void gpioDelay(unsigned micros) * * @return The current simulated tick value. */ -unsigned gpioTick() -{ +unsigned gpioTick() { Logger::logInfo("gpioTick() called"); return simulatedTick; } +/** + * @brief Set an ISR function for GPIO pin interrupt events. + * + * This function simulates setting an ISR function for GPIO pin interrupt events. + * It logs the function parameters but does not perform any actual ISR registration. + * + * @param gpio The GPIO pin number. + * @param edge The edge (RISING_EDGE, FALLING_EDGE, or EITHER_EDGE) to trigger the interrupt. + * @param timeout Interrupt timeout in milliseconds (<= 0 to cancel). + * @param f The ISR function to set. + * @param userdata Pointer to arbitrary user data. + * @return Returns 0 if OK, otherwise returns PI_BAD_GPIO, PI_BAD_EDGE, or PI_BAD_ISR_INIT. + */ +int gpioSetISRFuncEx(unsigned pin, int edge, int timeout, void (*func)(int, int, unsigned, void *), void *user) { + string message = "gpioSetISRFuncEx(pin: " + to_string(pin) + ", edge: " + to_string(edge) + ", timeout: " + + to_string(timeout) + + ", function: " + to_string(reinterpret_cast(func)) + ", userdata: " + + to_string(reinterpret_cast(user)) + ") called"; + Logger::logInfo(message); + // Store the callback function and user data for the specified pin + callbacks[pin].emplace_back( + [func, user](int gpio, int level, unsigned tick, void *userData) { func(gpio, level, tick, user); }); + + // Return success for the stub implementation + return 0; +} + +// This function is supposed to mimic setting the pull-up/pull-down resistors for a GPIO pin. +void gpioSetPullUpDown(unsigned pin, unsigned pud) { + string message = "gpioSetPullUpDown(pin: " + to_string(pin) + ", pud: " + to_string(pud) + ") called"; + Logger::logInfo(message); + callbacks[pin].emplace_back( + [pin, pud](int gpio, int level, unsigned tick, void *userData) { gpioWrite(pin, pud); }); +} + /** * @brief Set a callback function for GPIO pin alert events. * @@ -147,14 +172,13 @@ unsigned gpioTick() * @param user A user-defined pointer passed to the callback function. * @return Always returns 0 in this stub implementation. */ -int gpioSetAlertFuncEx(unsigned pin, void (*func)(int, int, unsigned, void *), void *user) -{ +int gpioSetAlertFuncEx(unsigned pin, void (*func)(int, int, unsigned, void *), void *user) { string message = "gpioSetAlertFuncEx(pin: " + to_string(pin) + ") called"; Logger::logInfo(message); // Store the callback function and user data for the specified pin - callbacks[pin].emplace_back([func, user](int gpio, int level, unsigned tick, void *userData) - { func(gpio, level, tick, user); }); + callbacks[pin].emplace_back( + [func, user](int gpio, int level, unsigned tick, void *userData) { func(gpio, level, tick, user); }); return 0; // Success } @@ -169,17 +193,16 @@ int gpioSetAlertFuncEx(unsigned pin, void (*func)(int, int, unsigned, void *), v * @param level The level value to pass to the callback function. * @param tick The tick value to pass to the callback function. */ -void simulateCallback(unsigned pin, int level, unsigned tick) -{ - string message = "simulateCallback(pin: " + to_string(pin) + ", level: " + to_string(level) + ", tick: " + to_string(tick) + ") called"; +void simulateCallback(unsigned pin, int level, unsigned tick) { + string message = + "simulateCallback(pin: " + to_string(pin) + ", level: " + to_string(level) + ", tick: " + to_string(tick) + + ") called"; Logger::logInfo(message); // Call all registered callback functions for the specified pin auto it = callbacks.find(pin); - if (it != callbacks.end()) - { - for (const auto &callback : it->second) - { + if (it != callbacks.end()) { + for (const auto &callback: it->second) { callback(pin, level, tick, nullptr); } } diff --git a/src/sensors/PushButton.cpp b/src/sensors/PushButton.cpp index a574d89..d1acf05 100644 --- a/src/sensors/PushButton.cpp +++ b/src/sensors/PushButton.cpp @@ -1,75 +1,59 @@ #include "sensors/PushButton.h" #include +#include - -/** - * @brief Constructs a PushButton instance associated with a specific GPIO pin. - * @param pin GPIO pin number to be used for the push button. - */ -PushButton::PushButton(int pin) : gpioPin(pin) { +PushButton::PushButton(int pin) : gpioPin(pin), buttonPressCallback(nullptr) { + // Initialize the GPIO pin and register the interrupt service routine + initialize(); } -/** - * @brief Destructs the PushButton instance. - * - * This destructor ensures that the interrupt service routine is detached, preventing any callbacks - * from being called after the object is destroyed. - */ PushButton::~PushButton() { -#if defined(__linux__) && defined(__arm__) - // Reset ISR handling on this pin - gpioSetISRFuncEx(gpioPin, FALLING_EDGE, 0, NULL, NULL); -#else - -#endif + // Detach the interrupt service routine to prevent any callbacks after the object is destroyed + detachInterruptHandler(); } -/** - * @brief Initializes the PushButton hardware interface. - * - * This method sets up the GPIO pin as an input with an internal pull-up resistor and - * registers the interrupt service routine to handle button presses. - */ void PushButton::initialize() { -#if defined(__linux__) && defined(__arm__) - // Initialize pigpio and set pin modes, only on Raspberry Pi - if (gpioInitialise() < 0) { - std::cerr << "Unable to connect PIGPIO, exiting" << std::endl; - return; - } + // Initialize the GPIO pin as an input with a pull-up resistor + gpioInit(); gpioSetMode(gpioPin, PI_INPUT); gpioSetPullUpDown(gpioPin, PI_PUD_UP); - // Set ISR for falling edge (button press) - gpioSetISRFuncEx(gpioPin, FALLING_EDGE, 0, buttonPressHandler, this); - // More initialization as necessary -#else -#endif + // Register the interrupt service routine to handle button presses + attachInterruptHandler(); +} +void PushButton::registerButtonPressCallback(ButtonCallback callback) { + buttonPressCallback = callback; +} +void PushButton::registerButtonReleaseCallback(ButtonCallback callback) { + buttonReleaseCallback = callback; } -/** - * @brief Registers a callback to be invoked when the button is pressed. - * @param callback The callback function to execute on a button press. - */ -void PushButton::registerButtonPressCallback(ButtonCallback callback) { - this->buttonPressCallback = callback; + +void PushButton::attachInterruptHandler() { + // Attach the interrupt service routine to the GPIO pin + gpioSetAlertFuncEx(gpioPin, &PushButton::buttonPressHandler, this); } -/** - * @brief Handles button press events by invoking the registered callback. - * - * This static method is called automatically when a button press event occurs. It checks if a valid - * callback is registered and calls it. The method logs the button press event details for debugging. - * @param gpio GPIO pin number where the event occurred. - * @param level New level of the GPIO pin (0 or 1). - * @param tick System tick at the time of the event. - * @param user User-defined data, which should be a pointer to the PushButton instance. - */ + +void PushButton::detachInterruptHandler() { + // Detach the interrupt service routine from the GPIO pin + gpioSetAlertFuncEx(gpioPin, nullptr, nullptr); +} + void PushButton::buttonPressHandler(int gpio, int level, uint32_t tick, void *user) { - // This function is called in the context of a new thread when the button is pressed - std::cout << "Button Pressed " << gpio << " " << level << " " << tick << std::endl; + // Cast the user data to the PushButton instance PushButton *button = static_cast(user); + + // Invoke the registered callback, if any if (button->buttonPressCallback) { - button->buttonPressCallback(); // Call the user's callback + button->buttonPressCallback(); + } +} + +void PushButton::gpioInit() { + // Initialize the GPIO library + if (gpioInitialise() < 0) { + std::cerr << "Unable to connect PIGPIO, exiting" << std::endl; + throw std::runtime_error("Failed to initialize PIGPIO"); } } \ No newline at end of file diff --git a/src/utils/FirestoreLogger.cpp b/src/utils/FirestoreLogger.cpp index 320a1c8..10e6e6e 100644 --- a/src/utils/FirestoreLogger.cpp +++ b/src/utils/FirestoreLogger.cpp @@ -36,3 +36,11 @@ std::string FirestoreLogger::GenerateTimestamp() { ss << std::put_time(std::localtime(&now_c), "%FT%T%z"); // Adjust the format if needed return ss.str(); } + +std::string FirestoreLogger::GetApiKey() { + return apiKey; +} + +std::string FirestoreLogger::GetBaseUrl() { + return baseUrl; +} \ No newline at end of file diff --git a/tests/hardware_tests/sensors/PushButton_test.cpp b/tests/hardware_tests/sensors/PushButton_test.cpp new file mode 100644 index 0000000..4c5271b --- /dev/null +++ b/tests/hardware_tests/sensors/PushButton_test.cpp @@ -0,0 +1,65 @@ +#define BOOST_TEST_MODULE PushButtonTest +#include + +#include "sensors/PushButton.h" +#include "pigpio_stub.h" +#include "utils/Logger.h" + +BOOST_AUTO_TEST_SUITE(PushButtonTests) + +// Flags to track the callback invocations +bool isButtonPressCallbackCalled = false; +bool isButtonReleaseCallbackCalled = false; + +// Callback functions for button press and release events +void onButtonPress() +{ + isButtonPressCallbackCalled = true; +} + +void onButtonRelease() +{ + isButtonReleaseCallbackCalled = true; +} + +BOOST_AUTO_TEST_CASE(ButtonPressAndReleaseHandlerTest) +{ + // Set up the mock environment + // Logger::setLogLevel(Logger::LogLevel::Debug); + gpioInitialise(); + + // Create a PushButton instance + PushButton button(17); + + // Register the callback functions + button.registerButtonPressCallback(onButtonPress); + button.registerButtonReleaseCallback(onButtonRelease); + + // Simulate a button press event + // Logger::logDebug("Simulating button press event..."); + simulateCallback(17, PI_LOW, gpioTick()); + + // Assertions for button press event + BOOST_CHECK_EQUAL(gpioRead(17), PI_LOW); + BOOST_CHECK(isButtonPressCallbackCalled); + BOOST_CHECK(!isButtonReleaseCallbackCalled); + + // // Reset the flags + // isButtonPressCallbackCalled = false; + // isButtonReleaseCallbackCalled = false; + + // // Simulate a button release event + // // Logger::logDebug("Simulating button release event..."); + // simulateCallback(17, PI_HIGH, gpioTick()); + + // // Assertions for button release event + // BOOST_CHECK_EQUAL(gpioRead(17), PI_HIGH); + // BOOST_CHECK(!isButtonPressCallbackCalled); + // BOOST_CHECK(isButtonReleaseCallbackCalled); + + // Tear down the mock environment + // Logger::logDebug("Tearing down the mock environment..."); + gpioTerminate(); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/tests/logic_tests/main/CarsTrafficLightSystem_test.cpp b/tests/logic_tests/main/CarsTrafficLightSystem_test.cpp new file mode 100644 index 0000000..e102ac8 --- /dev/null +++ b/tests/logic_tests/main/CarsTrafficLightSystem_test.cpp @@ -0,0 +1,66 @@ +#define BOOST_TEST_MODULE CarsTrafficLightSystemTest +#include +#include "main/CarsTrafficLightSystem.h" +#include "utils/Constants.h" +#include "pigpio_stub.h" + +struct CarsTrafficLightSystemFixture +{ + CarsTrafficLightSystem *trafficSystem; + + CarsTrafficLightSystemFixture() + { + gpioInitialise(); // Set up the simulated GPIO environment + trafficSystem = new CarsTrafficLightSystem(); + } + + ~CarsTrafficLightSystemFixture() + { + delete trafficSystem; + gpioTerminate(); // Clean up the simulated GPIO environment + } +}; + +BOOST_FIXTURE_TEST_SUITE(CarsTrafficLightSystemSuite, CarsTrafficLightSystemFixture) + +// Test the constructor and initialization logic. +BOOST_AUTO_TEST_CASE(Initialization) +{ + trafficSystem->initialize(); + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightGreenPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightYellowPin), PI_LOW); +} + +// Test the activation and running logic. +BOOST_AUTO_TEST_CASE(RunSystem) +{ + trafficSystem->initialize(); + trafficSystem->run(); // Assuming some logic in run() sets pins + // Check the expected state of the traffic lights after running the system. + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightGreenPin), PI_HIGH); +} + +// Test the deactivation logic. +BOOST_AUTO_TEST_CASE(DeactivateSystem) +{ + trafficSystem->initialize(); + trafficSystem->deactivate(); + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightGreenPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightYellowPin), PI_LOW); +} + +// Testing the state transitions could be based on specific requirements or states. +BOOST_AUTO_TEST_CASE(StateTransitions) +{ + trafficSystem->initialize(); + // Example transition from RED to GREEN + gpioWrite(Constants::CarsTrafficLightRedPin, PI_HIGH); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + trafficSystem->run(); // Implement logic to check/change state + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::CarsTrafficLightGreenPin), PI_HIGH); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/logic_tests/main/CheckingSystem_test.cpp b/tests/logic_tests/main/CheckingSystem_test.cpp new file mode 100644 index 0000000..be7c6c1 --- /dev/null +++ b/tests/logic_tests/main/CheckingSystem_test.cpp @@ -0,0 +1,91 @@ +#define BOOST_TEST_MODULE CheckingSystemTest +#include + +#include "main/CheckingSystem.h" +#include "pigpio_stub.h" +#include "utils/Logger.h" + +BOOST_AUTO_TEST_SUITE(CheckingSystemTests) + +BOOST_AUTO_TEST_CASE(test_pedestrian_button_press) +{ + // Create a mock CheckingSystem instance + CheckingSystem system; + + // Enable the pedestrians button + system.enablePedestriansButton(); + + // Set up a mock callback for the pedestrians button press + bool buttonPressed = false; + system.registerPedestriansButtonCallback([&]() + { buttonPressed = true; }); + + // Simulate a pedestrians button press + system.onPedestriansButtonPress(); + + // Verify that the callback was called + BOOST_CHECK(buttonPressed); +} + +BOOST_AUTO_TEST_CASE(test_pedestrian_motion_detection) +{ + // Create a mock CheckingSystem instance + CheckingSystem system; + + // Enable pedestrian motion detection + system.enablePedestriansMotionDetection(); + + // Set up a mock callback for pedestrian motion detection + bool pedestrianMotionDetected = false; + system.registerPedestriansMotionCallback([&]() + { pedestrianMotionDetected = true; }); + + // Simulate pedestrian motion detection using UltrasonicSensor + const int triggerPin = 23; // Assuming trigger pin for pedestrian sensor + const int echoPin = 24; // Assuming echo pin for pedestrian sensor + UltrasonicSensor sensor(triggerPin, echoPin); + // Simulate motion under the threshold set to trigger warning system + const uint32_t startTick2 = 0; + const uint32_t endTick2 = 291; // Time for 5 centimeters in microseconds (291.375us) + + simulateCallback(echoPin, 1, startTick2); + simulateCallback(echoPin, 0, endTick2); + + // Simulate motion detection within range + bool motionDetected = sensor.isMotionDetected(5.0f); // Adjust threshold as needed + + // Verify that the callback was called + BOOST_CHECK(pedestrianMotionDetected == motionDetected); +} + +BOOST_AUTO_TEST_CASE(test_car_motion_detection) +{ + // Create a mock CheckingSystem instance + CheckingSystem system; + + // Enable car motion detection + system.enableCarsMotionDetection(); + + // Set up a mock callback for car motion detection + bool carMotionDetected = false; + system.registerCarsMotionCallback([&]() + { carMotionDetected = true; }); + + // Simulate car motion detection using UltrasonicSensor + const int triggerPin = 25; // Assuming trigger pin for car sensor + const int echoPin = 26; // Assuming echo pin for car sensor + UltrasonicSensor sensor(triggerPin, echoPin); + // Simulate motion under the threshold set to trigger warning system + const uint32_t startTick2 = 0; + const uint32_t endTick2 = 291; // Time for 5 centimeters in microseconds (291.375us) + + simulateCallback(echoPin, 1, startTick2); + simulateCallback(echoPin, 0, endTick2); + // Simulate motion detection within range + bool motionDetected = sensor.isMotionDetected(5.0f); // Adjust threshold as needed + + // Verify that the callback was called + BOOST_CHECK(carMotionDetected == motionDetected); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/logic_tests/main/PedestriansTrafficLightSystem_test.cpp b/tests/logic_tests/main/PedestriansTrafficLightSystem_test.cpp new file mode 100644 index 0000000..b1bbf82 --- /dev/null +++ b/tests/logic_tests/main/PedestriansTrafficLightSystem_test.cpp @@ -0,0 +1,65 @@ +#define BOOST_TEST_MODULE PedestriansTrafficLightSystemTest +#include +#include "main/PedestriansTrafficLightSystem.h" +#include "utils/Constants.h" +#include "pigpio_stub.h" + + +struct PedestriansTrafficLightSystemFixture +{ + PedestriansTrafficLightSystem *trafficSystem; + + PedestriansTrafficLightSystemFixture() + { + gpioInitialise(); // Set up the simulated GPIO environment + trafficSystem = new PedestriansTrafficLightSystem(); + } + + ~PedestriansTrafficLightSystemFixture() + { + delete trafficSystem; + gpioTerminate(); // Clean up the simulated GPIO environment + } +}; + +BOOST_FIXTURE_TEST_SUITE(PedestriansTrafficLightSystemSuite, PedestriansTrafficLightSystemFixture) + +// Test the constructor and initialization logic. +BOOST_AUTO_TEST_CASE(Initialization) +{ + trafficSystem->initialize(); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_LOW); +} + +// Test the activation and running logic. +BOOST_AUTO_TEST_CASE(RunSystem) +{ + trafficSystem->initialize(); + trafficSystem->run(); // Assuming some logic in run() sets pins + // Check the expected state of the traffic lights after running the system. + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_HIGH); +} + +// Test the deactivation logic. +BOOST_AUTO_TEST_CASE(DeactivateSystem) +{ + trafficSystem->initialize(); + trafficSystem->deactivate(); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_LOW); +} + +// Testing the state transitions could be based on specific requirements or states. +BOOST_AUTO_TEST_CASE(StateTransitions) +{ + trafficSystem->initialize(); + // Example transition from RED to GREEN + gpioWrite(Constants::PedestriansTrafficLightRedPin, PI_HIGH); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + trafficSystem->run(); // Implement logic to check/change state + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_HIGH); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/logic_tests/main/WarningSystem_test.cpp b/tests/logic_tests/main/WarningSystem_test.cpp new file mode 100644 index 0000000..62df570 --- /dev/null +++ b/tests/logic_tests/main/WarningSystem_test.cpp @@ -0,0 +1,59 @@ +#define BOOST_TEST_MODULE WarningSystemTest +#include + +#include "main/WarningSystem.h" +#include "pigpio_stub.h" +#include "utils/Logger.h" + +BOOST_AUTO_TEST_SUITE(WarningSystemTests) + +BOOST_AUTO_TEST_CASE(WarningSystem_Initialize) +{ + // Create an instance of the WarningSystem + WarningSystem warningSystem; + + // Test the initialization of the warning system + BOOST_CHECK(!warningSystem.isInitialized()); + warningSystem.initialize(); + BOOST_CHECK(warningSystem.isInitialized()); +} + +BOOST_AUTO_TEST_CASE(WarningSystem_Activate) +{ + // Create an instance of the WarningSystem + WarningSystem warningSystem; + + // Initialize the warning system + warningSystem.initialize(); + + // Test the activation of the warning system + warningSystem.activate(); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin2), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin3), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::buzzerPin), PI_HIGH); +} + +BOOST_AUTO_TEST_CASE(WarningSystem_Deactivate) +{ + // Create an instance of the WarningSystem + WarningSystem warningSystem; + + // Initialize the warning system + warningSystem.initialize(); + + // Test the deactivation of the warning system + warningSystem.activate(); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin2), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin3), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::buzzerPin), PI_HIGH); + + warningSystem.deactivate(); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin2), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::ledPin3), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(WarningSystem::buzzerPin), PI_LOW); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/logic_tests/models/TrafficLight_test.cpp b/tests/logic_tests/models/TrafficLight_test.cpp new file mode 100644 index 0000000..9293b97 --- /dev/null +++ b/tests/logic_tests/models/TrafficLight_test.cpp @@ -0,0 +1,71 @@ +#define BOOST_TEST_MODULE TrafficLightTest +#include +#include "models/TrafficLight.h" +#include "actuators/LED.h" +#include "utils/Constants.h" +#include "pigpio_stub.h" + +#include // For sleep + +struct TrafficLightFixture +{ + TrafficLight *trafficLight; + + TrafficLightFixture() + { + gpioInitialise(); // Set up the simulated GPIO environment + trafficLight = new TrafficLight(Constants::PedestriansTrafficLightRedPin, + Constants::PedestriansTrafficLightGreenPin, + Constants::UnusedPin); + } + + ~TrafficLightFixture() + { + delete trafficLight; + gpioTerminate(); // Clean up the simulated GPIO environment + } +}; + +BOOST_FIXTURE_TEST_SUITE(TrafficLightSuite, TrafficLightFixture) + +// Test the constructor and initialization logic. +BOOST_AUTO_TEST_CASE(Initialization) +{ + trafficLight->turnRed(); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_LOW); +} + +// Test turning the light to red. +BOOST_AUTO_TEST_CASE(TurnRed) +{ + trafficLight->turnRed(); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_HIGH); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_LOW); +} + +// Test turning the light to green. +BOOST_AUTO_TEST_CASE(TurnGreen) +{ + trafficLight->turnGreen(); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_HIGH); +} + +// Test turning the light to yellow. +BOOST_AUTO_TEST_CASE(TurnYellow) +{ + trafficLight->turnYellow(); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_LOW); +} + +// Test turning off the light. +BOOST_AUTO_TEST_CASE(TurnOff) +{ + trafficLight->turnOff(); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightRedPin), PI_LOW); + BOOST_CHECK_EQUAL(gpioRead(Constants::PedestriansTrafficLightGreenPin), PI_LOW); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/logic_tests/utils/FirestoreLogger_test.cpp b/tests/logic_tests/utils/FirestoreLogger_test.cpp new file mode 100644 index 0000000..bae41b8 --- /dev/null +++ b/tests/logic_tests/utils/FirestoreLogger_test.cpp @@ -0,0 +1,69 @@ +#define BOOST_TEST_MODULE FirestoreLoggerTest +#include + +#include "utils/FirestoreLogger.h" + +BOOST_AUTO_TEST_SUITE(FirestoreLoggerTests) + +BOOST_AUTO_TEST_CASE(test_initialization) +{ + // Test initialization with a valid API key + std::string apiKey = ""; + FirestoreLogger::Initialize(apiKey); + + BOOST_CHECK_EQUAL(FirestoreLogger::GetApiKey(), apiKey); +} + +BOOST_AUTO_TEST_CASE(test_logging) +{ + // Test logging with a valid API key and message + std::string apiKey = ""; + FirestoreLogger::Initialize(apiKey); + + std::string logLevel = "info"; + std::string message = "Test log message"; + + // Redirect std::cerr to a stringstream to capture the output + std::stringstream capturedOutput; + std::streambuf *originalCerr = std::cerr.rdbuf(capturedOutput.rdbuf()); + + // Log the message + FirestoreLogger::Log(logLevel, message); + + // // Check if logging was successful by examining HTTP response status + // // For simplicity, assume successful logging if HTTP response status is 200 + // cpr::Response response = cpr::Post(cpr::Url{FirestoreLogger::GetBaseUrl() + "?key=" + apiKey}, + // cpr::Header{{"Content-Type", "application/json"}}, + // cpr::Body{R"({ "fields": { "log": { "stringValue": "Test log message" }, "level": { "stringValue": "info" }, "timestamp": { "stringValue": "2024-04-16T15:45:00+0000" } } })"}); + // BOOST_CHECK_EQUAL(response.status_code, 200); + + // Restore std::cerr + std::cerr.rdbuf(originalCerr); + + // Check if the log message was outputted correctly + std::string expectedOutput = "FirestoreLogger not initialized with API key."; + BOOST_CHECK_EQUAL(capturedOutput.str(), expectedOutput); +} + +BOOST_AUTO_TEST_CASE(test_timestamp_generation) +{ + // Test timestamp generation indirectly by checking if it's included in the log + // Initialize FirestoreLogger with API key + std::string apiKey = ""; // Replace with your API key + FirestoreLogger::Initialize(apiKey); + + // Log a message + std::string level = "info"; + std::string message = "Test log message"; + FirestoreLogger::Log(level, message); + + // Retrieve the logged message from Firestore (assuming it's stored with the timestamp) + // For simplicity, let's assume the logged message contains the timestamp + std::string loggedMessage = ""; // Replace with code to retrieve logged message + bool containsTimestamp = loggedMessage.find("2024-04-16T15:45:00+0000") != std::string::npos; + + // Validate that the logged message contains the timestamp + BOOST_CHECK(containsTimestamp); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/logic_tests/utils/Logger_test.cpp b/tests/logic_tests/utils/Logger_test.cpp new file mode 100644 index 0000000..cba539c --- /dev/null +++ b/tests/logic_tests/utils/Logger_test.cpp @@ -0,0 +1,76 @@ +#define BOOST_TEST_MODULE LoggerTest +#include +#include "utils/Logger.h" +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(LoggerTests) + +// Define a temporary log file name for testing +const std::string testLogFileName = "test.log"; + +BOOST_AUTO_TEST_CASE(test_initialization) +{ + // Initialize logger with the test log file name + Logger::init(testLogFileName); + + // Check if the log file is successfully opened + std::ifstream logFile(testLogFileName); + BOOST_CHECK(logFile.is_open()); + + // Close the log file + logFile.close(); + + // Close the logger + Logger::close(); +} + +BOOST_AUTO_TEST_CASE(test_logging) +{ + // Initialize logger with the test log file name + Logger::init(testLogFileName); + + // Log some messages + Logger::logInfo("This is an informational message."); + Logger::logError("This is an error message."); + + // Wait for a short time to ensure messages are written to the file + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // Check if messages are written to the log file + std::ifstream logFile(testLogFileName); + std::string line; + bool infoLogged = false; + bool errorLogged = false; + while (std::getline(logFile, line)) + { + if (line.find("[INFO]") != std::string::npos && line.find("This is an informational message.") != std::string::npos) + infoLogged = true; + if (line.find("[ERROR]") != std::string::npos && line.find("This is an error message.") != std::string::npos) + errorLogged = true; + } + BOOST_CHECK(infoLogged); + BOOST_CHECK(errorLogged); + + // Close the log file + logFile.close(); + + // Close the logger + Logger::close(); +} + +BOOST_AUTO_TEST_CASE(test_closing) +{ + // Initialize logger with the test log file name + Logger::init(testLogFileName); + + // Close the logger + Logger::close(); + + // Check if the log file is closed + std::ifstream logFile(testLogFileName); + BOOST_CHECK(!logFile.is_open()); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/TimerTest.cpp b/tests/logic_tests/utils/Timer_test.cpp similarity index 100% rename from tests/TimerTest.cpp rename to tests/logic_tests/utils/Timer_test.cpp